现在的位置: 首页 > 综合 > 正文

Typecho 代码阅读笔记(二) – 数据库访问

2013年08月14日 ⁄ 综合 ⁄ 共 3046字 ⁄ 字号 评论关闭

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

抱歉!评论已关闭.