YII Framework学习教程-YII的Model-数据库操作3-自定义的DAO操作

转自 http://blog.csdn.net/mengxiangbaidu/article/details/7029694


 虽然我们可以使用CActvieReord完成大部分对数据库的操作。他简化了数据库操作,但是有时候却把一些数据库操作复杂化了。所以YII同时允许我们可以自己连接数据库,组织查询语句,执行查询语句,获取查询结果。这样可以让我们灵活的选择使用哪一种方式。

    下面讲讲YII提供的DAO操作相关类的使用方法。具体类在framework/db文件夹中

 

[php]  view plain copy
  1. .  
  2. ├── ar  
  3. │   ├── CActiveFinder.php  
  4. │   ├── CActiveRecordBehavior.php  
  5. │   └── CActiveRecord.php  
  6. ├── CDbCommand.php主要用于执行数据库相关操作的sql语句  
  7. ├── CDbConnection.php用于连接数据库  
  8. ├── CDbDataReader.php对数据库结果集操作  
  9. ├── CDbException.php数据库异常类  
  10. ├── CDbMigration.php数据库迁移  
  11. ├── CDbTransaction.php数据库事务  
  12. └── schema底层的数据库操作语法,针对不同的数据库,如果你想自定义其他数据库操作,可以在这里参考yii提供的数据库操作的类实现。  
  13.     ├── CDbColumnSchema.php  
  14.     ├── CDbCommandBuilder.php  
  15.     ├── CDbCriteria.php  
  16.     ├── CDbExpression.php  
  17.     ├── CDbSchema.php  
  18.     ├── CDbTableSchema.php  
  19.     ├── mssql  
  20.     │   ├── CMssqlColumnSchema.php  
  21.     │   ├── CMssqlCommandBuilder.php  
  22.     │   ├── CMssqlPdoAdapter.php  
  23.     │   ├── CMssqlSchema.php  
  24.     │   └── CMssqlTableSchema.php  
  25.     ├── mysql  
  26.     │   ├── CMysqlColumnSchema.php  
  27.     │   ├── CMysqlSchema.php  
  28.     │   └── CMysqlTableSchema.php  
  29.     ├── oci  
  30.     │   ├── COciColumnSchema.php  
  31.     │   ├── COciCommandBuilder.php  
  32.     │   ├── COciSchema.php  
  33.     │   └── COciTableSchema.php  
  34.     ├── pgsql  
  35.     │   ├── CPgsqlColumnSchema.php  
  36.     │   ├── CPgsqlSchema.php  
  37.     │   └── CPgsqlTableSchema.php  
  38.     └── sqlite  
  39.         ├── CSqliteColumnSchema.php  
  40.         ├── CSqliteCommandBuilder.php  
  41.         └── CSqliteSchema.php  
  42.   
  43. 7 directories, 33 files  

可以看到,数据库操作类主要是:

├── CDbConnection.php

├── CDbCommand.php

├── CDbDataReader.php
├── CDbException.php
├── CDbMigration.php
├── CDbTransaction.php

连接,执行,结果集操作,事物,异常,数据迁移。

1.数据库连接 CDbConnection.php

YII中的DAO是封装的PDO,那么连接数据库要提供的必要信息(连接方式,用户名,密码)自然也类似。打开类看看具体实现方式和使用方法。

通过类的注释可以了解连接方法。

[php]  view plain copy
  1. * CDbConnection represents a connection to a database.  
  2. *  
  3. * CDbConnection works together with {@link CDbCommand}, {@link CDbDataReader}  
  4. and {@link CDbTransaction} to provide data access to various DBMS  
  5. * in a common set of APIs. They are a thin wrapper of the {@link http://www.php.net/manual/en/ref.pdo.php PDO}  
  6. * PHP extension.  
  7. *  
  8. * To establish a connection, set {@link setActive active} to true after  
  9. * specifying {@link connectionString}, {@link username} and {@link password}.  
  10. *  
  11. * The following example shows how to create a CDbConnection instance and establish  
  12. * the actual connection:  
  13. * <pre>  
  14. $connection=new CDbConnection($dsn,$username,$password);  
  15. $connection->active=true;  
  16. * </pre>  

参数:

$dsn:

[php]  view plain copy
  1. /** 
  2.  * @var string The Data Source Name, or DSN, contains the information required to connect to the database. 
  3.  * @see http://www.php.net/manual/en/function.PDO-construct.php 
  4.  * 
  5.  * Note that if you're using GBK or BIG5 then it's highly recommended to 
  6.  * update to PHP 5.3.6+ and to specify charset via DSN like 
  7.  * 'mysql:dbname=mydatabase;host=127.0.0.1;charset=GBK;'. 
  8.  */  
  9. public $connectionString;  
$dsn的具体规则可以参看

http://www.php.net/manual/en/function.PDO-construct.php。

http://cn2.php.net/manual/en/pdo.drivers.php

格式如下:

uri:file:///path/to/dsnfile

YII官方给出的常见的DSN格式如下:

  • SQLite: sqlite:/path/to/dbfile
  • MySQL: mysql:host=localhost;dbname=testdb
  • PostgreSQL: pgsql:host=localhost;port=5432;dbname=testdb
  • SQL Server: mssql:host=localhost;dbname=testdb
  • Oracle: oci:dbname=//localhost:1521/testdb
如果要指定连接数据库的编码可以添加charset=。当然可以执行sql语句设定编码格式。

$username

$password

具体举例如下:

/yii_dev/testwebap/protected/models/Member.php

[php]  view plain copy
  1.   

[php]  view plain copy
  1. <?php  
  2. class Member extends CModel  
  3. {  
  4.     private $connection = null;  
  5.     public function __construct ()  
  6.     {  
  7.         //YII的强大,让你可以直接用下面的语句连接,更简单  
  8.         $this->connection = Yii::app()->db;  
  9.         //or,下面也可以,就是蛮笨的,当然也是基本的  
  10.         /* 
  11.         $dsn = Yii::app()->db->connectionString; 
  12.         $username = Yii::app()->db->username; 
  13.         $password = Yii::app()->db->password; 
  14.         $this->connection = new CDbConnection($dsn, $username, $password); 
  15.         $this->connection->charset = 'utf8'; 
  16.         $this->connection->active = true;         
  17.          */  
  18.     }  
  19.     /** 
  20.      * Returns the static model of the specified AR class. 
  21.      * @return User the static model class 
  22.      */  
  23.     public static function model ($className = __CLASS__)  
  24.     {  
  25.         return parent::model($className);  
  26.     }  
  27.     /** 
  28.      *  
  29.      * 连接状态 
  30.      */  
  31.     public function stats ()  
  32.     {  
  33.         return $this->connection ? 'connection successful!' : 'connection fail!';  
  34.     }  
  35.     public function attributeNames ()  
  36.     {}  
  37. }  


$this->connection->active = true;表示打开连接。


/yii_dev/testwebap/protected/modules/testmod/controllers/DefaultController.php

[php]  view plain copy
  1. <?php  
  2. class DefaultController extends Controller  
  3. {  
  4.     public function actionDao ()  
  5.     {  
  6.         $memberModel = new Member();  
  7.         var_dump($memberModel->stats());  
  8.     }  



具体的实现方式,可以自行参考类,这里不再累述。



2.数据库基本操作CDbCommand.php

数据库连接建立后,便可以通过CDbCommand类提供的方法就可以进行数据库操作。

类给出的使用方法:

[php]  view plain copy
  1. * After the DB connection is established, one can execute an SQL statement like the following:  
  2. * <pre>  
  3. $command=$connection->createCommand($sqlStatement);  
  4. $command->execute();   // a non-query SQL statement execution  
  5. // or execute an SQL query and fetch the result set  
  6. $reader=$command->query();  
  7. *  
  8. // each $row is an array representing a row of data  
  9. foreach($reader as $row) ...  
  10. * </pre>  
  11. *  
  12. * One can do prepared SQL execution and bind parameters to the prepared SQL:  
  13. * <pre>  
  14. $command=$connection->createCommand($sqlStatement);  
  15. $command->bindParam($name1,$value1);  
  16. $command->bindParam($name2,$value2);  
  17. $command->execute();  
  18. * </pre>  


基本使用方法如下

[php]  view plain copy
  1. <?php  
  2. class Member extends CModel  
  3. {  
  4.     private $connection = null;  
  5.     private $command = null;  
  6.     public function __construct ()  
  7.     {  
  8.         $this->connection = Yii::app()->db;  
  9.     }  
  10.     /** 
  11.      * Returns the static model of the specified AR class. 
  12.      * @return User the static model class 
  13.      */  
  14.     public static function model ($className = __CLASS__)  
  15.     {  
  16.         return parent::model($className);  
  17.     }  
  18.     /** 
  19.      *  
  20.      * 连接状态 
  21.      */  
  22.     public function stats ()  
  23.     {  
  24.         return $this->connection ? 'connection successful!' : 'connection fail!';  
  25.     }  
  26.     /** 
  27.      *  
  28.      * 获取所有用户名 
  29.      */  
  30.     public function getUsernames ()  
  31.     {  
  32.         $sqlStatement = ' SELECT `username` FROM `testdrive`.`tbl_user` ';  
  33.         $this->command = $this->connection->createCommand($sqlStatement);  
  34.         return $this->command->queryAll();  
  35.     }  
  36.     /** 
  37.      *  
  38.      * 获取指定用户的昵称 
  39.      * @param string $userName 
  40.      */  
  41.     public function getNickname ($userName)  
  42.     {  
  43.         $sqlStatement = ' SELECT `username` FROM `testdrive`.`tbl_user` WHERE `username`=:username ';  
  44.         $this->command = $this->connection->createCommand($sqlStatement);  
  45.         $this->command->bindParam('username'$userName);  
  46.         return $this->command->queryAll();  
  47.     }  
  48.     /** 
  49.      *  
  50.      * 添加一个用户 
  51.      */  
  52.     public function addUser ()  
  53.     {  
  54.         $sqlStatement = " INSERT INTO `tbl_user` (`username`, `password`, `email`) VALUES ('test', 'test', 'test@test.com') ";  
  55.         $this->command = $this->connection->createCommand($sqlStatement);  
  56.         return $this->command->execute();  
  57.     }  
  58.     public function attributeNames ()  
  59.     {}  
  60. }  

[php]  view plain copy
  1. <?php  
  2. class DefaultController extends Controller  
  3. {  
  4.     public function actionUsernames ()  
  5.     {  
  6.         $memberModel = new Member();  
  7.         var_dump($memberModel->getUsernames());  
  8.     }  
  9.     public function actionNickname ()  
  10.     {  
  11.         $memberModel = new Member();  
  12.         var_dump($memberModel->getNickname('admin'));  
  13.     }  
  14.     public function actionAdduser ()  
  15.     {  
  16.         $memberModel = new Member();  
  17.         var_dump($memberModel->addUser());  
  18.     }  

 总结:

*****常用函数

(1)如果你执行的SQL语句有返回结果集: 例如SELECT。通常用query开头的系列函数:

常见的有:

$dataReader=$command->query();   // 执行一个 SQL 查询
$rows=$command->queryAll();      // 查询并返回结果中的所有行
$row=$command->queryRow();       // 查询并返回结果中的第一行
$column=$command->queryColumn(); // 查询并返回结果中的第一列
$value=$command->queryScalar();  // 查询并返回结果中第一行的第一个字段
query()方法执行如果成功,它将返回一个CDbDataReader 实例,通过此实例可以遍历数据的结果行。

为简便起见, (Yii)还实现了一系列queryXXX() 方法以直接返回查询结果。


(2)你执行的SQL语句返回的不是结果集,只是状态值,例如:INSERT ,UPDATE,DELETE.则用execute()

例如

$this->command->execute();  

*****结果集操作类CDbDataReader的使用方法有两种方法,参见如下代码

 

[php]  view plain copy
  1. /** 
  2.  *  
  3.  * 获取所有用户名 
  4.  */  
  5. public function getUsernames ()  
  6. {  
  7.     $sqlStatement = ' SELECT `username` FROM `testdrive`.`tbl_user` ';  
  8.     $this->command = $this->connection->createCommand($sqlStatement);  
  9.     $dataReader = $this->command->query();  
  10.     // 重复调用 read() 直到它返回 false  
  11.     while (($row = $dataReader->read()) !== false) {  
  12.         var_dump($row);  
  13.     }  
  14.     foreach ($dataReader as $row) {  
  15.         var_dump($row);  
  16.     }  
  17. }  

CDbDataReader还提供了其他的方法。例如获取行数,将所有数据转存储到一个数组等等,具体的可参考类的代码。


*****表前缀

从版本 1.1.0 起, Yii 提供了集成了对使用表前缀的支持。 表前缀是指在当前连接的数据库中的数据表的名字前面添加的一个字符串。 它常用于共享的服务器环境,这种环境中多个应用可能会共享同一个数据库,要使用不同的表前缀以相互区分。 例如,一个应用可以使用 tbl_ 作为表前缀而另一个可以使用 yii_

要使用表前缀,配置 CDbConnection::tablePrefix 属性为所希望的表前缀。 然后,在 SQL 语句中使用{{TableName}} 代表表的名字,其中的 TableName 是指不带前缀的表名。 例如,如果数据库含有一个名为tbl_user 的表,而 tbl_ 被配置为表前缀,那我们就可以使用如下代码执行用户相关的查询:

$sql='SELECT * FROM {{user}}';
$users=$connection->createCommand($sql)->queryAll();



*****绑定参数

要避免 SQL 注入攻击 并提高重复执行的 SQL 语句的效率, 你可以 "准备(prepare)"一条含有可选参数占位符的 SQL 语句,在参数绑定时,这些占位符将被替换为实际的参数。

参数占位符可以是命名的 (表现为一个唯一的标记) 或未命名的 (表现为一个问号)。调用CDbCommand::bindParam() 或 CDbCommand::bindValue() 以使用实际参数替换这些占位符。 这些参数不需要使用引号引起来:底层的数据库驱动会为你搞定这个。 参数绑定必须在 SQL 语句执行之前完成。

// 一条带有两个占位符 ":username" 和 ":email"的 SQL
$sql="INSERT INTO tbl_user (username, email) VALUES(:username,:email)";
$command=$connection->createCommand($sql);
// 用实际的用户名替换占位符 ":username" 
$command->bindParam(":username",$username,PDO::PARAM_STR);
// 用实际的 Email 替换占位符 ":email" 
$command->bindParam(":email",$email,PDO::PARAM_STR);
$command->execute();
// 使用新的参数集插入另一行
$command->bindParam(":username",$username2,PDO::PARAM_STR);
$command->bindParam(":email",$email2,PDO::PARAM_STR);
$command->execute();

方法 bindParam() 和 bindValue() 非常相似。唯一的区别就是前者使用一个 PHP 变量绑定参数, 而后者使用一个值。对于那些内存中的大数据块参数,处于性能的考虑,应优先使用前者。

关于绑定参数的更多信息,请参考 相关的PHP文档


*****绑定列

 

当获取查询结果时,你也可以使用 PHP 变量绑定列。 这样在每次获取查询结果中的一行时就会自动使用最新的值填充。

$sql="SELECT username, email FROM tbl_user";
$dataReader=$connection->createCommand($sql)->query();
// 使用 $username 变量绑定第一列 (username) 
$dataReader->bindColumn(1,$username);
// 使用 $email 变量绑定第二列 (email) 
$dataReader->bindColumn(2,$email);
while($dataReader->read()!==false)
{
    // $username 和 $email 含有当前行中的 username 和 email 
}


详细的使用方法参考官方的Query Builder》,下一节将会对其做翻译

3.数据库事务操作CDbTransaction.php

 

当一个应用要执行几条查询,每条查询要从数据库中读取并/或向数据库中写入信息时, 保证数据库没有留下几条查询而只执行了另外几条查询是非常重要的。 事务,在 Yii 中表现为 CDbTransaction 实例,可能会在下面的情况中启动:

  • 开始事务.
  • 一个个执行查询。任何对数据库的更新对外界不可见。
  • 提交事务。如果事务成功,更新变为可见。
  • 如果查询中的一个失败,整个事务回滚。

上述工作流可以通过如下代码实现:

$transaction=$connection->beginTransaction();
try
{
    $connection->createCommand($sql1)->execute();
    $connection->createCommand($sql2)->execute();
    //.... other SQL executions
    $transaction->commit();
}
catch(Exception $e) // 如果有一条查询失败,则会抛出异常
{
    $transaction->rollBack();
}


4.数据库操作异常类CDbException


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值