[ZF-10089] Zend_Log
[zend.git] / documentation / manual / fr / module_specs / Zend_Db_Table_Row.xml
blob93d1f320c0dc6dde34a5939070cd4e7e690f089f
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- EN-Revision: 20766 -->
3 <!-- Reviewed: no -->
4 <sect1 id="zend.db.table.row">
5     <title>Zend_Db_Table_Row</title>
7     <sect2 id="zend.db.table.row.introduction">
8         <title>Introduction</title>
10         <para>
11             <classname>Zend_Db_Table_Row</classname> est la classe qui donne accès à chacun
12             des résultats issus d'un objet <classname>Zend_Db_Table</classname>. Lorsque vous
13             exécutez une requête via une classe de Table, alors les résultats sont des objets
14             <classname>Zend_Db_Table_Row</classname>. Vous pouvez aussi utiliser ces objets comme
15             résultats vides : pour créer des nouveaux résultats à ajouter à la base de
16             données.
17         </para>
19         <para>
20             <classname>Zend_Db_Table_Row</classname> est une implémentation du design pattern
21             <ulink url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data
22             Gateway</ulink>
23         </para>
24     </sect2>
26     <sect2 id="zend.db.table.row.read">
27         <title>Récupérer un résultat (un "Row")</title>
29         <para>
30             <classname>Zend_Db_Table_Abstract</classname> possède des méthodes
31             <methodname>find()</methodname> et <methodname>fetchAll()</methodname>, qui retournent un objet de type
32             <classname>Zend_Db_Table_Rowset</classname>, et une méthode <methodname>fetchRow()</methodname>, qui
33             retourne un objet de type <classname>Zend_Db_Table_Row</classname>.
34         </para>
36         <example id="zend.db.table.row.read.example">
37             <title>Exemple de récupération d'un Row</title>
39             <programlisting language="php"><![CDATA[
40 $bugs = new Bugs();
41 $row = $bugs->fetchRow($bugs->select()
42                             ->where('bug_id = ?', 1));
43 ]]></programlisting>
44         </example>
46         <para>
47             Un objet <classname>Zend_Db_Table_Rowset</classname> contient une collection
48             d'objets <classname>Zend_Db_Table_Row</classname>. Voyez <xref
49             linkend="zend.db.table.rowset" />.
50         </para>
52         <example id="zend.db.table.row.read.example-rowset">
53             <title>Exemple de lecture d'un Row dans un Rowset</title>
55             <programlisting language="php"><![CDATA[
56 $bugs = new Bugs();
57 $rowset = $bugs->fetchAll($bugs->select()
58                                ->where('bug_status = ?', 1));
59 $row = $rowset->current();
60 ]]></programlisting>
61         </example>
63         <sect3 id="zend.db.table.row.read.get">
64             <title>Lecture des valeurs des colonnes, dans un Row</title>
66             <para>
67                 <classname>Zend_Db_Table_Row_Abstract</classname> possède des accesseurs. Les
68                 colonnes <acronym>SQL</acronym> du résultat sont disponibles en lecture et écriture, via des propriétés
69                 de classe.
70             </para>
72             <example id="zend.db.table.row.read.get.example">
73                 <title>Lecture d'une colonne dans un Row</title>
75                 <programlisting language="php"><![CDATA[
76 $bugs = new Bugs();
77 $row = $bugs->fetchRow($bugs->select()
78                             ->where('bug_id = ?', 1));
80 // Affiche la valeur de la colonne bug_description
81 echo $row->bug_description;
82 ]]></programlisting>
83             </example>
85             <note>
86                 <para>
87                     Les versions antérieures de <classname>Zend_Db_Table_Row</classname>
88                     utilisaient un processus de transformation nommé <emphasis>inflexion</emphasis>
89                     pour récupérer les valeurs des colonnes dans un résultat.
90                 </para>
92                 <para>
93                     Actuellement, <classname>Zend_Db_Table_Row</classname> n'utilise pas
94                     d'inflexion. Les noms des propriétés de l'objet doivent correspondre à
95                     l'orthographe des noms des colonnes dans la base de données sous-jacente
96                 </para>
97             </note>
98         </sect3>
100         <sect3 id="zend.db.table.row.read.to-array">
101             <title>Récupérer les valeurs des colonnes comme un tableau</title>
103             <para>
104                 Vous pouvez accéder aux données d'un row sous forme de tableau grâce à la
105                 méthode <methodname>toArray()</methodname>. Celle-ci retourne un tableau associatif.
106             </para>
108             <example id="zend.db.table.row.read.to-array.example">
109                 <title>Exemple avec toArray()</title>
111                 <programlisting language="php"><![CDATA[
112 $bugs = new Bugs();
113 $row = $bugs->fetchRow($bugs->select()
114                             ->where('bug_id = ?', 1));
116 // Récupère un tableau associatif column/value
117 $rowArray = $row->toArray();
119 // Utilisation comme un tableau normal
120 foreach ($rowArray as $column => $value) {
121     echo "Column: $column\n";
122     echo "Value:  $value\n";
124 ]]></programlisting>
125             </example>
127             <para>
128                 Le tableau retourné par <methodname>toArray()</methodname> n'est pas une référence. Vous
129                 pouvez modifier ses valeurs, cela n'aura aucune répercussion dans la base de
130                 données.
131             </para>
132         </sect3>
134         <sect3 id="zend.db.table.row.read.relationships">
135             <title>Récupérer des données des tables liées</title>
137             <para>
138                 <classname>Zend_Db_Table_Row_Abstract</classname> possède des méthodes
139                 permettant de récupérer des données des tables liées à la table interrogée. Voyez
140                 <xref linkend="zend.db.table.relationships" /> pour plus d'informations sur les
141                 relations entre les tables.
142             </para>
143         </sect3>
144     </sect2>
146     <sect2 id="zend.db.table.row.write">
147         <title>Sauvegarde un Row en base de données</title>
149         <sect3 id="zend.db.table.row.write.set">
150             <title>Changement des valeurs des colonnes d'un Row</title>
152             <para>
153                 Vous pouvez changer les valeurs de chaque colonne du résultat Row, simplement
154                 avec les accesseurs, comme en lecture. Effectuez une banale affectation.
155             </para>
157             <para>
158                 Utiliser l'accesseur pour spécifier une valeur à une colonne d'un résultat Row
159                 ne répercute pas le comportement immédiatement en base de données. Vous devez
160                 utiliser explicitement la méthode <methodname>save()</methodname> pour ceci.
161             </para>
163             <example id="zend.db.table.row.write.set.example">
164                 <title>Exemple de changement de la valeur d'une colonne dans un Row</title>
166                 <programlisting language="php"><![CDATA[
167 $bugs = new Bugs();
168 $row = $bugs->fetchRow($bugs->select()
169                             ->where('bug_id = ?', 1));
171 // Change la valeur d'une ou plusieurs colonnes
172 $row->bug_status = 'FIXED';
174 // MET A JOUR l'enregistrement dans la base de données
175 $row->save();
176 ]]></programlisting>
177             </example>
178         </sect3>
180         <sect3 id="zend.db.table.row.write.insert">
181             <title>Créer un Row vierge</title>
183             <para>
184                 Vous pouvez créer un nouvel enregistrement vierge (Row) pour une table avec la
185                 méthode <methodname>createRow()</methodname> issue de la classe de cette Table. Vous pouvez
186                 alors affecter des valeurs à ses colonnes grâce aux accesseurs, comme déjà vu, puis
187                 enregistrer le Row en base de données avec sa méthode <methodname>save()</methodname>.
188             </para>
190             <example id="zend.db.table.row.write.insert.example">
191                 <title>Exemple de création d'un Row vierge pour une table</title>
193                 <programlisting language="php"><![CDATA[
194 $bugs = new Bugs();
195 $newRow = $bugs->createRow();
197 // affecte des valeurs aux colonnes
198 $newRow->bug_description = '...description...';
199 $newRow->bug_status = 'NEW';
201 // INSERT le nouvel enregistrement dans la base de données
202 $newRow->save();
203 ]]></programlisting>
204             </example>
206             <para>
207                 L'argument optionnel de <methodname>createRow()</methodname> est un tableau associatif qui
208                 sert à peupler tout de suite l'objet de valeurs.
209             </para>
211             <example id="zend.db.table.row.write.insert.example2">
212                 <title>Exemple de remplissage des valeurs d'un nouveau Row vierge</title>
214                 <programlisting language="php"><![CDATA[
215 $data = array(
216     'bug_description' => '...description...',
217     'bug_status'      => 'NEW'
220 $bugs = new Bugs();
221 $newRow = $bugs->createRow($data);
223 // INSERT l'enregistrement en base de données
224 $newRow->save();
225 ]]></programlisting>
226             </example>
228             <note>
229                 <para>
230                     La méthode <methodname>createRow()</methodname> était nommée <methodname>fetchNew()</methodname>
231                     dans les anciennes version de <classname>Zend_Db_Table</classname>. Il est
232                     recommandé de ne plus utiliser cette ancienne appellation, même si celle-ci
233                     fonctionne toujours actuellement.
234                 </para>
235             </note>
236         </sect3>
238         <sect3 id="zend.db.table.row.write.set-from-array">
239             <title>Changement en masse des valeurs dans un Row</title>
241             <para>
242                 <classname>Zend_Db_Table_Row_Abstract</classname> possède une méthode
243                 <methodname>setFromArray()</methodname> qui permet de lui peupler ses valeurs avec celles issues
244                 d'un tableau associatif nom de la colonne / valeur.
245             </para>
247             <example id="zend.db.table.row.write.set-from-array.example">
248                 <title>
249                     Exemple d'utilisation de setFromArray() avec un enregistrement (Row) vierge
250                 </title>
252                 <programlisting language="php"><![CDATA[
253 $bugs = new Bugs();
254 $newRow = $bugs->createRow();
256 // Les données sont dans un tableau associatif
257 $data = array(
258     'bug_description' => '...description...',
259     'bug_status'      => 'NEW'
262 // Affecte toutes les valeurs des colonnes en une seule fois
263 $newRow->setFromArray($data);
265 // INSERT l'enregistrement en base de données
266 $newRow->save();
267 ]]></programlisting>
268             </example>
269         </sect3>
271         <sect3 id="zend.db.table.row.write.delete">
272             <title>Supprimer un Row</title>
274             <para>
275                 Vous pouvez appeler la méthode <methodname>delete()</methodname> d'un objet Row. Ceci
276                 supprime les lignes dans la base de données qui correspondent à la clé primaire de
277                 l'objet Row.
278             </para>
280             <example id="zend.db.table.row.write.delete.example">
281                 <title>Effacer un Row</title>
283                 <programlisting language="php"><![CDATA[
284 $bugs = new Bugs();
285 $row = $bugs->fetchRow('bug_id = 1');
287 // EFFACE cet enregistrement de la base de données
288 $row->delete();
289 ]]></programlisting>
290             </example>
292             <para>
293                 Notez qu'il n'est pas nécessaire d'appeler <methodname>save()</methodname> pour un
294                 effacement. Celui-ci est à effet immédiat.
295             </para>
296         </sect3>
297     </sect2>
299     <sect2 id="zend.db.table.row.serialize">
300         <title>Sérialisation et désérialisation d'un Row</title>
302         <para>
303             Il peut être utile de sauvegarder le contenu d'un enregistrement (Row) sur un
304             support quelconque, pour une utilisation ultérieure. La
305             <emphasis>sérialisation</emphasis> est le nom de l'opération qui consiste à transformer
306             un objet en une forme facilement stockable (dans un fichier par exemple). Les objets du
307             type <classname>Zend_Db_Table_Row_Abstract</classname> sont sérialisables.
308         </para>
310         <sect3 id="zend.db.table.row.serialize.serializing">
311             <title>Sérialiser un Row</title>
313             <para>
314                 Utilisez simplement la fonction <acronym>PHP</acronym> <methodname>serialize()</methodname> pour créer une
315                 chaîne de caractères représentant votre objet Row.
316             </para>
318             <example id="zend.db.table.row.serialize.serializing.example">
319                 <title>Exemple de sérialisation d'un Row</title>
321                 <programlisting language="php"><![CDATA[
322 $bugs = new Bugs();
323 $row = $bugs->fetchRow('bug_id = 1');
325 // Convertit l'objet en une forme sérialisée
326 $serializedRow = serialize($row);
328 // Maintenant vous pouvez utiliser $serializedRow
329 // pour l'écrire dans un fichier, etc.
330 ]]></programlisting>
331             </example>
332         </sect3>
334         <sect3 id="zend.db.table.row.serialize.unserializing">
335             <title>Désérialiser les données d'un Row</title>
337             <para>
338                 Utilisez simplement la fonction <acronym>PHP</acronym> <methodname>unserialize()</methodname>. L'objet Row
339                 originel est alors recréé.
340             </para>
342             <para>
343                 Notez que l'objet retourné fonctionne alors en mode
344                 <emphasis>déconnecté</emphasis>. Vous pouvez lire les valeurs des colonnes, mais pas
345                 les modifier ni enregistrer l'objet en base de données
346                 (<methodname>save()</methodname>).
347             </para>
349             <example id="zend.db.table.row.serialize.unserializing.example">
350                 <title>Exemple de désérialisation d'un objet Row sérialisé</title>
352                 <programlisting language="php"><![CDATA[
353 $rowClone = unserialize($serializedRow);
355 // Vous ne pouvez faire qu'une utilisation en lecture seule
356 echo $rowClone->bug_description;
357 ]]></programlisting>
358             </example>
360             <note>
361                 <title>Pourquoi ce mode déconnecté imposé ?</title>
363                 <para>
364                     Un objet sérialisé est une chaîne de caractère, humainement visible. Il
365                     est donc peu sécurisé d'y laisser un mot de passe vers un serveur de base de
366                     données. Le lecteur d'un objet Row sérialisé ne devrait pas pouvoir accéder à la
367                     base de données. De plus, une connexion à une base de données est un type non
368                     sérialisable par <acronym>PHP</acronym> (ressource).
369                 </para>
370             </note>
371         </sect3>
373         <sect3 id="zend.db.table.row.serialize.set-table">
374             <title>Reconnecter l'objet Row à la Table</title>
376             <para>
377                 Il est bien entendu possible de reconnecter l'objet Row à la base de données,
378                 et plus précisément à la Table dont il fut issu. Utilisez la méthode
379                 <methodname>setTable()</methodname> et passez lui une instance héritant de
380                 <classname>Zend_Db_Table_Abstract</classname>. Une fois reconnecté, l'objet Row
381                 possède de nouveau un accès à la base de données, et n'est donc plus en mode lecture
382                 seule.
383             </para>
385             <example id="zend.db.table.row.serialize.set-table.example">
386                 <title>Exemple de réactivation d'un Row</title>
388                 <programlisting language="php"><![CDATA[
389 $rowClone = unserialize($serializedRow);
391 $bugs = new Bugs();
393 // Reconnecte le Row à la table et donc, à la base de données
394 $rowClone->setTable($bugs);
396 // Maintenant il est possible de l'utiliser en mode écriture
397 $rowClone->bug_status = 'FIXED';
398 $rowClone->save();
399 ]]></programlisting>
400             </example>
401         </sect3>
402     </sect2>
404     <sect2 id="zend.db.table.row.extending">
405         <title>Étendre la classe Row</title>
407         <para>
408             Vous pouvez utilisez votre propre classe étendant
409             <classname>Zend_Db_Table_Row_Abstract</classname>. Spécifiez votre classe dans la
410             propriété protégée <varname>$_rowClass</varname> de la classe de votre Table, ou dans le
411             tableau du constructeur de l'objet Table.
412         </para>
414         <example id="zend.db.table.row.extending.example">
415             <title>Spécification d'une classe Row personnalisée</title>
417             <programlisting language="php"><![CDATA[
418 class MyRow extends Zend_Db_Table_Row_Abstract
420     // ...personnalisations
423 // Spécifie la classe de Row utilisée pour toutes les
424 // instance de la classe de Table
425 class Products extends Zend_Db_Table_Abstract
427     protected $_name = 'products';
428     protected $_rowClass = 'MyRow';
431 // Ou pour une classe de table spécifique, via son constructeur
432 $bugs = new Bugs(array('rowClass' => 'MyRow'));
433 ]]></programlisting>
434         </example>
436         <sect3 id="zend.db.table.row.extending.overriding">
437             <title>Initialisation et pré-traitements d'un Row</title>
439             <para>
440                 Si vous avez un besoin spécifique d'implémenter une logique spéciale après la
441                 création d'une instance de Row, vous pouvez utiliser sa méthode <methodname>init()</methodname>,
442                 qui est appelée dans son constructeur, mais après que les méta données aient été
443                 calculées. <example id="zend.db.table.row.init.usage.example">
444                         <title>Exemple d'utilisation de la méthode init()</title>
446                         <programlisting language="php"><![CDATA[
447 class MyApplicationRow extends Zend_Db_Table_Row_Abstract
449     protected $_role;
451     public function init()
452     {
453         $this->_role = new MyRoleClass();
454     }
456 ]]></programlisting>
457                     </example>
458                 </para>
459         </sect3>
461         <sect3 id="zend.db.table.row.extending.insert-update">
462             <title>
463                 Définir sa propre logique pour Insert, Update, et Delete dans Zend_Db_Table_Row
464             </title>
466             <para>
467                 La classe des Rows appelle les méthodes protégées <methodname>_insert()</methodname>,
468                 <methodname>_update()</methodname>, et <methodname>_delete()</methodname> avant d'effectuer chacune des
469                 opérations respectives <constant>INSERT</constant>, <constant>UPDATE</constant>, et
470                 <constant>DELETE</constant>. Il est donc possible de définir sa propre logique dans votre
471                 sous-classe de Row.
472             </para>
474             <para>
475                 Ci-dessous vous trouverez des exemples d'utilisation d'une logique
476                 personnalisée dans les classes de Row :
477             </para>
479             <example id="zend.db.table.row.extending.overriding-example1">
480                 <title>Exemple de logique personnalisée dans une classe de Row</title>
482                 <para>
483                     La logique personnelle peut donc être déportée dans une classe de Row qui
484                     ne s'appliquera qu'à certaines tables, et pas à d'autres. Sinon, la classe de
485                     Table utilise le Row par défaut.
486                 </para>
488                 <para>
489                     Par exemple, vous souhaitez historiser toutes les insertions sur une Table
490                     spécifique, mais uniquement si la configuration du site le permet :
491                 </para>
493                 <programlisting language="php"><![CDATA[
494 class MyLoggingRow extends Zend_Db_Table_Row_Abstract
496     protected function _insert()
497     {
498         $log = Zend_Registry::get('database_log');
499         $log->info(Zend_Debug::dump($this->_data,
500                                     "INSERT: $this->_tableClass",
501                                     false));
502     }
505 // $loggingEnabled est une variable d'exemple qui définit si
506 // l'historisation est activée ou pas
507 if ($loggingEnabled) {
508     $bugs = new Bugs(array('rowClass' => 'MyLoggingRow'));
509 } else {
510     $bugs = new Bugs();
512 ]]></programlisting>
513             </example>
515             <example id="zend.db.table.row.extending.overriding-example2">
516                 <title>Exemple d'une classe de Row qui historise les insertions de plusieurs
517                 tables</title>
519                 <para>
520                     En passant l'objet Row personnalisé à chacune des Tables concernées, alors
521                     vous n'aurez pas besoin de définir cette logique dans chacune des classes des
522                     Tables.
523                 </para>
525                 <para>
526                     Dans cet exemple, le code qui effectue l'historisation est identique à
527                     celui de l'exemple précédent.
528                 </para>
530                 <programlisting language="php"><![CDATA[
531 class MyLoggingRow extends Zend_Db_Table_Row_Abstract
533     protected function _insert()
534     {
535         $log = Zend_Registry::get('database_log');
536         $log->info(Zend_Debug::dump($this->_data,
537                                     "INSERT: $this->_tableClass",
538                                     false));
539     }
542 class Bugs extends Zend_Db_Table_Abstract
544     protected $_name = 'bugs';
545     protected $_rowClass = 'MyLoggingRow';
548 class Products extends Zend_Db_Table_Abstract
550     protected $_name = 'products';
551     protected $_rowClass = 'MyLoggingRow';
553 ]]></programlisting>
554             </example>
555         </sect3>
557         <sect3 id="zend.db.table.row.extending.inflection">
558             <title>Définir l'inflexion dans Zend_Db_Table_Row</title>
560             <para>
561                 Il peut être intéressant de personnaliser l'accès aux colonnes de la table
562                 représentée par un résultat Row, plutôt que d'utiliser le nom des colonnes telles
563                 que définies dans le SGBDR sous-jacent. La transformation de l'un vers l'autre est
564                 appelée <emphasis>inflexion</emphasis>.
565             </para>
567             <para>
568                 Les classes Zend_Db n'utilisent pas l'inflexion par défaut. Voyez <xref
569                 linkend="zend.db.table.extending.inflection" /> pour plus de détails sur ce
570                 procédé.
571             </para>
573             <para>
574                 Ainsi si vous voulez utiliser l'inflexion, vous devez implémenter vous-même la
575                 transformation à effectuer en redéfinissant la méthode
576                 <methodname>_transformColumn()</methodname> dans votre classe de Row, et bien entendu utiliser
577                 cette classe de Row pour votre Table.
578             </para>
580             <example id="zend.db.table.row.extending.inflection.example">
581                 <title>Exemple d'utilisation de l'inflexion</title>
583                 <para>
584                     Ceci vous permet d'utiliser les accesseurs de votre Row de manière
585                     transformée. La classe de votre Row utilisera <methodname>_transformColumn()</methodname>
586                     pour changer le nom de la colonne appelée, avant de le faire correspondre à un
587                     nom dans la table réelle de la base de données.
588                 </para>
590                 <programlisting language="php"><![CDATA[
591 class MyInflectedRow extends Zend_Db_Table_Row_Abstract
593     protected function _transformColumn($columnName)
594     {
595         $nativeColumnName = myCustomInflector($columnName);
596         return $nativeColumnName;
597     }
600 class Bugs extends Zend_Db_Table_Abstract
602     protected $_name = 'bugs';
603     protected $_rowClass = 'MyInflectedRow';
606 $bugs = new Bugs();
607 $row = $bugs->fetchNew();
609 // Utilisez des nom de colonnes CamelCase, l'inflecteur les
610 // transformera alors pour vous afin d'établir la correspondance
611 // avec les noms natifs des colonnes.
612 $row->bugDescription = 'New description';
613 ]]></programlisting>
614             </example>
616             <para>En revanche, c'est à vous d'écrire votre mécanisme d'inflexion.</para>
617         </sect3>
618     </sect2>
619 </sect1>