'
虽然我们可以使用CActvieReord完成大部分对数据库的操作。他简化了数据库操作,但是有时候却把一些数据库操作复杂化了。所以YII同时允许我们可以自己连接数据库,组织查询语句,执行查询语句,获取查询结果。这样可以让我们灵活的选择使用哪一种方式。
下面讲讲YII提供的DAO操作相关类的使用方法。具体类在framework/db文件夹中
可以看到,数据库操作类主要是:
├── CDbConnection.php
├── CDbCommand.php
├── CDbDataReader.php
├── CDbException.php
├── CDbMigration.php
├── CDbTransaction.php
连接,执行,结果集操作,事物,异常,数据迁移。
1.数据库连接
YII中的DAO是封装的PDO,那么连接数据库要提供的必要信息(连接方式,用户名,密码)自然也类似。打开类看看具体实现方式和使用方法。通过类的注释可以了解连接方法。
- $connection=new
CDbConnection($dsn,$username,$password); - $connection->active=true;
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
2.数据库基本操作CDbCommand.php
数据库连接建立后,便可以通过CDbCommand类提供的方法就可以进行数据库操作。你可以通过使用指定的SQL语句作为参数调用 CDbConnection::createCommand() 创建一个 CDbCommand 实例。
$connection=Yii::app()->db;
// 如果没有,你可能需要显式建立一个连接:
// $connection=new CDbConnection($dsn,$username,$password);
$command=$connection->createCommand($sql);
// 如果需要,此 SQL 语句可通过如下方式修改:
// $command->text=$newSQL;
一条 SQL 语句会通过 CDbCommand 以如下两种方式被执行:
execute(): 执行一个无查询 (non-query)SQL语句,例如 INSERT, UPDATE 和 DELETE 。如果成功,它将返回此执行所影响的行数。
query(): 执行一条会返回若干行数据的 SQL 语句,例如 SELECT。如果成功,它将返回一个 CDbDataReader 实例,通过此实例可以遍历数据的结果行。为简便起见,(Yii)还实现了一系列 queryXXX()(select操作) 方法以直接返回查询结果。
执行 SQL 语句时如果发生错误,将会抛出一个异常。
$rowCount=$command->execute();
$dataReader=$command->query();
$rows=$command->queryAll();
$row=$command->queryRow();
$column=$command->queryColumn(); // 查询并返回结果中的第一列
$value=$command->queryScalar();
3.结果集操作类CDbDataReader的使用
query()方法执行如果成功,它将返回一个CDbDataReader
执行的SQL语句返回的不是结果集,只是状态值,例如:INSERT ,UPDATE,DELETE.则用execute() 例如:$this->command->execute();
要使用表前缀,配置 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 变量绑定列。 这样在每次获取查询结果中的一行时就会自动使用最新的值填充
$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 }
4.数据库事务操作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();
}
'