用户名: 密码: 忘记密码? 注册

使用zend framework 搭建网站(十)- Zend_Db 简要分析

作者:  时间: 2011-01-02
    注:具体使用可查看帮助文档。


Zend Framework框架中 Zend_Db的设计是极为精巧的,不仅极大的减少了编码量,提高了安全性能,而且其基于适配器(Adapter)的设计使你如果有更换数据库的需求几乎不需要怎么修改程序。好处多多呀!好吧我们花点时间研究研究它吧,在这篇文章中暂时不包括Zend_Db_Table的分析(我不是太喜欢它^_^)。


Zend Framework版本:1.9.0

让我们看一下Zend_Db的结构,上图:
一、源码目录
Adapter文件夹下是适配器:我们可以看见里面有 Db2,Mysqli,Oracle,Sqlsrv ,可见Zend Framework是支持这么多数据库,当然你也可以使用Pdo。
Profiler:可以用来debug,分析sql语句执行效率。
Statement:In addition to convenient methods such asfetchAll() andinsert(), you can use a statement object to gain more options for running queries and fetching result sets。就是可以用这个类实现更多的功能方法。

Select.php :专注于select查询的类,用来组装select查询sql语句的。

这些都是最最核心的。

二、结构分析
我们以mysqli为类,看看整个过程.
1、 首先是创建适配器

$db = Zend_Db::factory(' Mysqli ', $params);
在 Zend/Db.php文件的244行:
$adapterName= strtolower($adapterNamespace.'_'.$adapter);
执行完后,$adapterName的值为 zend_db_adapter_mysqli。
在 Zend/Db.php文件的260行:
$dbAdapter=new$adapterName($config);
这就创建了MySQLi的适配器了。

在Zend/Db/Adapter文件夹下,Abstract.php中 Zend_Db_Adapter_Abstract是抽象类,它声明了一些方法并实现了部分方法,Mysqli.php文件中Zend_Db_Adapter_Mysqli类继承Zend_Db_Adapter_Abstract,实现了抽象类中的部分方法,比如 _connect()方法。因为每个数据库的连接方式都有不同,所以就在这里实现了。

2、 构造查询对象,查询数据

在这里我们要做一个select查询。
示例:
    $db = Zend_Db::factory('Mysqli', $params);
$select = $db->select();
$select->from('round_table', '*');
$select->where('noble_title = ?', 'Sir');
$select->order('first_name');
$select->limit(10,20);
$result = $db->fetchAll($select);


首先是要组装出SQL语句,Zend_Db_Select 可以组装出强大的SQL语句,这个类设计的很精巧,不过这里也没法修饰,大家可以看源码。

然后执行Zend_Db_Adapter_Abstract 中的fetchAll()函数,该函数在Zend/Db/Adapter.php的701行:

public function fetchAll($sql, $bind = array(), $fetchMode = null)
{
if ($fetchMode === null) {
$fetchMode = $this->_fetchMode;
}
$stmt = $this->query($sql, $bind);
$result = $stmt->fetchAll($fetchMode);
return $result;
}

$stmt = $this->query($sql, $bind);   会调用自身的445行的public function query($sql,$bind=array())函数。

在这个函数中 如果$sql变量是 Zend_Db_Select 对象的话,就由 Zend_Db_Select 处理,然后返回sql语句。
当然最关键的是要看467行的 $stmt=$this->prepare($sql);
因为Zend_Db_Adapter_Mysqli类继承Zend_Db_Adapter_Abstract,所以这会调用Zend_Db_Adapter_Mysqli中的370行的prepare($sql)函数:
       public function prepare($sql)
{
$this->_connect();
if ($this->_stmt) {
$this->_stmt->close();
}
$stmtClass = $this->_defaultStmtClass;
if (!class_exists($stmtClass)) {
require_once 'Zend/Loader.php';
Zend_Loader::loadClass($stmtClass);
}
$stmt = new $stmtClass($this, $sql);
if ($stmt === false) {
return false;
}
$stmt->setFetchMode($this->_fetchMode);
$this->_stmt = $stmt;
return $stmt;
}


其中:$stmtClass = $this->_defaultStmtClass;
这行代码中$stmtClass = ‘Zend_Db_Statement_Mysqli’;

$stmt = new $stmtClass($this, $sql); $stmt就是一个 Zend_Db_Statement_Mysqli对象了。

回到fetchAll()函数,这里该执行 $result=$stmt->fetchAll($fetchMode); 代码了,当然这里fetchAll()函数就是Zend_Db_Statement_Mysqli中的函数了。

好了,返回结果。


这篇文章分析的很粗浅,具体的大家可以阅读源码,会有很大收获的。