| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.db.table.row">
- <title>Zend_Db_Table_Row</title>
- <sect2 id="zend.db.table.row.introduction">
- <title>Introduction</title>
- <para>
- <classname>Zend_Db_Table_Row</classname> est la classe qui donne accès à chacun
- des résultats issus d'un objet <classname>Zend_Db_Table</classname>. Lorsque vous
- exécutez une requête via une classe de Table, alors les résultats sont des objets
- <classname>Zend_Db_Table_Row</classname>. Vous pouvez aussi utiliser ces objets comme
- résultats vides : pour créer des nouveaux résultats à ajouter à la base de
- données.
- </para>
- <para>
- <classname>Zend_Db_Table_Row</classname> est une implémentation du design pattern
- <ulink url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data
- Gateway</ulink>
- </para>
- </sect2>
- <sect2 id="zend.db.table.row.read">
- <title>Récupérer un résultat (un "Row")</title>
- <para>
- <classname>Zend_Db_Table_Abstract</classname> possède des méthodes
- <methodname>find()</methodname> et <methodname>fetchAll()</methodname>, qui retournent un objet de type
- <classname>Zend_Db_Table_Rowset</classname>, et une méthode <methodname>fetchRow()</methodname>, qui
- retourne un objet de type <classname>Zend_Db_Table_Row</classname>.
- </para>
- <example id="zend.db.table.row.read.example">
- <title>Exemple de récupération d'un Row</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $row = $bugs->fetchRow($bugs->select()
- ->where('bug_id = ?', 1));
- ]]></programlisting>
- </example>
- <para>
- Un objet <classname>Zend_Db_Table_Rowset</classname> contient une collection
- d'objets <classname>Zend_Db_Table_Row</classname>. Voyez <xref
- linkend="zend.db.table.rowset" />.
- </para>
- <example id="zend.db.table.row.read.example-rowset">
- <title>Exemple de lecture d'un Row dans un Rowset</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $rowset = $bugs->fetchAll($bugs->select()
- ->where('bug_status = ?', 1));
- $row = $rowset->current();
- ]]></programlisting>
- </example>
- <sect3 id="zend.db.table.row.read.get">
- <title>Lecture des valeurs des colonnes, dans un Row</title>
- <para>
- <classname>Zend_Db_Table_Row_Abstract</classname> possède des accesseurs. Les
- colonnes <acronym>SQL</acronym> du résultat sont disponibles en lecture et écriture, via des propriétés
- de classe.
- </para>
- <example id="zend.db.table.row.read.get.example">
- <title>Lecture d'une colonne dans un Row</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $row = $bugs->fetchRow($bugs->select()
- ->where('bug_id = ?', 1));
- // Affiche la valeur de la colonne bug_description
- echo $row->bug_description;
- ]]></programlisting>
- </example>
- <note>
- <para>
- Les versions antérieures de <classname>Zend_Db_Table_Row</classname>
- utilisaient un processus de transformation nommé <emphasis>inflexion</emphasis>
- pour récupérer les valeurs des colonnes dans un résultat.
- </para>
- <para>
- Actuellement, <classname>Zend_Db_Table_Row</classname> n'utilise pas
- d'inflexion. Les noms des propriétés de l'objet doivent correspondre à
- l'orthographe des noms des colonnes dans la base de données sous-jacente
- </para>
- </note>
- </sect3>
- <sect3 id="zend.db.table.row.read.to-array">
- <title>Récupérer les valeurs des colonnes comme un tableau</title>
- <para>
- Vous pouvez accéder aux données d'un row sous forme de tableau grâce à la
- méthode <methodname>toArray()</methodname>. Celle-ci retourne un tableau associatif.
- </para>
- <example id="zend.db.table.row.read.to-array.example">
- <title>Exemple avec toArray()</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $row = $bugs->fetchRow($bugs->select()
- ->where('bug_id = ?', 1));
- // Récupère un tableau associatif column/value
- $rowArray = $row->toArray();
- // Utilisation comme un tableau normal
- foreach ($rowArray as $column => $value) {
- echo "Column: $column\n";
- echo "Value: $value\n";
- }
- ]]></programlisting>
- </example>
- <para>
- Le tableau retourné par <methodname>toArray()</methodname> n'est pas une référence. Vous
- pouvez modifier ses valeurs, cela n'aura aucune répercussion dans la base de
- données.
- </para>
- </sect3>
- <sect3 id="zend.db.table.row.read.relationships">
- <title>Récupérer des données des tables liées</title>
- <para>
- <classname>Zend_Db_Table_Row_Abstract</classname> possède des méthodes
- permettant de récupérer des données des tables liées à la table interrogée. Voyez
- <xref linkend="zend.db.table.relationships" /> pour plus d'informations sur les
- relations entre les tables.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.row.write">
- <title>Sauvegarde un Row en base de données</title>
- <sect3 id="zend.db.table.row.write.set">
- <title>Changement des valeurs des colonnes d'un Row</title>
- <para>
- Vous pouvez changer les valeurs de chaque colonne du résultat Row, simplement
- avec les accesseurs, comme en lecture. Effectuez une banale affectation.
- </para>
- <para>
- Utiliser l'accesseur pour spécifier une valeur à une colonne d'un résultat Row
- ne répercute pas le comportement immédiatement en base de données. Vous devez
- utiliser explicitement la méthode <methodname>save()</methodname> pour ceci.
- </para>
- <example id="zend.db.table.row.write.set.example">
- <title>Exemple de changement de la valeur d'une colonne dans un Row</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $row = $bugs->fetchRow($bugs->select()
- ->where('bug_id = ?', 1));
- // Change la valeur d'une ou plusieurs colonnes
- $row->bug_status = 'FIXED';
- // MET A JOUR l'enregistrement dans la base de données
- $row->save();
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.row.write.insert">
- <title>Créer un Row vierge</title>
- <para>
- Vous pouvez créer un nouvel enregistrement vierge (Row) pour une table avec la
- méthode <methodname>createRow()</methodname> issue de la classe de cette Table. Vous pouvez
- alors affecter des valeurs à ses colonnes grâce aux accesseurs, comme déjà vu, puis
- enregistrer le Row en base de données avec sa méthode <methodname>save()</methodname>.
- </para>
- <example id="zend.db.table.row.write.insert.example">
- <title>Exemple de création d'un Row vierge pour une table</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $newRow = $bugs->createRow();
- // affecte des valeurs aux colonnes
- $newRow->bug_description = '...description...';
- $newRow->bug_status = 'NEW';
- // INSERT le nouvel enregistrement dans la base de données
- $newRow->save();
- ]]></programlisting>
- </example>
- <para>
- L'argument optionnel de <methodname>createRow()</methodname> est un tableau associatif qui
- sert à peupler tout de suite l'objet de valeurs.
- </para>
- <example id="zend.db.table.row.write.insert.example2">
- <title>Exemple de remplissage des valeurs d'un nouveau Row vierge</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'bug_description' => '...description...',
- 'bug_status' => 'NEW'
- );
- $bugs = new Bugs();
- $newRow = $bugs->createRow($data);
- // INSERT l'enregistrement en base de données
- $newRow->save();
- ]]></programlisting>
- </example>
- <note>
- <para>
- La méthode <methodname>createRow()</methodname> était nommée <methodname>fetchNew()</methodname>
- dans les anciennes version de <classname>Zend_Db_Table</classname>. Il est
- recommandé de ne plus utiliser cette ancienne appellation, même si celle-ci
- fonctionne toujours actuellement.
- </para>
- </note>
- </sect3>
- <sect3 id="zend.db.table.row.write.set-from-array">
- <title>Changement en masse des valeurs dans un Row</title>
- <para>
- <classname>Zend_Db_Table_Row_Abstract</classname> possède une méthode
- <methodname>setFromArray()</methodname> qui permet de lui peupler ses valeurs avec celles issues
- d'un tableau associatif nom de la colonne / valeur.
- </para>
- <example id="zend.db.table.row.write.set-from-array.example">
- <title>
- Exemple d'utilisation de setFromArray() avec un enregistrement (Row) vierge
- </title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $newRow = $bugs->createRow();
- // Les données sont dans un tableau associatif
- $data = array(
- 'bug_description' => '...description...',
- 'bug_status' => 'NEW'
- );
- // Affecte toutes les valeurs des colonnes en une seule fois
- $newRow->setFromArray($data);
- // INSERT l'enregistrement en base de données
- $newRow->save();
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.row.write.delete">
- <title>Supprimer un Row</title>
- <para>
- Vous pouvez appeler la méthode <methodname>delete()</methodname> d'un objet Row. Ceci
- supprime les lignes dans la base de données qui correspondent à la clé primaire de
- l'objet Row.
- </para>
- <example id="zend.db.table.row.write.delete.example">
- <title>Effacer un Row</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $row = $bugs->fetchRow('bug_id = 1');
- // EFFACE cet enregistrement de la base de données
- $row->delete();
- ]]></programlisting>
- </example>
- <para>
- Notez qu'il n'est pas nécessaire d'appeler <methodname>save()</methodname> pour un
- effacement. Celui-ci est à effet immédiat.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.row.serialize">
- <title>Sérialisation et désérialisation d'un Row</title>
- <para>
- Il peut être utile de sauvegarder le contenu d'un enregistrement (Row) sur un
- support quelconque, pour une utilisation ultérieure. La
- <emphasis>sérialisation</emphasis> est le nom de l'opération qui consiste à transformer
- un objet en une forme facilement stockable (dans un fichier par exemple). Les objets du
- type <classname>Zend_Db_Table_Row_Abstract</classname> sont sérialisables.
- </para>
- <sect3 id="zend.db.table.row.serialize.serializing">
- <title>Sérialiser un Row</title>
- <para>
- Utilisez simplement la fonction <acronym>PHP</acronym> <methodname>serialize()</methodname> pour créer une
- chaîne de caractères représentant votre objet Row.
- </para>
- <example id="zend.db.table.row.serialize.serializing.example">
- <title>Exemple de sérialisation d'un Row</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $row = $bugs->fetchRow('bug_id = 1');
- // Convertit l'objet en une forme sérialisée
- $serializedRow = serialize($row);
- // Maintenant vous pouvez utiliser $serializedRow
- // pour l'écrire dans un fichier, etc.
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.row.serialize.unserializing">
- <title>Désérialiser les données d'un Row</title>
- <para>
- Utilisez simplement la fonction <acronym>PHP</acronym> <methodname>unserialize()</methodname>. L'objet Row
- originel est alors recréé.
- </para>
- <para>
- Notez que l'objet retourné fonctionne alors en mode
- <emphasis>déconnecté</emphasis>. Vous pouvez lire les valeurs des colonnes, mais pas
- les modifier ni enregistrer l'objet en base de données
- (<methodname>save()</methodname>).
- </para>
- <example id="zend.db.table.row.serialize.unserializing.example">
- <title>Exemple de désérialisation d'un objet Row sérialisé</title>
- <programlisting language="php"><![CDATA[
- $rowClone = unserialize($serializedRow);
- // Vous ne pouvez faire qu'une utilisation en lecture seule
- echo $rowClone->bug_description;
- ]]></programlisting>
- </example>
- <note>
- <title>Pourquoi ce mode déconnecté imposé ?</title>
- <para>
- Un objet sérialisé est une chaîne de caractère, humainement visible. Il
- est donc peu sécurisé d'y laisser un mot de passe vers un serveur de base de
- données. Le lecteur d'un objet Row sérialisé ne devrait pas pouvoir accéder à la
- base de données. De plus, une connexion à une base de données est un type non
- sérialisable par <acronym>PHP</acronym> (ressource).
- </para>
- </note>
- </sect3>
- <sect3 id="zend.db.table.row.serialize.set-table">
- <title>Reconnecter l'objet Row à la Table</title>
- <para>
- Il est bien entendu possible de reconnecter l'objet Row à la base de données,
- et plus précisément à la Table dont il fut issu. Utilisez la méthode
- <methodname>setTable()</methodname> et passez lui une instance héritant de
- <classname>Zend_Db_Table_Abstract</classname>. Une fois reconnecté, l'objet Row
- possède de nouveau un accès à la base de données, et n'est donc plus en mode lecture
- seule.
- </para>
- <example id="zend.db.table.row.serialize.set-table.example">
- <title>Exemple de réactivation d'un Row</title>
- <programlisting language="php"><![CDATA[
- $rowClone = unserialize($serializedRow);
- $bugs = new Bugs();
- // Reconnecte le Row à la table et donc, à la base de données
- $rowClone->setTable($bugs);
- // Maintenant il est possible de l'utiliser en mode écriture
- $rowClone->bug_status = 'FIXED';
- $rowClone->save();
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.row.extending">
- <title>Étendre la classe Row</title>
- <para>
- Vous pouvez utilisez votre propre classe étendant
- <classname>Zend_Db_Table_Row_Abstract</classname>. Spécifiez votre classe dans la
- propriété protégée <varname>$_rowClass</varname> de la classe de votre Table, ou dans le
- tableau du constructeur de l'objet Table.
- </para>
- <example id="zend.db.table.row.extending.example">
- <title>Spécification d'une classe Row personnalisée</title>
- <programlisting language="php"><![CDATA[
- class MyRow extends Zend_Db_Table_Row_Abstract
- {
- // ...personnalisations
- }
- // Spécifie la classe de Row utilisée pour toutes les
- // instance de la classe de Table
- class Products extends Zend_Db_Table_Abstract
- {
- protected $_name = 'products';
- protected $_rowClass = 'MyRow';
- }
- // Ou pour une classe de table spécifique, via son constructeur
- $bugs = new Bugs(array('rowClass' => 'MyRow'));
- ]]></programlisting>
- </example>
- <sect3 id="zend.db.table.row.extending.overriding">
- <title>Initialisation et pré-traitements d'un Row</title>
- <para>
- Si vous avez un besoin spécifique d'implémenter une logique spéciale après la
- création d'une instance de Row, vous pouvez utiliser sa méthode <methodname>init()</methodname>,
- qui est appelée dans son constructeur, mais après que les méta données aient été
- calculées. <example id="zend.db.table.row.init.usage.example">
- <title>Exemple d'utilisation de la méthode init()</title>
- <programlisting language="php"><![CDATA[
- class MyApplicationRow extends Zend_Db_Table_Row_Abstract
- {
- protected $_role;
- public function init()
- {
- $this->_role = new MyRoleClass();
- }
- }
- ]]></programlisting>
- </example>
- </para>
- </sect3>
- <sect3 id="zend.db.table.row.extending.insert-update">
- <title>
- Définir sa propre logique pour Insert, Update, et Delete dans Zend_Db_Table_Row
- </title>
- <para>
- La classe des Rows appelle les méthodes protégées <methodname>_insert()</methodname>,
- <methodname>_update()</methodname>, et <methodname>_delete()</methodname> avant d'effectuer chacune des
- opérations respectives <constant>INSERT</constant>, <constant>UPDATE</constant>, et
- <constant>DELETE</constant>. Il est donc possible de définir sa propre logique dans votre
- sous-classe de Row.
- </para>
- <para>
- Ci-dessous vous trouverez des exemples d'utilisation d'une logique
- personnalisée dans les classes de Row :
- </para>
- <example id="zend.db.table.row.extending.overriding-example1">
- <title>Exemple de logique personnalisée dans une classe de Row</title>
- <para>
- La logique personnelle peut donc être déportée dans une classe de Row qui
- ne s'appliquera qu'à certaines tables, et pas à d'autres. Sinon, la classe de
- Table utilise le Row par défaut.
- </para>
- <para>
- Par exemple, vous souhaitez historiser toutes les insertions sur une Table
- spécifique, mais uniquement si la configuration du site le permet :
- </para>
- <programlisting language="php"><![CDATA[
- class MyLoggingRow extends Zend_Db_Table_Row_Abstract
- {
- protected function _insert()
- {
- $log = Zend_Registry::get('database_log');
- $log->info(Zend_Debug::dump($this->_data,
- "INSERT: $this->_tableClass",
- false));
- }
- }
- // $loggingEnabled est une variable d'exemple qui définit si
- // l'historisation est activée ou pas
- if ($loggingEnabled) {
- $bugs = new Bugs(array('rowClass' => 'MyLoggingRow'));
- } else {
- $bugs = new Bugs();
- }
- ]]></programlisting>
- </example>
- <example id="zend.db.table.row.extending.overriding-example2">
- <title>Exemple d'une classe de Row qui historise les insertions de plusieurs
- tables</title>
- <para>
- En passant l'objet Row personnalisé à chacune des Tables concernées, alors
- vous n'aurez pas besoin de définir cette logique dans chacune des classes des
- Tables.
- </para>
- <para>
- Dans cet exemple, le code qui effectue l'historisation est identique à
- celui de l'exemple précédent.
- </para>
- <programlisting language="php"><![CDATA[
- class MyLoggingRow extends Zend_Db_Table_Row_Abstract
- {
- protected function _insert()
- {
- $log = Zend_Registry::get('database_log');
- $log->info(Zend_Debug::dump($this->_data,
- "INSERT: $this->_tableClass",
- false));
- }
- }
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_rowClass = 'MyLoggingRow';
- }
- class Products extends Zend_Db_Table_Abstract
- {
- protected $_name = 'products';
- protected $_rowClass = 'MyLoggingRow';
- }
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.row.extending.inflection">
- <title>Définir l'inflexion dans Zend_Db_Table_Row</title>
- <para>
- Il peut être intéressant de personnaliser l'accès aux colonnes de la table
- représentée par un résultat Row, plutôt que d'utiliser le nom des colonnes telles
- que définies dans le SGBDR sous-jacent. La transformation de l'un vers l'autre est
- appelée <emphasis>inflexion</emphasis>.
- </para>
- <para>
- Les classes Zend_Db n'utilisent pas l'inflexion par défaut. Voyez <xref
- linkend="zend.db.table.extending.inflection" /> pour plus de détails sur ce
- procédé.
- </para>
- <para>
- Ainsi si vous voulez utiliser l'inflexion, vous devez implémenter vous-même la
- transformation à effectuer en redéfinissant la méthode
- <methodname>_transformColumn()</methodname> dans votre classe de Row, et bien entendu utiliser
- cette classe de Row pour votre Table.
- </para>
- <example id="zend.db.table.row.extending.inflection.example">
- <title>Exemple d'utilisation de l'inflexion</title>
- <para>
- Ceci vous permet d'utiliser les accesseurs de votre Row de manière
- transformée. La classe de votre Row utilisera <methodname>_transformColumn()</methodname>
- pour changer le nom de la colonne appelée, avant de le faire correspondre à un
- nom dans la table réelle de la base de données.
- </para>
- <programlisting language="php"><![CDATA[
- class MyInflectedRow extends Zend_Db_Table_Row_Abstract
- {
- protected function _transformColumn($columnName)
- {
- $nativeColumnName = myCustomInflector($columnName);
- return $nativeColumnName;
- }
- }
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_rowClass = 'MyInflectedRow';
- }
- $bugs = new Bugs();
- $row = $bugs->fetchNew();
- // Utilisez des nom de colonnes CamelCase, l'inflecteur les
- // transformera alors pour vous afin d'établir la correspondance
- // avec les noms natifs des colonnes.
- $row->bugDescription = 'New description';
- ]]></programlisting>
- </example>
- <para>En revanche, c'est à vous d'écrire votre mécanisme d'inflexion.</para>
- </sect3>
- </sect2>
- </sect1>
|