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 在调用时指定的是 push ,在 push 函数中返回的每一行数据都被压入 $stack ,这样 $stack 中就有了一行行的数据了。
Typecho 代码阅读笔记(二) - 数据库访问的更多相关文章
- Typecho 代码阅读笔记(三) - 插件机制
转载请注明出处:http://blog.csdn.net/jh_zzz 以 index.php 为例: /** 初始化组件 */ Typecho_Widget:: widget('Widget_Ini ...
- Typecho 代码阅读笔记(一) - 页面渲染及路由机制
转载请注明出处:http://blog.csdn.net/jh_zzz 从 index.php 开始看, /** 初始化组件 */ Typecho_Widget:: widget('Widget_In ...
- <<梦断代码>>阅读笔记二
这是第二篇读书笔记,这本书我已经读了有一大半了,感觉书中所描述的人都是疯子,一群有创造力,却又耐得住寂寞的疯子. 我从书中发现几点我比较感兴趣的内容. 第一个,乐高之梦.将程序用乐高积木一样拼接起来. ...
- Linux协议栈代码阅读笔记(二)网络接口的配置
Linux协议栈代码阅读笔记(二)网络接口的配置 (基于linux-2.6.11) (一)用户态通过C库函数ioctl进行网络接口的配置 例如,知名的ifconfig程序,就是通过C库函数sys_io ...
- [置顶] Linux协议栈代码阅读笔记(二)网络接口的配置
Linux协议栈代码阅读笔记(二)网络接口的配置 (基于linux-2.6.11) (一)用户态通过C库函数ioctl进行网络接口的配置 例如,知名的ifconfig程序,就是通过C库函数sys_io ...
- [置顶] Linux协议栈代码阅读笔记(一)
Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...
- Detectron2源码阅读笔记-(二)Registry&build_*方法
Trainer解析 我们继续Detectron2代码阅读笔记-(一)中的内容. 上图画出了detectron2文件夹中的三个子文件夹(tools,config,engine)之间的关系.那么剩下的 ...
- 《Java编程思想》阅读笔记二
Java编程思想 这是一个通过对<Java编程思想>(Think in java)进行阅读同时对java内容查漏补缺的系列.一些基础的知识不会被罗列出来,这里只会列出一些程序员经常会忽略或 ...
- Linux-3.0.8 input subsystem代码阅读笔记
先乱序记录一下阅读Linux input subsystem代码的笔记. 在input device driver的入口代码部分,需要分配并初始化input device结构,内核提供的API是inp ...
随机推荐
- ListView中RadioButton实现单项选择
1:FragmentHack5.java public class FragmentHack5 extends Fragment { View view; ListView lvCountries; ...
- Android中读取assets文件夹中的子文件夹内容
文件结构如下:assets/info/info AssetManager am = this.getResources().getAssets(); InputStream input = null; ...
- BZOJ 1497 最大获利(最大权闭合子图)
http://www.lydsy.com/JudgeOnline/problem.php?id=1497 思路:由题意可以得知,每个顾客都依赖2个中转站,那么让中转站连有向边到汇点,流量为它的建设费用 ...
- android showAsDropDown的用法属性介绍
使用PopupWindow可实现弹出窗口效果,,其实和AlertDialog一样,也是一种对话框,两者也经常混用,但是也各有特点.下面就看看使用方法.首先初始化一个PopupWindow,指定窗口大小 ...
- linux awk 使用
awk是linux下的一个命令,他对其他命令的输出,对文件的处理都十分强大,其实他更像一门编程语言,他可以自定义变量,有条件语句,有循环,有数组,有正则,有函数等.他读取输出,或者文件的方式是一行,一 ...
- android网址
1. 优麒麟手机助手 https://github.com/ubuntu-kylin/phone_manager 2. http://forum.xda-developers.com/index.ph ...
- ZOJ3829---模拟,贪心
这是2014年ACM亚洲区预赛牡丹江现场赛的一道题,铜牌题,可惜当时一路WA到死... 只有乘法的后缀表达式的特点有两个:(1)数字的数量一定大于‘*’的数量(2)最后一位一定是‘*’: 数字比*多的 ...
- Linux优化,history增加详细历史记录
主要功能: 1, 可以记录哪个ip和时间(精确到秒)以及哪个用户,作了哪些命令 2,最大日志记录增加到4096条 把下面的代码直接粘贴到/etc/profile后面就可以了 #history mo ...
- MySql 中的常见问题解决方法
一.关键字做字段 ,mssql的做法是[关键字],mysql的做法是 `关键字` ;ps:(` 是 tab键上面的一个按键) 二.mssql数据导入到mysql: 1.mssql导出insert语句( ...
- 河内塔(hanoi)
理论: 河内塔: 1.有三根杆子A,B,C.A杆上有若干碟子 2.每次移动一块碟子,小的只能叠在大的上面 3.把所有碟子从A杆全部移到C杆上 讲解: 设A上有n个盘子.如果n=1,则将圆盘从A直接 ...