Объекты доступа к данным (DAO) предоставляют общий API для доступа к данным, хранящимся в различных СУБД. Это позволяет без проблем поменять используемую СУБД на любую другую без необходимости изменения кода, использующего DAO для доступа к данным.
Yii DAO является надстройкой над PHP Data Objects (PDO) -
расширением, которое предоставляет унифицированный доступ к данным многих популярных
СУБД, таких как MySQL, PostgreSQL. Поэтому для использования Yii DAO необходимо, чтобы
были установлены расширение PDO и соответствующий используемой базе данных драйвер PDO (например, PDO_MYSQL).
Yii DAO состоит из четырёх основных классов:
Далее мы проиллюстрируем использование Yii DAO на различных примерах.
Для установления соединения с базой необходимо создать экземпляр класса CDbConnection и активировать его. Дополнительная информация, необходимая для подключения к БД (хост, порт, имя пользователя, пароль и т.д.), указывается в DSN (Data Source Name). В случае возникновения ошибки в процессе соединения с БД будет выброшено исключение (например, неверный 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-выражения, используя маркеры параметров (placeholders), которые в процессе привязки будут заменяться на реальные значения.
Маркеры параметров могут быть именованными (уникальные маркеры) или неименованными (вопросительные знаки). Для замены маркеров на реальные значения нужно вызвать методы 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 предоставляет встроенную поддержку префиксов таблиц.
Префикс таблиц — это строка, предваряющая имена таблиц в текущей подключённой БД.
В основном, префиксы используются на виртуальном (shared) хостинге, где к одной БД
подключаются несколько приложений, использующих различные префиксы таблиц в целях избежания конфликтов имён.
Например, одно приложение использует префикс tbl_, а другое — yii_.
Для использования префикса таблиц установите свойство CDbConnection::tablePrefix.
Затем в SQL-выражениях используйте {{TableName}} для указания имён таблиц, где TableName — имя
таблицы без префикса. Например, если БД содержит таблицу tbl_user, где tbl_ — это префикс таблиц,
то мы можем использовать следующий код для получения списка пользователей:
$sql='SELECT * FROM {{user}}';
$users=$connection->createCommand($sql)->queryAll();
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.