Typecho 代码阅读笔记(三) - 插件机制
Typecho 代码阅读笔记(二) - 数据库访问
Typecho 代码阅读笔记(一) - 页面渲染及路由机制
转载请注明出处:http://blog.csdn.net/jh_zzz
这一块比较复杂,我还没有完全理解为什么要把
SQL
语句的组装搞这么复杂。
从一个普通皮肤页面开始
themes/default/index.php
,代码如下:
<?php
while
($this
->
next()):
?>
<
div
class
="post">
<
h2
class
="entry_title"><
a
href
="<?php
$this
->
permalink() ?>"><?php
$this
->
title()
?></
a
></
h2
>
<
p
class
="entry_data">
<
span
><?php
_e('
作者:
'
); ?><?php
$this
->
author(); ?></
span
>
<
span
><?php
_e('
发布时间:
'
); ?><?php
$this
->
date('F j, Y'
); ?></
span
>
<
span
><?php
_e('
分类:
'
); ?><?php
$this
->
category(','
); ?></
span
>
<
a
href
="<?php
$this
->
permalink() ?>#comments"><?php
$this
->
commentsNum('No Comments'
, '1 Comment'
, '%d Comments'
); ?></
a
>
</
p
>
<?php
$this
->
content('
阅读剩余部分
...'
); ?>
</
div
>
<?php
endwhile
; ?>
从上面我们知道这个文件是在
Widget_Archive
执行时被
包含进来的,所以在这里
$this
就是
Widget_Archive
,
next()
函数具体实现在
Typecho_Widget
中,他只是从
$stack
中取出一行数据返回,然后移向下一行,
$stack
中的数据是如何生成的呢?
在
Widget_Archive
的
execute
函数中,有这几行:
$select
=
$this
->
select()->
where
('table.contents.status = ?'
, 'publish'
)
->
where('table.contents.created < ?'
, $this
->
options->
gmtTime);
…
中间代码略过
…
$select
->
order('table.contents.created'
, Typecho_Db::
SORT_DESC)
->
page($this
->
_currentPage, $this
->
parameter->
pageSize);
$this
->
db->
fetchAll
($select
, array
($this
, 'push'
));
下面是
Widget_Abstract_Contents::
select()
函数的具体实现:
return
$this
->
db->
select
('table.contents.cid'
, 'table.contents.title'
, 'table.contents.slug'
, 'table.contents.created'
, 'table.contents.authorId'
,
'table.contents.modified'
, 'table.contents.type'
, 'table.contents.status'
, 'table.contents.text'
, 'table.contents.commentsNum'
, 'table.contents.order'
,
'table.contents.template'
, 'table.contents.password'
, 'table.contents.allowComment'
, 'table.contents.allowPing'
, 'table.contents.allowFeed'
,
'table.contents.parent'
)->
from
('table.contents'
);
$this->db
是
Typecho_Db
对象,是
在
Widget_Abstract
初始化时赋值的:
$this
->
db =
Typecho_Db::
get();
这个值其实是在
config.inc.php
中创建的,在安装的时候根据用户选择生成的:
$db
=
new
Typecho_Db('Mysql'
, 'typecho_'
);
…
中间略过
Typecho_Db::
set($db
);
再看看
Typecho_Db
的
select()
函数,
return
call_user_func_array(array
($this
->
sql()
, 'select'
), $args
?
$args
:
array
('*'
));
$this->sql()
返回一个
Typecho_Db_Query
对象,所以上面这句是调用
Typecho_Db_Query
的
select
函数并将相应的参数传给它,
Typecho_Db_Query
会经过一系列的处理最终生成
SQL
语句,这里不再具体看了。
看看生成好的语句是怎么执行的,在最前面提到有这句代码:
$this
->
db->
fetchAll($select
, array
($this
, 'push'
));
Typecho_Db
的
fetchAll
具体实现如下:
public
function
fetchAll($query
, array
$filter
=
NULL
)
{
//
执行查询
$resource
=
$this
->
query
($query
, self::
READ);
$result
=
array
();
/**
取出过滤器
*/
if
(!
empty
($filter
)) {
list
($object
, $method
) =
$filter
;
}
//
取出每一行
while
($rows
=
$this
->
_adapter->
fetch
($resource
)) {
//
判断是否有过滤器
$result
[] =
$filter
?
call_user_func
(array
(&
$object
, $method
), $rows
) :
$rows
;
}
return
$result
;
}
首先执行
query()
,
query()
函数会执行:
$resource
=
$this
->
_adapter->
query($query
, $handle
, $op
, $action
);
然后将查询的结果返回,根据上面提到的
config.inc.php
,这里的
_adapter
是
Typecho_Db_Adapter_Mysql
,他其实就是执行了一个
mysql
查询:
if
($resource
=
@
mysql_query($query
instanceof
Typecho_Db_Query ?
$query
->
__toString()
:
$query
, $handle
)) {
return
$resource
;
}
这里的
$query->__toString()
会返回经过
Typecho_Db_Query
处理后的
最终用来执行的
SQL
语句。
得到查询结果后,上面的
fetchAll
函数就循环调用回调函数将数据回调出去,前面的代码中
Widget_Archive