免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2737 | 回复: 2

Yii分析10:Yii核心组件之数据库类CDbConnection [复制链接]

论坛徽章:
0
发表于 2012-02-17 14:24 |显示全部楼层
Yii分析10:Yii核心组件之数据库类CDbConnection




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

首先我将介绍和分析数据库连接管理类CDbConnection,CDbConnect作为CApplication的核心组件,在应用初始化时会自动进行初始化,对于使用者来说,需要在配置文件中将配置CDbConnection的初始化配置:
  1. //protected/config/main.php:   
  2. 'components'=>array(   
  3.     ……   
  4. 'db'=>array(   
  5.         //连接字符串,设置数据库类型,数据库主机地址,数据库名   
  6.             'connectionString' => 'mysql:host=localhost;dbname=blog',   
  7.             //用户名   
  8.             'username' => 'root',   
  9.             //密码   
  10.             'password' => '123456',   
  11.             //字符集   
  12.             'charset' => 'utf8',   
  13.         ),   
  14.     ……  

  15. //protected/config/main.php:
  16. 'components'=>array(
  17.         ……
  18. 'db'=>array(
  19.                 //连接字符串,设置数据库类型,数据库主机地址,数据库名
  20.                         'connectionString' => 'mysql:host=localhost;dbname=blog',
  21.                         //用户名
  22.                         'username' => 'root',
  23.                         //密码
  24.                         'password' => '123456',
  25.                         //字符集
  26.                         'charset' => 'utf8',
  27.                 ),
  28.         ……


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

复制代码
  1. //CApplication:   
  2.   
  3. abstract class CApplication extends CModule   
  4.     //构造函数   
  5. public function __construct($config=null)   
  6. {   
  7.         ……   
  8.         //注册核心组件   
  9.         $this->registerCoreComponents();   
  10.         ……   
  11. }   
  12. ……   
  13. protected function registerCoreComponents()   
  14. {   
  15.     //核心组件列表   
  16.         $components=array(   
  17.             ……   
  18.             'db'=>array(   
  19.                 'class'=>'CDbConnection',   
  20.             ),   
  21.             ……   
  22.         };   
  23.         //调用父类函数注册   
  24.         $this->setComponents($components);   
  25. }   
  26.   
  27. //CModule:   
  28. abstract class CModule extends CComponent   
  29.   
  30.     public function setComponents($components,$merge=true)   
  31.     {   
  32.         foreach($components as $id=>$component)   
  33.         {   
  34.             //如果是接口IApplicationComponent的一个实例   
  35.             //调用setComponent   
  36.             //CDbConnect继承自CApplicationComponent   
  37.             //CApplicationCompnent继承了IApplicationCompnent接口   
  38.             if($component instanceof IApplicationComponent)   
  39.                 $this->setComponent($id,$component);   
  40.             else if(isset($this->_componentConfig[$id]) && $merge)   
  41.                 $this->_componentConfig[$id]=CMap::mergeArray($this->_componentConfig[$id],$component);   
  42.             else  
  43.                 $this->_componentConfig[$id]=$component;   
  44.         }   
  45.     }   
  46.     public function setComponent($id,$component)   
  47.     {   
  48.         if($component===null)   
  49.             unset($this->_components[$id]);   
  50.         else  
  51.         {   
  52.             $this->_components[$id]=$component;   
  53.             //初始化组件   
  54.             if(!$component->getIsInitialized())   
  55.                 $component->init();   
  56.         }   
  57.     }   
  58. }  

  59. //CApplication:

  60. abstract class CApplication extends CModule
  61.         //构造函数
  62. public function __construct($config=null)
  63. {
  64.                 ……
  65.                 //注册核心组件
  66.                 $this->registerCoreComponents();
  67.                 ……
  68. }
  69. ……
  70. protected function registerCoreComponents()
  71. {
  72.         //核心组件列表
  73.                 $components=array(
  74.                         ……
  75.                         'db'=>array(
  76.                                 'class'=>'CDbConnection',
  77.                         ),
  78.                         ……
  79.                 };
  80.                 //调用父类函数注册
  81.                 $this->setComponents($components);
  82. }

  83. //CModule:
  84. abstract class CModule extends CComponent

  85.         public function setComponents($components,$merge=true)
  86.         {
  87.                 foreach($components as $id=>$component)
  88.                 {
  89.                         //如果是接口IApplicationComponent的一个实例
  90.                         //调用setComponent
  91.                         //CDbConnect继承自CApplicationComponent
  92.                         //CApplicationCompnent继承了IApplicationCompnent接口
  93.                         if($component instanceof IApplicationComponent)
  94.                                 $this->setComponent($id,$component);
  95.                         else if(isset($this->_componentConfig[$id]) && $merge)
  96.                                 $this->_componentConfig[$id]=CMap::mergeArray($this->_componentConfig[$id],$component);
  97.                         else
  98.                                 $this->_componentConfig[$id]=$component;
  99.                 }
  100.         }
  101.         public function setComponent($id,$component)
  102.         {
  103.                 if($component===null)
  104.                         unset($this->_components[$id]);
  105.                 else
  106.                 {
  107.                         $this->_components[$id]=$component;
  108.                         //初始化组件
  109.                         if(!$component->getIsInitialized())
  110.                                 $component->init();
  111.                 }
  112.         }
  113. }




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

复制代码
  1. /**  
  2. * CDbConnection与CDbCommand、CDbDataReader和CDbTransaction一起合作提供对DBMS的数据访问功能  
  3. * 它使用PDO作为数据库连接驱动  
  4. */  
  5. class CDbConnection extends CApplicationComponent   
  6. {   
  7.     //以下属性在配置文件中设置   
  8.     public $connectionString;   
  9.     public $username='';   
  10.     public $password='';   
  11.     public $charset;   
  12.   
  13.     //表结构缓存时间,单位是秒,默认不缓存   
  14.     public $schemaCachingDuration=0;   
  15.     //表结构缓存排除列表   
  16.     public $schemaCachingExclude=array();   
  17.     //表结构缓存ID   
  18.     public $schemaCacheID='cache';   
  19. <SPAN style="COLOR: #ff0000">   //自动连接,默认为true,如果设置为false,在使用时才会连接   
  20. </SPAN> public $autoConnect=true;   
  21.     //模仿prepare,默认为false,PDO会使用原生的prepare,对于某些数据库(例如MySql),最好设置为true,这样就不会使用有bug的PDO原生prepare,关于PDO的prepare相关信息可以查阅:http://php.net/manual/en/pdo.prepare.php   
  22.     public $emulatePrepare=false;   
  23. <SPAN style="COLOR: #ff0000">   //是否记录绑定变量(如果使用prepare方式进行查询,如果记录sql语句,是看不到绑定变量的值的),调试时使用   
  24. </SPAN> public $enableParamLogging=false;   
  25. <SPAN style="COLOR: #ff0000">   //是否记录SQL语句,调试时使用   
  26. </SPAN> public $enableProfiling=false;   
  27.     //数据表前缀   
  28.     public $tablePrefix;   
  29.     //在建立数据库连接之后立即执行的SQL语句   
  30.     public $initSQLs;   
  31.   
  32.     //目前支持的数据库驱动   
  33.     public $driverMap=array(   
  34.         'pgsql'=>'CPgsqlSchema',    // PostgreSQL   
  35.         'mysqli'=>'CMysqlSchema',   // MySQL   
  36.         'mysql'=>'CMysqlSchema',    // MySQL   
  37.         'sqlite'=>'CSqliteSchema',  // sqlite 3   
  38.         'sqlite2'=>'CSqliteSchema', // sqlite 2   
  39.         'mssql'=>'CMssqlSchema',    // Mssql driver on windows hosts   
  40.         'dblib'=>'CMssqlSchema',    // dblib drivers on linux (and maybe others os) hosts   
  41.         'sqlsrv'=>'CMssqlSchema',   // Mssql   
  42.         'oci'=>'COciSchema',        // Oracle driver   
  43.     );   
  44.     ……   
  45.     //初始化   
  46.     public function init()   
  47.     {   
  48.         //调用父类初始化   
  49.         parent::init();   
  50.         //   
  51.         if($this->autoConnect)   
  52.             $this->setActive(true);   
  53.     }   
  54.     ……   
  55.     public function setActive($value)   
  56.     {   
  57.         //如果需要设置的状态与当前状态不同   
  58.         if($value!=$this->_active)   
  59.         {   
  60.             if($value)   
  61.                 $this->open();   
  62.             else  
  63.                 $this->close();   
  64.         }   
  65.     }   
  66.     protected function open()   
  67.     {   
  68.         if($this->_pdo===null)   
  69.         {   
  70.             if(emptyempty($this->connectionString))   
  71.                 throw new CDbException(Yii::t('yii','CDbConnection.connectionString cannot be empty.'));   
  72.             try   
  73.             {   
  74.                 Yii::trace('Opening DB connection','system.db.CDbConnection');   
  75.                 //创建PDO实例   
  76.                 $this->_pdo=$this->createPdoInstance();   
  77.                 //初始化连接   
  78.                 $this->initConnection($this->_pdo);   
  79.                 $this->_active=true;   
  80.             }   
  81.             catch(PDOException $e)   
  82.             {   
  83.                 //异常处理   
  84.                 ……   
  85.             }   
  86.         }   
  87.     }   
  88.     ……   
  89.     //创建PDO实例   
  90.     protected function createPdoInstance()   
  91.     {   
  92.         $pdoClass='PDO';   
  93.         if(($pos=strpos($this->connectionString,':'))!==false)   
  94.         {   
  95.             $driver=strtolower(substr($this->connectionString,0,$pos));   
  96.             if($driver==='mssql' || $driver==='dblib')   
  97.                 $pdoClass='CMssqlPdoAdapter';   
  98.         }   
  99.         return new $pdoClass($this->connectionString,$this->username,   
  100.                                     $this->password,$this->_attributes);   
  101.     }   
  102.     ……   
  103.     //初始化连接   
  104.     protected function initConnection($pdo)   
  105.     {   
  106.         $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);   
  107.         if($this->emulatePrepare && constant('PDO::ATTR_EMULATE_PREPARES'))   
  108.             $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,true);   
  109.         if($this->charset!==null)   
  110.         {   
  111.             $driver=strtolower($pdo->getAttribute(PDO::ATTR_DRIVER_NAME));   
  112.             //pg,mysql,mysqli需要设置字符编码   
  113.             if(in_array($driver,array('pgsql','mysql','mysqli')))   
  114.                 $pdo->exec('SET NAMES '.$pdo->quote($this->charset));   
  115.         }   
  116.         //如果有初始化SQL,则执行   
  117.         if($this->initSQLs!==null)   
  118.         {   
  119.             foreach($this->initSQLs as $sql)   
  120.                 $pdo->exec($sql);   
  121.         }   
  122.     }   
  123. }  

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

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

  153.         //目前支持的数据库驱动
  154.         public $driverMap=array(
  155.                 'pgsql'=>'CPgsqlSchema',    // PostgreSQL
  156.                 'mysqli'=>'CMysqlSchema',   // MySQL
  157.                 'mysql'=>'CMysqlSchema',    // MySQL
  158.                 'sqlite'=>'CSqliteSchema',  // sqlite 3
  159.                 'sqlite2'=>'CSqliteSchema', // sqlite 2
  160.                 'mssql'=>'CMssqlSchema',    // Mssql driver on windows hosts
  161.                 'dblib'=>'CMssqlSchema',    // dblib drivers on linux (and maybe others os) hosts
  162.                 'sqlsrv'=>'CMssqlSchema',   // Mssql
  163.                 'oci'=>'COciSchema',        // Oracle driver
  164.         );
  165.         ……
  166.         //初始化
  167.         public function init()
  168.         {
  169.                 //调用父类初始化
  170.                 parent::init();
  171.                 //
  172.                 if($this->autoConnect)
  173.                         $this->setActive(true);
  174.         }
  175.         ……
  176.         public function setActive($value)
  177.         {
  178.                 //如果需要设置的状态与当前状态不同
  179.                 if($value!=$this->_active)
  180.                 {
  181.                         if($value)
  182.                                 $this->open();
  183.                         else
  184.                                 $this->close();
  185.                 }
  186.         }
  187.         protected function open()
  188.         {
  189.                 if($this->_pdo===null)
  190.                 {
  191.                         if(empty($this->connectionString))
  192.                                 throw new CDbException(Yii::t('yii','CDbConnection.connectionString cannot be empty.'));
  193.                         try
  194.                         {
  195.                                 Yii::trace('Opening DB connection','system.db.CDbConnection');
  196.                                 //创建PDO实例
  197.                                 $this->_pdo=$this->createPdoInstance();
  198.                                 //初始化连接
  199.                                 $this->initConnection($this->_pdo);
  200.                                 $this->_active=true;
  201.                         }
  202.                         catch(PDOException $e)
  203.                         {
  204.                                 //异常处理
  205.                                 ……
  206.                         }
  207.                 }
  208.         }
  209.         ……
  210.         //创建PDO实例
  211.         protected function createPdoInstance()
  212.         {
  213.                 $pdoClass='PDO';
  214.                 if(($pos=strpos($this->connectionString,':'))!==false)
  215.                 {
  216.                         $driver=strtolower(substr($this->connectionString,0,$pos));
  217.                         if($driver==='mssql' || $driver==='dblib')
  218.                                 $pdoClass='CMssqlPdoAdapter';
  219.                 }
  220.                 return new $pdoClass($this->connectionString,$this->username,
  221.                                                                         $this->password,$this->_attributes);
  222.         }
  223.         ……
  224.         //初始化连接
  225.         protected function initConnection($pdo)
  226.         {
  227.                 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  228.                 if($this->emulatePrepare && constant('PDO::ATTR_EMULATE_PREPARES'))
  229.                         $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,true);
  230.                 if($this->charset!==null)
  231.                 {
  232.                         $driver=strtolower($pdo->getAttribute(PDO::ATTR_DRIVER_NAME));
  233.                         //pg,mysql,mysqli需要设置字符编码
  234.                         if(in_array($driver,array('pgsql','mysql','mysqli')))
  235.                                 $pdo->exec('SET NAMES '.$pdo->quote($this->charset));
  236.                 }
  237.                 //如果有初始化SQL,则执行
  238.                 if($this->initSQLs!==null)
  239.                 {
  240.                         foreach($this->initSQLs as $sql)
  241.                                 $pdo->exec($sql);
  242.                 }
  243.         }
  244. }
  245.   
复制代码
以上便是CDbConnect初始化的过程,其实CDnConnection主要功能是为用户封装了PDO的实例,并且自定义了一些配置,方便用户使用。



如果我们在项目中不想使用应用核心组件数据库连接,想自定义一个数据库连接,那么可以直接创建CDbConnection的对象:



Php代码  
$connection=new CDbConnection($dsn,$username,$password);   
<STRONG>//CDbConnection的祖先类Ccomponent包含有__isset方法,自动会调用名称为set[attribute]的方法,即会调用CdbConnection::setActive方法   
</STRONG>$connection->active=true;  

$connection=new CDbConnection($dsn,$username,$password);
//CDbConnection的祖先类Ccomponent包含有__isset方法,自动会调用名称为set[attribute]的方法,即会调用CdbConnection::setActive方法
$connection->active=true;
        如果想直接执行一条SQL:
Php代码  
$command=$connection->createCommand($sqlStatement);   
$command->execute();   //   
// 执行SQL获取结果   
$reader=$command->query();   
  
//$row代表一条记录   
foreach($reader as $row) ...  

$command=$connection->createCommand($sqlStatement);
$command->execute();   //
// 执行SQL获取结果
$reader=$command->query();

//$row代表一条记录
foreach($reader as $row) ...
与CDbConnection密切相关的几个类有:


CDbCommand:用户生成SQL语句,执行SQL语句
CDbTransaction:用于管理数据库事务的类
CDbDataReader:用于管理SQL语句执行结果的类,实现了Iterator接口,能够像遍历数组一样遍历自身
这里不再详述每个类的内部细节,我们只需要了解用法即可。


论坛徽章:
0
发表于 2012-02-17 22:08 |显示全部楼层
谢谢分享

论坛徽章:
0
发表于 2012-02-22 11:25 |显示全部楼层
抓我的文章不注明出处啊,鄙视……
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP