| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818 |
- <sect1 id="zend.db.table">
- <title>Zend_Db_Table</title>
- <sect2 id="zend.db.table.introduction">
- <title>Класс таблицы - введение</title>
- <para>
- Класс Zend_Db_Table является объектно-ориентированным интерфейсом к
- таблицам баз данных. Он предоставляет методы для многих общих
- операций над таблицами. Базовый класс является расширяемым, поэтому
- вы можете добавлять свою логику.
- </para>
- <para>
- Решением Zend_Db_Table является реализация паттерна
- <ulink url="http://www.martinfowler.com/eaaCatalog/tableDataGateway.html">Table Data Gateway</ulink>.
- Это решение также включает в себя класс, реализующий паттерн
- <ulink url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data Gateway</ulink>.
- </para>
- </sect2>
- <sect2 id="zend.db.table.defining">
- <title>Определение класса таблицы</title>
- <para>
- Для каждой таблицы в БД, к которой нужен доступ, определяется класс,
- наследующий от Zend_Db_Table_Abstract.
- </para>
- <sect3 id="zend.db.table.defining.table-schema">
- <title>Определение имени и схемы таблицы</title>
- <para>
- Указывайте таблицу, для которой определен этот класс, используя
- защищенную переменную <varname>$_name</varname>. Переменная
- должна содержать имя таблицы в том виде, в котором она
- представлена в БД.
- </para>
- <example id="zend.db.table.defining.table-schema.example1">
- <title>Объявление класса таблицы с явным определением имени таблицы</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- }
- ]]>
- </programlisting>
- </example>
- <para>
- Если вы не определили имя таблицы, то по умолчанию оно равно
- имени класса. Если вы предпочитаете этот путь, то имя класса
- должно иметь то же написание, что и имя таблицы в БД.
- </para>
- <example id="zend.db.table.defining.table-schema.example">
- <title>Объявление класса таблицы с неявным определением имени таблицы</title>
- <programlisting language="php"><![CDATA[
- class bugs extends Zend_Db_Table_Abstract
- {
- // имя таблицы соответствует имени класса
- }
- ]]>
- </programlisting>
- </example>
- <para>
- Вы можете также объявить схему таблицы в защищенной переменной
- <varname>$_schema</varname> или через добавленное
- перед именем таблицы имя схемы в свойстве <varname>$_name</varname>.
- Схема, указанная с помощью свойства <varname>$_name</varname>,
- имеет более высокий приоритет, чем схема, объявленная с помощью
- свойства <varname>$_schema</varname>. В некоторых СУРБД вместо
- термина "схема" используются термины "база данных" или
- "пространство таблиц", они используются аналогичным образом.
- </para>
- <example id="zend.db.table.defining.table-schema.example3">
- <title>Объявление класса таблицы со схемой</title>
- <programlisting language="php"><![CDATA[
- // Первый способ:
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_schema = 'bug_db';
- protected $_name = 'bugs';
- }
- // Второй способ:
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_db.bugs';
- }
- // Если в обоих свойствах $_name м $_schema была объявлена схема,
- // то указанная в $_name имеет больший приоритет:
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_db.bugs';
- protected $_schema = 'ignored';
- }
- ]]>
- </programlisting>
- </example>
- <para>
- Схема и таблица могут быть указаны через конфигурационные
- директивы конструктора, которые замещают собой любые значения по
- умолчанию, определенные с помощью свойств <varname>$_name</varname> и
- <varname>$_schema</varname>. Спецификация схемы, данная через
- директиву <code>name</code>, замещает собой любое значение,
- переданное через опцию <code>schema</code>.
- </para>
- <example id="zend.db.table.defining.table-schema.example.constructor">
- <title>Объявление имен таблицы и схемы во время инстанцирования</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- }
- // Первый способ:
- $tableBugs = new Bugs(array('name' => 'bugs', 'schema' => 'bug_db'));
- // Второй способ:
- $tableBugs = new Bugs(array('name' => 'bug_db.bugs');
- // Если в обоих опциях 'name' и 'schema' была объявлена схема,
- // то указанная в 'name' имеет больший приоритет:
- $tableBugs = new Bugs(array('name' => 'bug_db.bugs',
- 'schema' => 'ignored');
- ]]>
- </programlisting>
- </example>
- <para>
- Если вы не указали имя схемы, то по умолчанию это будет
- схема, к которой подключен ваш экземпляр адаптера БД.
- </para>
- </sect3>
- <sect3 id="zend.db.table.defining.primary-key">
- <title>Определение первичного ключа таблицы</title>
- <para>
- Каждая таблица должна иметь первичный ключ. Вы можете объявить
- столбец для первичного ключа, используя защищенную переменную
- <varname>$_primary</varname>. Это может быть строка с именем одного
- столбца или массив имен столбцов, если первичный ключ является
- составным.
- </para>
- <example id="zend.db.table.defining.primary-key.example">
- <title>Пример определения первичного ключа</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_primary = 'bug_id';
- }
- ]]>
- </programlisting>
- </example>
- <para>
- Если вы не задали первичный ключ, то Zend_Db_Table_Abstract
- пытается определить его, основываясь на данных, полученных
- через метод <code>describeTable()</code>.
- </para>
- <note>
- <para>
- Класс таблицы должен знать, какой столбец (или столбцы)
- используются для уникальной адресации строк. Если в
- классе таблицы или аргументах конструктора (а также в
- метаданных таблицы, полученных через метод
- <code>describeTable()</code>) не были указаны
- первичные ключи, то эта таблица не может использоваться
- через Zend_Db_Table.
- </para>
- </note>
- </sect3>
- <sect3 id="zend.db.table.defining.setup">
- <title>Переопределение методов установки таблицы</title>
- <para>
- Когда создается экземпляр класса таблицы, конструктор вызывает
- ряд защищенных методов, инициализирующих метаданные для таблицы.
- Вы можете переопределить любые из этих методов для того, чтобы
- явно определить эти метаданные. Помните, что в конце должен
- вызываться родительский метод.
- </para>
- <example id="zend.db.table.defining.setup.example">
- <title>Пример переопределения метода _setupTableName()</title>
- <programlisting language="php">
- <![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected function _setupTableName()
- {
- $this->_name = 'bugs';
- parent::_setupTableName();
- }
- }
- ]]>
- </programlisting>
- </example>
- <para>
- Методы установки могут быть переопределены следующим образом:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <code>_setupDatabaseAdapter()</code> проверяет, был ли
- предоставлен адаптер БД, и извлекает используемый по
- умолчанию адаптер из реестра, если необходимо.
- Переопределив этот метод, вы можете
- установить адаптер БД из других источников.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>_setupTableName()</code> по умолчанию получает имя
- таблицы из имени класса. Переопределив
- этот метод, вы можете установить имя таблицы до того,
- как будут произведены эти действия по умолчанию.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>_setupMetadata()</code> устанавливает схему, если
- имя таблицы содержит структуру "schema.table", вызывает
- <code>describeTable()</code> для получения метаданных,
- по умолчанию определяет массив столбцов
- <varname>$_cols</varname>, полученных
- через <code>describeTable()</code>. Переопределелив этот
- метод, вы можете устанавливать столбцы самостоятельно.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>_setupPrimaryKey()</code> по умолчанию
- устанавливает столбцы первичного ключа, полученные через
- <code>describeTable()</code>, и проверяет, входят ли
- столбцы первичного ключа в массив <varname>$_cols</varname>.
- Переопределив этот метод, вы можете устанавливать
- столбцы первичного ключа.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.table.initialization">
- <title>Инициализация таблицы</title>
- <para>
- Если при создании объекта таблицы требуется выполнять код,
- реализующий логику приложения, то вы можете поместить этот код в
- метод <code>init()</code>, который вызвается после того, как
- были обработаны все метаданные таблицы. Рекомендуется
- использовать этот способ вместо переопределения метода
- <code>__construct</code>, если только не требуется изменять
- метаданные программным путем.
- <example id="zend.db.table.defining.init.usage.example">
- <title>Пример использования метода init()</title>
- <programlisting language="php">
- <![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_observer;
- protected function init()
- {
- $this->_observer = new MyObserverClass();
- }
- }
- ]]>
- </programlisting>
- </example>
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.constructing">
- <title>Создание экземпляра класса таблицы</title>
- <para>
- До того, как начать использование класса таблицы, создайте его
- экземпляр, используя конструктор. Единственным аргументом
- конструктора является массив опций. Наиболее важной опцией для
- конструктора является экземпляр адаптера БД, представляющий текущее
- соединение к какой-либо СУРБД. Есть три способа передачи адаптера БД
- классу таблицы, и эти три способа описаны ниже:
- </para>
- <sect3 id="zend.db.table.constructing.adapter">
- <title>Установка адаптера БД</title>
- <para>
- Первым способом предоставления адаптера БД классу таблицы
- является передача объекта типа Zend_Db_Adapter_Abstract в
- массиве опций под ключом <code>'db'</code>.
- </para>
- <example id="zend.db.table.constructing.adapter.example">
- <title>Пример создания экземпляра таблицы с использованием объекта адаптера</title>
- <programlisting language="php">
- <![CDATA[
- $db = Zend_Db::factory('PDO_MYSQL', $options);
- $table = new Bugs(array('db' => $db));
- ]]>
- </programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.constructing.default-adapter">
- <title>Установка используемого по умолчанию адаптера БД</title>
- <para>
- Вторым способом предоставления адаптера БД классу таблицы
- является декларирование объекта типа Zend_Db_Adapter_Abstract
- как используемого по умолчанию для всех экземпляров таблиц в
- вашем приложении. Вы можете делать это через статический метод
- <code>Zend_Db_Table_Abstract::setDefaultAdapter()</code>. Его
- аргументом является объект типа Zend_Db_Adapter_Abstract.
- </para>
- <example id="zend.db.table.constructing.default-adapter.example">
- <title>Пример создания экземпляра таблицы с адаптером, используемым по умолчанию</title>
- <programlisting language="php">
- <![CDATA[
- $db = Zend_Db::factory('PDO_MYSQL', $options);
- Zend_Db_Table_Abstract::setDefaultAdapter($db);
- // Далее...
- $table = new Bugs();
- ]]>
- </programlisting>
- </example>
- <para>
- Может быть удобным создавать объект адаптера БД в центральной
- части вашего приложения - например, в загрузочном коде - и затем
- сохранять его как адаптер, используемый по умолчанию. Это дает
- возможность быть уверенным в том, что во всем приложении
- используется один и тот же экземпляр адаптера. Но установка
- адаптера, используемого по умолчанию, ограничена одним
- экземпляром адаптера.
- </para>
- </sect3>
- <sect3 id="zend.db.table.constructing.registry">
- <title>Хранение адаптера БД в реестре</title>
- <para>
- Третий способ передачи адаптера БД классу таблицы -
- передача строки в массиве опций под ключом <code>'db'</code>.
- Эта строка используется как ключ для статического экземпляра
- Zend_Registry, в котором под этим ключом должен храниться объект
- типа Zend_Db_Adapter_Abstract.
- </para>
- <example id="zend.db.table.constructing.registry.example">
- <title>Пример создания экземпляра таблицы с использованием ключа реестра</title>
- <programlisting language="php">
- <![CDATA[
- $db = Zend_Db::factory('PDO_MYSQL', $options);
- Zend_Registry::set('my_db', $db);
- // Далее...
- $table = new Bugs(array('db' => 'my_db'));
- ]]>
- </programlisting>
- </example>
- <para>
- Как и в случае установки адаптера, используемого по умолчанию,
- это дает возможность быть уверенным в том, что во всем
- приложении используется один и тот же адаптер, но использование
- реестра является более гибким, т.к. вы можете хранить в
- нем более одного экземпляра адаптера. Экземпляр адаптера
- является индивидуальным для конкретной СУРБД и экземпляра БД.
- Если в вашем приложении необходимо подключаться к нескольким БД
- или даже различным СУРБД, то вам нужно использовать несколько
- адаптеров.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.insert">
- <title>Добавление строк в таблицу</title>
- <para>
- Вы можете использовать объект таблицы для добавления строк в таблицу
- БД, на которой основан объект таблицы. Для этого используйте метод
- <code>insert()</code> в объекте таблицы. Аргументом является
- ассоциативный массив, содержащий имена столбцов и соответствующие им
- значения.
- </para>
- <example id="zend.db.table.insert.example">
- <title>Пример добавления строк в таблицу</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $data = array(
- 'created_on' => '2007-03-22',
- 'bug_description' => 'Something wrong',
- 'bug_status' => 'NEW'
- );
- $table->insert($data);
- ]]>
- </programlisting>
- </example>
- <para>
- По умолчанию значения в вашем массиве данных добавляются как
- буквенные значения, с использованием параметров. Если вам нужно,
- чтобы они интерпретировались как выражения SQL, то необходимо
- обозначить их отличие от простых строк. Для этого используйте
- объекты типа Zend_Db_Expr.
- </para>
- <example id="zend.db.table.insert.example-expr">
- <title>Пример добавления выражений в таблицу</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $data = array(
- 'created_on' => new Zend_Db_Expr('CURDATE()'),
- 'bug_description' => 'Something wrong',
- 'bug_status' => 'NEW'
- );
- ]]>
- </programlisting>
- </example>
- <para>
- В примере добавления строки выше предполагается, что таблица имеет
- автоинкрементный первичный ключ. Это принятое по умолчанию поведение
- Zend_Db_Table_Abstract, но есть и другие типы первичных ключей.
- Следующий раздел описывает, как поддерживаются различные типы
- первичных ключей.
- </para>
- <sect3 id="zend.db.table.insert.key-auto">
- <title>Использование таблицы с автоинкрементным ключом</title>
- <para>
- Автоинкрементный первичный ключ генерирует уникальное
- целочисленное значение, если вы опустите столбец для
- первичного ключа в своем операторе <code>INSERT</code>.
- </para>
- <para>
- Если защищенная переменная в Zend_Db_Table_Abstract
- <varname>$_sequence</varname> имеет булево значение <constant>TRUE</constant>,
- то класс предполагает, что таблица имеет автоинкрементный
- столбец.
- </para>
- <example id="zend.db.table.insert.key-auto.example">
- <title>Пример объявления таблицы с автоинкрементным первичным ключом</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- // Это значение по умолчанию присутствует в Zend_Db_Table_Abstract,
- // устанавливать его не обязательно
- protected $_sequence = true;
- }
- ]]>
- </programlisting>
- </example>
- <para>
- Примерами СУРБД, поддерживающих автоинкрементные первичные ключи
- являются MySQL, Microsoft SQL Server и SQLite.
- </para>
- <para>
- PostgreSQL имеет нотацию <code>SERIAL</code>, которая неявно
- определяет последовательность, основанную на имени таблицы и
- столбца, и использует ее для генерации значений ключа при
- добавлении новых строк. IBM DB2 имеет нотацию
- <code>IDENTITY</code> которая работает аналогичным образом.
- Если вы используете одну из этих нотаций, то интерпретируйте
- свой класс Zend_Db_Table как имеющий автоинкрементный столбец,
- при этом члена <varname>$_sequence</varname> должен иметь значение
- <constant>TRUE</constant>.
- </para>
- </sect3>
- <sect3 id="zend.db.table.insert.key-sequence">
- <title>Использование таблицы с последовательностью</title>
- <para>
- Последовательность (sequence) является объектом базы данных,
- генерирующим уникальные значения, которые могут
- использоваться как значения уникальных ключей в одной и более
- таблицах БД.
- </para>
- <para>
- Если вы присвоили <varname>$_sequence</varname> строковое значение,
- то Zend_Db_Table_Abstract считает строку именем объекта
- последовательности в БД. Последовательность запускается для
- генерации нового значения, и это значение используется в
- операции
- <code>INSERT</code>.
- </para>
- <example id="zend.db.table.insert.key-sequence.example">
- <title>Пример объявления таблицы с последовательностью</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_sequence = 'bug_sequence';
- }
- ]]>
- </programlisting>
- </example>
- <para>
- Примерами СУРБД, поддерживающих объекты последовательностей
- являются Oracle, PostgreSQL и IBM DB2.
- </para>
- <para>
- PostgreSQL и IBM DB2 также имеют синтаксис, который неявно
- определяет последовательности и связывает их со столбцами.
- Если вы используете эту нотацию, то интерпретируйте таблицу
- как имеющую автоинкрементный ключевой столбец. Задавайте имя
- последовательности в виде строки только в тех случаях, когда вы
- собираетесь явно вызывать последовательности для получения
- следующего значения ключа.
- </para>
- </sect3>
- <sect3 id="zend.db.table.insert.key-natural">
- <title>Использование таблицы с естественным ключом</title>
- <para>
- Некоторые таблицы имеют естественные ключи. Это означает, что
- ключ не генерируется автоматически таблицей или
- последовательностью. В этом случае вы должны установить значение
- первичного ключа.
- </para>
- <para>
- Если вы присвоили <varname>$_sequence</varname> булево значение
- <constant>FALSE</constant>, то Zend_Db_Table_Abstract считает, что
- таблица имеет естественный первичный ключ. Вы должны
- предоставлять значения для столбцов первичного ключа в массиве
- данных для метода <code>insert()</code>, иначе метод бросает
- исключение Zend_Db_Table_Exception.
- </para>
- <example id="zend.db.table.insert.key-natural.example">
- <title>Пример объявления таблицы с естественным ключом</title>
- <programlisting language="php"><![CDATA[
- class BugStatus extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_status';
- protected $_sequence = false;
- }
- ]]>
- </programlisting>
- </example>
- <note>
- <para>
- Все СУРБД поддерживают таблицы с естественными ключами.
- Примеры таблиц, часто объявляемых как имеющие естественные
- ключи: справочные таблицы, таблицы пересечений в отношениях
- "многие-ко-многим", большинство таблиц с составными
- ключами.
- </para>
- </note>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.update">
- <title>Обновление строк в таблице</title>
- <para>
- Вы можете обновлять строки в таблице БД, используя метод
- <code>update</code> класса таблицы. Этот метод принимает два
- аргумента: первым является ассоциативный массив столбцов, которые
- требуется изменить, и новых значений, присваиваемых этим столбцам;
- вторым - выражение SQL, которое используется в предложении
- <code>WHERE</code> в качестве условия изменения строки в операции
- <code>UPDATE</code>.
- </para>
- <example id="zend.db.table.update.example">
- <title>Пример обновления строк в таблице</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $data = array(
- 'updated_on' => '2007-03-23',
- 'bug_status' => 'FIXED'
- );
- $where = $table->getAdapter()->quoteInto('bug_id = ?', 1234);
- $table->update($data, $where);
- ]]>
- </programlisting>
- </example>
- <para>
- Поскольку метод таблицы <code>update()</code> в свою очередь
- использует метод адаптера БД
- <link linkend="zend.db.adapter.update"><code>update()</code></link>,
- то второй аргумент может быть массивом SQL-выражений. Выражения
- объединяются как булевы условия через оператор <code>AND</code>.
- </para>
- <note>
- <para>
- Значения и идентификаторы в SQL-выражении не заключаются в
- кавычки автоматически. Если имеются значения или идентификаторы,
- которые требуют заключения в кавычки, то вы должны произвести
- его сами. Используйте методы <code>quote()</code>,
- <code>quoteInto()</code> и <code>quoteIdentifier()</code>
- адаптера БД.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.db.table.delete">
- <title>Удаление строк из таблицы</title>
- <para>
- Вы можете удалять строки из таблицы базы данных, используя метод
- <code>delete()</code>. Этот метод принимает один аргумент,
- являющийся SQL-выражением, который используется в предложении
- <code>WHERE</code> в качестве условия, по которому удаляются строки.
- </para>
- <example id="zend.db.table.delete.example">
- <title>Пример удаления строк из таблицы</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $where = $table->getAdapter()->quoteInto('bug_id = ?', 1235);
- $table->delete($where);
- ]]>
- </programlisting>
- </example>
- <para>
- Поскольку метод таблицы в свою очередь использует метод
- <code>delete()</code> адаптера БД, то второй аргумент может быть
- массивом SQL-выражений. Выражения объединяются как булевы условия
- через оператор <code>AND</code>.
- </para>
- <note>
- <para>
- Значения и идентификаторы в SQL-выражении не заключаются в
- кавычки автоматически. Если имеются значения или идентификаторы,
- которые требуют заключения в кавычки, то вы должны произвести
- его сами. Используйте методы <code>quote()</code>,
- <code>quoteInto()</code> и <code>quoteIdentifier()</code>
- адаптера БД.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.db.table.find">
- <title>Извлечение строк по первичному ключу</title>
- <para>
- Вы можете запрашивать из таблицы БД строки, соответствующие
- определенным значениям в первичном ключе, используя метод
- <code>find()</code>. Первым аргументом этого метода является
- единственное значение или массив значений, сопоставляемых с
- первичным ключом таблицы.
- </para>
- <example id="zend.db.table.find.example">
- <title>Пример извлечения строк по значениям первичного ключа</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- // Запрос одной строки
- // Возвращает набор строк (Rowset)
- $rows = $table->find(1234);
- // Запрос нескольких строк
- // Также возвращает набор строк (Rowset)
- $rows = $table->find(array(1234, 5678));
- ]]>
- </programlisting>
- </example>
- <para>
- Если вы задали одно значение, то метод вернет максимум одну
- строку, потому что первичный ключ не может содержать повторяющиеся
- значения и должна быть максимум одна строка в таблице БД,
- соответствующая данному значению. Если вы задали несколько
- значений, то метод вернет максимум столько строк, сколько
- несовпадающих значений было задано.
- </para>
- <para>
- Метод <code>find()</code> может возвращать меньше строк, чем было
- задано значений для первичного ключа, если для некоторых значений
- нет соответствующих строк в таблице БД. Метод может даже вернуть
- нулевое количество строк. Поскольку количество возвращаемых строк
- является переменным, то метод <code>find()</code> возвращает объект
- типа Zend_Db_Table_Rowset_Abstract (набор строк).
- </para>
- <para>
- Если первичный ключ является составным, т.e. он состоит из
- нескольких столбцов, то можно задать добавочные столбцы как
- дополнительные аргументы метода <code>find()</code>. Вы должны
- передать столько аргументов, сколько столбцов в первичном
- ключе таблицы.
- </para>
- <para>
- Для того чтобы найти несколько строк с составным первичным ключом,
- передавайте массив для каждого из аргументов. Все эти массивы должны
- иметь одно и то же количество элементов. Значения из всех массивов
- объединяются в "кортежи" в порядке следования; например, первые
- элементы каждого массива определяют значение первого составного
- первичного ключа, вторые элементы - второго составного ключа и т.д.
- </para>
- <example id="zend.db.table.find.example-compound">
- <title>Пример извлечения строк по значениям составного первичного ключа</title>
- <para>
- Вызов метода <code>find()</code> ниже для поиска нескольких
- строк может соответствовать двум строкам в БД. Первая строка
- должна иметь значение первичного ключа (1234, 'ABC'), вторая -
- (5678, 'DEF').
- </para>
- <programlisting language="php"><![CDATA[
- class BugsProducts extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs_products';
- protected $_primary = array('bug_id', 'product_id');
- }
- $table = new BugsProducts();
- // Запрашивает единственную строку через составной первичный ключ
- // Возвращает набор строк (Rowset)
- $rows = $table->find(1234, 'ABC');
- // Запрашивает несколько строк через составной первичный ключ
- // Также возвращает набор строк (Rowset)
- $rows = $table->find(array(1234, 5678), array('ABC', 'DEF'));
- ]]>
- </programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.table.fetch-all">
- <title>Извлечение наборов строк</title>
- <sect3 id="zend.db.table.fetch-all.select">
- <title>API для произведения выборки</title>
- <para>
- <warning>
- <para>
- API для операций извлечения был изменен для того,
- чтобы объект <code>Zend_Db_Table_Select</code> мог
- изменять запрос. Тем не менее, не рекомендуемый
- сейчас вариант использования <code>fetchRow()</code> и
- <code>fetchAll()</code> будет работать без изменений.
- </para>
- <para>
- Следующие варианты являются корректными и
- функционально идентичными, но, тем не менее,
- рекомендуется обновить свой код с тем, чтобы
- получить преимущества нового подхода.
- </para>
- <para>
- <programlisting language="php">
- <![CDATA[
- // Извлечение набора строк
- $rows = $table->fetchAll('bug_status = "NEW"', 'bug_id ASC', 10, 0);
- $rows = $table->fetchAll($table->select()->where('bug_status = ?', 'NEW')
- ->order('bug_id ASC')
- ->limit(10, 0));
- // Извлечение одной строки
- $row = $table->fetchRow('bug_status = "NEW"', 'bug_id ASC');
- $row = $table->fetchRow($table->select()->where('bug_status = ?', 'NEW')
- ->order('bug_id ASC'));
- ]]>
- </programlisting>
- </para>
- </warning>
- </para>
- <para>
- Объект <classname>Zend_Db_Table_Select</classname> является
- расширением объекта <classname>Zend_Db_Select</classname>,
- который накладывает некоторые специфические ограничения
- на запрос. Ниже перечислены дополнительные возможности и
- ограничения этого класса:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Вы <emphasis>можете</emphasis> выбрать возвращение
- набора столбцов запросами fetchRow и fetchAll.
- Это дает преимущества в плане оптимизации там, где
- извлечение большого набора строк со всеми столбцами
- было бы не желательным.
- </para>
- </listitem>
- <listitem>
- <para>
- Вы <emphasis>можете</emphasis> указывать столбцы,
- которые определяют выражения в таблице. Но это также
- означает, что возвращаемый объект строки или набора
- строк будет доступен только для чтения и к нему не могут
- применяться операции сохранения. Объект строки
- <code>Zend_Db_Table_Row</code> со статусом
- <property>readOnly</property> будет бросать исключение
- при попытке произвести операцию сохранения (метод
- <code>save()</code>).
- </para>
- </listitem>
- <listitem>
- <para>
- Вы <emphasis>можете</emphasis> разрешить предложения
- JOIN в выборке для поиска в нескольких таблицах.
- </para>
- </listitem>
- <listitem>
- <para>
- Вы <emphasis>не можете</emphasis> указывать столбцы
- из присоединенных таблиц в качестве возвращаемых в
- строке/наборе строк. Попытка сделать это вызовет ошибку
- PHP. Это сделано для того, чтобы гарантировать
- целостность <code>Zend_Db_Table</code>, т.е.
- <code>Zend_Db_Table_Row</code> должен содержать
- столбцы только из той таблицы, которую представляет
- данный объект <code>Zend_Db_Table</code>.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- <example id="zend.db.table.qry.rows.set.simple.usage.example">
- <title>Простое использование</title>
- <programlisting language="php">
- <![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]>
- </programlisting>
- </example>
- </para>
- <para>
- В данной компоненте поддерживается fluent interface,
- поэтому пример выше может быть переписан в более краткой форме.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.fluent.interface.example">
- <title>Пример использования fluent interface</title>
- <programlisting language="php">
- <![CDATA[
- $table = new Bugs();
- $rows =
- $table->fetchAll($table->select()->where('bug_status = ?', 'NEW'));
- ]]>
- </programlisting>
- </example>
- </para>
- </sect3>
- <sect3 id="zend.db.table.fetch-all.usage">
- <title>Извлечение набора строк</title>
- <para>
- Вы можете извлекать наборы строк, используя любое другое
- условие, отличное от значения первичного ключа, через метод
- <code>fetchAll()</code> класса таблицы. Этот метод возвращает
- объект типа <code>Zend_Db_Table_Rowset_Abstract</code>.
- </para>
- <example id="zend.db.table.qry.rows.set.finding.row.example">
- <title>Пример поиска строк по выражению</title>
- <programlisting language="php">
- <![CDATA[
- $table = new Bugs();
- $select = $table->select()->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]>
- </programlisting>
- </example>
- <para>
- Вы можете также передавать условие для сортировки, которое
- используется в предложении <code>ORDER BY</code>, и
- целочисленные значения смещения и количества строк для
- предложения <code>LIMIT</code> или эквивалентной
- ему логики в СУРБД, не поддерживающих синтаксис
- <code>LIMIT</code>.
- </para>
- <example id="zend.db.table.fetch-all.example2">
- <title>Пример поиска строк по выражению</title>
- <programlisting language="php">
- <![CDATA[
- $table = new Bugs();
- $order = 'bug_id';
- // Требуется вернуть строки начиная с 21-ой и кончая 30-й
- $count = 10;
- $offset = 20;
- $select = $table->select()->where(array('bug_status = ?' => 'NEW'))
- ->order($order)
- ->limit($count, $offset);
- $rows = $table->fetchAll($select);
- ]]>
- </programlisting>
- </example>
- <para>
- Все агрументы в примере выше являются опциональными. Если вы
- опустите предложение ORDER, то строки из таблицы будут
- возвращаться в непредсказуемом порядке. Если не было
- установлено предложение LIMIT, то вы получите все
- соответствующие предложению WHERE строки из таблицы.
- </para>
- </sect3>
- <sect3 id="zend.db.table.advanced.usage">
- <title>Расширенное использование</title>
- <para>
- Для более точных и оптимизированных запросов может
- потребоваться ограничить количество столбцов, возвращаемых в
- строке/наборе строк. Это может быть достигнуто путем передачи
- предложения FROM объекту выборки.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.retrieving.a.example">
- <title>Извлечение определенных столбцов</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->from($table, array('bug_id', 'bug_description'))
- ->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]>
- </programlisting>
- </example>
- </para>
- <para>
- <important>
- <para>
- Полученный набор строк будет содержать строки, которые
- по-прежнему являются "рабочими", только они
- содержат не все столбцы таблицы. Если для неполной
- строки был вызван метод save(), то будут изменены только
- доступные в объекте столбцы.
- </para>
- </important>
- Вы можете также указывать выражения в предложении FROM, но в
- этом случае будуте получать строки/наборы строк,
- доступные только для чтения. В этом примере мы будем возвращать
- строки из таблицы Bugs, которые показывают количество
- ошибок, сообщенное конкретным пользователем. Обратите
- внимание на предложение GROUP. Столбец 'count' будет доступен в
- объекте строки, и к нему можно обращаться так же, как если бы он
- был частью схемы.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.retrieving.b.example">
- <title>Извлечение выражений как столбцов</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->from($table,
- array('COUNT(reported_by) as `count`', 'reported_by'))
- ->where('bug_status = ?', 'NEW')
- ->group('reported_by');
- $rows = $table->fetchAll($select);
- ]]>
- </programlisting>
- </example>
- Вы можете использовать поиск как часть вашего запроса
- для дальнейшей детализации ваших операций извлечения.
- В этом примере таблица Accounts используется для
- поиска всех новых ошибок, о которых сообщил пользователь 'Bob'.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.refine.example">
- <title>Использование таблицы поиска для фильтрации результатов, возвращаемых fetchAll()</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->where('bug_status = ?', 'NEW')
- ->join('accounts', 'accounts.account_name = bugs.reported_by')
- ->where('accounts.account_name = ?', 'Bob');
- $rows = $table->fetchAll($select);
- ]]>
- </programlisting>
- </example>
- </para>
- <para>
- Класс <classname>Zend_Db_Table_Select</classname> главным
- образом используется для соблюдения и проверки
- корректности запроса.
- Тем не менее, могут быть определенные случаи, когда
- нужна большая гибкость компоненты Zend_Db_Table_Row и
- не требуется доступная для чтения или удаления строка.
- Для этого отдельного случая использования возможно получение
- строки/набора строк путем передачи значения false методу
- setIntegrityCheck().
- В результате строка/набор строк будет возвращаться в
- "заблокированном" состоянии, это значит, что save(),
- delete() и методы для установки значений полей будут бросать
- исключения.
- </para>
- <example id="zend.db.table.qry.rows.set.integrity.example">
- <title>Отключение проверки целостности в Zend_Db_Table_Select для получения объединенных строк</title>
- <programlisting><![CDATA[
- $table = new Bugs();
- $select = $table->select()->setIntegrityCheck(false);
- $select->where('bug_status = ?', 'NEW')
- ->join('accounts',
- 'accounts.account_name = bugs.reported_by',
- 'account_name')
- ->where('accounts.account_name = ?', 'Bob');
- $rows = $table->fetchAll($select);
- ]]>
- </programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.fetch-row">
- <title>Извлечение одной строки</title>
- <para>
- Вы можете запрашивать одну строку, используя условия, аналогичные
- тем, что используются в методе <code>fetchAll()</code>.
- </para>
- <example id="zend.db.table.fetch-row.example1">
- <title>Пример поиска одной строки по выражению</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select()->where('bug_status = ?', 'NEW')
- ->order('bug_id');
- $row = $table->fetchRow($select);
- ]]>
- </programlisting>
- </example>
- <para>
- Этот метод возвращает объект типа Zend_Db_Table_Row_Abstract. Если
- по заданному вами условию поиска не найдено ни одной строки в
- таблице БД, то <code>fetchRow()</code> вернет значение
- <constant>NULL</constant>.
- </para>
- </sect2>
- <sect2 id="zend.db.table.info">
- <title>Получение метаданных таблицы</title>
- <para>
- Класс Zend_Db_Table_Abstract предоставляет некоторую информацию о
- его метаданных. Метод <code>info()</code> возвращает массив с
- данными о таблице, ее столбцах, первичном ключе и другие метаданные.
- </para>
- <example id="zend.db.table.info.example">
- <title>Пример получения имени таблицы</title>
- <programlisting language="php">
- <![CDATA[
- $table = new Bugs();
- $info = $table->info();
- echo "The table name is " . $info['name'] . "\n";
- ]]>
- </programlisting>
- </example>
- <para>
- Ключи массива, возвращаемого методом <code>info()</code>, описаны
- ниже.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>name</emphasis> => имя таблицы
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>cols</emphasis> =>
- массив имен столбцов в таблице
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>primary</emphasis> =>
- массив имен столбцов в первичном ключе
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>metadata</emphasis> =>
- ассоциативный массив, включающий в себя имена столбцов и
- соответствующие им данные о столбцах. Это информация,
- возвращаемая методом <code>describeTable()</code>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>rowClass</emphasis> => имя
- определенного класса, используемого для объектов строк,
- возвращаемых методами данного экземпляра таблицы. По
- умолчанию это Zend_Db_Table_Row.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>rowsetClass</emphasis> =>
- имя определенного класса, используемого для объектов
- наборов строк, возвращаемых методами данного экземпляра
- таблицы. По умолчанию это Zend_Db_Table_Rowset.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>referenceMap</emphasis> =>
- ассоциативный массив с данными о ссылках на другие таблицы.
- См. <xref linkend="zend.db.table.relationships.defining" />.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>dependentTables</emphasis> =>
- массив имен классов таблиц, на которые ссылается данная
- таблица. См.
- <xref linkend="zend.db.table.relationships.defining" />.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>schema</emphasis> =>
- имя схемы (базы данных, пространства таблиц) для данной
- таблицы.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.db.table.metadata.caching">
- <title>Кэширование метаданных таблицы</title>
- <para>
- По умолчанию <code>Zend_Db_Table_Abstract</code> производит запрос к
- БД для определения <link linkend="zend.db.table.info">метаданных
- таблицы</link> во время инстанцирования объекта таблицы. Т.е. когда
- создается новый объект таблицы, поведением по умолчанию является
- извлечение метаданных таблицы из БД через метод
- <code>describeTable()</code>.
- </para>
- <para>
- В некоторых условиях, особенно когда к одной и той же таблице БД
- создается много объектов таблиц, произведение запросов для
- получения метаданных для каждого экземпляря может быть нежелательным
- с точки зрения производительности. В таких случаях можно производить
- кэширование метаданных таблицы, полученных из БД.
- </para>
- <para>
- Есть два основных способа кэширования:
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>Вызов метода
- Zend_Db_Table_Abstract::setDefaultMetadataCache()</emphasis>
- - Это позволяет разработчику единовременно установить
- объект кэша, используемый в всех классах таблиц.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Конфигурирование
- Zend_Db_Table_Abstract::__construct()</emphasis> - Это
- позволяет разработчику установить объект кэша для
- определенного экземпляра класса таблицы.
- </para>
- </listitem>
- </itemizedlist>
- В обоих случаях определением кэша может быть <constant>NULL</constant>
- (т.е. не используется кэширование) или экземпляр класса
- <link linkend="zend.cache.frontends.core"><code>Zend_Cache_Core</code></link>.
- Эти методы могут использоваться вместе для того, чтобы
- использовать по умолчанию определенный объект кэша и при этом иметь
- возможность изменять его для конкретного объекта таблицы.
- </para>
- <example id="zend.db.table.metadata.caching-default">
- <title>Кэширование метаданных по умолчанию для всех объектов таблиц</title>
- <para>
- Следующий код показывает, как установить объект кэша,
- используемый по умолчанию во всех объектах таблиц:
- </para>
- <programlisting language="php"><![CDATA[
- // Сначала создается объект кэша
- $frontendOptions = array(
- 'automatic_serialization' => true
- );
- $backendOptions = array(
- 'cacheDir' => 'cacheDir'
- );
- $cache = Zend_Cache::factory('Core',
- 'File',
- $frontendOptions,
- $backendOptions);
- // Далее, объект кэша устанавливается в качестве используемого
- // во всех объектах таблиц
- Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
- // Класс таблицы
- class Bugs extends Zend_Db_Table_Abstract
- {
- // ...
- }
- // Каждый экземпляр таблицы Bugs теперь использует
- // кэширование метаданных по умолчанию
- $bugs = new Bugs();
- ]]>
- </programlisting>
- </example>
- <example id="zend.db.table.metadata.caching-instance">
- <title>Кэширование метаданных для одного объекта таблицы</title>
- <para>
- Следующий код показывает, как устанавливается кэширование
- метаданных для одного конкретного объекта таблицы:
- </para>
- <programlisting language="php"><![CDATA[
- // Сначала создается объект кэша
- $frontendOptions = array(
- 'automatic_serialization' => true
- );
- $backendOptions = array(
- 'cacheDir' => 'cacheDir'
- );
- $cache = Zend_Cache::factory('Core',
- 'File',
- $frontendOptions,
- $backendOptions);
- // Класс таблицы
- class Bugs extends Zend_Db_Table_Abstract
- {
- // ...
- }
- // Экземпляр конфигурируется при инстанцировании
- $bugs = new Bugs(array('metadataCache' => $cache));
- ]]>
- </programlisting>
- </example>
- <note>
- <title>Автоматическая сериализация через фронтэнд кэша</title>
- <para>
- Поскольку информация, возвращаемая методом адаптера
- describeTable(), является массивом, то убедитесь, что опция
- <code>automatic_serialization</code> установлена в
- <constant>TRUE</constant> для фронтэнда <code>Zend_Cache_Core</code>.
- </para>
- </note>
- <para>
- Несмотря на то, что в примерах выше используется
- <code>Zend_Cache_Backend_File</code>, разработчики могут
- использовать другие бэкэнды, наиболее подходящие в данной ситуации.
- Более подробную информацию читайте в разделе
- <link linkend="zend.cache">Zend_Cache</link>.
- </para>
- </sect2>
- <sect2 id="zend.db.table.extending">
- <title>Расширение класса таблицы</title>
- <sect3 id="zend.db.table.extending.row-rowset">
- <title>Использование собственных классов строки и набора строк</title>
- <para>
- По умолчанию методы класса таблицы возвращают наборы строк в
- экземплярах класса Zend_Db_Table_Rowset, и эти наборы строк
- содержат в себе коллекции экземпляров класса Zend_Db_Table_Row.
- Вы можете указать альтернативные классы, используемые вместо
- них, но в любом случае они должны наследовать от классов
- Zend_Db_Table_Rowset_Abstract и Zend_Db_Table_Row_Abstract
- соответственно.
- </para>
- <para>
- Вы можете указать классы строки и набора строк в
- массиве опций конструктора таблицы под ключами
- <code>'rowClass'</code> и <code>'rowsetClass'</code>
- соответственно. Задавайте имена классов в виде обычных строк.
- </para>
- <example id="zend.db.table.extending.row-rowset.example">
- <title>Пример указания классов строки и набора строк</title>
- <programlisting language="php"><![CDATA[
- class My_Row extends Zend_Db_Table_Row_Abstract
- {
- ...
- }
- class My_Rowset extends Zend_Db_Table_Rowset_Abstract
- {
- ...
- }
- $table = new Bugs(
- array(
- 'rowClass' => 'My_Row',
- 'rowsetClass' => 'My_Rowset'
- )
- );
- $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
- // Возвращает объект типа My_Rowset,
- // содержащий массив объектов типа My_Row
- $rows = $table->fetchAll($where);
- ]]>
- </programlisting>
- </example>
- <para>
- Вы можете сменить используемые классы, указав их через методы
- <code>setRowClass()</code> и <code>setRowsetClass()</code>.
- Это изменение применяется к создаваемым впоследствии строкам и
- наборам строк и не влияет на класс объектов строк и наборов
- строк, созданных ранее.
- </para>
- <example id="zend.db.table.extending.row-rowset.example2">
- <title>Пример смены используемых для строк и наборов строк классов</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
- // Возвращает объект типа Zend_Db_Table_Rowset,
- // содержащий массив объектов типа Zend_Db_Table_Row.
- $rowsStandard = $table->fetchAll($where);
- $table->setRowClass('My_Row');
- $table->setRowsetClass('My_Rowset');
- // Возвращает объект типа My_Rowset,
- // содержащий массив объектов типа My_Row.
- $rowsCustom = $table->fetchAll($where);
- // Объект $rowsStandard по прежнему существует и не изменился.
- ]]>
- </programlisting>
- </example>
- <para>
- Более подробную информацию о классах строки и набора строк
- ищите в <xref linkend="zend.db.table.row" /> и
- <xref linkend="zend.db.table.rowset" />.
- </para>
- </sect3>
- <sect3 id="zend.db.table.extending.insert-update">
- <title>Определение собственной логики для добавления, обновления и удаления строк</title>
- <para>
- Вы можете переопределить методы <code>insert()</code> и
- <code>update()</code> в своем классе таблицы. Это дает
- возможность реализовать собственный
- код, который исполняется до того, как будет выполнена операция с
- БД. Всегда вызывайте метод родительского класса после своих
- действий.
- </para>
- <example id="zend.db.table.extending.insert-update.example">
- <title>Собственная логика для управления отметками времени</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- public function insert(array $data)
- {
- // добавление timestamp
- if (empty($data['created_on'])) {
- $data['created_on'] = time();
- }
- return parent::insert($data);
- }
- public function update(array $data, $where)
- {
- // добавление timestamp
- if (empty($data['updated_on'])) {
- $data['updated_on'] = time();
- }
- return parent::update($data, $where);
- }
- }
- ]]>
- </programlisting>
- </example>
- <para>
- Вы можете также переопределить метод <code>delete()</code>.
- </para>
- </sect3>
- <sect3 id="zend.db.table.extending.finders">
- <title>Определение собственных методов для поиска</title>
- <para>
- Вы можете реализовать собственные методы запросов в своем классе
- таблицы, если приходится часто делать запросы к таблице с одними
- и теми же условиями. Большинство запросов могут быть написаны с
- использованием <code>fetchAll()</code>, но это требует написания
- повторяющегося кода для формирования условий запроса в том
- случае, если вам нужно выполнять запрос в нескольких местах
- вашего приложения. Поэтому будет удобным добавить метод в класс
- таблицы для выполнения часто используемых запросов к таблице.
- </para>
- <example id="zend.db.table.extending.finders.example">
- <title>Метод для поиска ошибок с определенным статусом</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- public function findByStatus($status)
- {
- $where = $this->getAdapter()->quoteInto('bug_status = ?', $status);
- return $this->fetchAll($where, 'bug_id');
- }
- }
- ]]>
- </programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.extending.inflection">
- <title>Определение инфлекции в Zend_Db_Table</title>
- <para>
- Некоторые разработчики предпочитают, чтобы имя класса таблицы
- сопоставлялось с именем таблицы в СУРБД с применением
- преобразования, называемого <emphasis>инфлекцией</emphasis>.
- </para>
- <para>
- Например, если имя вашего класса таблицы -
- "<code>BugsProducts</code>", то класс должен соответствовать
- физической таблице в БД с названием
- "<code>bugs_products</code>", если вы не произвели явное
- объявление свойства класса <varname>$_name</varname>. В данном
- преобразовании имя класса в формате "CamelCase" должно
- приводиться к нижнему регистру с разделением слов символом
- подчеркивания.
- </para>
- <para>
- Вы можете указать имя таблицы БД независимо то имени класса,
- объявив его в свойстве <varname>$_name</varname> во всех классах этой
- таблицы.
- </para>
- <para>
- Zend_Db_Table_Abstract не производит инфлекцию при получении
- имени таблицы. Если вы опустите
- объявление свойства <varname>$_name</varname> в своем классе таблицы,
- то класс будет соответствовать таблице в БД с точно таким же
- именем, как и у него.
- </para>
- <para>
- Было бы неуместным использовать преобразование идентификаторов
- из БД, поскольку это может привести к неоднозначности или
- сделать некоторые идентификаторы недоступными.
- Использование SQL-идентификаторов в том виде, в котором они
- присутствуют в БД, делает Zend_Db_Table_Abstract проще и гибче в
- использовании.
- </para>
- <para>
- Если вы предпочитаете использовать инфлекцию, то должны
- реализовать преобразование сами, переопределив метод
- <code>_setupTableName()</code> в своем классе таблицы. Одним из
- возможных способов является определение абстрактного класса,
- наследующего от Zend_Db_Table_Abstract, и объявление
- классов остальных таблиц как наследующих от этого нового
- класса.
- </para>
- <example id="zend.db.table.extending.inflection.example">
- <title>Пример абстрактного класса таблицы, реализующего инфлекцию</title>
- <programlisting language="php"><![CDATA[
- abstract class MyAbstractTable extends Zend_Db_Table_Abstract
- {
- protected function _setupTableName()
- {
- if (!$this->_name) {
- $this->_name = myCustomInflector(get_class($this));
- }
- parent::_setupTableName();
- }
- }
- class BugsProducts extends MyAbstractTable
- {
- }
- ]]>
- </programlisting>
- </example>
- <para>
- Реализация функций для произведения инфлекционного
- преобразования возлагается на разработчика. Zend Framework не
- предоставляет для этих целей готовых функций.
- </para>
- </sect3>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|