Data Access Object (DAO) provides a common API for accessing data stored in different database management systems (DBMS). Therefore, when changing the underlying DBMS to another, there is no need to modify the code that uses DAO to access data.
Yii DAO is built based on PHP Data Objects (PDO). It is an extension that provides unified data access for many popular DBMS, including MySQL, PostgreSQL, etc. Therefore, to use Yii DAO, the PDO extension and specific PDO database driver (such as PDO_MYSQL) must be installed.
Yii DAO mainly includes the following four classes:
CDbConnection: represents a database connection.
CDbCommand: Represents a SQL statement executed through the database.
CDbDataReader: Represents a forward-only stream of rows from a query result set.
CDbTransaction: Represents a database transaction.
Below, we introduce the application of Yii DAO in different scenarios.
1. Establish a database connection
To establish a database connection, create a CDbConnection instance and activate it. Connecting to a database requires a data source name (DSN) to specify connection information. Username and password may also be used. When an error occurs while connecting to the database (for example, wrong DSN or invalid username/password), an exception will be thrown.
$connection=new CDbConnection($dsn,$username,$password); // 建立连接。你可以使用 try...catch 捕获可能抛出的异常 $connection->active=true; ......
$connection->active=false; // The format of the closed connection DSN depends on the PDO database driver used. In general, the DSN contains the name of the PDO driver, followed by a colon, followed by driver-specific connection syntax. Check out the PDO documentation for more information. Below is a list of commonly used DSN formats.
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
Since CDbConnection inherits from CApplicationComponent, we can also use it as an application component. To do this, please configure a db (or other name) application component in the application configuration as follows:
This example uses the MySQL chinook database and modify protected/config/main.php
'components'=>array( 'db'=>array( 'class'=>'CDbConnection', 'connectionString'=>'mysql:host=localhost;dbname=chinook', 'username'=>'root', 'password'=>'password', 'emulatePrepare'=>true, // needed by some MySQL installations ), ),
Then we can access the database connection through Yii::app()->db. It is automatically activated unless we specifically configure CDbConnection::autoConnect to false. This way, this single DB connection can be shared in many places in our code.
2. Execute SQL statements
After the database connection is established, SQL statements can be executed by using CDbCommand. You can create a CDbCommand instance by calling CDbConnection::createCommand() with the specified SQL statement as argument.
For the sake of simplicity, we use the Employee table in the Chinook database and modify the DataModel
class DataModel { public $employeeId; public $firstName; public $lastName; public $title; public $address; public $email; }
Note: This step of creating a DataModel is optional.
Modify the indexAction method of SiteController:
public function actionIndex(){ $model = array();$sql='SELECT * FROM Employee'; // 假设你已经建立了一个 "db" 连接$connection=Yii::app()->db; // 如果没有,你可能需要显式建立一个连接: // $connection=new CDbConnection($dsn,$username,$password); $command=$connection->createCommand($sql); // 如果需要,此 SQL 语句可通过如下方式修改: // $command->text=$newSQL; $dataReader=$command->query(); // each $row is an array representing a row of dataforeach($dataReader as $row){$employee = new DataModel(); $employee->employeeId=$row['EmployeeId']; $employee->firstName=$row['FirstName']; $employee->lastName=$row['LastName']; $employee->title=$row['Title']; $employee->address=$row['Address']; $employee->email=$row['Email']; $model[]=$employee;} $this->render('index', array('model' => $model,)); }
A SQL statement will be executed through CDbCommand in the following two ways:
execute(): execute a non-query (non- query ) SQL statements such as INSERT, UPDATE and DELETE. If successful, it returns the number of rows affected by this execution. query(): Execute a SQL statement that returns several rows of data, such as SELECT. If successful, it returns a CDbDataReader instance through which the resulting rows of data can be iterated. For simplicity, (Yii) also implements a series of queryXXX() methods to directly return query results.
If an error occurs when executing a SQL statement, an exception will be thrown.
$rowCount=$command->execute(); // 执行无查询 SQL $dataReader=$command->query(); // 执行一个 SQL 查询 $rows=$command->queryAll(); // 查询并返回结果中的所有行 $row=$command->queryRow(); // 查询并返回结果中的第一行 $column=$command->queryColumn(); // 查询并返回结果中的第一列 $value=$command->queryScalar(); // 查询并返回结果中第一行的第一个字段
3. Get query results
After CDbCommand::query() generates a CDbDataReader instance, you can get the rows in the results by repeatedly calling CDbDataReader::read(). You can also use CDbDataReader in PHP's foreach language construct to retrieve data row by row.
$dataReader=$command->query(); // 重复调用 read() 直到它返回 false while(($row=$dataReader->read())!==false) { ... } // 使用 foreach 遍历数据中的每一行 foreach($dataReader as $row) { ... } // 一次性提取所有行到一个数组 $rows=$dataReader->readAll();
4. Display query results
For the sake of simplicity, this example uses the echo statement to display Employee records. Later, GridView or ListView can be used to display database tables.
Modify protected/views/site/index.php
foreach($model as $employee) { echo 'EmployeeId:' . $employee->employeeId . ' '; echo 'First Name:' . $employee->firstName . ' '; echo 'Last Name:' . $employee->lastName . ' '; echo 'Title:' . $employee->title . ' '; echo 'Address:' . $employee->address . ' '; echo 'Email:' . $employee->email . ' '; echo '---------------------- '; } ?>
5. Use transactions
When an application needs to execute several queries, each query must be read from the database When fetching and/or writing information to the database, it is very important to ensure that the database does not leave several queries behind and only executes a few others. Transactions, represented in Yii as CDbTransaction instances, may be started in the following situations:
Start transaction. Execute queries one by one. Any updates to the database are not visible to the outside world. Commit the transaction. If the transaction succeeds, the update becomes visible. If one of the queries fails, the entire transaction is rolled back.
The above workflow can be implemented through the following code:
$transaction=$connection->beginTransaction(); try { $connection->createCommand($sql1)->execute(); $connection->createCommand($sql2)->execute(); //.... other SQL executions $transaction->commit(); } catch(Exception $e) // 如果有一条查询失败,则会抛出异常 { $transaction->rollBack(); }
6. Bind parameters
To avoid SQL injection attacks and improve the efficiency of repeatedly executed SQL statements, you can "Prepare" an SQL statement containing optional parameter placeholders that will be replaced with actual parameters when the parameters are bound.
Parameter placeholders can be named (appear as a unique token) or unnamed (appear as a question mark). Call CDbCommand::bindParam() or CDbCommand::bindValue() to replace these placeholders with actual parameters. These parameters do not need to be enclosed in quotes: the underlying database driver takes care of this for you. Parameter binding must be completed before the SQL statement is executed.
// 一条带有两个占位符 ":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文档。
7. 绑定列
当获取查询结果时,你也可以使用 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 }
8. 使用表前缀
从版本 1.1.0 起, Yii 提供了集成了对使用表前缀的支持。 表前缀是指在当前连接的数据 库中的数据表的名字前面添加的一个字符串。 它常用于共享的服务器环境,这种环境中多个应用可能会共享同一个数据库,要 使用不同的表前缀以相互区分。 例如,一个应用可以使用 tbl_ 作为表前缀而另一个可以使用 yii_。
要使用表前缀, 配置 CDbConnection::tablePrefix 属性为所希望的表前缀。 然后,在 SQL 语句中使用{{TableName}} 代表表的名字,其中的 TableName 是指不带前缀的表名。 例如,如果数据库含有一个名为tbl_user 的表,而 tbl_ 被配置为表前缀,那我们就可以使 用如下代码执行用户相关的查询:
$sql='SELECT * FROM {{user}}';$users=$connection->createCommand($sql)->queryAll();
以上就是PHP开发框架Yii Framework教程(24) 数据库-DAO示例的内容,更多相关内容请关注PHP中文网(www.php.cn)!