Zend_Db_Table_Row Введение 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. Пример извлечения строки fetchRow($bugs->select()->where('bug_id = ?', 1)); ]]> Объект Zend_Db_Table_Rowset содержит коллекцию объектов Zend_Db_Table_Row. Для получения более подробной информации читайте . Пример получения строки из набора строк fetchAll($bugs->select()->where('bug_status = ?', 1)); $row = $rowset->current(); ]]> Чтение значений столбцов из строки Zend_Db_Table_Row_Abstract предоставляет методы-аксессоры, благодаря которым можно ссылаться на столбцы в строке как на свойства объекта. Пример чтения столбца из строки fetchRow($bugs->select()->where('bug_id = ?', 1)); // Вывод значения столбца bug_description echo $row->bug_description; ]]> Более ранние версии Zend_Db_Table_Row сопоставляли аксессоры столбцов и имена столбцов в БД с использованием преобразования строк, называемым инфлекцией. Zend_Db_Table_Row в его текущей реализации не использует инфлекцию. Написание аксессоров столбцов должно в точности соответствовать именам столбцов, так, как они представлены в БД. Получение данных строки в виде массива Вы можете получать данные строки, используя метод toArray() объекта строки. Метод возвращает ассоциативный массив имен столбцов и их значений. Пример использования метода toArray() fetchRow($bugs->select()->where('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 предоставляет методы для извлечения строк и наборов строк из связанных таблиц. Читайте для получения более подробной информации о связях между таблицами. Редактирование строк в БД Изменение значений столбцов в строке Используя аксессоры столбцов, вы можете устанавливать значения отдельных столбцов по аналогии с чтением, т.е. так же, как если бы они были свойствами объекта. Использование аксессоров столбцов для установки значений изменяет значения столбцов в данном объекте строки, но эти изменения еще не фиксируются в БД. Вы можете произвести фиксацию через метод save(). Пример изменения значения столбца в строке fetchRow($bugs->select()->where('bug_id = ?', 1)); // Изменение значения одного или более столбцов $row->bug_status = 'FIXED'; // Обновление строки в БД с новыми значениями $row->save(); ]]> Вставка новой строки Вы можете создавать новые строки для определенной таблицы с помощью метода createRow() класса таблицы. Можно работать с полями этой строки через объектно-ориентированный интерфейс, но строка не сохраняется в БД до тех пор, пока вы не вызовете метод save(). Пример создания новой строки таблицы createRow(); // Установка значений столбцов $newRow->bug_description = '...description...'; $newRow->bug_status = 'NEW'; // Вставка новой строки в БД $newRow->save(); ]]> Опциональный аргумент метода является ассоциативным массивом, через который вы можете заполнить поля новой строки. Пример заполнения новой строки для таблицы '...description...', 'bug_status' => 'NEW' ); $bugs = new Bugs(); $newRow = $bugs->createRow($data); // вставка новой строки в БД $newRow->save(); ]]> В более ранних релизах Zend_Db_Table метод createRow() назывался fetchNew(). Мы рекомендуем использовать новое имя метода, несмотря на то, что старое имя метода по-прежнему работает в целях обеспечения обратной совместимости. Изменение значений в нескольких столбцах Zend_Db_Table_Row_Abstract предоставляет метод setFromArray() для того, чтобы можно было устанавливать значения нескольких столбцов одновременно, определив ассоциативный массив имен столбцов и их значений. Этот метод может быть удобным как при создании новых строк, так и при обновлении существующих. Пример использования метода setFromArray() для установки значений в новой строке createRow(); // Данные помещаются в ассоциативный массив $data = array( 'bug_description' => '...description...', 'bug_status' => 'NEW' ); // Одновременная установка значений всех столбцов $newRow->setFromArray($data); // Добавление новой строки в БД $newRow->save(); ]]> Удаление строки Вы можете использовать метод delete() объекта строки. Этот метод удаляет из таблицы строки, соответствующие первичному ключу в объекте строки. Пример удаления строки fetchRow('bug_id = 1'); // Удаление строки $row->delete(); ]]> Не нужно вызывать метод save() для фиксации удаления, оно сразу выполняется в БД. Сериализация и десериализация строк Часто бывает удобным сохранять содержимое строки БД для последующего использования. Сериализацией называется действие по преобразованию объекта в форму, удобную для хранения в автономном хранилище (например, в файле). Объекты типа Zend_Db_Table_Row_Abstract доступны для сериализации. Сериализация объекта строки Просто используйте функцию PHP serialize() для получения строки, содержащей представление объекта Row в виде последовательности байт. Пример сериализации объекта строки fetchRow('bug_id = 1'); // Преобразование объекта в сериализованную форму $serializedRow = serialize($row); // Теперь вы можете записать $serializedRow в файл и т.д. ]]> Десериализация данных строки Используйте функцию unserialize() для восстановления из строки, содержащей представление объекта в виде последовательности байт. Эта функция возвращает исходный объект. Внимание: объект строки возвращается без соединения. Вы можете читать объект Row и его свойства, но не можете изменять значения в строке или выполнять другие методы, требующие соединения с БД (например, запросы к связанным таблицам). Пример десериализации объекта строки bug_description; ]]> Почему объекты строки десериализуются без соединения? Сериализованный объект является строкой, которая доступна для чтения всем, кто ею обладает. Это создает угрозу безопасности, которая состоит в том, что в сериализованной строке сохраняются такие параметры, как логин и пароль для соединения с БД, в незашифрованном виде. Для вас может быть нежелательным сохранять такие данные в незащищенном текстовом файле, отправлять его через e-mail или любой другой носитель, который может быть прочитан потенциальным атакующим. Тот, кто прочитает сериализованный объект, не должен иметь возможности использовать его в получении несанкционированного доступа к БД. Восстановление соединения для объекта строки Вы можете восстановить соединение для строки, используя метод setTable(). Аргументом этого метода является объект типа Zend_Db_Table_Abstract, который создается вами. Создание объекта таблицы требует действующего соединения с БД, поэтому при переустановке таблицы объект строки получает доступ к БД. После этого можно изменять значения в объекте строки и сохранять изменения в БД. Пример восстановления соединения для строки setTable($bugs); // Теперь вы можете производить изменения в строке и сохранять их $rowClone->bug_status = 'FIXED'; $rowClone->save(); ]]> Расширение класса строки Zend_Db_Table_Row является используемым по умолчанию классом, который наследует от Zend_Db_Table_Row_Abstract. Вы можете определить свой собственный класс для экземпляров строк путем наследования от Zend_Db_Table_Row_Abstract. Для того, чтобы этот класс использовался для хранения результатов запросов к таблице, укажите его имя в защищенном свойстве $_rowClass класса таблицы или в массиве, передаваемом в качестве аргумента конструктору объекта таблицы. Указание своего класса строки 'MyRow')); ]]> Инициализация строки Если при создании объекта строки требуется выполнять код, реализующий логику приложения, то вы можете поместить этот код в метод init(), который вызывается после того, как были обработаны все метаданные строки. Рекомендуется использовать этот способ вместо переопределения метода __construct, если только не требуется изменять метаданные программным путем. Пример использования метода init() _role = new MyRoleClass(); } } ]]> Определение собственной логики для добавления, обновления и удаления в Zend_Db_Table_Row Класс строки вызывает защищенные методы _insert(), _update() и _delete() до выполнения соответствующих операций INSERT, UPDATE и DELETE. Вы можете добавлять собственную логику в эти методы в созданном вами подклассе строки. Если нужно выполнение собственной логики в определенной таблице, и эта логика должна выполняться для каждой операции в этой таблице, то разумным решением может быть реализация собственной логики в методах insert(), update() и delete() вашего класса таблицы. Тем не менее, иногда может быть необходимым выполнять собственную логику в классе строки. Ниже приведены примеры случаев, в которых имеет смысл реализовать свою логику в классе строки вместо класса таблицы: Пример собственной логики в классе строки Собственная логика может применяться не во всех случаях операций над определенной таблицей. Вы можете реализовать свою логику в классе строки и создавать экземпляр класса таблицы с указанием этого класса строки в качестве используемого. Иначе в таблице используется класс строки по умолчанию. Вам нужно, чтобы операции над данными в этой таблице журналировались через объект Zend_Log, но только если в конфигурации приложения включено это поведение. info(Zend_Debug::dump($this->_data, "INSERT: $this->_tableClass", false) ); } } // $loggingEnabled - свойство, используемое для примера и зависящее // от конфигурации вашего приложения if ($loggingEnabled) { $bugs = new Bugs(array('rowClass' => 'MyLoggingRow')); } else { $bugs = new Bugs(); } ]]> Пример класса строки, журналирующего добавляемые данные для нескольких таблиц Собственная логика может быть общей для нескольких таблиц. Вместо реализации одной и той же логики в каждом классе таблицы вы можете реализовать код этих действий в классе строки и использовать этот класс строки во всех ваших классах таблиц. В этом примере журналирующий код одинаков для всех классов таблиц. 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_Table_Row Некоторые разработчики предпочитают, чтобы имя класса таблицы соответствовало имени таблицы в СУРБД с применением преобразования, называемого инфлекцией. Классы Zend_Db по умолчанию не производят инфлекцию. Читайте для получения информации о причинах такого решения. Если вы предпочитаете использовать инфлекцию, то должны сами реализовать преобразование, переопределив метод _transformColumn() в своем классе строки и использовать этот класс при произведении запросов через ваш класс таблицы. Пример определения инфлекционного преобразования Это позволяет использовать в аксессорах преобразованный вариант имени столбца. Класс строки использует метод _transformColumn() для преобразования имени, которое используется в качестве "родного" имени столбца в таблице БД. createRow(); // Используются имена столбцов в формате CamelCase, преобразующая функция // изменяет их представление на "родное" $row->bugDescription = 'New description'; ]]> Реализация функций для произведения инфлекционного преобразования возлагается на разработчика. Zend Framework не предоставляет для этих целей готовых функций.