Объекты доступа к данным (DAO) предоставляют общий API для доступа к данным, хранящимся в различных СУБД. Это позволяет без проблем поменять используемую СУБД на любую другую без необходимости изменения кода, использующего DAO для доступа к данным.
Yii DAO является надстройкой над PHP Data Objects (PDO) -
расширением, которое предоставляет унифицированный доступ к данным многих популярных
СУБД, таких, как MySQL, PostgreSQL. Для использования Yii DAO необходимо, чтобы
были установлены расширение PDO и драйвер PDO, соответствующий используемой базе данных (например, PDO_MYSQL).
Yii DAO состоит из четырех основных классов:
Ниже мы проиллюстрируем использование Yii DAO.
Для установления соединения с базой необходимо создать экземпляр класса CDbConnection и активировать его. Дополнительную информацию, необходимую для подключения к БД (хост, порт, имя пользователя, пароль и пр.), указываем в DSN. В случае возникновения ошибки в процессе соединения с БД, будет вызвано исключение (например, неверный DSN или неправильные имя пользователя/пароль).
$connection=new CDbConnection($dsn,$username,$password); // устанавливаем соединение. Можно попробовать try…catch возможных исключений $connection->active=true; … $connection->active=false; // close connection
Формат DSN зависит от используемого драйвера PDO. Как правило, DSN состоит из имени драйвера PDO, за которым следует двоеточие, а далее указываются параметры подключения, соответствующие синтаксису подключения используемого драйвера. Подробнее с этим можно ознакомиться в документации по PDO. Ниже представлены несколько основных форматов DSN:
sqlite:/path/to/dbfilemysql:host=localhost;dbname=testdbpgsql:host=localhost;port=5432;dbname=testdbmssql:host=localhost;dbname=testdboci:dbname=//localhost:1521/testdbПоскольку CDbConnection является подклассом CApplicationComponent, то мы можем использовать его
в качестве компонента. Для этого нужно настроить
компонент db в конфигурации приложения
следующим образом:
array( … 'components'=>array( … 'db'=>array( 'class'=>'CDbConnection', 'connectionString'=>'mysql:host=localhost;dbname=testdb', 'username'=>'root', 'password'=>'password', 'emulatePrepare'=>true, // необходимо для некоторых версий инсталляций MySQL ), ), )
Теперь мы можем получить доступ к соединению с БД через Yii::app()->db. Чтобы соединение не активировалось
автоматически, необходимо установить значение CDbConnection::autoConnect в false.
Этот способ дает нам возможность использования одного подключения к БД в любом месте кода.
Когда соединение с БД установлено, мы можем выполнять SQL-выражения, используя CDbCommand. Для этого создаем экземпляр CDbCommand путем вызова CDbConnection::createCommand() с указанием SQL-выражения:
$connection=Yii::app()->db; // так можно сделать, если в конфигурации описан компонент соединения "db" // Если не описан — можно создать соединение явно: // $connection=new CDbConnection($dsn,$username,$password); $command=$connection->createCommand($sql); // если необходимо, SQL-выражение можно обновить: // $command->text=$newSQL;
Существует два варианта исполнения SQL-выражения с использованием CDbCommand:
execute(): выполняет SQL-выражения типа INSERT, UPDATE и DELETE.
В случае успешного исполнения, возвращает количество обработанных строк;
query(): выполняет SQL-выражения, возвращающие наборы данных, например, типа SELECT.
В случае успешного исполнения, возвращает экземпляр класса CDbDataReader, через который доступны полученные данные.
Для удобства также реализованы методы queryXXX(), возвращающие результаты запроса напрямую.
Если в процессе выполнения SQL-выражения возникнет ошибка, будет вызвано исключение.
$rowCount=$command->execute(); // исполнение выражения типа `INSERT`, `UPDATE` и `DELETE` $dataReader=$command->query(); // исполнение выражения типа `SELECT` $rows=$command->queryAll(); // запрос и возврат всех строк результата $row=$command->queryRow(); // запрос и возврат первой строки результата $column=$command->queryColumn(); // запрос и возврат первого столбца результата $value=$command->queryScalar(); // запрос и возврат первого поля в первой строке
После того, как CDbCommand::query() создает экземпляр класса CDbDataReader, мы можем
получить данные построчно путем повторного вызова метода CDbDataReader::read(). Для получения данных строка
за строкой можно также использовать CDbDataReader в конструкциях foreach.
$dataReader=$command->query(); // многократно вызываем read() до возврата методом значения false while(($row=$dataReader->read())!==false) { … } // используем foreach для построчного обхода данных foreach($dataReader as $row) { … } // получаем все строки разом в одном массиве $rows=$dataReader->readAll();
Примечание: Все методы
queryXXX(), в отличие от query(), возвращают все данные напрямую. Например, метод queryRow() возвращает массив с первой строкой результата запроса.
В случае, когда приложение выполняет несколько запросов, каждый из которых что-то пишет или читает из БД, важно удостовериться, что набор запросов выполнен полностью, а не наполовину. В этой ситуации можно воспользоваться транзакциями, представляемыми экземпляром класса CDbTransaction:
Эту последовательность действий можно реализовать следующим образом:
$transaction=$connection->beginTransaction(); try { $connection->createCommand($sql1)->execute(); $connection->createCommand($sql2)->execute(); //… прочие SQL запросы $transaction->commit(); } catch(Exception $e) // в случае ошибки при выполнении запроса выбрасывается исключение { $transaction->rollBack(); }
С целью избежания SQL-инъекций и улучшения производительности при выполнении повторно используемых SQL-выражений, мы можем «подготавливать» SQL-выражение с маркерами параметров (placeholder), которые в процессе привязки будут заменяться на реальные значения.
Маркеры параметров могут быть именованными (уникальные маркеры) или неименованными (вопросительные знаки). Для замены маркеров на реальные значения нужно вызвать CDbCommand::bindParam() или CDbCommand::bindValue(). Добавлять кавычки к параметрам нет необходимости, т.к. используемый драйвер базы данных все сделает сам. Связывание параметров должно быть завершено до исполнения SQL-выражения.
// выражение SQL с двумя маркерами «:username» и «:email» $sql="INSERT INTO tbl_user(username, email) VALUES(:username,:email)"; $command=$connection->createCommand($sql); // меняем маркер «:username» на соответствующее значение имени пользователя $command->bindParam(":username",$username,PDO::PARAM_STR); // меняем маркер «: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, а второй — к значению. Для параметров, представляющих большой объем данных, с точки зрения производительности предпочтительнее использовать метод bindParam().
Подробнее о связывании параметров можно узнать в соответствующей документации 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 текущей строки }
Yii обеспечивает встроенную поддержку
префиксов таблиц. Префикс таблиц — это строка, предваряющая имя таблиц в текущей
подключенной БД. В основном используется на общем хостинге, где к одной БД
подключается несколько приложений, использующих различные префиксы таблиц для
различения принадлежности таблиц к приложению. Например, одно приложение
использует префикс tbl_, а другое — yii_.
Для использования префикса таблиц, установите в свойстве
CDbConnection::tablePrefix желаемый префикс таблиц. Затем, в SQL выражении,
используйте {{TableName}} для ссылки на имена таблиц, где TableName — имя
таблицы без префикса. Например, если БД содержит таблицу с именем tbl_user,
где tbl_ — это префикс таблиц, тогда мы можем использовать следующий код для
запроса пользователей:
$sql='SELECT * FROM {{user}}'; $users=$connection->createCommand($sql)->queryAll();
Be the first person to leave a comment
Please login to leave your comment.