Yii的学习(2)--数据访问对象 (DAO)

摘自Yii官网:http://www.yiiframework.com/doc/guide/1.1/zh_cn/database.daophp

Yii提供了强大的数据库编程支持。Yii数据访问对象(DAO)创建在PHP的数据对象(PDO)extension上,使得在一个单一的统一的接口能够访问不一样的数据库管理系统(DBMS)。使用Yii的DAO开发的应用程序能够很容易地切换使用不一样的数据库管理系统,而不须要修改数据访问代码。mysql

数据访问对象(DAO) 对访问存储在不一样数据库管理系统(DBMS)中的数据提供了一个通用的API。 所以,在将底层 DBMS 更换为另外一个时,无需修改使用了 DAO 访问数据的代码。sql

Yii DAO 基于 PHP Data Objects (PDO) 构建。它是一个为众多流行的DBMS提供统一数据访问的扩展,这些 DBMS 包括 MySQL, PostgreSQL 等等。所以,要使用 Yii DAO,PDO 扩展和特定的 PDO 数据库驱动(例如PDO_MYSQL) 必须安装。数据库

Yii DAO 主要包含以下四个类:编程

  • CDbConnection: 表明一个数据库链接。
  • CDbCommand: 表明一条经过数据库执行的 SQL 语句。
  • CDbDataReader: 表明一个只向前移动的,来自一个查询结果集中的行的流。
  • CDbTransaction: 表明一个数据库事务。

下面,咱们介绍 Yii DAO 在不一样场景中的应用。api

1. 创建数据库链接 

要创建一个数据库链接,建立一个 CDbConnection 实例并将其激活。 链接到数据库须要一个数据源的名字(DSN)以指定链接信息。用户名和密码也可能会用到。 当链接到数据库的过程当中发生错误时 (例如,错误的 DSN 或无效的用户名/密码),将会抛出一个异常。数组

$connection=new CDbConnection($dsn,$username,$password);
// 创建链接。你可使用  try...catch 捕获可能抛出的异常
$connection->active=true;
......
$connection->active=false;  // 关闭链接

DSN 的格式取决于所使用的 PDO 数据库驱动。整体来讲, DSN 要含有 PDO 驱动的名字,跟上一个冒号,再跟上驱动特定的链接语法。可查阅 PDO 文档 获取更多信息。 下面是一个经常使用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

因为 CDbConnection 继承自 CApplicationComponent,咱们也能够将其做为一个 应用组件 使用。要这样作的话, 请在 应用配置 中配置一个 db (或其余名字)应用组件以下:app

array(
    ......
    'components'=>array(
        ......
        'db'=>array(
            'class'=>'CDbConnection',
            'connectionString'=>'mysql:host=localhost;dbname=testdb',
            'username'=>'root',
            'password'=>'password',
            'emulatePrepare'=>true,  // needed by some MySQL installations
        ),
    ),
)

而后咱们就能够经过 Yii::app()->db 访问数据库链接了。它已经被自动激活了,除非咱们特地配置了CDbConnection::autoConnect 为 false。经过这种方式,这个单独的DB链接就能够在咱们代码中的不少地方共享。yii

2. 执行 SQL 语句 

数据库链接创建后,SQL 语句就能够经过使用 CDbCommand 执行了。你能够经过使用指定的SQL语句做为参数调用 CDbConnection::createCommand() 建立一个 CDbCommand 实例。

$connection=Yii::app()->db;   // 假设你已经创建了一个 "db" 链接
// 若是没有,你可能须要显式创建一个链接:
// $connection=new CDbConnection($dsn,$username,$password);
$command=$connection->createCommand($sql);
// 若是须要,此 SQL 语句可经过以下方式修改:
// $command->text=$newSQL;

一条 SQL 语句会经过 CDbCommand 以以下两种方式被执行:

  • execute(): 执行一个无查询 (non-query)SQL语句, 例如 INSERTUPDATE 和 DELETE 。若是成功,它将返回此执行所影响的行数。

  • query(): 执行一条会返回若干行数据的 SQL 语句,例如 SELECT。 若是成功,它将返回一个CDbDataReader 实例,经过此实例能够遍历数据的结果行。为简便起见, (Yii)还实现了一系列queryXXX() 方法以直接返回查询结果。

执行 SQL 语句时若是发生错误,将会抛出一个异常。

$rowCount=$command->execute();   // 执行无查询 SQL
$dataReader=$command->query();   // 执行一个 SQL 查询
$rows=$command->queryAll();      // 查询并返回结果中的全部行
$row=$command->queryRow();       // 查询并返回结果中的第一行
$column=$command->queryColumn(); // 查询并返回结果中的第一列
$value=$command->queryScalar();  // 查询并返回结果中第一行的第一个字段

3. 获取查询结果 

在 CDbCommand::query() 生成 CDbDataReader 实例以后,你能够经过重复调用 CDbDataReader::read() 获取结果中的行。你也能够在 PHP 的 foreach 语言结构中使用 CDbDataReader 一行行检索数据。

$dataReader=$command->query();
// 重复调用 read() 直到它返回 false
while(($row=$dataReader->read())!==false) { ... }
// 使用 foreach 遍历数据中的每一行
foreach($dataReader as $row) { ... }
// 一次性提取全部行到一个数组
$rows=$dataReader->readAll();

注意: 不一样于 query(), 全部的 queryXXX() 方法会直接返回数据。 例如, queryRow() 会返回表明查询结果第一行的一个数组。

4. 使用事务 

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

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

上述工做流能够经过以下代码实现:

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

5. 绑定参数 

要避免 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文档

6. 绑定列 

当获取查询结果时,你也可使用 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 
}

7. 使用表前缀 

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

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

$sql='SELECT * FROM {{user}}';
$users=$connection->createCommand($sql)->queryAll();
相关文章
相关标签/搜索