1 <sect1 id="zend.db.table.rowset">
3 <title>Zend_Db_Table_Rowset</title>
5 <sect2 id="zend.db.table.rowset.introduction">
7 <title>Введение</title>
10 Когда вы производите запрос через класс таблицы, используя методы
11 <code>find()</code> или <code>fetchAll()</code>, результат
12 возвращается в объекте типа
13 <code>Zend_Db_Table_Rowset_Abstract</code>. Набор
14 строк (rowset) содержит коллекцию объектов, наследующих от
15 <code>Zend_Db_Table_Row_Abstract</code>. Вы можете
16 производить итерацию по набору строк и работать с отдельными
17 объектами строк, считывая или изменяя данные в строках.
22 <sect2 id="zend.db.table.rowset.fetch">
24 <title>Получение набора строк</title>
27 <code>Zend_Db_Table_Abstract</code> предоставляет методы
28 <code>find()</code> и <code>fetchAll()</code>, оба они возвращают
29 объект типа <code>Zend_Db_Table_Rowset_Abstract</code>.
32 <example id="zend.db.table.rowset.fetch.example">
34 <title>Пример извлечения набора строк</title>
36 <programlisting language="php"><![CDATA[
38 $rowset = $bugs->fetchAll("bug_status = 'NEW'");
46 <sect2 id="zend.db.table.rowset.rows">
48 <title>Получение строк из набора</title>
51 Обычно сам по себе набор строк представляет меньший интерес, чем
52 строки, содержащиеся в нем. Этот раздел показывает, как получать
53 строки из набора строк.
57 Правильно составленный запрос возвращает нулевое количество строк,
58 если в БД нет строк, соответствующих условиям запроса. Поэтому
59 объект набора строк может содержать нулевое количество объектов
60 строк. Поскольку <code>Zend_Db_Table_Rowset_Abstract</code>
61 реализует инерфейс <code>Countable</code>, то вы можете использовать
62 <code>count()</code> для определения количества строк в наборе
66 <example id="zend.db.table.rowset.rows.example.counting">
68 <title>Подсчет количества строк в наборе строк</title>
70 <programlisting language="php"><![CDATA[
71 $rowset = $bugs->fetchAll("bug_status = 'FIXED'");
73 $rowCount = count($rowset);
76 echo "found $rowCount rows";
78 echo 'no rows matched the query';
85 <example id="zend.db.table.rowset.rows.example.current">
87 <title>Чтение одной строки из набора строк</title>
90 Наиболее простой способ получения доступа к строке из набора
91 состоит в использовании метода <code>current()</code>. Этот
92 способ особенно подходит для тех случаев, когда набор строк
93 содержит только одну строку.
96 <programlisting language="php"><![CDATA[
98 $rowset = $bugs->fetchAll("bug_id = 1");
99 $row = $rowset->current();
106 Если набор строк содержит нулевое количество строк, то
107 <code>current()</code> вернет значение <constant>NULL</constant>.
110 <example id="zend.db.table.rowset.iterate.example">
112 <title>>Итерация по набору строк</title>
115 Объекты, наследующие от
116 <code>Zend_Db_Table_Rowset_Abstract</code>, реализуют интерфейс
117 <code>Iterator</code>. Это значит, что можно производить
118 циклический обход объектов, используя конструкцию
119 <code>foreach()</code>. Каждое значение, получаемое таким
120 образом, является объектом типа
121 <code>Zend_Db_Table_Row_Abstract</code>, который соответствует
122 одной записи в таблице.
125 <programlisting language="php"><![CDATA[
128 // извлечение всех записей из таблицы
129 $rowset = $bugs->fetchAll();
131 foreach ($rowset as $row) {
133 // выводит 'Zend_Db_Table_Row' или подобное
134 echo get_class($row) . "\n";
136 // чтение столбца в строке
137 $status = $row->bug_status;
139 // изменение столбца в текущей строке
140 $row->assigned_to = 'mmouse';
142 // сохранение изменений в БД
151 <code>getRow()</code> позволяет извлекать строку из
152 набора строк, используя номер ее позиции, при этом не забывайте,
153 что отсчет позиции начинается с нуля. Первый параметр метода
154 <code>getRow()</code> должен быть целочисленным и используется
155 для передачи позиции строки. Второй
156 необязательный параметр должен иметь булев тип, при передаче
157 значения true итератор перемещается в данную позицию
158 (по умолчанию используется значение false). По умолчанию
159 этот метод возвращает объект Zend_Db_Table_Row. Если запрошенная
160 позиция не существует, то бросается исключение. Ниже приведен
164 <programlisting language="php"><![CDATA[
167 // извлечение всех строк из таблицы
168 $rowset = $bugs->fetchAll();
170 // извлечение девятой строки:
174 $row9->assigned_to = 'mmouse';
180 После того, как получен отдельный объект строки, вы можете
181 работать с ним, используя методы, описанные в
182 <xref linkend="zend.db.table.row" />
187 <sect2 id="zend.db.table.rowset.to-array">
189 <title>Получение набора строк в виде массива</title>
192 Вы можете работать с данными в наборе строк как с массивом,
193 используя метод <code>toArray()</code> объекта набора строк. Он
194 возвращает массив, содержащий по одной записи на строку. Каждая
195 запись является ассоциативным массивом, в котором ключи
196 соответствуют именам столбцов, а элементы - значениям этих столбцов.
199 <example id="zend.db.table.rowset.to-array.example">
201 <title>Использование toArray()</title>
203 <programlisting language="php"><![CDATA[
205 $rowset = $bugs->fetchAll();
207 $rowsetArray = $rowset->toArray();
210 foreach ($rowsetArray as $rowArray) {
211 echo "row #$rowCount:\n";
212 foreach ($rowArray as $column => $value) {
213 echo "\t$column => $value\n";
223 Массив, возвращаемый методом <code>toArray()</code> не может
224 использоваться для обновления данных в БД. Вы можете изменять
225 значения в этом массиве так же, как и в любом другом массиве, но
226 эти изменения не сохраняются в БД.
231 <sect2 id="zend.db.table.rowset.serialize">
233 <title>Сериализация и десериализация наборов строк</title>
236 Объекты типа <code>Zend_Db_Table_Rowset_Abstract</code> доступны для
237 сериализации. Сериализация производится так же, как и для отдельных
238 объектов строк - вы можете сериализовать объект набора строк и
239 восстановить его позднее.
242 <example id="zend.db.table.rowset.serialize.example.serialize">
244 <title>Сериализация набора строк</title>
247 Используйте PHP-функцию <code>serialize()</code> для
248 получения строки, содержащей представление объекта набора строк
249 в виде последовательности байт.
252 <programlisting language="php"><![CDATA[
254 $rowset = $bugs->fetchAll();
256 // Преобразование объекта в сериализованную форму
257 $serializedRowset = serialize($rowset);
259 // Теперь вы можете записать $serializedRowset в файл и т.п.
265 <example id="zend.db.table.rowset.serialize.example.unserialize">
267 <title>Десериализация набора строк</title>
270 Используйте функцию <code>unserialize()</code> для
271 восстановления из строки, содержащей представление объекта в
272 виде последовательности байт. Эта функция возвращает исходный
277 Внимание: объект набора строк возвращается <emphasis>без
278 соединения с БД</emphasis>. Вы можете производить циклический
279 обход набора строк, читать объекты строк и их свойства, но не
280 изменять значения в строках или выполнять другие методы,
281 требующие соединения с БД (например, запросы к связанным
285 <programlisting language="php"><![CDATA[
286 $rowsetDisconnected = unserialize($serializedRowset);
288 // Теперь вы можете использовать свойства и методы объекта, но только для чтения
289 $row = $rowsetDisconnected->current();
290 echo $row->bug_description;
297 <title>Почему объекты наборов строк десериализируются без соединения с БД?</title>
299 Сериализованный объект является строкой, которая доступна
300 для чтения всем, кто ею обладает.
301 Это создает угрозу безопасности, которая состоит в
302 том, что в сериализованной строке сохраняются такие
303 параметры, как логин и пароль для соединения с БД, в
304 незашифрованном виде.
305 Для вас может быть нежелательным сохранять такие данные в
306 незащищенном текстовом файле, отправлять его через e-mail
307 или любой другой носитель, который может быть прочитан
308 потенциальным атакующим.
309 Тот, кто прочитает сериализованный объект, не должен иметь
310 возможности использовать его для получения
311 несанкционированного доступа к БД.
316 Вы можете восстановить соединение для набора строк, используя
317 метод <code>setTable()</code>. Аргументом этого метода является
318 объект типа <code>Zend_Db_Table_Abstract</code>, который создается
319 вами. Создание объекта таблицы требует действующего соединения с БД,
320 поэтому при переустановке таблицы объект набора строк получает
321 доступ к БД. После этого вы сможете изменять значения объектов
322 строк, содержащихся в объекте набора строк и сохранять изменения
326 <example id="zend.db.table.rowset.serialize.example.set-table">
328 <title>Пример восстановления соединения для набора строк</title>
330 <programlisting language="php"><![CDATA[
331 $rowset = unserialize($serializedRowset);
335 // Переустановка таблицы для набора строк,
336 // заодно восстанавливается соединение с БД
337 $rowset->setTable($bugs);
339 $row = $rowset->current();
341 // Теперь можно производить изменения в строке и сохранять их
342 $row->bug_status = 'FIXED';
350 Восстановление соединения для набора строк через метод
351 <code>setTable()</code> делает то же самое для всех объектов
352 строк, содержащихся в этом наборе строк.
357 <sect2 id="zend.db.table.rowset.extending">
359 <title>Расширение класса набора строк</title>
362 Вы можете использовать альтернативный класс для наборов
363 строк путем расширения класса Zend_Db_Table_Rowset_Abstract.
364 Указывайте новый класс набора строк через имя в защищенном свойстве
365 <varname>$_rowsetClass</varname> класса таблицы или в массиве,
366 передаваемом в качестве аргумента конструктору объекта таблицы.
369 <example id="zend.db.table.rowset.extending.example">
371 <title>Указание своего класса набора строк</title>
373 <programlisting language="php"><![CDATA[
374 class MyRowset extends Zend_Db_Table_Rowset_Abstract
379 // Укажите свой класс набора строк в качестве используемого по умолчанию
380 // во всех экземплярах класса таблицы
381 class Products extends Zend_Db_Table_Abstract
383 protected $_name = 'products';
384 protected $_rowsetClass = 'MyRowset';
387 // Или укажите свой класс набора строк для использования
388 // в конкретном экземпляре класса таблицы
395 Стандартный класс Zend_Db_Rowset подходит для большинства случаев
396 использования. Тем не менее, может потребоваться добавить свою
397 логику в набор строк, специфический для данной таблицы.
398 Например, новый метод может вычислять агрегированное значение для
402 <example id="zend.db.table.rowset.extending.example-aggregate">
404 <title>Пример класса набора строк с новым методом</title>
406 <programlisting language="php"><![CDATA[
407 class MyBugsRowset extends Zend_Db_Table_Rowset_Abstract
410 * Находит в текущем наборе строку с наибольшим
411 * значением в столбце 'updated_at'
413 public function getLatestUpdatedRow()
417 foreach ($this as $row) {
418 if ($row->updated_at > $max_updated_at) {
426 class Bugs extends Zend_Db_Table_Abstract
428 protected $_name = 'bugs';
429 protected $_rowsetClass = 'MyBugsRowset';