Объекты доступа к данным (DAO)
Объекты доступа к данным (DAO) предоставляют общий API для доступа к данным, хранящимся в различных СУБД. Это позволяет без проблем поменять используемую СУБД на любую другую без необходимости изменения кода, использующего DAO для доступа к данным.
Yii DAO является надстройкой над PHP Data Objects (PDO) -
расширением, которое предоставляет унифицированный доступ к данным многих популярных
СУБД, таких как MySQL, PostgreSQL. Поэтому для использования Yii DAO необходимо, чтобы
были установлены расширение PDO и соответствующий используемой базе данных драйвер PDO (например, PDO_MYSQL
).
Yii DAO состоит из четырёх основных классов:
- CDbConnection: представляет подключение к базе данных.
- CDbCommand: представляет запрос к базе данных, который необходимо выполнить.
- CDbDataReader: представляет однонаправленный поток строк данных, возвращаемых в ответ на запрос.
- CDbTransaction: представляет транзакцию базы данных.
Далее мы проиллюстрируем использование Yii DAO на различных примерах.
Соединение с базой данных
Для установления соединения с базой необходимо создать экземпляр класса CDbConnection и активировать его. Дополнительная информация, необходимая для подключения к БД (хост, порт, имя пользователя, пароль и т.д.), указывается в DSN (Data Source Name). В случае возникновения ошибки в процессе соединения с БД будет выброшено исключение (например, неверный DSN или неправильные имя пользователя/пароль).
Формат DSN зависит от используемого драйвера PDO. Как правило, DSN состоит из имени драйвера PDO, за которым следует двоеточие, далее указываются параметры подключения, соответствующие синтаксису подключения используемого драйвера. Подробнее с этим можно ознакомиться в документации PDO. Ниже представлены несколько основных форматов 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
Поскольку CDbConnection наследует класс CApplicationComponent, мы можем использовать его
в качестве компонента приложения. Для этого нужно настроить
компонент db
в конфигурации приложения
следующим образом:
Теперь мы можем получить доступ к соединению с БД через Yii::app()->db
. Чтобы соединение не активировалось
автоматически, необходимо установить значение CDbConnection::autoConnect в false.
Этот способ даёт нам возможность использовать одно и то же подключение к БД в любом месте кода.
Выполнение SQL-запросов
Когда соединение с БД установлено, мы можем выполнять SQL-запросы, используя CDbCommand. Для этого необходимо создать экземпляр класса CDbCommand путём вызова CDbConnection::createCommand(), указав SQL-выражение:
Существуют два способа выполнения SQL-запросов с использованием CDbCommand:
execute(): выполняет SQL-запросы
INSERT
,UPDATE
иDELETE
. В случае успешного выполнения возвращает количество затронутых строк.query(): выполняет SQL-запросы, возвращающие наборы данных, например, запросы
SELECT
. В случае успешного выполнения возвращает экземпляр класса CDbDataReader, обеспечивающий доступ к полученным данным. Для удобства также реализованы методы видаqueryXXX()
, возвращающие результаты напрямую.
Если в процессе выполнения SQL-запроса возникнет ошибка, то будет выброшено исключение.
Обработка результатов запроса
После того как CDbCommand::query() создаст экземпляр класса CDbDataReader, мы можем
получить результат запроса построчно путём повторения вызовов метода CDbDataReader::read().
Для получения данных строка за строкой можно также использовать CDbDataReader в конструкциях foreach
.
Примечание: Все методы
queryXXX()
, в отличие от query(), возвращают данные напрямую. Например, метод queryRow() возвращает массив, соответствующий первой строке результата запроса.
Использование транзакций
В случае когда приложение выполняет несколько запросов, каждый из которых что-то пишет или читает из БД, важно удостовериться, что набор запросов выполнен полностью, а не частично. В этой ситуации можно воспользоваться транзакциями, представляющими собой экземпляры класса CDbTransaction:
- Начало транзакции.
- Выполнение запросов по очереди. В этот момент все изменения в базе недоступны извне.
- Подтверждение транзакции. Если транзакция проведена успешно, то изменения становятся общедоступны.
- При возникновении ошибки в ходе выполнения запросов происходит откат транзакции в начальное состояние.
Эту последовательность действий можно реализовать следующим образом:
Привязка параметров
Для предотвращения SQL-инъекций и повышения производительности при выполнении однотипных SQL-запросов мы можем «подготавливать» SQL-выражения, используя маркеры параметров (placeholders), которые в процессе привязки будут заменяться на реальные значения.
Маркеры параметров могут быть именованными (уникальные маркеры) или неименованными (вопросительные знаки). Для замены маркеров на реальные значения нужно вызвать методы CDbCommand::bindParam() или CDbCommand::bindValue(). Экранировать или заключать в кавычки значения параметров не нужно, используемый драйвер базы данных всё сделает сам. Привязку параметров необходимо осуществить до выполнения SQL-запроса.
Методы bindParam() и bindValue() очень похожи. Единственное различие состоит в том, что первый привязывает параметр к ссылке на переменную PHP, а второй — к значению. Для параметров, представляющих большой объем данных, с точки зрения производительности предпочтительнее использовать метод bindParam().
Подробнее о привязке параметров можно узнать в соответствующей документации PHP.
Привязка полей
При получении результатов запроса мы также можем привязать поля таблицы к переменным PHP. Это позволяет автоматически присваивать значения переменным при чтении очередной строки:
Использование префиксов таблиц
Yii предоставляет встроенную поддержку префиксов таблиц.
Префикс таблиц — это строка, предваряющая имена таблиц в текущей подключённой БД.
В основном, префиксы используются на виртуальном (shared) хостинге, где к одной БД
подключаются несколько приложений, использующих различные префиксы таблиц в целях избежания конфликтов имён.
Например, одно приложение использует префикс tbl_
, а другое — yii_
.
Для использования префикса таблиц установите свойство CDbConnection::tablePrefix.
Затем в SQL-выражениях используйте {{TableName}}
для указания имён таблиц, где TableName
— имя
таблицы без префикса. Например, если БД содержит таблицу tbl_user
, где tbl_
— это префикс таблиц,
то мы можем использовать следующий код для получения списка пользователей: