Когда вы производите запрос через класс таблицы, используя методы
find()
или fetchAll()
, результат
возвращается в объекте типа
Zend_Db_Table_Rowset_Abstract
. Rowset (набор
строк) содержит коллекцию объектов, наследующих от
Zend_Db_Table_Row_Abstract
. Вы можете
производить итерацию по набору строк и работать с отдельными
объектами строк, считывая или изменяя данные в строках.
Zend_Db_Table_Abstract
предоставляет методы
find()
и fetchAll()
, оба они возвращают
объект типа Zend_Db_Table_Rowset_Abstract
.
Обычно набор строк сам по себе представляет меньший интерес, чем строки, содержащиеся в нем. Этот раздел показывает, как получать строки из набора строк.
Правильно составленный запрос возвращает нулевое количество строк,
если в БД нет строк, соответствующих условиям запроса. Поэтому
объект набора строк может содержать нулевое количество объектов
строк. Поскольку Zend_Db_Table_Rowset_Abstract
реализует инерфейс Countable
, то вы можете использовать
count()
для определения количества строк в наборе
строк.
Пример 9.83. Подсчет количества строк в наборе строк
<?php $rowset = $bugs->fetchAll("bug_status = 'FIXED'"); $rowCount = count($rowset); if ($rowCount > 0) { echo "found $rowCount rows"; } else { echo 'no rows matched the query'; } ?>
Пример 9.84. Чтение одной строки из набора строк
Наиболее простой способ получения доступа к строке из набора
состоит в использовании метода current()
. Этот
способ особенно подходит для тех случаев, когда набор строк
содержит только одну строку.
<?php $bugs = new Bugs(); $rowset = $bugs->fetchAll("bug_id = 1"); $row = $rowset->current(); ?>
Если набор строк содержит нулевое количество строк, то
current()
вернет значение null
.
Пример 9.85. >Итерация по набору строк
Объекты, наследующие от
Zend_Db_Table_Rowset_Abstract
, реализуют интерфейс
Iterator
. Это значит, что можно производить
циклический обход объектов, используя конструкцию
foreach()
. Каждое значение, получаемое таким
образом, является объектом
Zend_Db_Table_Row_Abstract
, который соответствует
одной записи в таблице.
<?php $bugs = new Bugs(); // извлечение всех записей из таблицы $rowset = $bugs->fetchAll(); foreach ($rowset as $row) { // выводит 'Zend_Db_Table_Row' или подобное echo get_class($row) . "\n"; // чтение столбца в строке $status = $row->bug_status; // изменение столбца в текущей строке $row->assigned_to = 'mmouse'; // сохранение изменений в БД $row->save(); } ?>
После того, как получен отдельный объект строки, вы можете работать с ним, используя методы, описанные в Раздел 9.6, «Zend_Db_Table_Row»
Вы можете работать во всеми данными в наборе строк как с массивом,
используя метод toArray()
объекта набора строк. Он
возвращает массив, содержащий по одной записи на строку. Каждая
запись является ассоциативным массивом, в котором ключи
соответствуют именам столбцов, а элементы - значениям этих столбцов.
Пример 9.86. Использование toArray()
<?php $bugs = new Bugs(); $rowset = $bugs->fetchAll(); $rowsetArray = $rowset->toArray(); $rowCount = 1; foreach ($rowsetArray as $rowArray) { echo "row #$rowCount:\n"; foreach ($rowArray as $column => $value) { echo "\t$column => $value\n"; } ++$rowCount; echo "\n"; } ?>
Массив, возвращаемый методом toArray()
не может
использоваться для обновления данных в БД. Вы можете изменять
значения в этом массиве так же, как и в любом другом массиве, но
эти изменения не передаются БД.
Объекты типа Zend_Db_Table_Rowset_Abstract доступны для сериализации. Сериализация производится так же, как и для отдельных объектов строк - вы можете сериализовать объект набора строк и восстановить его позднее.
Пример 9.87. Сериализация набора строк
Используйте обычную функцию PHP serialize()
для
получения строки, содержащей представление объекта набора строк
в виде последовательности байт.
<?php $bugs = new Bugs(); $rowset = $bugs->fetchAll(); // Convert object to serialized form // Преобразование объекта в сериализованную форму $serializedRowset = serialize($rowset); // Now you can write $serializedRowset to a file, etc. ?>
Пример 9.88. Десериализация набора строк
Используйте функцию unserialize()
для
восстановления из строки, содержащей представление объекта в
виде последовательности байт. Эта функция возвращает исходный
объект.
Внимание: объект набора строк возвращается без соединения с БД. Вы можете производить циклический обход набора строк, читать объекты строк и их свойства, но не изменять значения в строках или выполнять другие методы, требующие соединения с БД (например, запросы к связанным таблицам).
<?php $rowsetDisconnected = unserialize($serializedRowset); // Теперь вы можете использовать свойства и методы объекта, но только для чтения $row = $rowsetDisconnected->current(); echo $row->bug_description; ?>
Почему объекты наборов строк десериализируются без соединения с БД? | |
---|---|
Сериализованный объект является строкой, которая доступна для чтения всем, кто ею обладает. Это создает угрозу безопасности, которая состоит в том, что в сериализованной строке сохраняются такие параметры, как логин и пароль для соединения с БД, в незашифрованном виде. Для вас может быть нежелательным сохранять такие данные в незащищенном текстовом файле, отправлять его через e-mail или любой другой носитель, который может быть прочитан потенциальным атакующим. Тот, кто прочитает сериализованный объект, не должен иметь возможности использовать его для получения несанкционированного доступа к БД. |
Вы можете восстановить соединение для набора строк, используя
метод setTable()
. Аргументом этого метода является
объект типа Zend_Db_Table_Abstract
, который создается
вами. Создание объекта таблицы требует действующего соединения с БД,
поэтому при переустановке таблицы объект набора строк получает
доступ к БД. После этого вы сможете изменять значения объектов
строк, содержащихся в объекте набора строк и сохранять изменения
в БД.
Пример 9.89. Пример восстановления соединения для набора строк
<?php $rowset = unserialize($serializedRowset); $bugs = new Bugs(); // Переустановка таблицы для набора строк, // заодно восстанавливается соединение с БД $rowset->setTable($bugs); $row = $rowset->current(); // Теперь можно производить изменения в строке и сохранять их $row->bug_status = 'FIXED'; $row->save(); ?>
Восстановление соединения для набора строк через метод
setTable()
делает то же самое для всех объектов
строк, содержащихся в этом наборе строк.
Это действует только для одного объекта набора строк, но не для других наборов строк или объектов строк, содержащихся в них, даже если эти объекты связаны с одними и теми же строками в БД.
Вы можете использовать альтернативный класс для наборов
строк путем расширения класса Zend_Db_Table_Rowset_Abstract.
Указывайте новый класс набора строк через имя в защищенном члене
$_rowsetClass
класса таблицы или в массиве,
передаваемом в качестве аргуемента конструктору объекта таблицы.
Пример 9.90. Указание своего класса набора строк в качестве используемого
<?php class MyRowset extends Zend_Db_Table_Rowset_Abstract { // ... } // Укажите свой класс набора строк в качестве используемого по умолчанию // во всех экземплярах класса таблицы class Products extends Zend_Db_Table_Abstract { protected $_name = 'products'; protected $_rowsetClass = 'MyRowset'; } // Или укажите свой класс набора строк для использования // в конкретном экземпляре класса таблицы $bugs = new Bugs(array('rowsetClass' => 'MyRowset')); ?>
Стандартный класс Zend_Db_Rowset подходит для большинства случаев использования. Тем не менее, может потребоваться добавить свою логику в набор строк, специфический для данной таблицы. Например, новый метод может вычислять агрегированное значение для всех строк в наборе.
Пример 9.91. Пример класса набора строк с новым методом
<?php class MyBugsRowset extends Zend_Db_Table_Rowset_Abstract { /** * Находит в текущем наборе строку с наибольшим * значением в столбце 'updated_at' */ public function getLatestUpdatedRow() { $max_updated_at = 0; $latestRow = null; foreach ($this as $row) { if ($row->updated_at > $max_updated_at) { $latestRow = $row; } } return $latestRow; } } class Bugs extends Zend_Db_Table_Abstract { protected $_name = 'bugs'; protected $_rowsetClass = 'MyBugsRowset'; } ?>