Typecho中Widget_Archive详解

## Widget_Archive的内涵 ##
Widget_Archive是Typecho中非常重要的一个组件,基本上所有文章/页面内容的渲染都离不开这个组件。
Widget_Archive类位于/var/Widget/Archive.php里面,其继承关系如下:

![Widget_Archive继承关系.png][1]

所以,在实际开发过程中,需要关注的api主要有两类,1.Widget_Archive中的各种get函数,2.Typecho_Wdiget中的魔术函数。

1. Widget_Archive中的各种get函数
这类函数包括`getArchiveSlug()`/`getArchiveType()`/`getArchiveTitle()`等等,各位在制作Typecho模板的时候,可以即时参考源代码,这里就不一一赘述。

2. Typecho_Wdiget中的魔术函数

**魔术函数`__get($name)`,获取内部变量**

public function __get($name){
if (array_key_exists($name, $this->row)) {
return $this->row[$name];
} else {
$method = ‘___’ . $name;

if (method_exists($this, $method)) {
return $this->$method();
} else {
$return = $this->pluginHandle()->trigger($plugged)->{$method}($this);
if ($plugged) {
return $return;
}
}
}

return NULL;
}
从贴出的代码可以看出,当我们在模板页面中调用$this->author的时候,会发生什么事情呢?首先,看看当前row中是否存在key为author的值(row里面的内容一般情况下和数据表字段一一对应),如果有则直接返回。如果没有找到,那么继续尝试找是否存在名为`__author`的函数,有则直接调用。如果还是没有找到,那么继续尝试从找插件中找。

**魔术函数`__set($name,$value)`,改变当前row的值**

public function __set($name, $value){
$this->row[$name] = $value;
}

这个比较简单,就不细说了。在实战中,可以通过这个方式来临时改变row中的内容,以供其他地方调用。

**魔术函数`__call($name)`,直接输出当前row中的某个值**

public function __call($name, $args){
echo $this->{$name};
}
譬如在模板中调用`$this->author()`,那么会直接输出作者名到模板中。但注意看上面的代码,这个调用方式不是return回来的,而是直接echo出去的。

## Widget_Archive路由 ##
究竟从哪些url会路由到Widget_Archive呢?或者说Widget_Archive会处理哪些业务呢?从[《Typecho路由速查》][2]一文,可以查到,首页、文章、附件、归档等等请求,都会路由到Widget_Archive中。

root@localhost:/tmp# cat typecho_r.txt | grep Widget_Archive -B 1 -A 2
#首页
[url] => /
[widget] => Widget_Archive
[action] => render
[regx] => |^[/]?$|

#[常见]访问某篇文章,譬如/archives/10/,表示打开cid为10的文章
[url] => /archives/[cid:digital]/
[widget] => Widget_Archive
[action] => render
[regx] => |^/archives/([0-9]+)[/]?$|

#访问某个附件
[url] => /attachment/[cid:digital]/
[widget] => Widget_Archive
[action] => render
[regx] => |^/attachment/([0-9]+)[/]?$|

#[常用]访问某个分类。譬如/category/news/ 表示打开某个分类缩略名为news的文章列表
[url] => /category/[slug]/
[widget] => Widget_Archive
[action] => render
[regx] => |^/category/([^/]+)[/]?$|

#访问某个tag
[url] => /tag/[slug]/
[widget] => Widget_Archive
[action] => render
[regx] => |^/tag/([^/]+)[/]?$|

#打开某个作者的文件列表
[url] => /author/[uid:digital]/
[widget] => Widget_Archive
[action] => render
[regx] => |^/author/([0-9]+)[/]?$|

#搜索
[url] => /search/[keywords]/
[widget] => Widget_Archive
[action] => render
[regx] => |^/search/([^/]+)[/]?$|

#访问以“年”为维度的归档
[url] => /[year:digital:4]/
[widget] => Widget_Archive
[action] => render
[regx] => |^/([0-9]{4})[/]?$|

#访问以“年/月”为维度的归档
[url] => /[year:digital:4]/[month:digital:2]/
[widget] => Widget_Archive
[action] => render
[regx] => |^/([0-9]{4})/([0-9]{2})[/]?$|

#访问以“年/月/日”为维度的归档
[url] => /[year:digital:4]/[month:digital:2]/[day:digital:2]/
[widget] => Widget_Archive
[action] => render
[regx] => |^/([0-9]{4})/([0-9]{2})/([0-9]{2})[/]?$|

#访问某个独立页面
[url] => /[slug].html
[widget] => Widget_Archive
[action] => render
[regx] => |^/([^/]+).html[/]?$|

## 以post页为例,简要说明 ##
假如存在url `http://www.typechodev.com/index.php/archives/9/`,从上述的路由表可以看到,此url将会匹配如下路由:

[post] => Array
(
[url] => /archives/[cid:digital]/
[widget] => Widget_Archive
[action] => render
[regx] => |^/archives/([0-9]+)[/]?$|
[format] => /archives/%s/
[params] => Array
(
[0] => cid
)

)

>PS:如果对Typecho的路由机制不熟悉,可以参考[《Typecho中的路由解析》][3]一文。

匹配之后,发生了什么事情呢?
1. Typecho的路由系统对url进行解析以及正则匹配,最终会将`Widget_Archive`这个类load进来并进行初始化。
2. Widget_Archive初始化阶段,Typecho的Widget系统会将`cid=10`作为参数,来初始化这个Widget_Archive控件,并执行`Widget_Archive`的`execute()`函数。
3. 最后,Typecho的路由系统拿到步骤2中初始化的Widget_Archive实例后,执行其`render()`函数,进行页面渲染。

>提醒:Widget_Archive的render函数中,是通过`require_once`的方式来加载主题页面片的,所以在页面片中(譬如post.php),才可以直接使用`$this`来调用Widget_Archive实例中的函数。

## Widget_Archive常见用法:
以slug方式加载某分类文章列表:

$archives = $this->widget(‘Widget_Archive’, ‘pageSize=10&type=category&page=’.$page, ‘slug=’.$slug)
以mid方式加载某分类文章列表:

$archives = $this->widget(‘Widget_Archive’, ‘pageSize=10&type=category&page=’.$page, ‘mid=’.$slug)
加载搜索结果列表:

$archives = $this->widget(‘Widget_Archive’, ‘pageSize=10&type=search&page=’.$page, ‘keywords=’.$query);

[1]: https://www.typechodev.com/usr/uploads/2015/01/2661196701.png
[2]: http://www.typechodev.com/index.php/archives/9/
[3]: http://www.typechodev.com/index.php/archives/26/

上一篇 2014-12-31 上午1:41
下一篇 2014-12-31 上午2:02