1 <sect1 id="zend.db.table">
3 <title>Zend_Db_Table</title>
5 <sect2 id="zend.db.table.introduction">
7 <title>Класс таблицы - введение</title>
10 Класс Zend_Db_Table является объектно-ориентированным интерфейсом к
11 таблицам баз данных. Он предоставляет методы для многих общих
12 операций над таблицами. Базовый класс является расширяемым, поэтому
13 вы можете добавлять свою логику.
17 Решением Zend_Db_Table является реализация паттерна
18 <ulink url="http://www.martinfowler.com/eaaCatalog/tableDataGateway.html">Table Data Gateway</ulink>.
19 Это решение также включает в себя класс, реализующий паттерн
20 <ulink url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data Gateway</ulink>.
25 <sect2 id="zend.db.table.defining">
27 <title>Определение класса таблицы</title>
30 Для каждой таблицы в БД, к которой нужен доступ, определяется класс,
31 наследующий от Zend_Db_Table_Abstract.
34 <sect3 id="zend.db.table.defining.table-schema">
36 <title>Определение имени и схемы таблицы</title>
39 Указывайте таблицу, для которой определен этот класс, используя
40 защищенную переменную <varname>$_name</varname>. Переменная
41 должна содержать имя таблицы в том виде, в котором она
45 <example id="zend.db.table.defining.table-schema.example1">
47 <title>Объявление класса таблицы с явным определением имени таблицы</title>
49 <programlisting language="php"><![CDATA[
50 class Bugs extends Zend_Db_Table_Abstract
52 protected $_name = 'bugs';
60 Если вы не определили имя таблицы, то по умолчанию оно равно
61 имени класса. Если вы предпочитаете этот путь, то имя класса
62 должно иметь то же написание, что и имя таблицы в БД.
65 <example id="zend.db.table.defining.table-schema.example">
67 <title>Объявление класса таблицы с неявным определением имени таблицы</title>
69 <programlisting language="php"><![CDATA[
70 class bugs extends Zend_Db_Table_Abstract
72 // имя таблицы соответствует имени класса
80 Вы можете также объявить схему таблицы в защищенной переменной
81 <varname>$_schema</varname> или через добавленное
82 перед именем таблицы имя схемы в свойстве <varname>$_name</varname>.
83 Схема, указанная с помощью свойства <varname>$_name</varname>,
84 имеет более высокий приоритет, чем схема, объявленная с помощью
85 свойства <varname>$_schema</varname>. В некоторых СУРБД вместо
86 термина "схема" используются термины "база данных" или
87 "пространство таблиц", они используются аналогичным образом.
90 <example id="zend.db.table.defining.table-schema.example3">
92 <title>Объявление класса таблицы со схемой</title>
94 <programlisting language="php"><![CDATA[
96 class Bugs extends Zend_Db_Table_Abstract
98 protected $_schema = 'bug_db';
99 protected $_name = 'bugs';
103 class Bugs extends Zend_Db_Table_Abstract
105 protected $_name = 'bug_db.bugs';
108 // Если в обоих свойствах $_name м $_schema была объявлена схема,
109 // то указанная в $_name имеет больший приоритет:
110 class Bugs extends Zend_Db_Table_Abstract
112 protected $_name = 'bug_db.bugs';
113 protected $_schema = 'ignored';
121 Схема и таблица могут быть указаны через конфигурационные
122 директивы конструктора, которые замещают собой любые значения по
123 умолчанию, определенные с помощью свойств <varname>$_name</varname> и
124 <varname>$_schema</varname>. Спецификация схемы, данная через
125 директиву <code>name</code>, замещает собой любое значение,
126 переданное через опцию <code>schema</code>.
129 <example id="zend.db.table.defining.table-schema.example.constructor">
131 <title>Объявление имен таблицы и схемы во время инстанцирования</title>
133 <programlisting language="php"><![CDATA[
134 class Bugs extends Zend_Db_Table_Abstract
140 $tableBugs = new Bugs(array('name' => 'bugs', 'schema' => 'bug_db'));
144 $tableBugs = new Bugs(array('name' => 'bug_db.bugs');
146 // Если в обоих опциях 'name' и 'schema' была объявлена схема,
147 // то указанная в 'name' имеет больший приоритет:
149 $tableBugs = new Bugs(array('name' => 'bug_db.bugs',
150 'schema' => 'ignored');
157 Если вы не указали имя схемы, то по умолчанию это будет
158 схема, к которой подключен ваш экземпляр адаптера БД.
163 <sect3 id="zend.db.table.defining.primary-key">
165 <title>Определение первичного ключа таблицы</title>
168 Каждая таблица должна иметь первичный ключ. Вы можете объявить
169 столбец для первичного ключа, используя защищенную переменную
170 <varname>$_primary</varname>. Это может быть строка с именем одного
171 столбца или массив имен столбцов, если первичный ключ является
175 <example id="zend.db.table.defining.primary-key.example">
177 <title>Пример определения первичного ключа</title>
179 <programlisting language="php"><![CDATA[
180 class Bugs extends Zend_Db_Table_Abstract
182 protected $_name = 'bugs';
183 protected $_primary = 'bug_id';
191 Если вы не задали первичный ключ, то Zend_Db_Table_Abstract
192 пытается определить его, основываясь на данных, полученных
193 через метод <code>describeTable()</code>.
199 Класс таблицы должен знать, какой столбец (или столбцы)
200 используются для уникальной адресации строк. Если в
201 классе таблицы или аргументах конструктора (а также в
202 метаданных таблицы, полученных через метод
203 <code>describeTable()</code>) не были указаны
204 первичные ключи, то эта таблица не может использоваться
212 <sect3 id="zend.db.table.defining.setup">
214 <title>Переопределение методов установки таблицы</title>
217 Когда создается экземпляр класса таблицы, конструктор вызывает
218 ряд защищенных методов, инициализирующих метаданные для таблицы.
219 Вы можете переопределить любые из этих методов для того, чтобы
220 явно определить эти метаданные. Помните, что в конце должен
221 вызываться родительский метод.
224 <example id="zend.db.table.defining.setup.example">
226 <title>Пример переопределения метода _setupTableName()</title>
228 <programlisting language="php">
230 class Bugs extends Zend_Db_Table_Abstract
232 protected function _setupTableName()
234 $this->_name = 'bugs';
235 parent::_setupTableName();
244 Методы установки могут быть переопределены следующим образом:
250 <code>_setupDatabaseAdapter()</code> проверяет, был ли
251 предоставлен адаптер БД, и извлекает используемый по
252 умолчанию адаптер из реестра, если необходимо.
253 Переопределив этот метод, вы можете
254 установить адаптер БД из других источников.
259 <code>_setupTableName()</code> по умолчанию получает имя
260 таблицы из имени класса. Переопределив
261 этот метод, вы можете установить имя таблицы до того,
262 как будут произведены эти действия по умолчанию.
267 <code>_setupMetadata()</code> устанавливает схему, если
268 имя таблицы содержит структуру "schema.table", вызывает
269 <code>describeTable()</code> для получения метаданных,
270 по умолчанию определяет массив столбцов
271 <varname>$_cols</varname>, полученных
272 через <code>describeTable()</code>. Переопределелив этот
273 метод, вы можете устанавливать столбцы самостоятельно.
278 <code>_setupPrimaryKey()</code> по умолчанию
279 устанавливает столбцы первичного ключа, полученные через
280 <code>describeTable()</code>, и проверяет, входят ли
281 столбцы первичного ключа в массив <varname>$_cols</varname>.
282 Переопределив этот метод, вы можете устанавливать
283 столбцы первичного ключа.
290 <sect3 id="zend.db.table.initialization">
292 <title>Инициализация таблицы</title>
295 Если при создании объекта таблицы требуется выполнять код,
296 реализующий логику приложения, то вы можете поместить этот код в
297 метод <code>init()</code>, который вызвается после того, как
298 были обработаны все метаданные таблицы. Рекомендуется
299 использовать этот способ вместо переопределения метода
300 <code>__construct</code>, если только не требуется изменять
301 метаданные программным путем.
303 <example id="zend.db.table.defining.init.usage.example">
305 <title>Пример использования метода init()</title>
307 <programlisting language="php">
309 class Bugs extends Zend_Db_Table_Abstract
311 protected $_observer;
313 protected function init()
315 $this->_observer = new MyObserverClass();
329 <sect2 id="zend.db.table.constructing">
331 <title>Создание экземпляра класса таблицы</title>
334 До того, как начать использование класса таблицы, создайте его
335 экземпляр, используя конструктор. Единственным аргументом
336 конструктора является массив опций. Наиболее важной опцией для
337 конструктора является экземпляр адаптера БД, представляющий текущее
338 соединение к какой-либо СУРБД. Есть три способа передачи адаптера БД
339 классу таблицы, и эти три способа описаны ниже:
342 <sect3 id="zend.db.table.constructing.adapter">
344 <title>Установка адаптера БД</title>
347 Первым способом предоставления адаптера БД классу таблицы
348 является передача объекта типа Zend_Db_Adapter_Abstract в
349 массиве опций под ключом <code>'db'</code>.
352 <example id="zend.db.table.constructing.adapter.example">
354 <title>Пример создания экземпляра таблицы с использованием объекта адаптера</title>
356 <programlisting language="php">
358 $db = Zend_Db::factory('PDO_MYSQL', $options);
360 $table = new Bugs(array('db' => $db));
368 <sect3 id="zend.db.table.constructing.default-adapter">
370 <title>Установка используемого по умолчанию адаптера БД</title>
373 Вторым способом предоставления адаптера БД классу таблицы
374 является декларирование объекта типа Zend_Db_Adapter_Abstract
375 как используемого по умолчанию для всех экземпляров таблиц в
376 вашем приложении. Вы можете делать это через статический метод
377 <code>Zend_Db_Table_Abstract::setDefaultAdapter()</code>. Его
378 аргументом является объект типа Zend_Db_Adapter_Abstract.
381 <example id="zend.db.table.constructing.default-adapter.example">
383 <title>Пример создания экземпляра таблицы с адаптером, используемым по умолчанию</title>
385 <programlisting language="php">
387 $db = Zend_Db::factory('PDO_MYSQL', $options);
388 Zend_Db_Table_Abstract::setDefaultAdapter($db);
399 Может быть удобным создавать объект адаптера БД в центральной
400 части вашего приложения - например, в загрузочном коде - и затем
401 сохранять его как адаптер, используемый по умолчанию. Это дает
402 возможность быть уверенным в том, что во всем приложении
403 используется один и тот же экземпляр адаптера. Но установка
404 адаптера, используемого по умолчанию, ограничена одним
405 экземпляром адаптера.
411 <sect3 id="zend.db.table.constructing.registry">
413 <title>Хранение адаптера БД в реестре</title>
416 Третий способ передачи адаптера БД классу таблицы -
417 передача строки в массиве опций под ключом <code>'db'</code>.
418 Эта строка используется как ключ для статического экземпляра
419 Zend_Registry, в котором под этим ключом должен храниться объект
420 типа Zend_Db_Adapter_Abstract.
423 <example id="zend.db.table.constructing.registry.example">
425 <title>Пример создания экземпляра таблицы с использованием ключа реестра</title>
427 <programlisting language="php">
429 $db = Zend_Db::factory('PDO_MYSQL', $options);
430 Zend_Registry::set('my_db', $db);
434 $table = new Bugs(array('db' => 'my_db'));
441 Как и в случае установки адаптера, используемого по умолчанию,
442 это дает возможность быть уверенным в том, что во всем
443 приложении используется один и тот же адаптер, но использование
444 реестра является более гибким, т.к. вы можете хранить в
445 нем более одного экземпляра адаптера. Экземпляр адаптера
446 является индивидуальным для конкретной СУРБД и экземпляра БД.
447 Если в вашем приложении необходимо подключаться к нескольким БД
448 или даже различным СУРБД, то вам нужно использовать несколько
456 <sect2 id="zend.db.table.insert">
458 <title>Добавление строк в таблицу</title>
461 Вы можете использовать объект таблицы для добавления строк в таблицу
462 БД, на которой основан объект таблицы. Для этого используйте метод
463 <code>insert()</code> в объекте таблицы. Аргументом является
464 ассоциативный массив, содержащий имена столбцов и соответствующие им
468 <example id="zend.db.table.insert.example">
470 <title>Пример добавления строк в таблицу</title>
472 <programlisting language="php"><![CDATA[
476 'created_on' => '2007-03-22',
477 'bug_description' => 'Something wrong',
478 'bug_status' => 'NEW'
481 $table->insert($data);
488 По умолчанию значения в вашем массиве данных добавляются как
489 буквенные значения, с использованием параметров. Если вам нужно,
490 чтобы они интерпретировались как выражения SQL, то необходимо
491 обозначить их отличие от простых строк. Для этого используйте
492 объекты типа Zend_Db_Expr.
495 <example id="zend.db.table.insert.example-expr">
497 <title>Пример добавления выражений в таблицу</title>
499 <programlisting language="php"><![CDATA[
503 'created_on' => new Zend_Db_Expr('CURDATE()'),
504 'bug_description' => 'Something wrong',
505 'bug_status' => 'NEW'
513 В примере добавления строки выше предполагается, что таблица имеет
514 автоинкрементный первичный ключ. Это принятое по умолчанию поведение
515 Zend_Db_Table_Abstract, но есть и другие типы первичных ключей.
516 Следующий раздел описывает, как поддерживаются различные типы
520 <sect3 id="zend.db.table.insert.key-auto">
522 <title>Использование таблицы с автоинкрементным ключом</title>
525 Автоинкрементный первичный ключ генерирует уникальное
526 целочисленное значение, если вы опустите столбец для
527 первичного ключа в своем операторе <code>INSERT</code>.
531 Если защищенная переменная в Zend_Db_Table_Abstract
532 <varname>$_sequence</varname> имеет булево значение <constant>TRUE</constant>,
533 то класс предполагает, что таблица имеет автоинкрементный
537 <example id="zend.db.table.insert.key-auto.example">
539 <title>Пример объявления таблицы с автоинкрементным первичным ключом</title>
541 <programlisting language="php"><![CDATA[
542 class Bugs extends Zend_Db_Table_Abstract
544 protected $_name = 'bugs';
546 // Это значение по умолчанию присутствует в Zend_Db_Table_Abstract,
547 // устанавливать его не обязательно
548 protected $_sequence = true;
556 Примерами СУРБД, поддерживающих автоинкрементные первичные ключи
557 являются MySQL, Microsoft SQL Server и SQLite.
561 PostgreSQL имеет нотацию <code>SERIAL</code>, которая неявно
562 определяет последовательность, основанную на имени таблицы и
563 столбца, и использует ее для генерации значений ключа при
564 добавлении новых строк. IBM DB2 имеет нотацию
565 <code>IDENTITY</code> которая работает аналогичным образом.
566 Если вы используете одну из этих нотаций, то интерпретируйте
567 свой класс Zend_Db_Table как имеющий автоинкрементный столбец,
568 при этом члена <varname>$_sequence</varname> должен иметь значение
569 <constant>TRUE</constant>.
574 <sect3 id="zend.db.table.insert.key-sequence">
576 <title>Использование таблицы с последовательностью</title>
579 Последовательность (sequence) является объектом базы данных,
580 генерирующим уникальные значения, которые могут
581 использоваться как значения уникальных ключей в одной и более
586 Если вы присвоили <varname>$_sequence</varname> строковое значение,
587 то Zend_Db_Table_Abstract считает строку именем объекта
588 последовательности в БД. Последовательность запускается для
589 генерации нового значения, и это значение используется в
594 <example id="zend.db.table.insert.key-sequence.example">
596 <title>Пример объявления таблицы с последовательностью</title>
598 <programlisting language="php"><![CDATA[
599 class Bugs extends Zend_Db_Table_Abstract
601 protected $_name = 'bugs';
603 protected $_sequence = 'bug_sequence';
611 Примерами СУРБД, поддерживающих объекты последовательностей
612 являются Oracle, PostgreSQL и IBM DB2.
616 PostgreSQL и IBM DB2 также имеют синтаксис, который неявно
617 определяет последовательности и связывает их со столбцами.
618 Если вы используете эту нотацию, то интерпретируйте таблицу
619 как имеющую автоинкрементный ключевой столбец. Задавайте имя
620 последовательности в виде строки только в тех случаях, когда вы
621 собираетесь явно вызывать последовательности для получения
622 следующего значения ключа.
627 <sect3 id="zend.db.table.insert.key-natural">
629 <title>Использование таблицы с естественным ключом</title>
632 Некоторые таблицы имеют естественные ключи. Это означает, что
633 ключ не генерируется автоматически таблицей или
634 последовательностью. В этом случае вы должны установить значение
639 Если вы присвоили <varname>$_sequence</varname> булево значение
640 <constant>FALSE</constant>, то Zend_Db_Table_Abstract считает, что
641 таблица имеет естественный первичный ключ. Вы должны
642 предоставлять значения для столбцов первичного ключа в массиве
643 данных для метода <code>insert()</code>, иначе метод бросает
644 исключение Zend_Db_Table_Exception.
647 <example id="zend.db.table.insert.key-natural.example">
649 <title>Пример объявления таблицы с естественным ключом</title>
651 <programlisting language="php"><![CDATA[
652 class BugStatus extends Zend_Db_Table_Abstract
654 protected $_name = 'bug_status';
656 protected $_sequence = false;
666 Все СУРБД поддерживают таблицы с естественными ключами.
667 Примеры таблиц, часто объявляемых как имеющие естественные
668 ключи: справочные таблицы, таблицы пересечений в отношениях
669 "многие-ко-многим", большинство таблиц с составными
679 <sect2 id="zend.db.table.update">
681 <title>Обновление строк в таблице</title>
684 Вы можете обновлять строки в таблице БД, используя метод
685 <code>update</code> класса таблицы. Этот метод принимает два
686 аргумента: первым является ассоциативный массив столбцов, которые
687 требуется изменить, и новых значений, присваиваемых этим столбцам;
688 вторым - выражение SQL, которое используется в предложении
689 <code>WHERE</code> в качестве условия изменения строки в операции
693 <example id="zend.db.table.update.example">
695 <title>Пример обновления строк в таблице</title>
697 <programlisting language="php"><![CDATA[
701 'updated_on' => '2007-03-23',
702 'bug_status' => 'FIXED'
705 $where = $table->getAdapter()->quoteInto('bug_id = ?', 1234);
707 $table->update($data, $where);
714 Поскольку метод таблицы <code>update()</code> в свою очередь
715 использует метод адаптера БД
716 <link linkend="zend.db.adapter.update"><code>update()</code></link>,
717 то второй аргумент может быть массивом SQL-выражений. Выражения
718 объединяются как булевы условия через оператор <code>AND</code>.
724 Значения и идентификаторы в SQL-выражении не заключаются в
725 кавычки автоматически. Если имеются значения или идентификаторы,
726 которые требуют заключения в кавычки, то вы должны произвести
727 его сами. Используйте методы <code>quote()</code>,
728 <code>quoteInto()</code> и <code>quoteIdentifier()</code>
736 <sect2 id="zend.db.table.delete">
738 <title>Удаление строк из таблицы</title>
741 Вы можете удалять строки из таблицы базы данных, используя метод
742 <code>delete()</code>. Этот метод принимает один аргумент,
743 являющийся SQL-выражением, который используется в предложении
744 <code>WHERE</code> в качестве условия, по которому удаляются строки.
747 <example id="zend.db.table.delete.example">
749 <title>Пример удаления строк из таблицы</title>
751 <programlisting language="php"><![CDATA[
754 $where = $table->getAdapter()->quoteInto('bug_id = ?', 1235);
756 $table->delete($where);
763 Поскольку метод таблицы в свою очередь использует метод
764 <code>delete()</code> адаптера БД, то второй аргумент может быть
765 массивом SQL-выражений. Выражения объединяются как булевы условия
766 через оператор <code>AND</code>.
772 Значения и идентификаторы в SQL-выражении не заключаются в
773 кавычки автоматически. Если имеются значения или идентификаторы,
774 которые требуют заключения в кавычки, то вы должны произвести
775 его сами. Используйте методы <code>quote()</code>,
776 <code>quoteInto()</code> и <code>quoteIdentifier()</code>
784 <sect2 id="zend.db.table.find">
786 <title>Извлечение строк по первичному ключу</title>
789 Вы можете запрашивать из таблицы БД строки, соответствующие
790 определенным значениям в первичном ключе, используя метод
791 <code>find()</code>. Первым аргументом этого метода является
792 единственное значение или массив значений, сопоставляемых с
793 первичным ключом таблицы.
796 <example id="zend.db.table.find.example">
798 <title>Пример извлечения строк по значениям первичного ключа</title>
800 <programlisting language="php"><![CDATA[
803 // Запрос одной строки
804 // Возвращает набор строк (Rowset)
805 $rows = $table->find(1234);
807 // Запрос нескольких строк
808 // Также возвращает набор строк (Rowset)
809 $rows = $table->find(array(1234, 5678));
816 Если вы задали одно значение, то метод вернет максимум одну
817 строку, потому что первичный ключ не может содержать повторяющиеся
818 значения и должна быть максимум одна строка в таблице БД,
819 соответствующая данному значению. Если вы задали несколько
820 значений, то метод вернет максимум столько строк, сколько
821 несовпадающих значений было задано.
825 Метод <code>find()</code> может возвращать меньше строк, чем было
826 задано значений для первичного ключа, если для некоторых значений
827 нет соответствующих строк в таблице БД. Метод может даже вернуть
828 нулевое количество строк. Поскольку количество возвращаемых строк
829 является переменным, то метод <code>find()</code> возвращает объект
830 типа Zend_Db_Table_Rowset_Abstract (набор строк).
834 Если первичный ключ является составным, т.e. он состоит из
835 нескольких столбцов, то можно задать добавочные столбцы как
836 дополнительные аргументы метода <code>find()</code>. Вы должны
837 передать столько аргументов, сколько столбцов в первичном
842 Для того чтобы найти несколько строк с составным первичным ключом,
843 передавайте массив для каждого из аргументов. Все эти массивы должны
844 иметь одно и то же количество элементов. Значения из всех массивов
845 объединяются в "кортежи" в порядке следования; например, первые
846 элементы каждого массива определяют значение первого составного
847 первичного ключа, вторые элементы - второго составного ключа и т.д.
850 <example id="zend.db.table.find.example-compound">
852 <title>Пример извлечения строк по значениям составного первичного ключа</title>
855 Вызов метода <code>find()</code> ниже для поиска нескольких
856 строк может соответствовать двум строкам в БД. Первая строка
857 должна иметь значение первичного ключа (1234, 'ABC'), вторая -
861 <programlisting language="php"><![CDATA[
862 class BugsProducts extends Zend_Db_Table_Abstract
864 protected $_name = 'bugs_products';
865 protected $_primary = array('bug_id', 'product_id');
868 $table = new BugsProducts();
870 // Запрашивает единственную строку через составной первичный ключ
871 // Возвращает набор строк (Rowset)
872 $rows = $table->find(1234, 'ABC');
874 // Запрашивает несколько строк через составной первичный ключ
875 // Также возвращает набор строк (Rowset)
876 $rows = $table->find(array(1234, 5678), array('ABC', 'DEF'));
884 <sect2 id="zend.db.table.fetch-all">
886 <title>Извлечение наборов строк</title>
888 <sect3 id="zend.db.table.fetch-all.select">
890 <title>API для произведения выборки</title>
897 API для операций извлечения был изменен для того,
898 чтобы объект <code>Zend_Db_Table_Select</code> мог
899 изменять запрос. Тем не менее, не рекомендуемый
900 сейчас вариант использования <code>fetchRow()</code> и
901 <code>fetchAll()</code> будет работать без изменений.
905 Следующие варианты являются корректными и
906 функционально идентичными, но, тем не менее,
907 рекомендуется обновить свой код с тем, чтобы
908 получить преимущества нового подхода.
913 <programlisting language="php">
915 // Извлечение набора строк
916 $rows = $table->fetchAll('bug_status = "NEW"', 'bug_id ASC', 10, 0);
917 $rows = $table->fetchAll($table->select()->where('bug_status = ?', 'NEW')
918 ->order('bug_id ASC')
921 // Извлечение одной строки
922 $row = $table->fetchRow('bug_status = "NEW"', 'bug_id ASC');
923 $row = $table->fetchRow($table->select()->where('bug_status = ?', 'NEW')
924 ->order('bug_id ASC'));
935 Объект <classname>Zend_Db_Table_Select</classname> является
936 расширением объекта <classname>Zend_Db_Select</classname>,
937 который накладывает некоторые специфические ограничения
938 на запрос. Ниже перечислены дополнительные возможности и
939 ограничения этого класса:
945 Вы <emphasis>можете</emphasis> выбрать возвращение
946 набора столбцов запросами fetchRow и fetchAll.
947 Это дает преимущества в плане оптимизации там, где
948 извлечение большого набора строк со всеми столбцами
949 было бы не желательным.
955 Вы <emphasis>можете</emphasis> указывать столбцы,
956 которые определяют выражения в таблице. Но это также
957 означает, что возвращаемый объект строки или набора
958 строк будет доступен только для чтения и к нему не могут
959 применяться операции сохранения. Объект строки
960 <code>Zend_Db_Table_Row</code> со статусом
961 <property>readOnly</property> будет бросать исключение
962 при попытке произвести операцию сохранения (метод
963 <code>save()</code>).
969 Вы <emphasis>можете</emphasis> разрешить предложения
970 JOIN в выборке для поиска в нескольких таблицах.
976 Вы <emphasis>не можете</emphasis> указывать столбцы
977 из присоединенных таблиц в качестве возвращаемых в
978 строке/наборе строк. Попытка сделать это вызовет ошибку
979 PHP. Это сделано для того, чтобы гарантировать
980 целостность <code>Zend_Db_Table</code>, т.е.
981 <code>Zend_Db_Table_Row</code> должен содержать
982 столбцы только из той таблицы, которую представляет
983 данный объект <code>Zend_Db_Table</code>.
990 <example id="zend.db.table.qry.rows.set.simple.usage.example">
992 <title>Простое использование</title>
994 <programlisting language="php">
998 $select = $table->select();
999 $select->where('bug_status = ?', 'NEW');
1001 $rows = $table->fetchAll($select);
1010 В данной компоненте поддерживается fluent interface,
1011 поэтому пример выше может быть переписан в более краткой форме.
1016 <example id="zend.db.table.qry.rows.set.fluent.interface.example">
1018 <title>Пример использования fluent interface</title>
1020 <programlisting language="php">
1022 $table = new Bugs();
1025 $table->fetchAll($table->select()->where('bug_status = ?', 'NEW'));
1035 <sect3 id="zend.db.table.fetch-all.usage">
1037 <title>Извлечение набора строк</title>
1040 Вы можете извлекать наборы строк, используя любое другое
1041 условие, отличное от значения первичного ключа, через метод
1042 <code>fetchAll()</code> класса таблицы. Этот метод возвращает
1043 объект типа <code>Zend_Db_Table_Rowset_Abstract</code>.
1046 <example id="zend.db.table.qry.rows.set.finding.row.example">
1048 <title>Пример поиска строк по выражению</title>
1050 <programlisting language="php">
1052 $table = new Bugs();
1054 $select = $table->select()->where('bug_status = ?', 'NEW');
1056 $rows = $table->fetchAll($select);
1063 Вы можете также передавать условие для сортировки, которое
1064 используется в предложении <code>ORDER BY</code>, и
1065 целочисленные значения смещения и количества строк для
1066 предложения <code>LIMIT</code> или эквивалентной
1067 ему логики в СУРБД, не поддерживающих синтаксис
1071 <example id="zend.db.table.fetch-all.example2">
1073 <title>Пример поиска строк по выражению</title>
1075 <programlisting language="php">
1077 $table = new Bugs();
1081 // Требуется вернуть строки начиная с 21-ой и кончая 30-й
1085 $select = $table->select()->where(array('bug_status = ?' => 'NEW'))
1087 ->limit($count, $offset);
1089 $rows = $table->fetchAll($select);
1096 Все агрументы в примере выше являются опциональными. Если вы
1097 опустите предложение ORDER, то строки из таблицы будут
1098 возвращаться в непредсказуемом порядке. Если не было
1099 установлено предложение LIMIT, то вы получите все
1100 соответствующие предложению WHERE строки из таблицы.
1105 <sect3 id="zend.db.table.advanced.usage">
1107 <title>Расширенное использование</title>
1110 Для более точных и оптимизированных запросов может
1111 потребоваться ограничить количество столбцов, возвращаемых в
1112 строке/наборе строк. Это может быть достигнуто путем передачи
1113 предложения FROM объекту выборки.
1118 <example id="zend.db.table.qry.rows.set.retrieving.a.example">
1120 <title>Извлечение определенных столбцов</title>
1122 <programlisting language="php"><![CDATA[
1123 $table = new Bugs();
1125 $select = $table->select();
1126 $select->from($table, array('bug_id', 'bug_description'))
1127 ->where('bug_status = ?', 'NEW');
1129 $rows = $table->fetchAll($select);
1142 Полученный набор строк будет содержать строки, которые
1143 по-прежнему являются "рабочими", только они
1144 содержат не все столбцы таблицы. Если для неполной
1145 строки был вызван метод save(), то будут изменены только
1146 доступные в объекте столбцы.
1151 Вы можете также указывать выражения в предложении FROM, но в
1152 этом случае будуте получать строки/наборы строк,
1153 доступные только для чтения. В этом примере мы будем возвращать
1154 строки из таблицы Bugs, которые показывают количество
1155 ошибок, сообщенное конкретным пользователем. Обратите
1156 внимание на предложение GROUP. Столбец 'count' будет доступен в
1157 объекте строки, и к нему можно обращаться так же, как если бы он
1163 <example id="zend.db.table.qry.rows.set.retrieving.b.example">
1165 <title>Извлечение выражений как столбцов</title>
1167 <programlisting language="php"><![CDATA[
1168 $table = new Bugs();
1170 $select = $table->select();
1171 $select->from($table,
1172 array('COUNT(reported_by) as `count`', 'reported_by'))
1173 ->where('bug_status = ?', 'NEW')
1174 ->group('reported_by');
1176 $rows = $table->fetchAll($select);
1182 Вы можете использовать поиск как часть вашего запроса
1183 для дальнейшей детализации ваших операций извлечения.
1184 В этом примере таблица Accounts используется для
1185 поиска всех новых ошибок, о которых сообщил пользователь 'Bob'.
1190 <example id="zend.db.table.qry.rows.set.refine.example">
1192 <title>Использование таблицы поиска для фильтрации результатов, возвращаемых fetchAll()</title>
1194 <programlisting language="php"><![CDATA[
1195 $table = new Bugs();
1197 $select = $table->select();
1198 $select->where('bug_status = ?', 'NEW')
1199 ->join('accounts', 'accounts.account_name = bugs.reported_by')
1200 ->where('accounts.account_name = ?', 'Bob');
1202 $rows = $table->fetchAll($select);
1211 Класс <classname>Zend_Db_Table_Select</classname> главным
1212 образом используется для соблюдения и проверки
1213 корректности запроса.
1214 Тем не менее, могут быть определенные случаи, когда
1215 нужна большая гибкость компоненты Zend_Db_Table_Row и
1216 не требуется доступная для чтения или удаления строка.
1217 Для этого отдельного случая использования возможно получение
1218 строки/набора строк путем передачи значения false методу
1219 setIntegrityCheck().
1220 В результате строка/набор строк будет возвращаться в
1221 "заблокированном" состоянии, это значит, что save(),
1222 delete() и методы для установки значений полей будут бросать
1226 <example id="zend.db.table.qry.rows.set.integrity.example">
1228 <title>Отключение проверки целостности в Zend_Db_Table_Select для получения объединенных строк</title>
1230 <programlisting><![CDATA[
1231 $table = new Bugs();
1233 $select = $table->select()->setIntegrityCheck(false);
1234 $select->where('bug_status = ?', 'NEW')
1236 'accounts.account_name = bugs.reported_by',
1238 ->where('accounts.account_name = ?', 'Bob');
1240 $rows = $table->fetchAll($select);
1250 <sect2 id="zend.db.table.fetch-row">
1252 <title>Извлечение одной строки</title>
1255 Вы можете запрашивать одну строку, используя условия, аналогичные
1256 тем, что используются в методе <code>fetchAll()</code>.
1259 <example id="zend.db.table.fetch-row.example1">
1261 <title>Пример поиска одной строки по выражению</title>
1263 <programlisting language="php"><![CDATA[
1264 $table = new Bugs();
1266 $select = $table->select()->where('bug_status = ?', 'NEW')
1269 $row = $table->fetchRow($select);
1276 Этот метод возвращает объект типа Zend_Db_Table_Row_Abstract. Если
1277 по заданному вами условию поиска не найдено ни одной строки в
1278 таблице БД, то <code>fetchRow()</code> вернет значение
1279 <constant>NULL</constant>.
1284 <sect2 id="zend.db.table.info">
1286 <title>Получение метаданных таблицы</title>
1289 Класс Zend_Db_Table_Abstract предоставляет некоторую информацию о
1290 его метаданных. Метод <code>info()</code> возвращает массив с
1291 данными о таблице, ее столбцах, первичном ключе и другие метаданные.
1294 <example id="zend.db.table.info.example">
1296 <title>Пример получения имени таблицы</title>
1298 <programlisting language="php">
1300 $table = new Bugs();
1302 $info = $table->info();
1304 echo "The table name is " . $info['name'] . "\n";
1311 Ключи массива, возвращаемого методом <code>info()</code>, описаны
1318 <emphasis>name</emphasis> => имя таблицы
1323 <emphasis>cols</emphasis> =>
1324 массив имен столбцов в таблице
1329 <emphasis>primary</emphasis> =>
1330 массив имен столбцов в первичном ключе
1335 <emphasis>metadata</emphasis> =>
1336 ассоциативный массив, включающий в себя имена столбцов и
1337 соответствующие им данные о столбцах. Это информация,
1338 возвращаемая методом <code>describeTable()</code>.
1343 <emphasis>rowClass</emphasis> => имя
1344 определенного класса, используемого для объектов строк,
1345 возвращаемых методами данного экземпляра таблицы. По
1346 умолчанию это Zend_Db_Table_Row.
1351 <emphasis>rowsetClass</emphasis> =>
1352 имя определенного класса, используемого для объектов
1353 наборов строк, возвращаемых методами данного экземпляра
1354 таблицы. По умолчанию это Zend_Db_Table_Rowset.
1359 <emphasis>referenceMap</emphasis> =>
1360 ассоциативный массив с данными о ссылках на другие таблицы.
1361 См. <xref linkend="zend.db.table.relationships.defining" />.
1366 <emphasis>dependentTables</emphasis> =>
1367 массив имен классов таблиц, на которые ссылается данная
1369 <xref linkend="zend.db.table.relationships.defining" />.
1374 <emphasis>schema</emphasis> =>
1375 имя схемы (базы данных, пространства таблиц) для данной
1383 <sect2 id="zend.db.table.metadata.caching">
1385 <title>Кэширование метаданных таблицы</title>
1388 По умолчанию <code>Zend_Db_Table_Abstract</code> производит запрос к
1389 БД для определения <link linkend="zend.db.table.info">метаданных
1390 таблицы</link> во время инстанцирования объекта таблицы. Т.е. когда
1391 создается новый объект таблицы, поведением по умолчанию является
1392 извлечение метаданных таблицы из БД через метод
1393 <code>describeTable()</code>.
1397 В некоторых условиях, особенно когда к одной и той же таблице БД
1398 создается много объектов таблиц, произведение запросов для
1399 получения метаданных для каждого экземпляря может быть нежелательным
1400 с точки зрения производительности. В таких случаях можно производить
1401 кэширование метаданных таблицы, полученных из БД.
1405 Есть два основных способа кэширования:
1410 <emphasis>Вызов метода
1411 Zend_Db_Table_Abstract::setDefaultMetadataCache()</emphasis>
1412 - Это позволяет разработчику единовременно установить
1413 объект кэша, используемый в всех классах таблиц.
1418 <emphasis>Конфигурирование
1419 Zend_Db_Table_Abstract::__construct()</emphasis> - Это
1420 позволяет разработчику установить объект кэша для
1421 определенного экземпляра класса таблицы.
1426 В обоих случаях определением кэша может быть <constant>NULL</constant>
1427 (т.е. не используется кэширование) или экземпляр класса
1428 <link linkend="zend.cache.frontends.core"><code>Zend_Cache_Core</code></link>.
1429 Эти методы могут использоваться вместе для того, чтобы
1430 использовать по умолчанию определенный объект кэша и при этом иметь
1431 возможность изменять его для конкретного объекта таблицы.
1434 <example id="zend.db.table.metadata.caching-default">
1436 <title>Кэширование метаданных по умолчанию для всех объектов таблиц</title>
1439 Следующий код показывает, как установить объект кэша,
1440 используемый по умолчанию во всех объектах таблиц:
1443 <programlisting language="php"><![CDATA[
1444 // Сначала создается объект кэша
1445 $frontendOptions = array(
1446 'automatic_serialization' => true
1449 $backendOptions = array(
1450 'cacheDir' => 'cacheDir'
1453 $cache = Zend_Cache::factory('Core',
1459 // Далее, объект кэша устанавливается в качестве используемого
1460 // во всех объектах таблиц
1461 Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
1465 class Bugs extends Zend_Db_Table_Abstract
1471 // Каждый экземпляр таблицы Bugs теперь использует
1472 // кэширование метаданных по умолчанию
1479 <example id="zend.db.table.metadata.caching-instance">
1481 <title>Кэширование метаданных для одного объекта таблицы</title>
1484 Следующий код показывает, как устанавливается кэширование
1485 метаданных для одного конкретного объекта таблицы:
1488 <programlisting language="php"><![CDATA[
1489 // Сначала создается объект кэша
1490 $frontendOptions = array(
1491 'automatic_serialization' => true
1494 $backendOptions = array(
1495 'cacheDir' => 'cacheDir'
1498 $cache = Zend_Cache::factory('Core',
1504 class Bugs extends Zend_Db_Table_Abstract
1510 // Экземпляр конфигурируется при инстанцировании
1511 $bugs = new Bugs(array('metadataCache' => $cache));
1519 <title>Автоматическая сериализация через фронтэнд кэша</title>
1522 Поскольку информация, возвращаемая методом адаптера
1523 describeTable(), является массивом, то убедитесь, что опция
1524 <code>automatic_serialization</code> установлена в
1525 <constant>TRUE</constant> для фронтэнда <code>Zend_Cache_Core</code>.
1531 Несмотря на то, что в примерах выше используется
1532 <code>Zend_Cache_Backend_File</code>, разработчики могут
1533 использовать другие бэкэнды, наиболее подходящие в данной ситуации.
1534 Более подробную информацию читайте в разделе
1535 <link linkend="zend.cache">Zend_Cache</link>.
1540 <sect2 id="zend.db.table.extending">
1542 <title>Расширение класса таблицы</title>
1544 <sect3 id="zend.db.table.extending.row-rowset">
1546 <title>Использование собственных классов строки и набора строк</title>
1549 По умолчанию методы класса таблицы возвращают наборы строк в
1550 экземплярах класса Zend_Db_Table_Rowset, и эти наборы строк
1551 содержат в себе коллекции экземпляров класса Zend_Db_Table_Row.
1552 Вы можете указать альтернативные классы, используемые вместо
1553 них, но в любом случае они должны наследовать от классов
1554 Zend_Db_Table_Rowset_Abstract и Zend_Db_Table_Row_Abstract
1559 Вы можете указать классы строки и набора строк в
1560 массиве опций конструктора таблицы под ключами
1561 <code>'rowClass'</code> и <code>'rowsetClass'</code>
1562 соответственно. Задавайте имена классов в виде обычных строк.
1565 <example id="zend.db.table.extending.row-rowset.example">
1567 <title>Пример указания классов строки и набора строк</title>
1569 <programlisting language="php"><![CDATA[
1570 class My_Row extends Zend_Db_Table_Row_Abstract
1575 class My_Rowset extends Zend_Db_Table_Rowset_Abstract
1582 'rowClass' => 'My_Row',
1583 'rowsetClass' => 'My_Rowset'
1587 $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
1589 // Возвращает объект типа My_Rowset,
1590 // содержащий массив объектов типа My_Row
1591 $rows = $table->fetchAll($where);
1598 Вы можете сменить используемые классы, указав их через методы
1599 <code>setRowClass()</code> и <code>setRowsetClass()</code>.
1600 Это изменение применяется к создаваемым впоследствии строкам и
1601 наборам строк и не влияет на класс объектов строк и наборов
1602 строк, созданных ранее.
1605 <example id="zend.db.table.extending.row-rowset.example2">
1607 <title>Пример смены используемых для строк и наборов строк классов</title>
1609 <programlisting language="php"><![CDATA[
1610 $table = new Bugs();
1612 $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
1614 // Возвращает объект типа Zend_Db_Table_Rowset,
1615 // содержащий массив объектов типа Zend_Db_Table_Row.
1616 $rowsStandard = $table->fetchAll($where);
1618 $table->setRowClass('My_Row');
1619 $table->setRowsetClass('My_Rowset');
1621 // Возвращает объект типа My_Rowset,
1622 // содержащий массив объектов типа My_Row.
1623 $rowsCustom = $table->fetchAll($where);
1625 // Объект $rowsStandard по прежнему существует и не изменился.
1632 Более подробную информацию о классах строки и набора строк
1633 ищите в <xref linkend="zend.db.table.row" /> и
1634 <xref linkend="zend.db.table.rowset" />.
1639 <sect3 id="zend.db.table.extending.insert-update">
1641 <title>Определение собственной логики для добавления, обновления и удаления строк</title>
1644 Вы можете переопределить методы <code>insert()</code> и
1645 <code>update()</code> в своем классе таблицы. Это дает
1646 возможность реализовать собственный
1647 код, который исполняется до того, как будет выполнена операция с
1648 БД. Всегда вызывайте метод родительского класса после своих
1652 <example id="zend.db.table.extending.insert-update.example">
1654 <title>Собственная логика для управления отметками времени</title>
1656 <programlisting language="php"><![CDATA[
1657 class Bugs extends Zend_Db_Table_Abstract
1659 protected $_name = 'bugs';
1661 public function insert(array $data)
1663 // добавление timestamp
1664 if (empty($data['created_on'])) {
1665 $data['created_on'] = time();
1667 return parent::insert($data);
1670 public function update(array $data, $where)
1672 // добавление timestamp
1673 if (empty($data['updated_on'])) {
1674 $data['updated_on'] = time();
1676 return parent::update($data, $where);
1685 Вы можете также переопределить метод <code>delete()</code>.
1690 <sect3 id="zend.db.table.extending.finders">
1692 <title>Определение собственных методов для поиска</title>
1695 Вы можете реализовать собственные методы запросов в своем классе
1696 таблицы, если приходится часто делать запросы к таблице с одними
1697 и теми же условиями. Большинство запросов могут быть написаны с
1698 использованием <code>fetchAll()</code>, но это требует написания
1699 повторяющегося кода для формирования условий запроса в том
1700 случае, если вам нужно выполнять запрос в нескольких местах
1701 вашего приложения. Поэтому будет удобным добавить метод в класс
1702 таблицы для выполнения часто используемых запросов к таблице.
1705 <example id="zend.db.table.extending.finders.example">
1707 <title>Метод для поиска ошибок с определенным статусом</title>
1709 <programlisting language="php"><![CDATA[
1710 class Bugs extends Zend_Db_Table_Abstract
1712 protected $_name = 'bugs';
1714 public function findByStatus($status)
1716 $where = $this->getAdapter()->quoteInto('bug_status = ?', $status);
1717 return $this->fetchAll($where, 'bug_id');
1727 <sect3 id="zend.db.table.extending.inflection">
1729 <title>Определение инфлекции в Zend_Db_Table</title>
1732 Некоторые разработчики предпочитают, чтобы имя класса таблицы
1733 сопоставлялось с именем таблицы в СУРБД с применением
1734 преобразования, называемого <emphasis>инфлекцией</emphasis>.
1738 Например, если имя вашего класса таблицы -
1739 "<code>BugsProducts</code>", то класс должен соответствовать
1740 физической таблице в БД с названием
1741 "<code>bugs_products</code>", если вы не произвели явное
1742 объявление свойства класса <varname>$_name</varname>. В данном
1743 преобразовании имя класса в формате "CamelCase" должно
1744 приводиться к нижнему регистру с разделением слов символом
1749 Вы можете указать имя таблицы БД независимо то имени класса,
1750 объявив его в свойстве <varname>$_name</varname> во всех классах этой
1755 Zend_Db_Table_Abstract не производит инфлекцию при получении
1756 имени таблицы. Если вы опустите
1757 объявление свойства <varname>$_name</varname> в своем классе таблицы,
1758 то класс будет соответствовать таблице в БД с точно таким же
1759 именем, как и у него.
1763 Было бы неуместным использовать преобразование идентификаторов
1764 из БД, поскольку это может привести к неоднозначности или
1765 сделать некоторые идентификаторы недоступными.
1766 Использование SQL-идентификаторов в том виде, в котором они
1767 присутствуют в БД, делает Zend_Db_Table_Abstract проще и гибче в
1772 Если вы предпочитаете использовать инфлекцию, то должны
1773 реализовать преобразование сами, переопределив метод
1774 <code>_setupTableName()</code> в своем классе таблицы. Одним из
1775 возможных способов является определение абстрактного класса,
1776 наследующего от Zend_Db_Table_Abstract, и объявление
1777 классов остальных таблиц как наследующих от этого нового
1781 <example id="zend.db.table.extending.inflection.example">
1783 <title>Пример абстрактного класса таблицы, реализующего инфлекцию</title>
1785 <programlisting language="php"><![CDATA[
1786 abstract class MyAbstractTable extends Zend_Db_Table_Abstract
1788 protected function _setupTableName()
1790 if (!$this->_name) {
1791 $this->_name = myCustomInflector(get_class($this));
1793 parent::_setupTableName();
1797 class BugsProducts extends MyAbstractTable
1806 Реализация функций для произведения инфлекционного
1807 преобразования возлагается на разработчика. Zend Framework не
1808 предоставляет для этих целей готовых функций.
1817 vim:se ts=4 sw=4 et: