| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- <sect1 id="zend.db.table.rowset">
- <title>Zend_Db_Table_Rowset</title>
- <sect2 id="zend.db.table.rowset.introduction">
- <title>Введение</title>
- <para>
- Когда вы производите запрос через класс таблицы, используя методы
- <code>find()</code> или <code>fetchAll()</code>, результат
- возвращается в объекте типа
- <code>Zend_Db_Table_Rowset_Abstract</code>. Набор
- строк (rowset) содержит коллекцию объектов, наследующих от
- <code>Zend_Db_Table_Row_Abstract</code>. Вы можете
- производить итерацию по набору строк и работать с отдельными
- объектами строк, считывая или изменяя данные в строках.
- </para>
- </sect2>
- <sect2 id="zend.db.table.rowset.fetch">
- <title>Получение набора строк</title>
- <para>
- <code>Zend_Db_Table_Abstract</code> предоставляет методы
- <code>find()</code> и <code>fetchAll()</code>, оба они возвращают
- объект типа <code>Zend_Db_Table_Rowset_Abstract</code>.
- </para>
- <example id="zend.db.table.rowset.fetch.example">
- <title>Пример извлечения набора строк</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $rowset = $bugs->fetchAll("bug_status = 'NEW'");
- ]]>
- </programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.table.rowset.rows">
- <title>Получение строк из набора</title>
- <para>
- Обычно сам по себе набор строк представляет меньший интерес, чем
- строки, содержащиеся в нем. Этот раздел показывает, как получать
- строки из набора строк.
- </para>
- <para>
- Правильно составленный запрос возвращает нулевое количество строк,
- если в БД нет строк, соответствующих условиям запроса. Поэтому
- объект набора строк может содержать нулевое количество объектов
- строк. Поскольку <code>Zend_Db_Table_Rowset_Abstract</code>
- реализует инерфейс <code>Countable</code>, то вы можете использовать
- <code>count()</code> для определения количества строк в наборе
- строк.
- </para>
- <example id="zend.db.table.rowset.rows.example.counting">
- <title>Подсчет количества строк в наборе строк</title>
- <programlisting language="php"><![CDATA[
- $rowset = $bugs->fetchAll("bug_status = 'FIXED'");
- $rowCount = count($rowset);
- if ($rowCount > 0) {
- echo "found $rowCount rows";
- } else {
- echo 'no rows matched the query';
- }
- ]]>
- </programlisting>
- </example>
- <example id="zend.db.table.rowset.rows.example.current">
- <title>Чтение одной строки из набора строк</title>
- <para>
- Наиболее простой способ получения доступа к строке из набора
- состоит в использовании метода <code>current()</code>. Этот
- способ особенно подходит для тех случаев, когда набор строк
- содержит только одну строку.
- </para>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $rowset = $bugs->fetchAll("bug_id = 1");
- $row = $rowset->current();
- ]]>
- </programlisting>
- </example>
- <para>
- Если набор строк содержит нулевое количество строк, то
- <code>current()</code> вернет значение <constant>NULL</constant>.
- </para>
- <example id="zend.db.table.rowset.iterate.example">
- <title>>Итерация по набору строк</title>
- <para>
- Объекты, наследующие от
- <code>Zend_Db_Table_Rowset_Abstract</code>, реализуют интерфейс
- <code>Iterator</code>. Это значит, что можно производить
- циклический обход объектов, используя конструкцию
- <code>foreach()</code>. Каждое значение, получаемое таким
- образом, является объектом типа
- <code>Zend_Db_Table_Row_Abstract</code>, который соответствует
- одной записи в таблице.
- </para>
- <programlisting language="php"><![CDATA[
- $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();
- }
- ]]>
- </programlisting>
- </example>
- <para>
- <code>getRow()</code> позволяет извлекать строку из
- набора строк, используя номер ее позиции, при этом не забывайте,
- что отсчет позиции начинается с нуля. Первый параметр метода
- <code>getRow()</code> должен быть целочисленным и используется
- для передачи позиции строки. Второй
- необязательный параметр должен иметь булев тип, при передаче
- значения true итератор перемещается в данную позицию
- (по умолчанию используется значение false). По умолчанию
- этот метод возвращает объект Zend_Db_Table_Row. Если запрошенная
- позиция не существует, то бросается исключение. Ниже приведен
- пример:
- </para>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- // извлечение всех строк из таблицы
- $rowset = $bugs->fetchAll();
- // извлечение девятой строки:
- $row9->getRow(8);
- // и ее применение:
- $row9->assigned_to = 'mmouse';
- $row9->save();
- ]]>
- </programlisting>
- <para>
- После того, как получен отдельный объект строки, вы можете
- работать с ним, используя методы, описанные в
- <xref linkend="zend.db.table.row" />
- </para>
- </sect2>
- <sect2 id="zend.db.table.rowset.to-array">
- <title>Получение набора строк в виде массива</title>
- <para>
- Вы можете работать с данными в наборе строк как с массивом,
- используя метод <code>toArray()</code> объекта набора строк. Он
- возвращает массив, содержащий по одной записи на строку. Каждая
- запись является ассоциативным массивом, в котором ключи
- соответствуют именам столбцов, а элементы - значениям этих столбцов.
- </para>
- <example id="zend.db.table.rowset.to-array.example">
- <title>Использование toArray()</title>
- <programlisting language="php"><![CDATA[
- $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";
- }
- ]]>
- </programlisting>
- </example>
- <para>
- Массив, возвращаемый методом <code>toArray()</code> не может
- использоваться для обновления данных в БД. Вы можете изменять
- значения в этом массиве так же, как и в любом другом массиве, но
- эти изменения не сохраняются в БД.
- </para>
- </sect2>
- <sect2 id="zend.db.table.rowset.serialize">
- <title>Сериализация и десериализация наборов строк</title>
- <para>
- Объекты типа <code>Zend_Db_Table_Rowset_Abstract</code> доступны для
- сериализации. Сериализация производится так же, как и для отдельных
- объектов строк - вы можете сериализовать объект набора строк и
- восстановить его позднее.
- </para>
- <example id="zend.db.table.rowset.serialize.example.serialize">
- <title>Сериализация набора строк</title>
- <para>
- Используйте PHP-функцию <code>serialize()</code> для
- получения строки, содержащей представление объекта набора строк
- в виде последовательности байт.
- </para>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $rowset = $bugs->fetchAll();
- // Преобразование объекта в сериализованную форму
- $serializedRowset = serialize($rowset);
- // Теперь вы можете записать $serializedRowset в файл и т.п.
- ]]>
- </programlisting>
- </example>
- <example id="zend.db.table.rowset.serialize.example.unserialize">
- <title>Десериализация набора строк</title>
- <para>
- Используйте функцию <code>unserialize()</code> для
- восстановления из строки, содержащей представление объекта в
- виде последовательности байт. Эта функция возвращает исходный
- объект.
- </para>
- <para>
- Внимание: объект набора строк возвращается <emphasis>без
- соединения с БД</emphasis>. Вы можете производить циклический
- обход набора строк, читать объекты строк и их свойства, но не
- изменять значения в строках или выполнять другие методы,
- требующие соединения с БД (например, запросы к связанным
- таблицам).
- </para>
- <programlisting language="php"><![CDATA[
- $rowsetDisconnected = unserialize($serializedRowset);
- // Теперь вы можете использовать свойства и методы объекта, но только для чтения
- $row = $rowsetDisconnected->current();
- echo $row->bug_description;
- ]]>
- </programlisting>
- </example>
- <note>
- <title>Почему объекты наборов строк десериализируются без соединения с БД?</title>
- <para>
- Сериализованный объект является строкой, которая доступна
- для чтения всем, кто ею обладает.
- Это создает угрозу безопасности, которая состоит в
- том, что в сериализованной строке сохраняются такие
- параметры, как логин и пароль для соединения с БД, в
- незашифрованном виде.
- Для вас может быть нежелательным сохранять такие данные в
- незащищенном текстовом файле, отправлять его через e-mail
- или любой другой носитель, который может быть прочитан
- потенциальным атакующим.
- Тот, кто прочитает сериализованный объект, не должен иметь
- возможности использовать его для получения
- несанкционированного доступа к БД.
- </para>
- </note>
- <para>
- Вы можете восстановить соединение для набора строк, используя
- метод <code>setTable()</code>. Аргументом этого метода является
- объект типа <code>Zend_Db_Table_Abstract</code>, который создается
- вами. Создание объекта таблицы требует действующего соединения с БД,
- поэтому при переустановке таблицы объект набора строк получает
- доступ к БД. После этого вы сможете изменять значения объектов
- строк, содержащихся в объекте набора строк и сохранять изменения
- в БД.
- </para>
- <example id="zend.db.table.rowset.serialize.example.set-table">
- <title>Пример восстановления соединения для набора строк</title>
- <programlisting language="php"><![CDATA[
- $rowset = unserialize($serializedRowset);
- $bugs = new Bugs();
- // Переустановка таблицы для набора строк,
- // заодно восстанавливается соединение с БД
- $rowset->setTable($bugs);
- $row = $rowset->current();
- // Теперь можно производить изменения в строке и сохранять их
- $row->bug_status = 'FIXED';
- $row->save();
- ]]>
- </programlisting>
- </example>
- <para>
- Восстановление соединения для набора строк через метод
- <code>setTable()</code> делает то же самое для всех объектов
- строк, содержащихся в этом наборе строк.
- </para>
- </sect2>
- <sect2 id="zend.db.table.rowset.extending">
- <title>Расширение класса набора строк</title>
- <para>
- Вы можете использовать альтернативный класс для наборов
- строк путем расширения класса Zend_Db_Table_Rowset_Abstract.
- Указывайте новый класс набора строк через имя в защищенном свойстве
- <varname>$_rowsetClass</varname> класса таблицы или в массиве,
- передаваемом в качестве аргумента конструктору объекта таблицы.
- </para>
- <example id="zend.db.table.rowset.extending.example">
- <title>Указание своего класса набора строк</title>
- <programlisting language="php"><![CDATA[
- class MyRowset extends Zend_Db_Table_Rowset_Abstract
- {
- // ...кастомизация
- }
- // Укажите свой класс набора строк в качестве используемого по умолчанию
- // во всех экземплярах класса таблицы
- class Products extends Zend_Db_Table_Abstract
- {
- protected $_name = 'products';
- protected $_rowsetClass = 'MyRowset';
- }
- // Или укажите свой класс набора строк для использования
- // в конкретном экземпляре класса таблицы
- ]]>
- </programlisting>
- </example>
- <para>
- Стандартный класс Zend_Db_Rowset подходит для большинства случаев
- использования. Тем не менее, может потребоваться добавить свою
- логику в набор строк, специфический для данной таблицы.
- Например, новый метод может вычислять агрегированное значение для
- всех строк в наборе.
- </para>
- <example id="zend.db.table.rowset.extending.example-aggregate">
- <title>Пример класса набора строк с новым методом</title>
- <programlisting language="php"><![CDATA[
- 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';
- }
- ]]>
- </programlisting>
- </example>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|