Zend_Db_Table_Row является классом, содержащим отдельную строку объекта Zend_Db_Table. Когда вы производите запрос через класс таблицы, результат возвращается в виде набора объектов Zend_Db_Table_Row. Вы можете также использовать этот объект для создания новых строк и их добавления в таблицу БД.
Zend_Db_Table_Row является реализацией паттерна Row Data Gateway.
Zend_Db_Table_Abstract предоставляет методы find()
и
fetchAll()
, которые возвращают объект типа
Zend_Db_Table_Rowset, и метод fetchRow()
, который
возвращает объект типа Zend_Db_Table_Row.
Пример 10.102. Пример извлечения строки
<?php $bugs = new Bugs(); $row = $bugs->fetchRow('bug_id = 1');
Объект Zend_Db_Table_Rowset содержит коллекцию объектов Zend_Db_Table_Row. См. Раздел 10.7, «Zend_Db_Table_Rowset».
Пример 10.103. Пример получения строки из набора строк
<?php $bugs = new Bugs(); $rowset = $bugs->fetchAll("bug_status = 'NEW'"); $row = $rowset->current();
Замечание | |
---|---|
Значения и идентификаторы в SQL-выражении не заключаются в
кавычки автоматически. Если имеются значения или идентификаторы,
которые требуют заключения в кавычки, то вы должны произвести
его сами. Используйте методы |
Zend_Db_Table_Row_Abstract предоставляет методы-аксессоры, таким образом, можно ссылаться на столбцы в строке как на свойства объекта.
Пример 10.104. Пример чтения столбца в строке
<?php $bugs = new Bugs(); $row = $bugs->fetchRow('bug_id = 1'); // Вывод значения столбца bug_description echo $row->bug_description;
Замечание | |
---|---|
Более ранние версии Zend_Db_Table_Row сопоставляли аксессоры столбцов и имена столбцов в БД с использованием преобразования строк, называемым инфлекцией. Zend_Db_Table_Row в его текущей реализации не использует инфлекцию. Написание аксессоров столбцов должно в точности соответствовать именам столбцов, так, как они представлены в БД. |
Вы можете получить доступ к данным строки, используя метод
toArray()
объекта строки. Метод возвращает
ассоциативный массив имен столбцов и их значений.
Пример 10.105. Пример использования метода toArray()
<?php $bugs = new Bugs(); $row = $bugs->fetchRow('bug_id = 1'); // Получение ассоциативного массива столбцов и их значений из объекта Row $rowArray = $row->toArray(); // Теперь используется как обычный массив foreach ($rowArray as $column => $value) { echo "Column: $column\n"; echo "Value: $value\n"; }
Массив, возвращаемый методом toArray()
не может
использоваться для обновления данных в БД. Мы можете изменять
значения в этом массиве так же, как и в любом другом массиве, но
не можете сохранять измененные значения непосредственно из этого
массива в БД.
Класс Zend_Db_Table_Row_Abstract предоставляет методы для извлечения строк и наборов строк из связанных таблиц. Cм. Раздел 10.8, «Связи между таблицами Zend_Db_Table» для более подробной информации о связях между таблицами.
Используя аксессоры столбцов, вы можете устанавливать значения отдельных столбцов по аналогии с чтением, т.е. так же, как если бы они были свойствами объекта.
Использование аксессоров столбцов для установки значений
изменяет значения столбцов в данном объекте строки, но
эти изменения еще не фиксируются в БД. Вы можете произвести
фиксацию через метод save()
.
Пример 10.106. Пример изменения значения столбца в строке
<?php $bugs = new Bugs(); $row = $bugs->fetchRow('bug_id = 1'); // Изменение значения одного или более столбцов $row->bug_status = 'FIXED'; // Обновление строки в БД с новыми значениями $row->save();
Вы можете создавать новые строки для определенной таблицы с
помощью метода createRow()
класса таблицы. Можно
работать с полями этой строки через объектно-ориентированный
интерфейс, но строка не сохраняется в БД до тех пор, пока вы не
вызовете метод save()
.
Пример 10.107. Пример создания новой строки таблицы
<?php $bugs = new Bugs(); $newRow = $bugs->createRow(); // Установка значений столбцов $newRow->bug_description = '...description...'; $newRow->bug_status = 'NEW'; // Вставка новой строки в БД $newRow->save();
Опциональный аргумент метода является ассоциативным массивом, через который вы можете заполнить поля новой строки.
Пример 10.108. Пример заполнения новой строки для таблицы
<?php $data = array( 'bug_description' => '...description...', 'bug_status' => 'NEW' ); $bugs = new Bugs(); $newRow = $bugs->createRow($data); // вставка новой строки в БД $newRow->save();
Замечание | |
---|---|
В более ранних релизах Zend_Db_Table метод
|
Zend_Db_Table_Row_Abstract предоставляет метод
setFromArray()
для того, чтобы можно было
устанавливать значения нескольких столбцов одновременно,
определив ассоциативный массив имен столбцов и их значений.
Этот метод может быть удобным как при создании новых строк, так
и при обновлении существующих.
Пример 10.109. Пример использования метода setFromArray() для установки значений в новой строке
<?php $bugs = new Bugs(); $newRow = $bugs->createRow(); // Данные помещаются в ассоциативный массив $data = array( 'bug_description' => '...description...', 'bug_status' => 'NEW' ); // Одновременная установка значений всех столбцов $newRow->setFromArray($data); // Добавление новой строки в БД $newRow->save();
Вы можете использовать метод delete()
объекта
строки. Этот метод удаляет из таблицы строки, соответствующие
первичному ключу в объекте строки.
Пример 10.110. Пример удаления строки
<?php $bugs = new Bugs(); $row = $bugs->fetchRow('bug_id = 1'); // Удаление строки $row->delete();
Вы не должны вызывать save()
для фиксации удаления,
оно сразу же выполняется в БД.
Часто бывает удобным сохранять содержимое строки БД для последующего использования. Сериализацией называется действие по преобразованию объекта в форму, удобную для хранения в автономном хранилище (например, в файле). Объекты типа Zend_Db_Table_Row_Abstract доступны для сериализации.
Просто используйте функцию PHP serialize()
для
получения строки, содержащей представление объекта Row в виде
последовательности байт.
Пример 10.111. Пример сериализации объекта строки
<?php $bugs = new Bugs(); $row = $bugs->fetchRow('bug_id = 1'); // Преобразование объекта в сериализованную форму $serializedRow = serialize($row); // Теперь вы можете записать $serializedRow в файл и т.д.
Используйте функцию unserialize()
для
восстановления из строки, содержащей представление объекта в
виде последовательности байт. Эта функция возвращает исходный объект.
Внимание: объект строки возвращается без соединения. Вы можете читать объект Row и его свойства, но не можете изменять значения в строке или выполнять другие методы, требующие соединения с БД (например, запросы к связанным таблицам).
Пример 10.112. Пример десериализации объекта строки
<?php $rowClone = unserialize($serializedRow); // Теперь вы можете использовать свойства объекта, но только для чтения echo $rowClone->bug_description;
Почему объекты строки десериализуются в состояние без соединения? | |
---|---|
Сериализованный объект является строкой, которая доступна для чтения всем, кто ею обладает. Это создает угрозу безопасности, которая состоит в том, что в сериализованной строке сохраняются такие параметры, как логин и пароль для соединения с БД, в незашифрованном виде. Для вас может быть нежелательным сохранять такие данные в незащищенном текстовом файле, отправлять его через e-mail или любой другой носитель, который может быть прочитан потенциальным атакующим. Тот, кто прочитает сериализованный объект, не должен иметь возможности использовать его в получении несанкционированного доступа к БД. |
Вы можете восстановить соединение для строки, используя метод
setTable()
. Аргументом этого метода является объект
типа Zend_Db_Table_Abstract, который создается вами. Создание
объекта таблицы требует действующего соединения с БД, поэтому
при переустановке таблицы объект строки получает доступ к БД.
После этого можно изменять значения в объекте строки и
сохранять изменения в БД.
Пример 10.113. Пример восстановления соединения для строки
<?php $rowClone = unserialize($serializedRow); $bugs = new Bugs(); // Привязка строки к таблице с действующим соединением БД $rowClone->setTable($bugs); // Теперь вы можете производить изменения в строке и сохранять их $rowClone->bug_status = 'FIXED'; $rowClone->save();
Zend_Db_Table_Row является используемым по умолчанию классом,
наследующим от Zend_Db_Table_Row_Abstract. Вы можете определить свой
собственный класс для экземпляров строк путем наследования от
Zend_Db_Table_Row_Abstract. Для того, чтобы этот класс использовался
для хранения результатов запросов к таблице, укажите его имя в
защищенном свойстве $_rowClass
класса таблицы или в
массиве, передаваемом в качестве аргумента конструктору объекта
таблицы.
Пример 10.114. Указание своего класса строки
<?php class MyRow extends Zend_Db_Table_Row_Abstract { // ...кастомизация } // Укажите свой класс строки в качестве используемого по умолчанию // во всех экземплярах класса таблицы class Products extends Zend_Db_Table_Abstract { protected $_name = 'products'; protected $_rowClass = 'MyRow'; } // Или укажите свой класс строки для использования // в конкретном экземпляре класса таблицы $bugs = new Bugs(array('rowClass' => 'MyRow'));
Класс строки вызывает защищенные методы _insert()
,
_update()
и _delete()
до выполнения
соответствующих операций INSERT
,
UPDATE
и DELETE
. Вы можете добавлять
собственную логику в эти методы в созданном вами подклассе
строки.
Если нужно выполнение собственной логики в определенной
таблице, и эта логика должна выполняться для каждой операции в
этой таблице, то разумным решением может быть реализация
собственной логики в методах insert()
,
update()
и delete()
вашего класса
таблицы. Тем не менее, иногда может быть необходимым выполнять
собственную логику в классе строки.
Ниже приведены примеры некоторых случаев, в которых имеет смысл реализовать свою логику в классе строки вместо класса таблицы:
Пример 10.115. Пример собственной логики в классе строки
Собственная логика может применяться не во всех случаях операций над определенной таблицей. Вы можете реализовать свою логику в классе строки и создавать экземпляр класса таблицы с указанием этого класса строки в качестве используемого. Иначе в таблице используется класс строки по умолчанию.
Вам нужно, чтобы операции над данными в этой таблице журналировались через объект Zend_Log, но только если в конфигурации приложения включено это поведение.
<?php class MyLoggingRow extends Zend_Db_Table_Row_Abstract { protected function _insert() { $log = Zend_Registry::get('database_log'); $log->info(Zend_Debug::dump($this->_data, "INSERT: $this->_tableClass", false)); } } // $loggingEnabled - свойство, используемое для примера и зависящее // от конфигурации вашего приложения if ($loggingEnabled) { $bugs = new Bugs(array('rowClass' => 'MyLoggingRow')); } else { $bugs = new Bugs(); }
Пример 10.116. Пример класса строки, журналирующего добавляемые данные для нескольких таблиц
Собственная логика может быть общей для нескольких таблиц. Вместо реализации одной и той же логики в каждом классе таблицы вы можете реализовать код этих действий в классе строки и использовать этот класс строки во всех ваших классах таблиц.
В этом примере журналирующий код одинаков для всех классов таблиц.
<?php class MyLoggingRow extends Zend_Db_Table_Row_Abstract { protected function _insert() { $log = Zend_Registry::get('database_log'); $log->info(Zend_Debug::dump($this->_data, "INSERT: $this->_tableClass", false)); } } class Bugs extends Zend_Db_Table_Abstract { protected $_name = 'bugs'; protected $_rowClass = 'MyLoggingRow'; } class Products extends Zend_Db_Table_Abstract { protected $_name = 'products'; protected $_rowClass = 'MyLoggingRow'; }
Некоторые разработчики предпочитают, чтобы имя класса таблицы соответствовало имени таблицы в СУРБД с применением преобразования, называемого инфлекцией.
Классы Zend_Db по умолчанию не производят инфлекцию. Причины такого решения приведены в Раздел 10.5.12.4, «Определение инфлекции в Zend_Db_Table».
Если вы предпочитаете использовать инфлекцию, то должны сами
реализовать преобразование, переопределив метод
_transformColumn()
в своем классе строки и
использовать этот класс при произведении запросов через ваш
класс таблицы.
Пример 10.117. Пример определения инфлекционного преобразования
Это позволяет использовать в аксессорах преобразованный
вариант имени столбца. Класс строки использует метод
_transformColumn()
для преобразования имени,
которое используется в качестве "родного" имени столбца в
таблице БД.
<?php class MyInflectedRow extends Zend_Db_Table_Row_Abstract { protected function _transformColumn($key) { $nativeKey = myCustomInflector($key); return $nativeKey; } } class Bugs extends Zend_Db_Table_Abstract { protected $_name = 'bugs'; protected $_rowClass = 'MyInflectedRow'; } $bugs = new Bugs(); $row = $bugs->createRow(); // Используются имена столбцов в формате CamelCase, преобразующая функция // изменяет их представление на "родное" $row->bugDescription = 'New description';
Реализация функций для произведения инфлекционного преобразования возлагается на разработчика. Zend Framework не предоставляет для этих целей готовых функций.