[ZF-10089] Zend_Log
[zend.git] / documentation / manual / fr / module_specs / Zend_Db_Table.xml
blob6145dab8b623d0293139bdb8970da55c5aa1d1db
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- EN-Revision: 21829 -->
3 <!-- Reviewed: no -->
4 <sect1 id="zend.db.table">
5     <title>Zend_Db_Table</title>
7     <sect2 id="zend.db.table.introduction">
8         <title>Introduction</title>
10         <para>
11             La classe <classname>Zend_Db_Table</classname> est une interface orientée objet
12             vers les tables d'une base de données. Elle fournit des méthodes pour la gestion de la
13             plupart des opérations concernant une table. Bien entendu, vous pouvez étendre la classe
14             de base pour ajouter une logique personnalisée.
15         </para>
17         <para>
18             La solution que représente <classname>Zend_Db_Table</classname> est basée sur le
19             motif de conception <ulink
20             url="http://www.martinfowler.com/eaaCatalog/tableDataGateway.html">Table Data
21             Gateway</ulink>. Cette solution inclut aussi une classe implémentant le motif <ulink
22             url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data
23             Gateway</ulink>.
24         </para>
25     </sect2>
27     <sect2 id="zend.db.table.defining">
28         <title>Définir une classe de Table</title>
30         <para>
31             Pour chaque table de la base de données envers laquelle vous souhaitez un accès,
32             définissez une classe étendant <classname>Zend_Db_Table_Abstract</classname>.
33         </para>
35         <sect3 id="zend.db.table.defining.table-schema">
36             <title>Définir le nom de la table, et de la base de données</title>
38             <para>
39                 Déclarez le nom de la table pour laquelle la classe va agir, en utilisant la
40                 propriété protégée <varname>$_name</varname>. C'est une chaîne, elle doit contenir le nom
41                 de la table tel qu'il apparaît dans la base de données.
42             </para>
44             <example id="zend.db.table.defining.table-schema.example1">
45                 <title>Déclarer une classe de Table avec un nom de table spécifique</title>
47                 <programlisting language="php"><![CDATA[
48 class Bugs extends Zend_Db_Table_Abstract
50     protected $_name = 'bugs';
52 ]]></programlisting>
53             </example>
55             <para>
56                 Si vous ne spécifiez pas le nom de la table, le nom de la classe sera alors
57                 utilisé comme nom de table par défaut.
58             </para>
60             <example id="zend.db.table.defining.table-schema.example">
61                 <title>Déclarer une classe de Table sans nom de table spécifique</title>
63                 <programlisting language="php"><![CDATA[
64 class bugs extends Zend_Db_Table_Abstract
66     // le nom de la table est ici supposé être le nom de la classe
68 ]]></programlisting>
69             </example>
71             <para>
72                 Vous pouvez aussi déclarer le nom de la base de données contenant la table,
73                 toujours au moyen d'une propriété protégée de la classe&#160;:
74                 <varname>$_schema</varname>, ou avec le nom de la base précédant le nom de la table dans
75                 la propriété <varname>$_name</varname>. Si vous choisissez de définir le nom de la base de
76                 données dans la propriété <varname>$_name</varname>, alors ce choix sera prioritaire sur
77                 celui utilisant <varname>$_schema</varname>.
78             </para>
80             <example id="zend.db.table.defining.table-schema.example3">
81                 <title>Déclarer une classe de Table avec un nom de base de données</title>
83                 <programlisting language="php"><![CDATA[
84 // Première alternative :
85 class Bugs extends Zend_Db_Table_Abstract
87     protected $_schema = 'bug_db';
88     protected $_name   = 'bugs';
91 // Seconde alternative :
92 class Bugs extends Zend_Db_Table_Abstract
94     protected $_name = 'bug_db.bugs';
97 // Si le nom de la base est spécifiée dans $_name ET $_schema,
98 // alors c'est celui spécifié dans $_name qui prime :
100 class Bugs extends Zend_Db_Table_Abstract
102     protected $_name   = 'bug_db.bugs';
103     protected $_schema = 'ignored';
105 ]]></programlisting>
106             </example>
108             <para>
109                 Les noms de la base de données et de la table peuvent aussi être définis via
110                 le constructeur de la classe de Table. Ils écrasent alors ceux éventuellement
111                 définis dans les propriétés de la classe (avec <varname>$_name</varname> et
112                 <varname>$_schema</varname>).
113             </para>
115             <example id="zend.db.table.defining.table-schema.example.constructor">
116                 <title>Déclarer les noms de table et base de donnée à l'instanciation</title>
118                 <programlisting language="php"><![CDATA[
119 class Bugs extends Zend_Db_Table_Abstract
123 // Première alternative :
125 $tableBugs = new Bugs(array('name' => 'bugs', 'schema' => 'bug_db'));
127 // Seconde alternative :
129 $tableBugs = new Bugs(array('name' => 'bug_db.bugs'));
131 // Si le nom de la base est spécifié dans name ET schema, alors c'est
132 // celui spécifié dans name qui prime :
134 $tableBugs = new Bugs(array('name' => 'bug_db.bugs',
135                             'schema' => 'ignored'));
136 ]]></programlisting>
137             </example>
139             <para>
140                 Si vous n'indiquez pas de base de données, c'est celle utilisée par
141                 l'adaptateur qui sera utilisée.
142             </para>
143         </sect3>
145         <sect3 id="zend.db.table.defining.primary-key">
146             <title>Définir la clé primaire d'une table</title>
148             <para>
149                 Toute table doit posséder une clé primaire.
150                 <classname>Zend_Db_Table</classname> ne fonctionne pas avec les tables sans clé
151                 primaire. Vous pouvez les déclarer la(les) colonne servant de clé primaire grâce à
152                 la propriété protégée de la classe <varname>$_primary</varname>. Celle-ci peut être soit
153                 une chaîne, dans le cas d'une clé sur une colonne, ou un tableau de chaînes pour une
154                 clé sur plusieurs colonnes (clé primaire composée).
155             </para>
157             <example id="zend.db.table.defining.primary-key.example">
158                 <title>Exemple de spécification de la clé primaire</title>
160                 <programlisting language="php"><![CDATA[
161 class Bugs extends Zend_Db_Table_Abstract
163     protected $_name = 'bugs';
164     protected $_primary = 'bug_id';
166 ]]></programlisting>
167             </example>
169             <para>
170                 Si vous ne spécifiez pas explicitement de clé primaire, alors
171                 <classname>Zend_Db_Table_Abstract</classname> va essayer de la trouver lui-même en
172                 utilisant les informations renvoyées par <methodname>describeTable()</methodname>.
173             </para>
175             <note>
176                 <para>
177                     Toute classe de table doit, par un moyen ou un autre, connaître la clé
178                     primaire de la table ciblée. Si la clé primaire ne peut être trouvée ( spécifiée
179                     dans la classe, ou découverte par <methodname>describeTable()</methodname>), alors la table
180                     ne va pas pouvoir être utilisée avec
181                     <classname>Zend_Db_Table</classname>.
182                 </para>
183             </note>
184         </sect3>
186         <sect3 id="zend.db.table.defining.setup">
187             <title>Redéfinir les méthodes de configuration de la classe de Table</title>
189             <para>
190                 Lorsque vous créez votre instance de classe
191                 <classname>Zend_Db_Table</classname>, le constructeur décompose le processus via
192                 plusieurs méthodes permettant l'initialisation des métadonnées de la table. Chacune
193                 de ces étapes est matérialisée par une méthode de la classe, surchargeable.
194                 N'oubliez cependant pas d'appeler la méthode parente respective à la fin de votre
195                 traitement.
196             </para>
198             <example id="zend.db.table.defining.setup.example">
199                 <title>Exemple de redéfinition de la méthode _setupTableName()</title>
201                 <programlisting language="php"><![CDATA[
202 class Bugs extends Zend_Db_Table_Abstract
204     protected function _setupTableName()
205     {
206         $this->_name = 'bugs';
207         parent::_setupTableName();
208     }
210 ]]></programlisting>
211             </example>
213             <para>Les méthodes de configuration que vous pouvez redéfinir sont :</para>
215             <itemizedlist>
216                 <listitem>
217                     <para>
218                         <methodname>_setupDatabaseAdapter()</methodname> vérifie si un adaptateur a été
219                         passé à la classe, éventuellement en récupère un depuis le registre. En
220                         redéfinissant cette méthode, vous pouvez ajouter une source de recherche
221                         pour l'adaptateur.
222                     </para>
223                 </listitem>
225                 <listitem>
226                     <para>
227                         <methodname>_setupTableName()</methodname> donne le nom de la table par défaut
228                         comme étant le nom de la classe. En redéfinissant cette méthode, vous pouvez
229                         spécifier le nom de la table avant son intervention.
230                     </para>
231                 </listitem>
233                 <listitem>
234                     <para>
235                         <methodname>_setupMetadata()</methodname> définit le nom de la base de données si
236                         le nom de la table est de la forme "base.table"; appelle
237                         <methodname>describeTable()</methodname> pour récupérer les méta-données; remplir le
238                         tableau <varname>$_cols</varname> avec les noms des colonnes reçus via
239                         <methodname>describeTable()</methodname>. La redéfinition de cette méthode permet de
240                         spécifier soi-même les noms des colonnes de la table.
241                     </para>
242                 </listitem>
244                 <listitem>
245                     <para>
246                         <methodname>_setupPrimaryKey()</methodname> donne le nom de la clé primaire par
247                         défaut en cherchant dans <methodname>describeTable()</methodname>; vérifie que la clé
248                         primaire fait bien partie du tableau <varname>$_cols</varname>. En redéfinissant
249                         cette méthode, vous pouvez spécifier une clé primaire manuellement.
250                     </para>
251                 </listitem>
252             </itemizedlist>
253         </sect3>
255         <sect3 id="zend.db.table.initialization">
256             <title>Initialisation de la Table</title>
258             <para>
259                 Si lors de la construction de l'objet représentant votre Table, vous avez
260                 besoin d'implémenter une logique spécifique, vous devriez utiliser la méthode
261                 <methodname>init()</methodname>, qui est appelée juste après le constructeur, donc une fois la
262                 table correctement créée.
263                 </para>
265             <example id="zend.db.table.defining.init.usage.example">
266                 <title>Exemple d'utilisation de la méthode init()</title>
268                 <programlisting language="php"><![CDATA[
269 class Bugs extends Zend_Db_Table_Abstract
271     protected $_observer;
273     public function init()
274     {
275         $this->_observer = new MyObserverClass();
276     }
278 ]]></programlisting>
279             </example>
280         </sect3>
281     </sect2>
283     <sect2 id="zend.db.table.constructing">
284         <title>Créer une instance de la classe de Table</title>
286         <para>
287             Avant d'utiliser votre classe de Table, il faut en créer une instance, via son
288             constructeur. Celui-ci accepte un tableau d'options. La plus importante d'entre elles
289             est l'adaptateur de base de données, qui représente la connexion au SGBD. Il y a trois
290             façon de le spécifier&#160;:
291         </para>
293         <sect3 id="zend.db.table.constructing.adapter">
294             <title>Spécifier l'adaptateur de base de données</title>
296             <para>
297                 La première manière de spécifier l'objet d'adaptateur à la classe de Table,
298                 est de le passer dans le tableau d'options, à l'index <code>"db"</code>.
299             </para>
301             <example id="zend.db.table.constructing.adapter.example">
302                 <title>Exemple de construction d'un objet Table avec l'objet adaptateur</title>
304                 <programlisting language="php"><![CDATA[
305 $db = Zend_Db::factory('PDO_MYSQL', $options);
307 $table = new Bugs(array('db' => $db));
308 ]]></programlisting>
309             </example>
310         </sect3>
312         <sect3 id="zend.db.table.constructing.default-adapter">
313             <title>Spécifier un adaptateur par défaut</title>
315             <para>
316                 La deuxième manière de donner un objet adaptateur à la classe de Table est de
317                 le déclarer comme étant l'objet adaptateur par défaut pour toutes les classes de
318                 Table. Vous pouvez faire ceci en utilisant la méthode statique
319                 <methodname>Zend_Db_Table_Abstract::setDefaultAdapter()</methodname>. Son argument est
320                 un objet de type <classname>Zend_Db_Adapter_Abstract</classname>.
321             </para>
323             <example id="zend.db.table.constructing.default-adapter.example">
324                 <title>
325                     Exemple de construction d'un objet Table en utilisant l'adaptateur par défaut
326                 </title>
328                 <programlisting language="php"><![CDATA[
329 $db = Zend_Db::factory('PDO_MYSQL', $options);
330 Zend_Db_Table_Abstract::setDefaultAdapter($db);
332 // Plus tard...
334 $table = new Bugs();
335 ]]></programlisting>
336             </example>
338             <para>
339                 Il peut être intéressant de créer son objet adaptateur de base de données en
340                 un lieu approprié, comme le fichier d'amorçage ("bootstrap"), et ensuite de le
341                 spécifier comme adaptateur par défaut pour toutes les tables, à travers toute
342                 l'application. Attention toutefois, ce procédé fixe un et un seul adaptateur, pour
343                 toutes les classes de table (héritant de
344                 <classname>Zend_Db_Table_Abstract</classname>).
345             </para>
346         </sect3>
348         <sect3 id="zend.db.table.constructing.registry">
349             <title>Stocker l'objet adaptateur dans le registre</title>
351             <para>
352                 La troisième manière de passer l'objet adaptateur de base de données à votre
353                 classe de Table, est de passer une chaîne de caractères dans la clé
354                 <code>"db"</code> du tableau de configuration accepté par le constructeur. Cette
355                 chaîne représente alors l'index auquel est stocké l'adaptateur, dans le registre
356                 statique.
357             </para>
359             <example id="zend.db.table.constructing.registry.example">
360                 <title>Exemple de construction de l'objet Table avec le registre</title>
362                 <programlisting language="php"><![CDATA[
363 $db = Zend_Db::factory('PDO_MYSQL', $options);
364 Zend_Registry::set('my_db', $db);
366 // Plus tard...
368 $table = new Bugs(array('db' => 'my_db'));
369 ]]></programlisting>
370             </example>
372             <para>
373                 Cette option est très semblable à celle qui consiste à définir un adaptateur
374                 par défaut à toutes les classes. Le registre est en revanche plus flexible, car vous
375                 pouvez y stocker plusieurs adaptateurs, correspondants à plusieurs SGBD différents.
376                 Changer de SGBD pour ses classes de Table est alors aussi simple que de changer de
377                 valeur de registre.
378             </para>
379         </sect3>
380     </sect2>
382     <sect2 id="zend.db.table.insert">
383         <title>Insérer des enregistrement dans une table</title>
385         <para>
386             Vous pouvez utiliser votre objet de Table pour insérer des données dans la table
387             sur laquelle l'objet se base. Utilisez sa méthode <methodname>insert()</methodname> qui accepte un
388             seul paramètre&#160;: c'est un tableau dont les clés sont les noms des colonnes de la
389             table, et les valeurs les valeurs souhaitées pour insertions.
390         </para>
392         <example id="zend.db.table.insert.example">
393             <title>Exemple d'insertion de données dans la table</title>
395             <programlisting language="php"><![CDATA[
396 $table = new Bugs();
398 $data = array(
399     'created_on'      => '2007-03-22',
400     'bug_description' => 'Something wrong',
401     'bug_status'      => 'NEW'
404 $table->insert($data);
405 ]]></programlisting>
406         </example>
408         <para>
409             Par défaut les paramètres sont traités comme des valeurs littérales. Si vous
410             souhaitez utiliser une expression <acronym>SQL</acronym> à la place, manipulez un objet
411             <classname>Zend_Db_Expr</classname> plutôt.
412         </para>
414         <example id="zend.db.table.insert.example-expr">
415             <title>Exemple d'insertion d'expressions dans une table</title>
417             <programlisting language="php"><![CDATA[
418 $table = new Bugs();
420 $data = array(
421     'created_on'      => new Zend_Db_Expr('CURDATE()'),
422     'bug_description' => 'Something wrong',
423     'bug_status'      => 'NEW'
425 ]]></programlisting>
426         </example>
428         <para>
429             Dans les exemples ci-dessus, il est supposé que la table possède une clé primaire
430             auto-incrémentée. C'est le comportement par défaut que gère
431             <classname>Zend_Db_Table_Abstract</classname>, mais il y a d'autres comportements
432             valides, qui sont détaillés ci-dessous.
433         </para>
435         <sect3 id="zend.db.table.insert.key-auto">
436             <title>Utiliser une table avec une clé primaire auto-incrémentée</title>
438             <para>
439                 Une clé primaire auto-incrémentée génère une valeur entière unique si vous
440                 omettez la colonne de la clé primaire dans une requête <acronym>SQL</acronym> de type
441                 <constant>INSERT</constant>.
442             </para>
444             <para>
445                 Dans <classname>Zend_Db_Table_Abstract</classname>, si vous définissez la
446                 variable protégée <varname>$_sequence</varname> à un booléen <constant>TRUE</constant> (défaut),
447                 alors la classe va supposer que la table qu'elle représente possède une clé primaire
448                 auto-incrémentée.
449             </para>
451             <example id="zend.db.table.insert.key-auto.example">
452                 <title>Exemple de déclaration d'une clé primaire auto-incrémentée</title>
454                 <programlisting language="php"><![CDATA[
455 class Bugs extends Zend_Db_Table_Abstract
457     protected $_name = 'bugs';
459     // Ce comportement est celui par défaut, il est noté ici
460     // uniquement pour l'exemple, mais non necéssaire
461     protected $_sequence = true;
463 ]]></programlisting>
464             </example>
466             <para>
467                 MySQL, MSSQL, et SQLite sont des exemples de SGBD supportant les clé primaires
468                 auto-incrémentées.
469             </para>
471             <para>
472                 PostgreSQL a une propriété <constant>SERIAL</constant> qui définit une séquence
473                 automatiquement, basée sur le nom de la table et d'une colonne, et utilise cette
474                 séquence pour générer des valeurs de clés pour les nouveaux enregistrements. IBM DB2
475                 a une propriété <constant>IDENTITY</constant> qui fonctionne de la même manière. Si vous
476                 utilisez ces propriétés d'automatisme, considérez votre classe de Table
477                 (<classname>Zend_Db_Table</classname>) comme si elle avait une clé primaire
478                 auto-incrémentée. Déclarez ainsi <varname>$_sequence</varname> à <constant>TRUE</constant>.
479             </para>
480         </sect3>
482         <sect3 id="zend.db.table.insert.key-sequence">
483             <title>Utiliser une Table avec une séquence</title>
485             <para>
486                 Une séquence est un objet de base de données qui génère des valeurs uniques
487                 pouvant être utilisées comme clés primaires dans une ou plusieurs tables de la base
488                 de données.
489             </para>
491             <para>
492                 Si vous définissez <varname>$_sequence</varname> avec une chaîne de caractères,
493                 <classname>Zend_Db_Table_Abstract</classname> va alors supposer que cette chaîne
494                 représente le nom de l'objet de séquence. Elle sera donc utilisée pour générer une
495                 valeur lors de requêtes <constant>INSERT</constant> le nécessitant.
496             </para>
498             <example id="zend.db.table.insert.key-sequence.example">
499                 <title>Exemple de déclaration d'une séquence dans une classe de Table</title>
501                 <programlisting language="php"><![CDATA[
502 class Bugs extends Zend_Db_Table_Abstract
504     protected $_name = 'bugs';
506     protected $_sequence = 'bug_sequence';
508 ]]></programlisting>
509             </example>
511             <para>
512                 Oracle, PostgreSQL, et IBM DB2 sont des SGBDs qui supportent les séquences.
513             </para>
515             <para>
516                 PostgreSQL et IBM DB2 ont aussi des mécanismes définissant implicitement la
517                 séquence et les colonnes associées. Si vous utilisez un de ces procédés, considérez
518                 votre classe de table comme ayant une clé primaire auto-incrémentée. N'utilisez la
519                 chaîne de la séquence dans $_sequence que si vous voulez explicitement utiliser
520                 cette séquence pour générer la valeur suivante de clé.
521             </para>
522         </sect3>
524         <sect3 id="zend.db.table.insert.key-natural">
525             <title>Utiliser une classe de Table avec une clé naturelle</title>
527             <para>
528                 Certaines tables ont des clé naturelles, c'est à dire que vous devez fournir
529                 vous même, manuellement, la valeur de la clé concernée. Aucun mécanisme automatique
530                 (auto-incrémentation ou séquence) ne le fait pour vous.
531             </para>
533             <para>
534                 Si vous utilisez <varname>$_sequence</varname> avec la valeur booléenne
535                 <constant>FALSE</constant>, alors <classname>Zend_Db_Table_Abstract</classname> se
536                 comportera comme si une clé naturelle est utilisée. Ainsi, lors de l'appel de la
537                 méthode <methodname>insert()</methodname>, vous devrez spécifier la valeur de la clé primaire
538                 vous même, autrement une <classname>Zend_Db_Table_Exception</classname> sera
539                 levée.
540             </para>
542             <example id="zend.db.table.insert.key-natural.example">
543                 <title>Exemple de déclaration d'une clé naturelle</title>
545                 <programlisting language="php"><![CDATA[
546 class BugStatus extends Zend_Db_Table_Abstract
548     protected $_name = 'bug_status';
550     protected $_sequence = false;
552 ]]></programlisting>
553             </example>
555             <note>
556                 <para>
557                     Tous les SGBDs gère ce cas. Les tables d'intersection dans les relations
558                     de type "plusieurs à plusieurs" sont de bons exemples de clés naturelles,
559                     souvent composées d'autres clés étrangères.
560                 </para>
561             </note>
562         </sect3>
563     </sect2>
565     <sect2 id="zend.db.table.update">
566         <title>Mettre à jour des enregistrements dans une table</title>
568         <para>
569             Vous pouvez mettre à jour des enregistrements de votre table en utilisant la
570             méthode <code>update</code> de votre classe de Table. Elle accepte deux paramètres. Le
571             premier est un tableau associatifs des colonnes concernées, et de leurs valeurs
572             respectives. Le deuxième est une expression <acronym>SQL</acronym> qui sera utiliser comme clause
573             <constant>WHERE</constant> dans la requête <constant>UPDATE</constant>.
574         </para>
576         <example id="zend.db.table.update.example">
577             <title>Exemple de mise à jour d'enregistrements dans une table</title>
579             <programlisting language="php"><![CDATA[
580 $table = new Bugs();
582 $data = array(
583     'updated_on'      => '2007-03-23',
584     'bug_status'      => 'FIXED'
587 $where = $table->getAdapter()->quoteInto('bug_id = ?', 1234);
589 $table->update($data, $where);
590 ]]></programlisting>
591         </example>
593         <para>
594             La méthode de la classe de Table <methodname>update()</methodname> est proxiées vers la
595             méthode <link linkend="zend.db.adapter.write.update"><methodname>update()</methodname></link> de
596             l'adaptateur. Le deuxième paramètre peut donc être un tableau d'arguments pour la clause
597             WHERE. Chaque élément du tableau sera joint au suivant avec une opération
598             <constant>AND</constant>.
599         </para>
601         <note>
602             <para>
603                 Les valeurs et les identifiants <acronym>SQL</acronym> ne sont pas échappés automatiquement. Si
604                 vous voulez échapper des valeurs, vous devrez utiliser <methodname>quote()</methodname>,
605                 <methodname>quoteInto()</methodname>, et <methodname>quoteIdentifier()</methodname> de l'adaptateur.
606             </para>
607         </note>
608     </sect2>
610     <sect2 id="zend.db.table.delete">
611         <title>Supprimer des enregistrements d'une Table</title>
613         <para>
614             Pour effacer des enregistrements de votre table en utilisant sa classe de Table,
615             utilisez sa méthode <methodname>delete()</methodname>. Son seul paramètre est une chaîne ou un
616             tableau définissant la clause <constant>WHERE</constant> à utiliser lors de la requête
617             <constant>DELETE</constant>.
618         </para>
620         <example id="zend.db.table.delete.example">
621             <title>Exemple de suppression d'enregistrements</title>
623             <programlisting language="php"><![CDATA[
624 $table = new Bugs();
626 $where = $table->getAdapter()->quoteInto('bug_id = ?', 1235);
628 $table->delete($where);
629 ]]></programlisting>
630         </example>
632         <para>
633             Cette méthode est proxiée vers <link
634             linkend="zend.db.adapter.write.delete"><methodname>delete()</methodname></link> de l'adaptateur. Si
635             le paramètre est un tableau, chacun des éléments du tableau sera joint au suivant avec
636             l'opération <constant>AND</constant> pour former la clause WHERE.
637         </para>
639         <note>
640             <para>
641                 Les valeurs et les identifiants <acronym>SQL</acronym> ne sont pas échappés automatiquement. Si
642                 vous voulez échapper des valeurs, vous devrez utiliser <methodname>quote()</methodname>,
643                 <methodname>quoteInto()</methodname>, et <methodname>quoteIdentifier()</methodname> de l'adaptateur.
644             </para>
645         </note>
646     </sect2>
648     <sect2 id="zend.db.table.find">
649         <title>Récupérer des enregistrements par clé primaire</title>
651         <para>
652             Vous pouvez interroger votre table afin de récupérer des enregistrements en
653             spécifiant une ou plusieurs valeurs de clé primaire. La méthode <methodname>find()</methodname>
654             permet ceci, elle prend comme premier paramètre une valeur ou un tableau de valeurs de
655             clé primaire.
656         </para>
658         <example id="zend.db.table.find.example">
659             <title>Exemple de récupération d'enregistrements par clé primaire</title>
661             <programlisting language="php"><![CDATA[
662 $table = new Bugs();
664 // Récupère un enregistrement, mais
665 // retourne un Rowset
666 $rows = $table->find(1234);
668 // Récupère plusieurs enregistrement
669 // retourne un Rowset
670 $rows = $table->find(array(1234, 5678));
671 ]]></programlisting>
672         </example>
674         <para>
675             Si une seule clé est passée en paramètre, la méthode retournera au plus un
676             résultat (car par définition, une clé primaire assure l'unicité d'un enregistrement). Si
677             vous passez plusieurs valeurs de clés, alors la méthode pourra retourner plusieurs
678             enregistrements. Cette méthode pourra aussi retourner zéro enregistrement. Quoiqu'il en
679             soit, l'objet de retour est bien un
680             <classname>Zend_Db_Table_Rowset_Abstract</classname>.
681         </para>
683         <para>
684             Si votre clé primaire est une clé composée de plusieurs colonnes, passez alors les
685             autres valeurs de colonne comme paramètres à la méthode <methodname>find()</methodname>. Il doit y
686             avoir autant de paramètres passés à la méthode, que de colonnes composant la clé.
687         </para>
689         <para>
690             Ainsi, pour trouver plusieurs enregistrements en passant plusieurs valeurs de clés
691             primaires composées, passez autant de tableaux composés, que de colonnes représentant
692             les clés. Les tableaux doivent donc, comporter le même nombre de valeurs. Celles-ci vont
693             ainsi fonctionner par tuples&#160;: tous les premiers éléments des tableaux seront
694             évalués pour la première recherche, et chacun représentera une colonne composant la clé
695             primaire. Puis ainsi de suite, jusqu'à la fin des tableaux.
696         </para>
698         <example id="zend.db.table.find.example-compound">
699             <title>Exemple de recherche avec une clé primaire composée</title>
701             <para>
702                 L'exemple suivant appelle <methodname>find()</methodname> pour récupérer deux enregistrements en
703                 se basant sur une clé à deux colonnes. Le premier enregistrement aura une clé
704                 primaire (1234, 'ABC'), et le second une valeur de clé primaire (5678, 'DEF').
705             </para>
707             <programlisting language="php"><![CDATA[
708 class BugsProducts extends Zend_Db_Table_Abstract
710     protected $_name = 'bugs_products';
711     protected $_primary = array('bug_id', 'product_id');
714 $table = new BugsProducts();
716 // Retourne un enregistrement unique, basé sur une clé
717 // primaire à deux colonnes
718 $rows = $table->find(1234, 'ABC');
720 // Retourne deux enregistrements, basés sur une clé
721 // primaire à deux colonnes
722 $rows = $table->find(array(1234, 5678), array('ABC', 'DEF'));
723 ]]></programlisting>
724         </example>
725     </sect2>
727     <sect2 id="zend.db.table.fetch-all">
728         <title>Requêter pour plusieurs enregistrements</title>
730         <sect3 id="zend.db.table.fetch-all.select">
731             <title>API de l'objet Select</title>
733             <para>
734                 <warning>
735                     <para>
736                         L'API pour les opérations de récupération d'enregistrements a été
737                         améliorée afin d'autoriser un objet
738                         <classname>Zend_Db_Table_Select</classname> à modifier la requête. Les
739                         anciens comportements de <methodname>fetchRow()</methodname> et <methodname>fetchAll()</methodname>
740                         sont désormais dépréciés, mais toujours fonctionnels à ce jour.
741                     </para>
743                     <para>
744                         Les requêtes suivantes sont sémantiquement identiques et fonctionnent.
745                         Il est conseillé cependant d'utiliser l'implémentation avec l'objet
746                         select.
747                     </para>
749                     <para>
750                         <programlisting language="php"><![CDATA[
751 // Récupérer un rowset
752 $rows = $table->fetchAll('bug_status = "NEW"', 'bug_id ASC', 10, 0);
753 $rows = $table->fetchAll($table->select()->where('bug_status = ?', 'NEW')
754                                          ->order('bug_id ASC')
755                                          ->limit(10, 0));
756 // ou avec liaison :
757 $rows = $table->fetchAll(
758     $table->select()
759         ->where('bug_status = :status')
760         ->bind(array(':status'=>'NEW')
761         ->order('bug_id ASC')
762         ->limit(10, 0)
763     );
765 // Récupérer un row
766 $row = $table->fetchRow('bug_status = "NEW"', 'bug_id ASC');
767 $row = $table->fetchRow($table->select()->where('bug_status = ?', 'NEW')
768                                         ->order('bug_id ASC'));
769 // ou avec liaison :
770 $row = $table->fetchRow(
771     $table->select()
772         ->where('bug_status = :status')
773         ->bind(array(':status'=>'NEW')
774         ->order('bug_id ASC')
775     );
776 ]]></programlisting></para>
777                     </warning>
778                 </para>
780             <para>
781                 L'objet <classname>Zend_Db_Table_Select</classname> est une extension de
782                 <classname>Zend_Db_Select</classname> mais qui applique des restrictions
783                 particulières à la requête. Les restrictions sont :
784             </para>
786             <itemizedlist>
787                 <listitem>
788                     <para>
789                         Vous <emphasis>pouvez</emphasis> utiliser l'objet pour ne sélectionner
790                         que certaines colonnes de l'enregistrement à retourner. Ceci est pratique
791                         dans le cas où vous n'avez pas besoin spécifiquement de toutes les colonnes
792                         d'une table.
793                     </para>
794                 </listitem>
796                 <listitem>
797                     <para>
798                         Vous <emphasis>pouvez</emphasis> spécifier des colonnes avec des
799                         évaluations envers des expressions <acronym>SQL</acronym>. Cependant, l'enregistrement
800                         résultant sera alors en mode lecture seule (<property>readOnly</property>)
801                         et ne pourra pas être propagé en base de données (<methodname>save()</methodname>). Un
802                         appel à <methodname>save()</methodname> lèvera une exception.
803                     </para>
804                 </listitem>
806                 <listitem>
807                     <para>
808                         Vous <emphasis>pouvez</emphasis> utiliser des jointures JOIN vers
809                         d'autres tables, mais uniquement pour des critères de jointure, et non
810                         sélectionner des colonnes jointes.
811                     </para>
812                 </listitem>
814                 <listitem>
815                     <para>
816                         Vous <emphasis>ne pouvez pas</emphasis> spécifier de colonnes JOINtes
817                         comme faisant partie du résultat de la requête. L'objet row/rowset serait
818                         alors corrompu, et contiendrait des données d'une table étrangère à sa table
819                         originale. Une erreur sera renvoyée dans un tel cas.
820                     </para>
821                 </listitem>
822             </itemizedlist>
824             <para>
825                 <example id="zend.db.table.qry.rows.set.simple.usage.example">
826                     <title>Utilisation simple</title>
828                     <programlisting language="php"><![CDATA[
829 $table = new Bugs();
831 $select = $table->select();
832 $select->where('bug_status = ?', 'NEW');
834 $rows = $table->fetchAll($select);
835 ]]></programlisting>
836                 </example>
837             </para>
839             <para>
840                 L'objet <code>Select</code> utilise une interface fluide (fluent interface),
841                 permettant le chaînage des méthodes.
842             </para>
844             <para>
845                 <example id="zend.db.table.qry.rows.set.fluent.interface.example">
846                     <title>Exemple d'interface fluide</title>
848                     <programlisting language="php"><![CDATA[
849 $table = new Bugs();
851 $rows = $table->fetchAll($table->select()
852                                ->where('bug_status = ?', 'NEW'));
853 ]]></programlisting>
854                 </example>
855             </para>
856         </sect3>
858         <sect3 id="zend.db.table.fetch-all.usage">
859             <title>Récupérer un jeu d'enregistrements&#160;:</title>
861             <para>
862                 Vous pouvez demander une requête qui retourne plusieurs enregistrements. La
863                 méthode <methodname>fetchAll()</methodname> de votre classe de Table permet ceci. Elle retourne
864                 un objet de type <classname>Zend_Db_Table_Rowset_Abstract</classname>, même si aucun
865                 enregistrement ne correspond à la requête.
866             </para>
868             <example id="zend.db.table.qry.rows.set.finding.row.example">
869                 <title>Exemple de récupération d'enregistrements</title>
871                 <programlisting language="php"><![CDATA[
872 $table = new Bugs();
874 $select = $table->select()->where('bug_status = ?', 'NEW');
876 $rows = $table->fetchAll($select);
877 ]]></programlisting>
878             </example>
880             <para>
881                 Vous pouvez aussi définir les clauses <acronym>SQL</acronym> <code>ORDER BY</code> ou encore
882                 <constant>LIMIT</constant> (ou autre équivalent comme OFFSET).
883             </para>
885             <example id="zend.db.table.fetch-all.example2">
886                 <title>Exemple de récupération d'enregistrements avec des clauses SQL</title>
888                 <programlisting language="php"><![CDATA[
889 $table = new Bugs();
891 $order  = 'bug_id';
893 // Retourne les enregistrements du 21ème au 30ème
894 $count  = 10;
895 $offset = 20;
897 $select = $table->select()->where('bug_status = ?', 'NEW')
898                           ->order($order)
899                           ->limit($count, $offset);
901 $rows = $table->fetchAll($select);
902 ]]></programlisting>
903             </example>
905             <para>
906                 Tous les arguments de requêtes sont optionnels. Vous pouvez écrire une requête
907                 sans clause WHERE ni LIMIT ou encore ORDER.
908             </para>
909         </sect3>
911         <sect3 id="zend.db.table.advanced.usage">
912             <title>Utilisation avancée</title>
914             <para>
915                 Pour une utilisation plus avancée, vous pourriez vouloir spécifier une à une
916                 les colonnes que les enregistrements trouvés doivent comporter. Ceci se fait au
917                 moyen de la clause FROM de l'objet select. Le premier paramètre dans la clause FROM
918                 est le même que celui d'un objet Zend_Db_Select, cependant l'objet
919                 Zend_Db_Table_Select admet une instance de Zend_Db_Table_Abstract pour définir le
920                 nom de la table.
921             </para>
923             <para>
924                 <example id="zend.db.table.qry.rows.set.retrieving.a.example">
925                     <title>Récupérer des colonnes spécifiques sur les enregistrements</title>
927                     <programlisting language="php"><![CDATA[
928 $table = new Bugs();
930 $select = $table->select();
931 $select->from($table, array('bug_id', 'bug_description'))
932        ->where('bug_status = ?', 'NEW');
934 $rows = $table->fetchAll($select);
935 ]]></programlisting>
936                 </example>
937             </para>
939             <para>
940                 <important>
941                     <para>
942                         Le jeu de résultats retourné est tout de même valide. Il ne possède en
943                         revanche que certaines colonnes de la table. La méthode <methodname>save()</methodname>
944                         est appelable, mais elle ne mettre à jour que ces colonnes.
945                     </para>
946                 </important> Il est aussi possible de spécifier des expressions dans une clause
947             FROM, et donc récupérer un objet row/rowset en lecture seule. Dans l'exemple
948             ci-après, nous retournons un enregistrement de la table "bugs" qui représente un
949             agrégat du nombre de nouveaux bugs reportés. Regardez la clause GROUP. L'alias SQL
950             "count" sera accessible dans le row/rowset résultant, comme si il faisait parti de
951                 la table en tant que colonne.
952             </para>
954             <para>
955                 <example id="zend.db.table.qry.rows.set.retrieving.b.example">
956                     <title>Récupérer des enregistrements avec des requêtes incluant des
957                     expressions</title>
959                     <programlisting language="php"><![CDATA[
960 $table = new Bugs();
962 $select = $table->select();
963 $select->from($table,
964               array('COUNT(reported_by) as `count`', 'reported_by'))
965        ->where('bug_status = ?', 'NEW')
966        ->group('reported_by');
968 $rows = $table->fetchAll($select);
969 ]]></programlisting>
970                 </example> Vous pouvez aussi utiliser une table de jointure comme partie de
971             votre requête. Dans l'exemple ci-dessous, nous utilisons la table "accounts" comme
972             partie de la recherche, pour tous les bugs reportés par "Bob".
973             </para>
975             <para>
976                 <example id="zend.db.table.qry.rows.set.refine.example">
977                     <title>Utiliser une table intermédiaire par jointure avec
978                     <methodname>fetchAll()</methodname></title>
980                     <programlisting language="php"><![CDATA[
981 $table = new Bugs();
983 // Récupération avec la partie from déjà spécifié, important lors des jointures
984 $select = $table->select(Zend_Db_Table::SELECT_WITH_FROM_PART);
985 $select->setIntegrityCheck(false)
986        ->where('bug_status = ?', 'NEW')
987        ->join('accounts', 'accounts.account_name = bugs.reported_by')
988        ->where('accounts.account_name = ?', 'Bob');
990 $rows = $table->fetchAll($select);
991 ]]></programlisting>
992                 </example>
993             </para>
995             <para>
996                 L'objet <classname>Zend_Db_Table_Select</classname> est destiné à sélectionner
997                 des données sur une table précise. Des jointures peuvent être faites, mais il n'est
998                 pas possible de sélectionner des colonnes ne faisant pas partie de la table
999                 sous-jacente. Cependant, ceci aurait pu être utile dans certains cas, et l'objet
1000                 <classname>Zend_Db_Table_Select</classname> possède une clause spéciale
1001                 déverrouillant cette limitation. Passez la valeur <constant>FALSE</constant> à sa méthode
1002                 <code>setIntegrityCheck</code>. Il est alors possible de sélectionner des colonnes
1003                 hors table. Attention toutefois, l'objet row/rowset résultant sera verrouillé.
1004                 Impossible d'y appeler <methodname>save()</methodname>, <methodname>delete()</methodname> ou même d'affecter
1005                 une valeur à certains de ses champs. Une exception sera systématiquement
1006                 levée.
1007             </para>
1009             <example id="zend.db.table.qry.rows.set.integrity.example">
1010                 <title>
1011                     Déverrouiller un objet Zend_Db_Table_Select pour récupérer des colonnes JOINtes
1012                 </title>
1014                 <programlisting><![CDATA[
1015 $table = new Bugs();
1017 $select = $table->select(Zend_Db_Table::SELECT_WITH_FROM_PART)
1018                 ->setIntegrityCheck(false);
1019 $select->where('bug_status = ?', 'NEW')
1020        ->join('accounts',
1021               'accounts.account_name = bugs.reported_by',
1022               'account_name')
1023        ->where('accounts.account_name = ?', 'Bob');
1025 $rows = $table->fetchAll($select);
1026 ]]></programlisting>
1027             </example>
1028         </sect3>
1029     </sect2>
1031     <sect2 id="zend.db.table.fetch-row">
1032         <title>Récupérer un seul enregistrement</title>
1034         <para>
1035             Vous pouvez demander à ne récupérer qu'un seul résultat, en requêtant de manière
1036             similaire à la méthode <methodname>fetchAll()</methodname>.
1037         </para>
1039         <example id="zend.db.table.fetch-row.example1">
1040             <title>Exemple de récupération d'un seul enregistrement</title>
1042             <programlisting language="php"><![CDATA[
1043 $table = new Bugs();
1045 $select  = $table->select()->where('bug_status = ?', 'NEW')
1046                            ->order('bug_id');
1048 $row = $table->fetchRow($select);
1049 ]]></programlisting>
1050         </example>
1052         <para>
1053             Cette méthode retourne un objet de type Zend_Db_Table_Row_Abstract. Si la requête
1054             ne trouve aucun enregistrement, alors <methodname>fetchRow()</methodname> retournera
1055             <constant>NULL</constant>.
1056         </para>
1057     </sect2>
1059     <sect2 id="zend.db.table.info">
1060         <title>Récupérer les méta données d'une Table</title>
1062         <para>
1063             La classe Zend_Db_Table_Abstract propose des informations concernant ses méta
1064             données.La méthode <methodname>info()</methodname> retourne un tableau d'informations sur les
1065             colonnes, la clé primaire, etc. de la table.
1066         </para>
1068         <example id="zend.db.table.info.example">
1069             <title>Exemple de récupération du nom de la table</title>
1071             <programlisting language="php"><![CDATA[
1072 $table = new Bugs();
1074 $info = $table->info();
1076 echo "The table name is " . $info['name'] . "\n";
1077 ]]></programlisting>
1078         </example>
1080         <para>Les clés du tableau retourné par <methodname>info()</methodname> sont les suivantes :</para>
1082         <itemizedlist>
1083             <listitem>
1084                 <para><emphasis>name</emphasis>&#160;=&gt; nom de la table.</para>
1085             </listitem>
1087             <listitem>
1088                 <para>
1089                     <emphasis>cols</emphasis>&#160;=&gt; un tableau contenant les colonnes de la
1090                     table.
1091                 </para>
1092             </listitem>
1094             <listitem>
1095                 <para>
1096                     <emphasis>primary</emphasis>&#160;=&gt; un tableau contenant la(les) colonnes
1097                     utilisée(s) pour définir la clé primaire de la table.
1098                 </para>
1099             </listitem>
1101             <listitem>
1102                 <para>
1103                     <emphasis>metadata</emphasis>&#160;=&gt; un tableau associatif, associant les
1104                     noms des colonnes de la tables, à leurs informations intrinsèques. Les données
1105                     sont les mêmes que celles retournée par <methodname>describeTable()</methodname>.
1106                 </para>
1107             </listitem>
1109             <listitem>
1110                 <para>
1111                     <emphasis>rowClass</emphasis>&#160;=&gt; le nom de la classe concrète servant
1112                     les objets représentants les enregistrements de la table. Par défaut&#160;:
1113                     Zend_Db_Table_Row.
1114                 </para>
1115             </listitem>
1117             <listitem>
1118                 <para>
1119                     <emphasis>rowsetClass</emphasis>&#160;=&gt; le nom de la classe concrète
1120                     servant de conteneur d'objets représentants les enregistrements de la table. Par
1121                     défaut : Zend_Db_Table_Rowset.
1122                 </para>
1123             </listitem>
1125             <listitem>
1126                 <para>
1127                     <emphasis>referenceMap</emphasis>&#160;=&gt; un tableau associatif. Il
1128                     représente les références de cette table vers ses parents éventuelles. Voyez
1129                     <xref linkend="zend.db.table.relationships.defining" />.
1130                 </para>
1131             </listitem>
1133             <listitem>
1134                 <para>
1135                     <emphasis>dependentTables</emphasis>&#160;=&gt; un tableau de noms de classes
1136                     de tables qui référencent cette table. Voyez <xref
1137                     linkend="zend.db.table.relationships.defining" />.
1138                 </para>
1139             </listitem>
1141             <listitem>
1142                 <para>
1143                     <emphasis>schema</emphasis>&#160;=&gt; Le nom de la base de données comportant
1144                     cette table.
1145                 </para>
1146             </listitem>
1147         </itemizedlist>
1148     </sect2>
1150     <sect2 id="zend.db.table.metadata.caching">
1151         <title>Cacher les méta données de la table</title>
1153         <para>
1154             Par défaut, <classname>Zend_Db_Table_Abstract</classname> demande à la base de
1155             données les <link linkend="zend.db.table.info">méta données de table</link>, à chaque
1156             instanciation d'objet de table. L'objet de table analyse les métadonnées de la table
1157             dans le SGDB en utilisant la méthode <methodname>describeTable()</methodname> de l'adaptateur. Les
1158             opérations nécessitant cette introspection incluent&#160;:
1159         </para>
1161         <itemizedlist>
1162             <listitem>
1163                 <para><methodname>insert()</methodname></para>
1164             </listitem>
1166             <listitem>
1167                 <para><methodname>find()</methodname></para>
1168             </listitem>
1170             <listitem>
1171                 <para><methodname>info()</methodname></para>
1172             </listitem>
1173         </itemizedlist>
1175         <para>
1176             Cependant, il peut être dégradant pour les performances du SGBD de lui demander
1177             ces informations à chaque instanciation de chaque objet de chaque table. Ainsi, un
1178             système de cache pour les méta données a été mis en place.
1179         </para>
1181         <para>
1182             La mise en cache des méta données des tables peut être contrôlée de deux manières&#160;:
1183             <itemizedlist>
1184                     <listitem>
1185                     <para>
1186                         <emphasis>Un appel à la méthode statique
1187                         Zend_Db_Table_Abstract::setDefaultMetadataCache()</emphasis> - Ceci permet
1188                         d'enregistrer une fois pour toutes l'objet de cache que toutes les tables
1189                         devront utiliser.
1190                     </para>
1191                 </listitem>
1193                 <listitem>
1194                     <para>
1195                         <emphasis>L'appel au constructeur
1196                         Zend_Db_Table_Abstract::__construct()</emphasis> - Il va permettre de
1197                         spécifier l'objet de cache pour une table en particulier.
1198                     </para>
1199                 </listitem>
1200             </itemizedlist>
1201             Dans tous les cas, vous devrez passer soit <constant>NULL</constant> (et
1202             ainsi désactiver le cache des méta données des tables), soit une instance de <link
1203             linkend="zend.cache.frontends.core"><classname>Zend_Cache_Core</classname></link>. Il
1204             est possible d'utiliser à la fois <code>setDefaultMetadataCache</code> et le
1205             constructeur afin d'avoir un objet de cache par défaut, puis un spécifique pour
1206             certaines classes.
1207         </para>
1209         <example id="zend.db.table.metadata.caching-default">
1210             <title>Utiliser un objet de cache de méta données pour toutes les classes</title>
1212             <para>
1213                 L'exemple qui suit illustre la manière de passer un objet de cache de méta
1214                 données général, pour toutes les classes de table&#160;:
1215             </para>
1217             <programlisting language="php"><![CDATA[
1218 // D'abord, configurons le cache
1219 $frontendOptions = array(
1220     'automatic_serialization' => true
1221     );
1223 $backendOptions  = array(
1224     'cache_dir'                => 'cacheDir'
1225     );
1227 $cache = Zend_Cache::factory('Core',
1228                              'File',
1229                              $frontendOptions,
1230                              $backendOptions);
1232 // Puis passons le comme objet de cache par défaut
1233 Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
1235 // Testons avec une classe
1236 class Bugs extends Zend_Db_Table_Abstract
1238     // ...
1241 // Chaque instance utilise l'objet par défaut
1242 $bugs = new Bugs();
1243 ]]></programlisting>
1244         </example>
1246         <example id="zend.db.table.metadata.caching-instance">
1247             <title>Utiliser un objet de cache de métadonnées pour une instance précise</title>
1249             <para>
1250                 L'exemple qui suit illustre la manière de passer un objet de cache de méta
1251                 données spécifique, pour une instance précise&#160;:
1252             </para>
1254             <programlisting language="php"><![CDATA[
1255 // D'abord, configurons le cache
1256 $frontendOptions = array(
1257     'automatic_serialization' => true
1258     );
1260 $backendOptions  = array(
1261     'cache_dir'                => 'cacheDir'
1262     );
1264 $cache = Zend_Cache::factory('Core',
1265                              'File',
1266                              $frontendOptions,
1267                              $backendOptions);
1269 // Testons avec une classe
1270 class Bugs extends Zend_Db_Table_Abstract
1272     // ...
1275 // Lors de son instanciation, il est possible
1276 // de lui passer l'objet de cache
1277 $bugs = new Bugs(array('metadataCache' => $cache));
1278 ]]></programlisting>
1279         </example>
1281         <note>
1282             <title>Sérialisation automatique avec Cache Frontend</title>
1284             <para>
1285                 Étant donné que les informations retournées par
1286                 <methodname>describeTable()</methodname> le sont sous forme de tableau, assurez vous
1287                 que le paramètre <code>automatic_serialization</code> est à <constant>TRUE</constant> pour
1288                 l'objet de la classe <classname>Zend_Cache_Core</classname>.
1289             </para>
1290         </note>
1292         <para>
1293             Dans nos exemples, nous utilisons <classname>Zend_Cache_Backend_File</classname>,
1294             mais vous pouvez utiliser le backend que vous souhaitez, voyez <link
1295             linkend="zend.cache">Zend_Cache</link> pour plus d'informations.
1296         </para>
1298         <sect3 id="zend.db.table.metadata.caching.hardcoding">
1299             <title>Coder en dur les métadonnées de tables</title>
1301             <para>
1302                 Pour cacher les métadonnées une étape plus avant, vous pouvez aussi choisir de
1303                 coder en dur ces métadonnées. Dans ce cas particulier, cependant, tout changement au
1304                 schéma de la table requerra un changement dans votre code. Ainsi, il est seulement
1305                 recommandé pour ceux qui sont dans la phase d'optimisation pour un usage en
1306                 production.
1307             </para>
1309             <para>La structure des métadonnées est comme ceci&#160;:</para>
1311             <programlisting language="php"><![CDATA[
1312 protected $_metadata = array(
1313     '<column_name>' => array(
1314         'SCHEMA_NAME'      => <string>,
1315         'TABLE_NAME'       => <string>,
1316         'COLUMN_NAME'      => <string>,
1317         'COLUMN_POSITION'  => <int>,
1318         'DATA_TYPE'        => <string>,
1319         'DEFAULT'          => NULL|<value>,
1320         'NULLABLE'         => <bool>,
1321         'LENGTH'           => <string - length>,
1322         'SCALE'            => NULL|<value>,
1323         'PRECISION'        => NULL|<value>,
1324         'UNSIGNED'         => NULL|<bool>,
1325         'PRIMARY'          => <bool>,
1326         'PRIMARY_POSITION' => <int>,
1327         'IDENTITY'         => <bool>,
1328     ),
1329     // additional columns...
1331 ]]></programlisting>
1333             <para>
1334                 Une manière simple de récupérer les valeurs appropriées est d'activer le cache
1335                 des métadonnées et d'utiliser celles présentes dans votre cache.
1336             </para>
1338             <para>
1339                 Vous pouvez désactiver cette optimisation en mettant à <constant>FALSE</constant> le
1340                 paramètre <code>metadataCacheInClass</code>&#160;:
1341             </para>
1343             <programlisting language="php"><![CDATA[
1344 // Lors de l'instanciation :
1345 $bugs = new Bugs(array('metadataCacheInClass' => false));
1347 // Ou plus tard :
1348 $bugs->setMetadataCacheInClass(false);
1349 ]]></programlisting>
1351             <para>
1352                 Ce paramètre est activé par défaut, ce qui assure que le tableau
1353                 <varname>$_metadata</varname> n'est chargé qu'une seule fois par instance
1354             </para>
1355         </sect3>
1356     </sect2>
1358     <sect2 id="zend.db.table.extending">
1359         <title>Personnaliser et étendre une classe de Table</title>
1361         <sect3 id="zend.db.table.extending.row-rowset">
1362             <title>Utiliser des objets Row ou Rowset personnalisés</title>
1364             <para>
1365                 Par défaut, les méthodes de la classe de Table retourne des jeux
1366                 d'enregistrements comme étant des instances de la classe
1367                 <classname>Zend_Db_Table_Rowset</classname>, ces "Rowsets" contiennent des
1368                 enregistrements de la table, représentés par des objets instances de
1369                 <classname>Zend_Db_Table_Row</classname>. Vous pouvez spécifier vos propres classes
1370                 pour row/rowset, mais elles doivent étendre
1371                 <classname>Zend_Db_Table_Rowset_Abstract</classname> ou
1372                 <classname>Zend_Db_Table_Row_Abstract</classname>, respectivement.
1373             </para>
1375             <para>
1376                 Vous pouvez spécifier vos classes row/rowset en utilisant le constructeur de
1377                 la classe de Table, via le tableau d'options, aux clés <code>"rowClass"</code> et
1378                 <code>"rowsetClass"</code>. Indiquez les noms des classes sous forme de chaînes de
1379                 caractères.
1380             </para>
1382             <example id="zend.db.table.extending.row-rowset.example">
1383                 <title>Exemple de spécification de ses propres classes Row et Rowset</title>
1385                 <programlisting language="php"><![CDATA[
1386 class My_Row extends Zend_Db_Table_Row_Abstract
1388     ...
1391 class My_Rowset extends Zend_Db_Table_Rowset_Abstract
1393     ...
1396 $table = new Bugs(
1397     array(
1398         'rowClass'    => 'My_Row',
1399         'rowsetClass' => 'My_Rowset'
1400     )
1403 $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
1405 // Retourne un objet de type My_Rowset,
1406 // contenant des objets de type My_Row.
1407 $rows = $table->fetchAll($where);
1408 ]]></programlisting>
1409             </example>
1411             <para>
1412                 Vous pouvez aussi utiliser les méthodes <methodname>setRowClass()</methodname> et
1413                 <methodname>setRowsetClass()</methodname>. Ceci s'applique alors de manière ponctuelle, et non
1414                 plus globale pour toute la classe de Table en tout point.
1415             </para>
1417             <example id="zend.db.table.extending.row-rowset.example2">
1418                 <title>Exemple de changement ponctuel des classes de Row et Rowset</title>
1420                 <programlisting language="php"><![CDATA[
1421 $table = new Bugs();
1423 $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
1425 // Retourne un objet de type Zend_Db_Table_Rowset
1426 // contenant des objets de type Zend_Db_Table_Row.
1427 $rowsStandard = $table->fetchAll($where);
1429 $table->setRowClass('My_Row');
1430 $table->setRowsetClass('My_Rowset');
1432 // Retourne un objet de type My_Rowset,
1433 // contenant des objets de type My_Row.
1434 $rowsCustom = $table->fetchAll($where);
1436 // L'objet $rowsStandard existe toujours et n'a pas changé d'état.
1437 ]]></programlisting>
1438             </example>
1440             <para>
1441                 Pour des informations détaillées concernant les classes Row et Rowset, voyez
1442                 <xref linkend="zend.db.table.row" /> et <xref
1443                 linkend="zend.db.table.rowset" />.
1444             </para>
1445         </sect3>
1447         <sect3 id="zend.db.table.extending.insert-update">
1448             <title>Personnaliser les logiques Insert, Update, et Delete</title>
1450             <para>
1451                 Vous pouvez redéfinir les méthodes <methodname>insert()</methodname> et
1452                 <methodname>update()</methodname> afin d'y ajouter votre propre logique. Assurez vous d'appeler
1453                 les méthodes parentes une fois votre code écrit.
1454             </para>
1456             <example id="zend.db.table.extending.insert-update.example">
1457                 <title>
1458                     Exemple d'implémentation d'une logique personnalisée gérant des timestamps
1459                 </title>
1461                 <programlisting language="php"><![CDATA[
1462 class Bugs extends Zend_Db_Table_Abstract
1464     protected $_name = 'bugs';
1466     public function insert(array $data)
1467     {
1468         // Ajout d'un timestamp
1469         if (empty($data['created_on'])) {
1470             $data['created_on'] = time();
1471         }
1472         return parent::insert($data);
1473     }
1475     public function update(array $data, $where)
1476     {
1477         // Ajout d'un timestamp
1478         if (empty($data['updated_on'])) {
1479             $data['updated_on'] = time();
1480         }
1481         return parent::update($data, $where);
1482     }
1484 ]]></programlisting>
1485             </example>
1487             <para>Il est aussi possible de redéfinir la méthode <methodname>delete()</methodname>.</para>
1488         </sect3>
1490         <sect3 id="zend.db.table.extending.finders">
1491             <title>Définir des méthodes de recherches personnalisées dans Zend_Db_Table</title>
1493             <para>
1494                 Bien que <methodname>fetchAll()</methodname> fonctionne très bien, si vous avez plusieurs
1495                 appels similaires à cette méthode (ou une autre), il peut être intéressant de
1496                 factoriser du code en créant votre propre méthode de récupération d'enregistrements,
1497                 utilisant <methodname>fetchAll()</methodname> ou une autre méthode.
1498             </para>
1500             <example id="zend.db.table.extending.finders.example">
1501                 <title>Méthode personnalisée de récupération d'enregistrements "bugs" par
1502                 critère "status"</title>
1504                 <programlisting language="php"><![CDATA[
1505 class Bugs extends Zend_Db_Table_Abstract
1507     protected $_name = 'bugs';
1509     public function findByStatus($status)
1510     {
1511         $where = $this->getAdapter()->quoteInto('bug_status = ?',
1512                                                 $status);
1513         return $this->fetchAll($where, 'bug_id');
1514     }
1516 ]]></programlisting>
1517             </example>
1518         </sect3>
1520         <sect3 id="zend.db.table.extending.inflection">
1521             <title>Utiliser l'inflexion dans Zend_Db_Table</title>
1523             <para>
1524                 L'<emphasis>inflexion</emphasis> est un processus de transformations de
1525                 caractères. Par défaut, si vous ne définissez pas de nom à votre table via la
1526                 propriété protégée <varname>$_name</varname>,
1527                 <classname>Zend_Db_Table_Abstract</classname> va utiliser le nom de la classe comme
1528                 nom de table, sans effectuer aucune transformation.
1529             </para>
1531             <para>
1532                 Certaines personnes peuvent vouloir utiliser un mécanisme d'inflexion pour
1533                 transformer le nom de la classe d'une manière bien spécifique, afin de retrouver le
1534                 nom de la table.
1535             </para>
1537             <para>
1538                 Par exemple, une classe nommée "<code>BugsProducts</code>", peut vouloir
1539                 refléter une table s'appelant "<code>bugs_products</code>," sans utiliser la
1540                 propriété de classe <varname>$_name</varname>. Dans cette règle d'inflexion, les mots
1541                 composant le nom de la classe sont écrits en "CamelCase", et seraient transformés en
1542                 mots en minuscules, et séparés par des tirets bas.
1543             </para>
1545             <para>
1546                 Vous pouvez aussi spécifier le nom de la table indépendamment du nom de la
1547                 classe. Utilisez pour cela la propriété <varname>$_name</varname> de la classe de
1548                 Table.
1549             </para>
1551             <para>
1552                 Si vous voulez utiliser l'inflexion, vous devrez créer une classe (abstraite)
1553                 étendant <classname>Zend_Db_Table_Abstract</classname>, et redéfinissant sa méthode
1554                 protégée <methodname>_setupTableName()</methodname>. Toutes les classes de Table devront alors
1555                 hériter de cette nouvelle classe abstraite.
1556             </para>
1558             <example id="zend.db.table.extending.inflection.example">
1559                 <title>Exemple d'une classe abstraite utilisant l'inflexion</title>
1561                 <programlisting language="php"><![CDATA[
1562 abstract class MyAbstractTable extends Zend_Db_Table_Abstract
1564     protected function _setupTableName()
1565     {
1566         if (!$this->_name) {
1567             $this->_name = myCustomInflector(get_class($this));
1568         }
1569         parent::_setupTableName();
1570     }
1573 class BugsProducts extends MyAbstractTable
1576 ]]></programlisting>
1577             </example>
1579             <para>
1580                 C'est à vous d'écrire les fonctions qui vont établir le mécanisme
1581                 d'inflexion.
1582             </para>
1583         </sect3>
1584     </sect2>
1585 </sect1>