Zend_Db_Table.xml 82 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818
  1. <sect1 id="zend.db.table">
  2. <title>Zend_Db_Table</title>
  3. <sect2 id="zend.db.table.introduction">
  4. <title>Класс таблицы - введение</title>
  5. <para>
  6. Класс Zend_Db_Table является объектно-ориентированным интерфейсом к
  7. таблицам баз данных. Он предоставляет методы для многих общих
  8. операций над таблицами. Базовый класс является расширяемым, поэтому
  9. вы можете добавлять свою логику.
  10. </para>
  11. <para>
  12. Решением Zend_Db_Table является реализация паттерна
  13. <ulink url="http://www.martinfowler.com/eaaCatalog/tableDataGateway.html">Table Data Gateway</ulink>.
  14. Это решение также включает в себя класс, реализующий паттерн
  15. <ulink url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data Gateway</ulink>.
  16. </para>
  17. </sect2>
  18. <sect2 id="zend.db.table.defining">
  19. <title>Определение класса таблицы</title>
  20. <para>
  21. Для каждой таблицы в БД, к которой нужен доступ, определяется класс,
  22. наследующий от Zend_Db_Table_Abstract.
  23. </para>
  24. <sect3 id="zend.db.table.defining.table-schema">
  25. <title>Определение имени и схемы таблицы</title>
  26. <para>
  27. Указывайте таблицу, для которой определен этот класс, используя
  28. защищенную переменную <varname>$_name</varname>. Переменная
  29. должна содержать имя таблицы в том виде, в котором она
  30. представлена в БД.
  31. </para>
  32. <example id="zend.db.table.defining.table-schema.example1">
  33. <title>Объявление класса таблицы с явным определением имени таблицы</title>
  34. <programlisting language="php"><![CDATA[
  35. class Bugs extends Zend_Db_Table_Abstract
  36. {
  37. protected $_name = 'bugs';
  38. }
  39. ]]>
  40. </programlisting>
  41. </example>
  42. <para>
  43. Если вы не определили имя таблицы, то по умолчанию оно равно
  44. имени класса. Если вы предпочитаете этот путь, то имя класса
  45. должно иметь то же написание, что и имя таблицы в БД.
  46. </para>
  47. <example id="zend.db.table.defining.table-schema.example">
  48. <title>Объявление класса таблицы с неявным определением имени таблицы</title>
  49. <programlisting language="php"><![CDATA[
  50. class bugs extends Zend_Db_Table_Abstract
  51. {
  52. // имя таблицы соответствует имени класса
  53. }
  54. ]]>
  55. </programlisting>
  56. </example>
  57. <para>
  58. Вы можете также объявить схему таблицы в защищенной переменной
  59. <varname>$_schema</varname> или через добавленное
  60. перед именем таблицы имя схемы в свойстве <varname>$_name</varname>.
  61. Схема, указанная с помощью свойства <varname>$_name</varname>,
  62. имеет более высокий приоритет, чем схема, объявленная с помощью
  63. свойства <varname>$_schema</varname>. В некоторых СУРБД вместо
  64. термина "схема" используются термины "база данных" или
  65. "пространство таблиц", они используются аналогичным образом.
  66. </para>
  67. <example id="zend.db.table.defining.table-schema.example3">
  68. <title>Объявление класса таблицы со схемой</title>
  69. <programlisting language="php"><![CDATA[
  70. // Первый способ:
  71. class Bugs extends Zend_Db_Table_Abstract
  72. {
  73. protected $_schema = 'bug_db';
  74. protected $_name = 'bugs';
  75. }
  76. // Второй способ:
  77. class Bugs extends Zend_Db_Table_Abstract
  78. {
  79. protected $_name = 'bug_db.bugs';
  80. }
  81. // Если в обоих свойствах $_name м $_schema была объявлена схема,
  82. // то указанная в $_name имеет больший приоритет:
  83. class Bugs extends Zend_Db_Table_Abstract
  84. {
  85. protected $_name = 'bug_db.bugs';
  86. protected $_schema = 'ignored';
  87. }
  88. ]]>
  89. </programlisting>
  90. </example>
  91. <para>
  92. Схема и таблица могут быть указаны через конфигурационные
  93. директивы конструктора, которые замещают собой любые значения по
  94. умолчанию, определенные с помощью свойств <varname>$_name</varname> и
  95. <varname>$_schema</varname>. Спецификация схемы, данная через
  96. директиву <code>name</code>, замещает собой любое значение,
  97. переданное через опцию <code>schema</code>.
  98. </para>
  99. <example id="zend.db.table.defining.table-schema.example.constructor">
  100. <title>Объявление имен таблицы и схемы во время инстанцирования</title>
  101. <programlisting language="php"><![CDATA[
  102. class Bugs extends Zend_Db_Table_Abstract
  103. {
  104. }
  105. // Первый способ:
  106. $tableBugs = new Bugs(array('name' => 'bugs', 'schema' => 'bug_db'));
  107. // Второй способ:
  108. $tableBugs = new Bugs(array('name' => 'bug_db.bugs');
  109. // Если в обоих опциях 'name' и 'schema' была объявлена схема,
  110. // то указанная в 'name' имеет больший приоритет:
  111. $tableBugs = new Bugs(array('name' => 'bug_db.bugs',
  112. 'schema' => 'ignored');
  113. ]]>
  114. </programlisting>
  115. </example>
  116. <para>
  117. Если вы не указали имя схемы, то по умолчанию это будет
  118. схема, к которой подключен ваш экземпляр адаптера БД.
  119. </para>
  120. </sect3>
  121. <sect3 id="zend.db.table.defining.primary-key">
  122. <title>Определение первичного ключа таблицы</title>
  123. <para>
  124. Каждая таблица должна иметь первичный ключ. Вы можете объявить
  125. столбец для первичного ключа, используя защищенную переменную
  126. <varname>$_primary</varname>. Это может быть строка с именем одного
  127. столбца или массив имен столбцов, если первичный ключ является
  128. составным.
  129. </para>
  130. <example id="zend.db.table.defining.primary-key.example">
  131. <title>Пример определения первичного ключа</title>
  132. <programlisting language="php"><![CDATA[
  133. class Bugs extends Zend_Db_Table_Abstract
  134. {
  135. protected $_name = 'bugs';
  136. protected $_primary = 'bug_id';
  137. }
  138. ]]>
  139. </programlisting>
  140. </example>
  141. <para>
  142. Если вы не задали первичный ключ, то Zend_Db_Table_Abstract
  143. пытается определить его, основываясь на данных, полученных
  144. через метод <code>describeTable()</code>.
  145. </para>
  146. <note>
  147. <para>
  148. Класс таблицы должен знать, какой столбец (или столбцы)
  149. используются для уникальной адресации строк. Если в
  150. классе таблицы или аргументах конструктора (а также в
  151. метаданных таблицы, полученных через метод
  152. <code>describeTable()</code>) не были указаны
  153. первичные ключи, то эта таблица не может использоваться
  154. через Zend_Db_Table.
  155. </para>
  156. </note>
  157. </sect3>
  158. <sect3 id="zend.db.table.defining.setup">
  159. <title>Переопределение методов установки таблицы</title>
  160. <para>
  161. Когда создается экземпляр класса таблицы, конструктор вызывает
  162. ряд защищенных методов, инициализирующих метаданные для таблицы.
  163. Вы можете переопределить любые из этих методов для того, чтобы
  164. явно определить эти метаданные. Помните, что в конце должен
  165. вызываться родительский метод.
  166. </para>
  167. <example id="zend.db.table.defining.setup.example">
  168. <title>Пример переопределения метода _setupTableName()</title>
  169. <programlisting language="php">
  170. <![CDATA[
  171. class Bugs extends Zend_Db_Table_Abstract
  172. {
  173. protected function _setupTableName()
  174. {
  175. $this->_name = 'bugs';
  176. parent::_setupTableName();
  177. }
  178. }
  179. ]]>
  180. </programlisting>
  181. </example>
  182. <para>
  183. Методы установки могут быть переопределены следующим образом:
  184. </para>
  185. <itemizedlist>
  186. <listitem>
  187. <para>
  188. <code>_setupDatabaseAdapter()</code> проверяет, был ли
  189. предоставлен адаптер БД, и извлекает используемый по
  190. умолчанию адаптер из реестра, если необходимо.
  191. Переопределив этот метод, вы можете
  192. установить адаптер БД из других источников.
  193. </para>
  194. </listitem>
  195. <listitem>
  196. <para>
  197. <code>_setupTableName()</code> по умолчанию получает имя
  198. таблицы из имени класса. Переопределив
  199. этот метод, вы можете установить имя таблицы до того,
  200. как будут произведены эти действия по умолчанию.
  201. </para>
  202. </listitem>
  203. <listitem>
  204. <para>
  205. <code>_setupMetadata()</code> устанавливает схему, если
  206. имя таблицы содержит структуру "schema.table", вызывает
  207. <code>describeTable()</code> для получения метаданных,
  208. по умолчанию определяет массив столбцов
  209. <varname>$_cols</varname>, полученных
  210. через <code>describeTable()</code>. Переопределелив этот
  211. метод, вы можете устанавливать столбцы самостоятельно.
  212. </para>
  213. </listitem>
  214. <listitem>
  215. <para>
  216. <code>_setupPrimaryKey()</code> по умолчанию
  217. устанавливает столбцы первичного ключа, полученные через
  218. <code>describeTable()</code>, и проверяет, входят ли
  219. столбцы первичного ключа в массив <varname>$_cols</varname>.
  220. Переопределив этот метод, вы можете устанавливать
  221. столбцы первичного ключа.
  222. </para>
  223. </listitem>
  224. </itemizedlist>
  225. </sect3>
  226. <sect3 id="zend.db.table.initialization">
  227. <title>Инициализация таблицы</title>
  228. <para>
  229. Если при создании объекта таблицы требуется выполнять код,
  230. реализующий логику приложения, то вы можете поместить этот код в
  231. метод <code>init()</code>, который вызвается после того, как
  232. были обработаны все метаданные таблицы. Рекомендуется
  233. использовать этот способ вместо переопределения метода
  234. <code>__construct</code>, если только не требуется изменять
  235. метаданные программным путем.
  236. <example id="zend.db.table.defining.init.usage.example">
  237. <title>Пример использования метода init()</title>
  238. <programlisting language="php">
  239. <![CDATA[
  240. class Bugs extends Zend_Db_Table_Abstract
  241. {
  242. protected $_observer;
  243. protected function init()
  244. {
  245. $this->_observer = new MyObserverClass();
  246. }
  247. }
  248. ]]>
  249. </programlisting>
  250. </example>
  251. </para>
  252. </sect3>
  253. </sect2>
  254. <sect2 id="zend.db.table.constructing">
  255. <title>Создание экземпляра класса таблицы</title>
  256. <para>
  257. До того, как начать использование класса таблицы, создайте его
  258. экземпляр, используя конструктор. Единственным аргументом
  259. конструктора является массив опций. Наиболее важной опцией для
  260. конструктора является экземпляр адаптера БД, представляющий текущее
  261. соединение к какой-либо СУРБД. Есть три способа передачи адаптера БД
  262. классу таблицы, и эти три способа описаны ниже:
  263. </para>
  264. <sect3 id="zend.db.table.constructing.adapter">
  265. <title>Установка адаптера БД</title>
  266. <para>
  267. Первым способом предоставления адаптера БД классу таблицы
  268. является передача объекта типа Zend_Db_Adapter_Abstract в
  269. массиве опций под ключом <code>'db'</code>.
  270. </para>
  271. <example id="zend.db.table.constructing.adapter.example">
  272. <title>Пример создания экземпляра таблицы с использованием объекта адаптера</title>
  273. <programlisting language="php">
  274. <![CDATA[
  275. $db = Zend_Db::factory('PDO_MYSQL', $options);
  276. $table = new Bugs(array('db' => $db));
  277. ]]>
  278. </programlisting>
  279. </example>
  280. </sect3>
  281. <sect3 id="zend.db.table.constructing.default-adapter">
  282. <title>Установка используемого по умолчанию адаптера БД</title>
  283. <para>
  284. Вторым способом предоставления адаптера БД классу таблицы
  285. является декларирование объекта типа Zend_Db_Adapter_Abstract
  286. как используемого по умолчанию для всех экземпляров таблиц в
  287. вашем приложении. Вы можете делать это через статический метод
  288. <code>Zend_Db_Table_Abstract::setDefaultAdapter()</code>. Его
  289. аргументом является объект типа Zend_Db_Adapter_Abstract.
  290. </para>
  291. <example id="zend.db.table.constructing.default-adapter.example">
  292. <title>Пример создания экземпляра таблицы с адаптером, используемым по умолчанию</title>
  293. <programlisting language="php">
  294. <![CDATA[
  295. $db = Zend_Db::factory('PDO_MYSQL', $options);
  296. Zend_Db_Table_Abstract::setDefaultAdapter($db);
  297. // Далее...
  298. $table = new Bugs();
  299. ]]>
  300. </programlisting>
  301. </example>
  302. <para>
  303. Может быть удобным создавать объект адаптера БД в центральной
  304. части вашего приложения - например, в загрузочном коде - и затем
  305. сохранять его как адаптер, используемый по умолчанию. Это дает
  306. возможность быть уверенным в том, что во всем приложении
  307. используется один и тот же экземпляр адаптера. Но установка
  308. адаптера, используемого по умолчанию, ограничена одним
  309. экземпляром адаптера.
  310. </para>
  311. </sect3>
  312. <sect3 id="zend.db.table.constructing.registry">
  313. <title>Хранение адаптера БД в реестре</title>
  314. <para>
  315. Третий способ передачи адаптера БД классу таблицы -
  316. передача строки в массиве опций под ключом <code>'db'</code>.
  317. Эта строка используется как ключ для статического экземпляра
  318. Zend_Registry, в котором под этим ключом должен храниться объект
  319. типа Zend_Db_Adapter_Abstract.
  320. </para>
  321. <example id="zend.db.table.constructing.registry.example">
  322. <title>Пример создания экземпляра таблицы с использованием ключа реестра</title>
  323. <programlisting language="php">
  324. <![CDATA[
  325. $db = Zend_Db::factory('PDO_MYSQL', $options);
  326. Zend_Registry::set('my_db', $db);
  327. // Далее...
  328. $table = new Bugs(array('db' => 'my_db'));
  329. ]]>
  330. </programlisting>
  331. </example>
  332. <para>
  333. Как и в случае установки адаптера, используемого по умолчанию,
  334. это дает возможность быть уверенным в том, что во всем
  335. приложении используется один и тот же адаптер, но использование
  336. реестра является более гибким, т.к. вы можете хранить в
  337. нем более одного экземпляра адаптера. Экземпляр адаптера
  338. является индивидуальным для конкретной СУРБД и экземпляра БД.
  339. Если в вашем приложении необходимо подключаться к нескольким БД
  340. или даже различным СУРБД, то вам нужно использовать несколько
  341. адаптеров.
  342. </para>
  343. </sect3>
  344. </sect2>
  345. <sect2 id="zend.db.table.insert">
  346. <title>Добавление строк в таблицу</title>
  347. <para>
  348. Вы можете использовать объект таблицы для добавления строк в таблицу
  349. БД, на которой основан объект таблицы. Для этого используйте метод
  350. <code>insert()</code> в объекте таблицы. Аргументом является
  351. ассоциативный массив, содержащий имена столбцов и соответствующие им
  352. значения.
  353. </para>
  354. <example id="zend.db.table.insert.example">
  355. <title>Пример добавления строк в таблицу</title>
  356. <programlisting language="php"><![CDATA[
  357. $table = new Bugs();
  358. $data = array(
  359. 'created_on' => '2007-03-22',
  360. 'bug_description' => 'Something wrong',
  361. 'bug_status' => 'NEW'
  362. );
  363. $table->insert($data);
  364. ]]>
  365. </programlisting>
  366. </example>
  367. <para>
  368. По умолчанию значения в вашем массиве данных добавляются как
  369. буквенные значения, с использованием параметров. Если вам нужно,
  370. чтобы они интерпретировались как выражения SQL, то необходимо
  371. обозначить их отличие от простых строк. Для этого используйте
  372. объекты типа Zend_Db_Expr.
  373. </para>
  374. <example id="zend.db.table.insert.example-expr">
  375. <title>Пример добавления выражений в таблицу</title>
  376. <programlisting language="php"><![CDATA[
  377. $table = new Bugs();
  378. $data = array(
  379. 'created_on' => new Zend_Db_Expr('CURDATE()'),
  380. 'bug_description' => 'Something wrong',
  381. 'bug_status' => 'NEW'
  382. );
  383. ]]>
  384. </programlisting>
  385. </example>
  386. <para>
  387. В примере добавления строки выше предполагается, что таблица имеет
  388. автоинкрементный первичный ключ. Это принятое по умолчанию поведение
  389. Zend_Db_Table_Abstract, но есть и другие типы первичных ключей.
  390. Следующий раздел описывает, как поддерживаются различные типы
  391. первичных ключей.
  392. </para>
  393. <sect3 id="zend.db.table.insert.key-auto">
  394. <title>Использование таблицы с автоинкрементным ключом</title>
  395. <para>
  396. Автоинкрементный первичный ключ генерирует уникальное
  397. целочисленное значение, если вы опустите столбец для
  398. первичного ключа в своем операторе <code>INSERT</code>.
  399. </para>
  400. <para>
  401. Если защищенная переменная в Zend_Db_Table_Abstract
  402. <varname>$_sequence</varname> имеет булево значение <constant>TRUE</constant>,
  403. то класс предполагает, что таблица имеет автоинкрементный
  404. столбец.
  405. </para>
  406. <example id="zend.db.table.insert.key-auto.example">
  407. <title>Пример объявления таблицы с автоинкрементным первичным ключом</title>
  408. <programlisting language="php"><![CDATA[
  409. class Bugs extends Zend_Db_Table_Abstract
  410. {
  411. protected $_name = 'bugs';
  412. // Это значение по умолчанию присутствует в Zend_Db_Table_Abstract,
  413. // устанавливать его не обязательно
  414. protected $_sequence = true;
  415. }
  416. ]]>
  417. </programlisting>
  418. </example>
  419. <para>
  420. Примерами СУРБД, поддерживающих автоинкрементные первичные ключи
  421. являются MySQL, Microsoft SQL Server и SQLite.
  422. </para>
  423. <para>
  424. PostgreSQL имеет нотацию <code>SERIAL</code>, которая неявно
  425. определяет последовательность, основанную на имени таблицы и
  426. столбца, и использует ее для генерации значений ключа при
  427. добавлении новых строк. IBM DB2 имеет нотацию
  428. <code>IDENTITY</code> которая работает аналогичным образом.
  429. Если вы используете одну из этих нотаций, то интерпретируйте
  430. свой класс Zend_Db_Table как имеющий автоинкрементный столбец,
  431. при этом члена <varname>$_sequence</varname> должен иметь значение
  432. <constant>TRUE</constant>.
  433. </para>
  434. </sect3>
  435. <sect3 id="zend.db.table.insert.key-sequence">
  436. <title>Использование таблицы с последовательностью</title>
  437. <para>
  438. Последовательность (sequence) является объектом базы данных,
  439. генерирующим уникальные значения, которые могут
  440. использоваться как значения уникальных ключей в одной и более
  441. таблицах БД.
  442. </para>
  443. <para>
  444. Если вы присвоили <varname>$_sequence</varname> строковое значение,
  445. то Zend_Db_Table_Abstract считает строку именем объекта
  446. последовательности в БД. Последовательность запускается для
  447. генерации нового значения, и это значение используется в
  448. операции
  449. <code>INSERT</code>.
  450. </para>
  451. <example id="zend.db.table.insert.key-sequence.example">
  452. <title>Пример объявления таблицы с последовательностью</title>
  453. <programlisting language="php"><![CDATA[
  454. class Bugs extends Zend_Db_Table_Abstract
  455. {
  456. protected $_name = 'bugs';
  457. protected $_sequence = 'bug_sequence';
  458. }
  459. ]]>
  460. </programlisting>
  461. </example>
  462. <para>
  463. Примерами СУРБД, поддерживающих объекты последовательностей
  464. являются Oracle, PostgreSQL и IBM DB2.
  465. </para>
  466. <para>
  467. PostgreSQL и IBM DB2 также имеют синтаксис, который неявно
  468. определяет последовательности и связывает их со столбцами.
  469. Если вы используете эту нотацию, то интерпретируйте таблицу
  470. как имеющую автоинкрементный ключевой столбец. Задавайте имя
  471. последовательности в виде строки только в тех случаях, когда вы
  472. собираетесь явно вызывать последовательности для получения
  473. следующего значения ключа.
  474. </para>
  475. </sect3>
  476. <sect3 id="zend.db.table.insert.key-natural">
  477. <title>Использование таблицы с естественным ключом</title>
  478. <para>
  479. Некоторые таблицы имеют естественные ключи. Это означает, что
  480. ключ не генерируется автоматически таблицей или
  481. последовательностью. В этом случае вы должны установить значение
  482. первичного ключа.
  483. </para>
  484. <para>
  485. Если вы присвоили <varname>$_sequence</varname> булево значение
  486. <constant>FALSE</constant>, то Zend_Db_Table_Abstract считает, что
  487. таблица имеет естественный первичный ключ. Вы должны
  488. предоставлять значения для столбцов первичного ключа в массиве
  489. данных для метода <code>insert()</code>, иначе метод бросает
  490. исключение Zend_Db_Table_Exception.
  491. </para>
  492. <example id="zend.db.table.insert.key-natural.example">
  493. <title>Пример объявления таблицы с естественным ключом</title>
  494. <programlisting language="php"><![CDATA[
  495. class BugStatus extends Zend_Db_Table_Abstract
  496. {
  497. protected $_name = 'bug_status';
  498. protected $_sequence = false;
  499. }
  500. ]]>
  501. </programlisting>
  502. </example>
  503. <note>
  504. <para>
  505. Все СУРБД поддерживают таблицы с естественными ключами.
  506. Примеры таблиц, часто объявляемых как имеющие естественные
  507. ключи: справочные таблицы, таблицы пересечений в отношениях
  508. "многие-ко-многим", большинство таблиц с составными
  509. ключами.
  510. </para>
  511. </note>
  512. </sect3>
  513. </sect2>
  514. <sect2 id="zend.db.table.update">
  515. <title>Обновление строк в таблице</title>
  516. <para>
  517. Вы можете обновлять строки в таблице БД, используя метод
  518. <code>update</code> класса таблицы. Этот метод принимает два
  519. аргумента: первым является ассоциативный массив столбцов, которые
  520. требуется изменить, и новых значений, присваиваемых этим столбцам;
  521. вторым - выражение SQL, которое используется в предложении
  522. <code>WHERE</code> в качестве условия изменения строки в операции
  523. <code>UPDATE</code>.
  524. </para>
  525. <example id="zend.db.table.update.example">
  526. <title>Пример обновления строк в таблице</title>
  527. <programlisting language="php"><![CDATA[
  528. $table = new Bugs();
  529. $data = array(
  530. 'updated_on' => '2007-03-23',
  531. 'bug_status' => 'FIXED'
  532. );
  533. $where = $table->getAdapter()->quoteInto('bug_id = ?', 1234);
  534. $table->update($data, $where);
  535. ]]>
  536. </programlisting>
  537. </example>
  538. <para>
  539. Поскольку метод таблицы <code>update()</code> в свою очередь
  540. использует метод адаптера БД
  541. <link linkend="zend.db.adapter.update"><code>update()</code></link>,
  542. то второй аргумент может быть массивом SQL-выражений. Выражения
  543. объединяются как булевы условия через оператор <code>AND</code>.
  544. </para>
  545. <note>
  546. <para>
  547. Значения и идентификаторы в SQL-выражении не заключаются в
  548. кавычки автоматически. Если имеются значения или идентификаторы,
  549. которые требуют заключения в кавычки, то вы должны произвести
  550. его сами. Используйте методы <code>quote()</code>,
  551. <code>quoteInto()</code> и <code>quoteIdentifier()</code>
  552. адаптера БД.
  553. </para>
  554. </note>
  555. </sect2>
  556. <sect2 id="zend.db.table.delete">
  557. <title>Удаление строк из таблицы</title>
  558. <para>
  559. Вы можете удалять строки из таблицы базы данных, используя метод
  560. <code>delete()</code>. Этот метод принимает один аргумент,
  561. являющийся SQL-выражением, который используется в предложении
  562. <code>WHERE</code> в качестве условия, по которому удаляются строки.
  563. </para>
  564. <example id="zend.db.table.delete.example">
  565. <title>Пример удаления строк из таблицы</title>
  566. <programlisting language="php"><![CDATA[
  567. $table = new Bugs();
  568. $where = $table->getAdapter()->quoteInto('bug_id = ?', 1235);
  569. $table->delete($where);
  570. ]]>
  571. </programlisting>
  572. </example>
  573. <para>
  574. Поскольку метод таблицы в свою очередь использует метод
  575. <code>delete()</code> адаптера БД, то второй аргумент может быть
  576. массивом SQL-выражений. Выражения объединяются как булевы условия
  577. через оператор <code>AND</code>.
  578. </para>
  579. <note>
  580. <para>
  581. Значения и идентификаторы в SQL-выражении не заключаются в
  582. кавычки автоматически. Если имеются значения или идентификаторы,
  583. которые требуют заключения в кавычки, то вы должны произвести
  584. его сами. Используйте методы <code>quote()</code>,
  585. <code>quoteInto()</code> и <code>quoteIdentifier()</code>
  586. адаптера БД.
  587. </para>
  588. </note>
  589. </sect2>
  590. <sect2 id="zend.db.table.find">
  591. <title>Извлечение строк по первичному ключу</title>
  592. <para>
  593. Вы можете запрашивать из таблицы БД строки, соответствующие
  594. определенным значениям в первичном ключе, используя метод
  595. <code>find()</code>. Первым аргументом этого метода является
  596. единственное значение или массив значений, сопоставляемых с
  597. первичным ключом таблицы.
  598. </para>
  599. <example id="zend.db.table.find.example">
  600. <title>Пример извлечения строк по значениям первичного ключа</title>
  601. <programlisting language="php"><![CDATA[
  602. $table = new Bugs();
  603. // Запрос одной строки
  604. // Возвращает набор строк (Rowset)
  605. $rows = $table->find(1234);
  606. // Запрос нескольких строк
  607. // Также возвращает набор строк (Rowset)
  608. $rows = $table->find(array(1234, 5678));
  609. ]]>
  610. </programlisting>
  611. </example>
  612. <para>
  613. Если вы задали одно значение, то метод вернет максимум одну
  614. строку, потому что первичный ключ не может содержать повторяющиеся
  615. значения и должна быть максимум одна строка в таблице БД,
  616. соответствующая данному значению. Если вы задали несколько
  617. значений, то метод вернет максимум столько строк, сколько
  618. несовпадающих значений было задано.
  619. </para>
  620. <para>
  621. Метод <code>find()</code> может возвращать меньше строк, чем было
  622. задано значений для первичного ключа, если для некоторых значений
  623. нет соответствующих строк в таблице БД. Метод может даже вернуть
  624. нулевое количество строк. Поскольку количество возвращаемых строк
  625. является переменным, то метод <code>find()</code> возвращает объект
  626. типа Zend_Db_Table_Rowset_Abstract (набор строк).
  627. </para>
  628. <para>
  629. Если первичный ключ является составным, т.e. он состоит из
  630. нескольких столбцов, то можно задать добавочные столбцы как
  631. дополнительные аргументы метода <code>find()</code>. Вы должны
  632. передать столько аргументов, сколько столбцов в первичном
  633. ключе таблицы.
  634. </para>
  635. <para>
  636. Для того чтобы найти несколько строк с составным первичным ключом,
  637. передавайте массив для каждого из аргументов. Все эти массивы должны
  638. иметь одно и то же количество элементов. Значения из всех массивов
  639. объединяются в "кортежи" в порядке следования; например, первые
  640. элементы каждого массива определяют значение первого составного
  641. первичного ключа, вторые элементы - второго составного ключа и т.д.
  642. </para>
  643. <example id="zend.db.table.find.example-compound">
  644. <title>Пример извлечения строк по значениям составного первичного ключа</title>
  645. <para>
  646. Вызов метода <code>find()</code> ниже для поиска нескольких
  647. строк может соответствовать двум строкам в БД. Первая строка
  648. должна иметь значение первичного ключа (1234, 'ABC'), вторая -
  649. (5678, 'DEF').
  650. </para>
  651. <programlisting language="php"><![CDATA[
  652. class BugsProducts extends Zend_Db_Table_Abstract
  653. {
  654. protected $_name = 'bugs_products';
  655. protected $_primary = array('bug_id', 'product_id');
  656. }
  657. $table = new BugsProducts();
  658. // Запрашивает единственную строку через составной первичный ключ
  659. // Возвращает набор строк (Rowset)
  660. $rows = $table->find(1234, 'ABC');
  661. // Запрашивает несколько строк через составной первичный ключ
  662. // Также возвращает набор строк (Rowset)
  663. $rows = $table->find(array(1234, 5678), array('ABC', 'DEF'));
  664. ]]>
  665. </programlisting>
  666. </example>
  667. </sect2>
  668. <sect2 id="zend.db.table.fetch-all">
  669. <title>Извлечение наборов строк</title>
  670. <sect3 id="zend.db.table.fetch-all.select">
  671. <title>API для произведения выборки</title>
  672. <para>
  673. <warning>
  674. <para>
  675. API для операций извлечения был изменен для того,
  676. чтобы объект <code>Zend_Db_Table_Select</code> мог
  677. изменять запрос. Тем не менее, не рекомендуемый
  678. сейчас вариант использования <code>fetchRow()</code> и
  679. <code>fetchAll()</code> будет работать без изменений.
  680. </para>
  681. <para>
  682. Следующие варианты являются корректными и
  683. функционально идентичными, но, тем не менее,
  684. рекомендуется обновить свой код с тем, чтобы
  685. получить преимущества нового подхода.
  686. </para>
  687. <para>
  688. <programlisting language="php">
  689. <![CDATA[
  690. // Извлечение набора строк
  691. $rows = $table->fetchAll('bug_status = "NEW"', 'bug_id ASC', 10, 0);
  692. $rows = $table->fetchAll($table->select()->where('bug_status = ?', 'NEW')
  693. ->order('bug_id ASC')
  694. ->limit(10, 0));
  695. // Извлечение одной строки
  696. $row = $table->fetchRow('bug_status = "NEW"', 'bug_id ASC');
  697. $row = $table->fetchRow($table->select()->where('bug_status = ?', 'NEW')
  698. ->order('bug_id ASC'));
  699. ]]>
  700. </programlisting>
  701. </para>
  702. </warning>
  703. </para>
  704. <para>
  705. Объект <classname>Zend_Db_Table_Select</classname> является
  706. расширением объекта <classname>Zend_Db_Select</classname>,
  707. который накладывает некоторые специфические ограничения
  708. на запрос. Ниже перечислены дополнительные возможности и
  709. ограничения этого класса:
  710. </para>
  711. <itemizedlist>
  712. <listitem>
  713. <para>
  714. Вы <emphasis>можете</emphasis> выбрать возвращение
  715. набора столбцов запросами fetchRow и fetchAll.
  716. Это дает преимущества в плане оптимизации там, где
  717. извлечение большого набора строк со всеми столбцами
  718. было бы не желательным.
  719. </para>
  720. </listitem>
  721. <listitem>
  722. <para>
  723. Вы <emphasis>можете</emphasis> указывать столбцы,
  724. которые определяют выражения в таблице. Но это также
  725. означает, что возвращаемый объект строки или набора
  726. строк будет доступен только для чтения и к нему не могут
  727. применяться операции сохранения. Объект строки
  728. <code>Zend_Db_Table_Row</code> со статусом
  729. <property>readOnly</property> будет бросать исключение
  730. при попытке произвести операцию сохранения (метод
  731. <code>save()</code>).
  732. </para>
  733. </listitem>
  734. <listitem>
  735. <para>
  736. Вы <emphasis>можете</emphasis> разрешить предложения
  737. JOIN в выборке для поиска в нескольких таблицах.
  738. </para>
  739. </listitem>
  740. <listitem>
  741. <para>
  742. Вы <emphasis>не можете</emphasis> указывать столбцы
  743. из присоединенных таблиц в качестве возвращаемых в
  744. строке/наборе строк. Попытка сделать это вызовет ошибку
  745. PHP. Это сделано для того, чтобы гарантировать
  746. целостность <code>Zend_Db_Table</code>, т.е.
  747. <code>Zend_Db_Table_Row</code> должен содержать
  748. столбцы только из той таблицы, которую представляет
  749. данный объект <code>Zend_Db_Table</code>.
  750. </para>
  751. </listitem>
  752. </itemizedlist>
  753. <para>
  754. <example id="zend.db.table.qry.rows.set.simple.usage.example">
  755. <title>Простое использование</title>
  756. <programlisting language="php">
  757. <![CDATA[
  758. $table = new Bugs();
  759. $select = $table->select();
  760. $select->where('bug_status = ?', 'NEW');
  761. $rows = $table->fetchAll($select);
  762. ]]>
  763. </programlisting>
  764. </example>
  765. </para>
  766. <para>
  767. В данной компоненте поддерживается fluent interface,
  768. поэтому пример выше может быть переписан в более краткой форме.
  769. </para>
  770. <para>
  771. <example id="zend.db.table.qry.rows.set.fluent.interface.example">
  772. <title>Пример использования fluent interface</title>
  773. <programlisting language="php">
  774. <![CDATA[
  775. $table = new Bugs();
  776. $rows =
  777. $table->fetchAll($table->select()->where('bug_status = ?', 'NEW'));
  778. ]]>
  779. </programlisting>
  780. </example>
  781. </para>
  782. </sect3>
  783. <sect3 id="zend.db.table.fetch-all.usage">
  784. <title>Извлечение набора строк</title>
  785. <para>
  786. Вы можете извлекать наборы строк, используя любое другое
  787. условие, отличное от значения первичного ключа, через метод
  788. <code>fetchAll()</code> класса таблицы. Этот метод возвращает
  789. объект типа <code>Zend_Db_Table_Rowset_Abstract</code>.
  790. </para>
  791. <example id="zend.db.table.qry.rows.set.finding.row.example">
  792. <title>Пример поиска строк по выражению</title>
  793. <programlisting language="php">
  794. <![CDATA[
  795. $table = new Bugs();
  796. $select = $table->select()->where('bug_status = ?', 'NEW');
  797. $rows = $table->fetchAll($select);
  798. ]]>
  799. </programlisting>
  800. </example>
  801. <para>
  802. Вы можете также передавать условие для сортировки, которое
  803. используется в предложении <code>ORDER BY</code>, и
  804. целочисленные значения смещения и количества строк для
  805. предложения <code>LIMIT</code> или эквивалентной
  806. ему логики в СУРБД, не поддерживающих синтаксис
  807. <code>LIMIT</code>.
  808. </para>
  809. <example id="zend.db.table.fetch-all.example2">
  810. <title>Пример поиска строк по выражению</title>
  811. <programlisting language="php">
  812. <![CDATA[
  813. $table = new Bugs();
  814. $order = 'bug_id';
  815. // Требуется вернуть строки начиная с 21-ой и кончая 30-й
  816. $count = 10;
  817. $offset = 20;
  818. $select = $table->select()->where(array('bug_status = ?' => 'NEW'))
  819. ->order($order)
  820. ->limit($count, $offset);
  821. $rows = $table->fetchAll($select);
  822. ]]>
  823. </programlisting>
  824. </example>
  825. <para>
  826. Все агрументы в примере выше являются опциональными. Если вы
  827. опустите предложение ORDER, то строки из таблицы будут
  828. возвращаться в непредсказуемом порядке. Если не было
  829. установлено предложение LIMIT, то вы получите все
  830. соответствующие предложению WHERE строки из таблицы.
  831. </para>
  832. </sect3>
  833. <sect3 id="zend.db.table.advanced.usage">
  834. <title>Расширенное использование</title>
  835. <para>
  836. Для более точных и оптимизированных запросов может
  837. потребоваться ограничить количество столбцов, возвращаемых в
  838. строке/наборе строк. Это может быть достигнуто путем передачи
  839. предложения FROM объекту выборки.
  840. </para>
  841. <para>
  842. <example id="zend.db.table.qry.rows.set.retrieving.a.example">
  843. <title>Извлечение определенных столбцов</title>
  844. <programlisting language="php"><![CDATA[
  845. $table = new Bugs();
  846. $select = $table->select();
  847. $select->from($table, array('bug_id', 'bug_description'))
  848. ->where('bug_status = ?', 'NEW');
  849. $rows = $table->fetchAll($select);
  850. ]]>
  851. </programlisting>
  852. </example>
  853. </para>
  854. <para>
  855. <important>
  856. <para>
  857. Полученный набор строк будет содержать строки, которые
  858. по-прежнему являются "рабочими", только они
  859. содержат не все столбцы таблицы. Если для неполной
  860. строки был вызван метод save(), то будут изменены только
  861. доступные в объекте столбцы.
  862. </para>
  863. </important>
  864. Вы можете также указывать выражения в предложении FROM, но в
  865. этом случае будуте получать строки/наборы строк,
  866. доступные только для чтения. В этом примере мы будем возвращать
  867. строки из таблицы Bugs, которые показывают количество
  868. ошибок, сообщенное конкретным пользователем. Обратите
  869. внимание на предложение GROUP. Столбец 'count' будет доступен в
  870. объекте строки, и к нему можно обращаться так же, как если бы он
  871. был частью схемы.
  872. </para>
  873. <para>
  874. <example id="zend.db.table.qry.rows.set.retrieving.b.example">
  875. <title>Извлечение выражений как столбцов</title>
  876. <programlisting language="php"><![CDATA[
  877. $table = new Bugs();
  878. $select = $table->select();
  879. $select->from($table,
  880. array('COUNT(reported_by) as `count`', 'reported_by'))
  881. ->where('bug_status = ?', 'NEW')
  882. ->group('reported_by');
  883. $rows = $table->fetchAll($select);
  884. ]]>
  885. </programlisting>
  886. </example>
  887. Вы можете использовать поиск как часть вашего запроса
  888. для дальнейшей детализации ваших операций извлечения.
  889. В этом примере таблица Accounts используется для
  890. поиска всех новых ошибок, о которых сообщил пользователь 'Bob'.
  891. </para>
  892. <para>
  893. <example id="zend.db.table.qry.rows.set.refine.example">
  894. <title>Использование таблицы поиска для фильтрации результатов, возвращаемых fetchAll()</title>
  895. <programlisting language="php"><![CDATA[
  896. $table = new Bugs();
  897. $select = $table->select();
  898. $select->where('bug_status = ?', 'NEW')
  899. ->join('accounts', 'accounts.account_name = bugs.reported_by')
  900. ->where('accounts.account_name = ?', 'Bob');
  901. $rows = $table->fetchAll($select);
  902. ]]>
  903. </programlisting>
  904. </example>
  905. </para>
  906. <para>
  907. Класс <classname>Zend_Db_Table_Select</classname> главным
  908. образом используется для соблюдения и проверки
  909. корректности запроса.
  910. Тем не менее, могут быть определенные случаи, когда
  911. нужна большая гибкость компоненты Zend_Db_Table_Row и
  912. не требуется доступная для чтения или удаления строка.
  913. Для этого отдельного случая использования возможно получение
  914. строки/набора строк путем передачи значения false методу
  915. setIntegrityCheck().
  916. В результате строка/набор строк будет возвращаться в
  917. "заблокированном" состоянии, это значит, что save(),
  918. delete() и методы для установки значений полей будут бросать
  919. исключения.
  920. </para>
  921. <example id="zend.db.table.qry.rows.set.integrity.example">
  922. <title>Отключение проверки целостности в Zend_Db_Table_Select для получения объединенных строк</title>
  923. <programlisting><![CDATA[
  924. $table = new Bugs();
  925. $select = $table->select()->setIntegrityCheck(false);
  926. $select->where('bug_status = ?', 'NEW')
  927. ->join('accounts',
  928. 'accounts.account_name = bugs.reported_by',
  929. 'account_name')
  930. ->where('accounts.account_name = ?', 'Bob');
  931. $rows = $table->fetchAll($select);
  932. ]]>
  933. </programlisting>
  934. </example>
  935. </sect3>
  936. </sect2>
  937. <sect2 id="zend.db.table.fetch-row">
  938. <title>Извлечение одной строки</title>
  939. <para>
  940. Вы можете запрашивать одну строку, используя условия, аналогичные
  941. тем, что используются в методе <code>fetchAll()</code>.
  942. </para>
  943. <example id="zend.db.table.fetch-row.example1">
  944. <title>Пример поиска одной строки по выражению</title>
  945. <programlisting language="php"><![CDATA[
  946. $table = new Bugs();
  947. $select = $table->select()->where('bug_status = ?', 'NEW')
  948. ->order('bug_id');
  949. $row = $table->fetchRow($select);
  950. ]]>
  951. </programlisting>
  952. </example>
  953. <para>
  954. Этот метод возвращает объект типа Zend_Db_Table_Row_Abstract. Если
  955. по заданному вами условию поиска не найдено ни одной строки в
  956. таблице БД, то <code>fetchRow()</code> вернет значение
  957. <constant>NULL</constant>.
  958. </para>
  959. </sect2>
  960. <sect2 id="zend.db.table.info">
  961. <title>Получение метаданных таблицы</title>
  962. <para>
  963. Класс Zend_Db_Table_Abstract предоставляет некоторую информацию о
  964. его метаданных. Метод <code>info()</code> возвращает массив с
  965. данными о таблице, ее столбцах, первичном ключе и другие метаданные.
  966. </para>
  967. <example id="zend.db.table.info.example">
  968. <title>Пример получения имени таблицы</title>
  969. <programlisting language="php">
  970. <![CDATA[
  971. $table = new Bugs();
  972. $info = $table->info();
  973. echo "The table name is " . $info['name'] . "\n";
  974. ]]>
  975. </programlisting>
  976. </example>
  977. <para>
  978. Ключи массива, возвращаемого методом <code>info()</code>, описаны
  979. ниже.
  980. </para>
  981. <itemizedlist>
  982. <listitem>
  983. <para>
  984. <emphasis>name</emphasis> => имя таблицы
  985. </para>
  986. </listitem>
  987. <listitem>
  988. <para>
  989. <emphasis>cols</emphasis> =>
  990. массив имен столбцов в таблице
  991. </para>
  992. </listitem>
  993. <listitem>
  994. <para>
  995. <emphasis>primary</emphasis> =>
  996. массив имен столбцов в первичном ключе
  997. </para>
  998. </listitem>
  999. <listitem>
  1000. <para>
  1001. <emphasis>metadata</emphasis> =>
  1002. ассоциативный массив, включающий в себя имена столбцов и
  1003. соответствующие им данные о столбцах. Это информация,
  1004. возвращаемая методом <code>describeTable()</code>.
  1005. </para>
  1006. </listitem>
  1007. <listitem>
  1008. <para>
  1009. <emphasis>rowClass</emphasis> => имя
  1010. определенного класса, используемого для объектов строк,
  1011. возвращаемых методами данного экземпляра таблицы. По
  1012. умолчанию это Zend_Db_Table_Row.
  1013. </para>
  1014. </listitem>
  1015. <listitem>
  1016. <para>
  1017. <emphasis>rowsetClass</emphasis> =>
  1018. имя определенного класса, используемого для объектов
  1019. наборов строк, возвращаемых методами данного экземпляра
  1020. таблицы. По умолчанию это Zend_Db_Table_Rowset.
  1021. </para>
  1022. </listitem>
  1023. <listitem>
  1024. <para>
  1025. <emphasis>referenceMap</emphasis> =>
  1026. ассоциативный массив с данными о ссылках на другие таблицы.
  1027. См. <xref linkend="zend.db.table.relationships.defining" />.
  1028. </para>
  1029. </listitem>
  1030. <listitem>
  1031. <para>
  1032. <emphasis>dependentTables</emphasis> =>
  1033. массив имен классов таблиц, на которые ссылается данная
  1034. таблица. См.
  1035. <xref linkend="zend.db.table.relationships.defining" />.
  1036. </para>
  1037. </listitem>
  1038. <listitem>
  1039. <para>
  1040. <emphasis>schema</emphasis> =>
  1041. имя схемы (базы данных, пространства таблиц) для данной
  1042. таблицы.
  1043. </para>
  1044. </listitem>
  1045. </itemizedlist>
  1046. </sect2>
  1047. <sect2 id="zend.db.table.metadata.caching">
  1048. <title>Кэширование метаданных таблицы</title>
  1049. <para>
  1050. По умолчанию <code>Zend_Db_Table_Abstract</code> производит запрос к
  1051. БД для определения <link linkend="zend.db.table.info">метаданных
  1052. таблицы</link> во время инстанцирования объекта таблицы. Т.е. когда
  1053. создается новый объект таблицы, поведением по умолчанию является
  1054. извлечение метаданных таблицы из БД через метод
  1055. <code>describeTable()</code>.
  1056. </para>
  1057. <para>
  1058. В некоторых условиях, особенно когда к одной и той же таблице БД
  1059. создается много объектов таблиц, произведение запросов для
  1060. получения метаданных для каждого экземпляря может быть нежелательным
  1061. с точки зрения производительности. В таких случаях можно производить
  1062. кэширование метаданных таблицы, полученных из БД.
  1063. </para>
  1064. <para>
  1065. Есть два основных способа кэширования:
  1066. <itemizedlist>
  1067. <listitem>
  1068. <para>
  1069. <emphasis>Вызов метода
  1070. Zend_Db_Table_Abstract::setDefaultMetadataCache()</emphasis>
  1071. - Это позволяет разработчику единовременно установить
  1072. объект кэша, используемый в всех классах таблиц.
  1073. </para>
  1074. </listitem>
  1075. <listitem>
  1076. <para>
  1077. <emphasis>Конфигурирование
  1078. Zend_Db_Table_Abstract::__construct()</emphasis> - Это
  1079. позволяет разработчику установить объект кэша для
  1080. определенного экземпляра класса таблицы.
  1081. </para>
  1082. </listitem>
  1083. </itemizedlist>
  1084. В обоих случаях определением кэша может быть <constant>NULL</constant>
  1085. (т.е. не используется кэширование) или экземпляр класса
  1086. <link linkend="zend.cache.frontends.core"><code>Zend_Cache_Core</code></link>.
  1087. Эти методы могут использоваться вместе для того, чтобы
  1088. использовать по умолчанию определенный объект кэша и при этом иметь
  1089. возможность изменять его для конкретного объекта таблицы.
  1090. </para>
  1091. <example id="zend.db.table.metadata.caching-default">
  1092. <title>Кэширование метаданных по умолчанию для всех объектов таблиц</title>
  1093. <para>
  1094. Следующий код показывает, как установить объект кэша,
  1095. используемый по умолчанию во всех объектах таблиц:
  1096. </para>
  1097. <programlisting language="php"><![CDATA[
  1098. // Сначала создается объект кэша
  1099. $frontendOptions = array(
  1100. 'automatic_serialization' => true
  1101. );
  1102. $backendOptions = array(
  1103. 'cacheDir' => 'cacheDir'
  1104. );
  1105. $cache = Zend_Cache::factory('Core',
  1106. 'File',
  1107. $frontendOptions,
  1108. $backendOptions);
  1109. // Далее, объект кэша устанавливается в качестве используемого
  1110. // во всех объектах таблиц
  1111. Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
  1112. // Класс таблицы
  1113. class Bugs extends Zend_Db_Table_Abstract
  1114. {
  1115. // ...
  1116. }
  1117. // Каждый экземпляр таблицы Bugs теперь использует
  1118. // кэширование метаданных по умолчанию
  1119. $bugs = new Bugs();
  1120. ]]>
  1121. </programlisting>
  1122. </example>
  1123. <example id="zend.db.table.metadata.caching-instance">
  1124. <title>Кэширование метаданных для одного объекта таблицы</title>
  1125. <para>
  1126. Следующий код показывает, как устанавливается кэширование
  1127. метаданных для одного конкретного объекта таблицы:
  1128. </para>
  1129. <programlisting language="php"><![CDATA[
  1130. // Сначала создается объект кэша
  1131. $frontendOptions = array(
  1132. 'automatic_serialization' => true
  1133. );
  1134. $backendOptions = array(
  1135. 'cacheDir' => 'cacheDir'
  1136. );
  1137. $cache = Zend_Cache::factory('Core',
  1138. 'File',
  1139. $frontendOptions,
  1140. $backendOptions);
  1141. // Класс таблицы
  1142. class Bugs extends Zend_Db_Table_Abstract
  1143. {
  1144. // ...
  1145. }
  1146. // Экземпляр конфигурируется при инстанцировании
  1147. $bugs = new Bugs(array('metadataCache' => $cache));
  1148. ]]>
  1149. </programlisting>
  1150. </example>
  1151. <note>
  1152. <title>Автоматическая сериализация через фронтэнд кэша</title>
  1153. <para>
  1154. Поскольку информация, возвращаемая методом адаптера
  1155. describeTable(), является массивом, то убедитесь, что опция
  1156. <code>automatic_serialization</code> установлена в
  1157. <constant>TRUE</constant> для фронтэнда <code>Zend_Cache_Core</code>.
  1158. </para>
  1159. </note>
  1160. <para>
  1161. Несмотря на то, что в примерах выше используется
  1162. <code>Zend_Cache_Backend_File</code>, разработчики могут
  1163. использовать другие бэкэнды, наиболее подходящие в данной ситуации.
  1164. Более подробную информацию читайте в разделе
  1165. <link linkend="zend.cache">Zend_Cache</link>.
  1166. </para>
  1167. </sect2>
  1168. <sect2 id="zend.db.table.extending">
  1169. <title>Расширение класса таблицы</title>
  1170. <sect3 id="zend.db.table.extending.row-rowset">
  1171. <title>Использование собственных классов строки и набора строк</title>
  1172. <para>
  1173. По умолчанию методы класса таблицы возвращают наборы строк в
  1174. экземплярах класса Zend_Db_Table_Rowset, и эти наборы строк
  1175. содержат в себе коллекции экземпляров класса Zend_Db_Table_Row.
  1176. Вы можете указать альтернативные классы, используемые вместо
  1177. них, но в любом случае они должны наследовать от классов
  1178. Zend_Db_Table_Rowset_Abstract и Zend_Db_Table_Row_Abstract
  1179. соответственно.
  1180. </para>
  1181. <para>
  1182. Вы можете указать классы строки и набора строк в
  1183. массиве опций конструктора таблицы под ключами
  1184. <code>'rowClass'</code> и <code>'rowsetClass'</code>
  1185. соответственно. Задавайте имена классов в виде обычных строк.
  1186. </para>
  1187. <example id="zend.db.table.extending.row-rowset.example">
  1188. <title>Пример указания классов строки и набора строк</title>
  1189. <programlisting language="php"><![CDATA[
  1190. class My_Row extends Zend_Db_Table_Row_Abstract
  1191. {
  1192. ...
  1193. }
  1194. class My_Rowset extends Zend_Db_Table_Rowset_Abstract
  1195. {
  1196. ...
  1197. }
  1198. $table = new Bugs(
  1199. array(
  1200. 'rowClass' => 'My_Row',
  1201. 'rowsetClass' => 'My_Rowset'
  1202. )
  1203. );
  1204. $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
  1205. // Возвращает объект типа My_Rowset,
  1206. // содержащий массив объектов типа My_Row
  1207. $rows = $table->fetchAll($where);
  1208. ]]>
  1209. </programlisting>
  1210. </example>
  1211. <para>
  1212. Вы можете сменить используемые классы, указав их через методы
  1213. <code>setRowClass()</code> и <code>setRowsetClass()</code>.
  1214. Это изменение применяется к создаваемым впоследствии строкам и
  1215. наборам строк и не влияет на класс объектов строк и наборов
  1216. строк, созданных ранее.
  1217. </para>
  1218. <example id="zend.db.table.extending.row-rowset.example2">
  1219. <title>Пример смены используемых для строк и наборов строк классов</title>
  1220. <programlisting language="php"><![CDATA[
  1221. $table = new Bugs();
  1222. $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
  1223. // Возвращает объект типа Zend_Db_Table_Rowset,
  1224. // содержащий массив объектов типа Zend_Db_Table_Row.
  1225. $rowsStandard = $table->fetchAll($where);
  1226. $table->setRowClass('My_Row');
  1227. $table->setRowsetClass('My_Rowset');
  1228. // Возвращает объект типа My_Rowset,
  1229. // содержащий массив объектов типа My_Row.
  1230. $rowsCustom = $table->fetchAll($where);
  1231. // Объект $rowsStandard по прежнему существует и не изменился.
  1232. ]]>
  1233. </programlisting>
  1234. </example>
  1235. <para>
  1236. Более подробную информацию о классах строки и набора строк
  1237. ищите в <xref linkend="zend.db.table.row" /> и
  1238. <xref linkend="zend.db.table.rowset" />.
  1239. </para>
  1240. </sect3>
  1241. <sect3 id="zend.db.table.extending.insert-update">
  1242. <title>Определение собственной логики для добавления, обновления и удаления строк</title>
  1243. <para>
  1244. Вы можете переопределить методы <code>insert()</code> и
  1245. <code>update()</code> в своем классе таблицы. Это дает
  1246. возможность реализовать собственный
  1247. код, который исполняется до того, как будет выполнена операция с
  1248. БД. Всегда вызывайте метод родительского класса после своих
  1249. действий.
  1250. </para>
  1251. <example id="zend.db.table.extending.insert-update.example">
  1252. <title>Собственная логика для управления отметками времени</title>
  1253. <programlisting language="php"><![CDATA[
  1254. class Bugs extends Zend_Db_Table_Abstract
  1255. {
  1256. protected $_name = 'bugs';
  1257. public function insert(array $data)
  1258. {
  1259. // добавление timestamp
  1260. if (empty($data['created_on'])) {
  1261. $data['created_on'] = time();
  1262. }
  1263. return parent::insert($data);
  1264. }
  1265. public function update(array $data, $where)
  1266. {
  1267. // добавление timestamp
  1268. if (empty($data['updated_on'])) {
  1269. $data['updated_on'] = time();
  1270. }
  1271. return parent::update($data, $where);
  1272. }
  1273. }
  1274. ]]>
  1275. </programlisting>
  1276. </example>
  1277. <para>
  1278. Вы можете также переопределить метод <code>delete()</code>.
  1279. </para>
  1280. </sect3>
  1281. <sect3 id="zend.db.table.extending.finders">
  1282. <title>Определение собственных методов для поиска</title>
  1283. <para>
  1284. Вы можете реализовать собственные методы запросов в своем классе
  1285. таблицы, если приходится часто делать запросы к таблице с одними
  1286. и теми же условиями. Большинство запросов могут быть написаны с
  1287. использованием <code>fetchAll()</code>, но это требует написания
  1288. повторяющегося кода для формирования условий запроса в том
  1289. случае, если вам нужно выполнять запрос в нескольких местах
  1290. вашего приложения. Поэтому будет удобным добавить метод в класс
  1291. таблицы для выполнения часто используемых запросов к таблице.
  1292. </para>
  1293. <example id="zend.db.table.extending.finders.example">
  1294. <title>Метод для поиска ошибок с определенным статусом</title>
  1295. <programlisting language="php"><![CDATA[
  1296. class Bugs extends Zend_Db_Table_Abstract
  1297. {
  1298. protected $_name = 'bugs';
  1299. public function findByStatus($status)
  1300. {
  1301. $where = $this->getAdapter()->quoteInto('bug_status = ?', $status);
  1302. return $this->fetchAll($where, 'bug_id');
  1303. }
  1304. }
  1305. ]]>
  1306. </programlisting>
  1307. </example>
  1308. </sect3>
  1309. <sect3 id="zend.db.table.extending.inflection">
  1310. <title>Определение инфлекции в Zend_Db_Table</title>
  1311. <para>
  1312. Некоторые разработчики предпочитают, чтобы имя класса таблицы
  1313. сопоставлялось с именем таблицы в СУРБД с применением
  1314. преобразования, называемого <emphasis>инфлекцией</emphasis>.
  1315. </para>
  1316. <para>
  1317. Например, если имя вашего класса таблицы -
  1318. "<code>BugsProducts</code>", то класс должен соответствовать
  1319. физической таблице в БД с названием
  1320. "<code>bugs_products</code>", если вы не произвели явное
  1321. объявление свойства класса <varname>$_name</varname>. В данном
  1322. преобразовании имя класса в формате "CamelCase" должно
  1323. приводиться к нижнему регистру с разделением слов символом
  1324. подчеркивания.
  1325. </para>
  1326. <para>
  1327. Вы можете указать имя таблицы БД независимо то имени класса,
  1328. объявив его в свойстве <varname>$_name</varname> во всех классах этой
  1329. таблицы.
  1330. </para>
  1331. <para>
  1332. Zend_Db_Table_Abstract не производит инфлекцию при получении
  1333. имени таблицы. Если вы опустите
  1334. объявление свойства <varname>$_name</varname> в своем классе таблицы,
  1335. то класс будет соответствовать таблице в БД с точно таким же
  1336. именем, как и у него.
  1337. </para>
  1338. <para>
  1339. Было бы неуместным использовать преобразование идентификаторов
  1340. из БД, поскольку это может привести к неоднозначности или
  1341. сделать некоторые идентификаторы недоступными.
  1342. Использование SQL-идентификаторов в том виде, в котором они
  1343. присутствуют в БД, делает Zend_Db_Table_Abstract проще и гибче в
  1344. использовании.
  1345. </para>
  1346. <para>
  1347. Если вы предпочитаете использовать инфлекцию, то должны
  1348. реализовать преобразование сами, переопределив метод
  1349. <code>_setupTableName()</code> в своем классе таблицы. Одним из
  1350. возможных способов является определение абстрактного класса,
  1351. наследующего от Zend_Db_Table_Abstract, и объявление
  1352. классов остальных таблиц как наследующих от этого нового
  1353. класса.
  1354. </para>
  1355. <example id="zend.db.table.extending.inflection.example">
  1356. <title>Пример абстрактного класса таблицы, реализующего инфлекцию</title>
  1357. <programlisting language="php"><![CDATA[
  1358. abstract class MyAbstractTable extends Zend_Db_Table_Abstract
  1359. {
  1360. protected function _setupTableName()
  1361. {
  1362. if (!$this->_name) {
  1363. $this->_name = myCustomInflector(get_class($this));
  1364. }
  1365. parent::_setupTableName();
  1366. }
  1367. }
  1368. class BugsProducts extends MyAbstractTable
  1369. {
  1370. }
  1371. ]]>
  1372. </programlisting>
  1373. </example>
  1374. <para>
  1375. Реализация функций для произведения инфлекционного
  1376. преобразования возлагается на разработчика. Zend Framework не
  1377. предоставляет для этих целей готовых функций.
  1378. </para>
  1379. </sect3>
  1380. </sect2>
  1381. </sect1>
  1382. <!--
  1383. vim:se ts=4 sw=4 et:
  1384. -->