Объекты доступа к данным (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-выражения:
$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 users(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 users"; $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 текущей строки }
Be the first person to leave a comment
Please login to leave your comment.