日期:2014-05-16  浏览次数:20707 次

Yii分析10:Yii核心组件之数据库类CDbConnection

?

数据库类几乎是每个PHP框架必不可少的组件之一,Yii的数据库核心主要包含两类,一类是管理数据库连接的CDbConnection及相关类,另一类是ORM(Object Relation Model),即管理数据库表记录的CActiveRecord及相关类。

首先我将介绍和分析数据库连接管理类CDbConnection,CDbConnect作为CApplication的核心组件,在应用初始化时会自动进行初始化,对于使用者来说,需要在配置文件中将配置CDbConnection的初始化配置:

?

//protected/config/main.php:
'components'=>array(
	……
'db'=>array(
		//连接字符串,设置数据库类型,数据库主机地址,数据库名
			'connectionString' => 'mysql:host=localhost;dbname=blog',
			//用户名
			'username' => 'root',
			//密码
			'password' => '123456',
			//字符集
			'charset' => 'utf8',
		),
	……

?

?在应用初始化时,会自动初始化CDbConnectiont:

?

//CApplication:

abstract class CApplication extends CModule
	//构造函数
public function __construct($config=null)
{
		……
		//注册核心组件
		$this->registerCoreComponents();
		……
}
……
protected function registerCoreComponents()
{
	//核心组件列表
		$components=array(
			……
			'db'=>array(
				'class'=>'CDbConnection',
			),
			……
		};
		//调用父类函数注册
		$this->setComponents($components);
}

//CModule:
abstract class CModule extends CComponent

	public function setComponents($components,$merge=true)
	{
		foreach($components as $id=>$component)
		{
			//如果是接口IApplicationComponent的一个实例
			//调用setComponent
			//CDbConnect继承自CApplicationComponent
			//CApplicationCompnent继承了IApplicationCompnent接口
			if($component instanceof IApplicationComponent)
				$this->setComponent($id,$component);
			else if(isset($this->_componentConfig[$id]) && $merge)
				$this->_componentConfig[$id]=CMap::mergeArray($this->_componentConfig[$id],$component);
			else
				$this->_componentConfig[$id]=$component;
		}
	}
	public function setComponent($id,$component)
	{
		if($component===null)
			unset($this->_components[$id]);
		else
		{
			$this->_components[$id]=$component;
			//初始化组件
			if(!$component->getIsInitialized())
				$component->init();
		}
	}
}

?

?

接下来我们看看CDbConnect在初始化阶段,都做了那些事情:

?

/**
* CDbConnection与CDbCommand、CDbDataReader和CDbTransaction一起合作提供对DBMS的数据访问功能
* 它使用PDO作为数据库连接驱动
*/
class CDbConnection extends CApplicationComponent
{
	//以下属性在配置文件中设置
	public $connectionString;
	public $username='';
	public $password='';
	public $charset;

	//表结构缓存时间,单位是秒,默认不缓存
	public $schemaCachingDuration=0;
	//表结构缓存排除列表
	public $schemaCachingExclude=array();
	//表结构缓存ID
	public $schemaCacheID='cache';
	//自动连接,默认为true,如果设置为false,在使用时才会连接
	public $autoConnect=true;
	//模仿prepare,默认为false,PDO会使用原生的prepare,对于某些数据库(例如MySql),最好设置为true,这样就不会使用有bug的PDO原生prepare,关于PDO的prepare相关信息可以查阅:http://php.net/manual/en/pdo.prepare.php
	public $emulatePrepare=false;
	//是否记录绑定变量(如果使用prepare方式进行查询,如果记录sql语句,是看不到绑定变量的值的),调试时使用
	public $enableParamLogging=false;
	//是否记录SQL语句,调试时使用
	public $enableProfiling=false;
	//数据表前缀
	public $tablePrefix;
	//在建立数据库连接之后立即执行的SQL语句
	public $initSQLs;

	//目前支持的数据库驱动
	public $driverMap=array(
		'pgsql'=>'CPgsqlSchema',    // PostgreSQL
		'mysqli'=>'CMysqlSchema',   // MySQL
		'mysql'=>'CMysqlSchema',    // MySQL
		'sqlite'=>'CSqliteSchema',  // sqlite 3
		'sqlite2'=>'CSqliteSchema', // sqlite 2
		'mssql'=>'CMssqlSchema',    // Mssql driver on windows hosts
		'dblib'=>'CMssqlSchema',    // dblib drivers on linux (and maybe others os) hosts
		'sqlsrv'=>'CMssqlSchema',   // Mssql
		'oci'=>'COciSchema',        // Oracle driver
	);
	……
	//初始化
	public function init()
	{
		//调用父类初始化
		parent::init();
		//
		if($this->autoConnect)
			$this->setActive(true);
	}
	……
	public function setActive($value)
	{
		//如果需要设置的状态与当前状态不同
		if($value!=$this->_active)
		{
			if($value)
				$this->open();
			else
				$this->close();
		}
	}
	protected function open()
	{
		if($this->_pdo===null)
		{
			if(empty($this->connec