| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273 |
- <?xml version="1.0" encoding="utf-8"?>
- <!-- EN-Revision: 14084 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.db.table">
- <title>Zend_Db_Table</title>
- <sect2 id="zend.db.table.introduction">
- <title>Introduction</title>
- <para>La classe <classname>Zend_Db_Table</classname> est une interface orientée objet vers les tables d'une base de
- données. Elle fournit des méthodes pour la gestion de la plupart des opérations concernant une table. Bien
- entendu, vous pouvez étendre la classe de base pour ajouter une logique personnalisée.</para>
- <para>La solution que représente <classname>Zend_Db_Table</classname> est basée sur le motif de conception <ulink
- url="http://www.martinfowler.com/eaaCatalog/tableDataGateway.html">Table Data Gateway</ulink>. Cette solution
- inclut aussi une classe implémentant le motif <ulink
- url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data Gateway</ulink>.</para>
- </sect2>
- <sect2 id="zend.db.table.defining">
- <title>Définir une classe de Table</title>
- <para>Pour chaque table de la base de données envers laquelle vous souhaitez un accès, définissez une classe
- étendant <classname>Zend_Db_Table_Abstract</classname>.</para>
- <sect3 id="zend.db.table.defining.table-schema">
- <title>Définir le nom de la table, et de la base de données</title>
- <para>Déclarez le nom de la table pour laquelle la classe va agir, en utilisant la propriété protégée
- <code>$_name</code>. C'est une chaîne, elle doit contenir le nom de la table tel qu'il apparaît dans la base
- de données.</para>
- <example id="zend.db.table.defining.table-schema.example1">
- <title>Déclarer une classe de Table avec un nom de table spécifique</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- }
- ]]></programlisting>
- </example>
- <para>Si vous ne spécifiez pas le nom de la table, le nom de la classe sera alors utilisé comme nom de table
- par défaut.</para>
- <example id="zend.db.table.defining.table-schema.example">
- <title>Déclarer une classe de Table sans nom de table spécifique</title>
- <programlisting role="php"><![CDATA[
- class bugs extends Zend_Db_Table_Abstract
- {
- // le nom de la table est ici supposé être le nom de la classe
- }
- ]]></programlisting>
- </example>
- <para>Vous pouvez aussi déclarer le nom de la base de données contenant la table, toujours au moyen d'une
- propriété protégée de la classe : <code>$_schema</code>, ou avec le nom de la base précédant le nom de la
- table dans la propriété <code>$_name</code>. Si vous choisissez de définir le nom de la base de données dans
- la propriété <code>$_name</code>, alors ce choix sera prioritaire sur celui utilisant
- <code>$_schema</code>.</para>
- <example id="zend.db.table.defining.table-schema.example3">
- <title>Déclarer une classe de Table avec un nom de base de données</title>
- <programlisting role="php"><![CDATA[
- // Première alternative :
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_schema = 'bug_db';
- protected $_name = 'bugs';
- }
- // Seconde alternative :
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_db.bugs';
- }
- // Si le nom de la base est spécifiée dans $_name ET $_schema,
- // alors c'est celui spécifié dans $_name qui prime :
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_db.bugs';
- protected $_schema = 'ignored';
- }
- ]]></programlisting>
- </example>
- <para>Les noms de la base de données et de la table peuvent aussi être définis via le constructeur de la
- classe de Table. Ils écrasent alors ceux éventuellement définis dans les propriétés de la classe (avec
- <code>$_name</code> et <code>$_schema</code>).</para>
- <example id="zend.db.table.defining.table-schema.example.constructor">
- <title>Déclarer les noms de table et base de donnée à l'instanciation</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- }
- // Première alternative :
- $tableBugs = new Bugs(array('name' => 'bugs', 'schema' => 'bug_db'));
- // Seconde alternative :
- $tableBugs = new Bugs(array('name' => 'bug_db.bugs'));
- // Si le nom de la base est spécifié dans name ET schema, alors c'est
- // celui spécifié dans name qui prime :
- $tableBugs = new Bugs(array('name' => 'bug_db.bugs',
- 'schema' => 'ignored'));
- ]]></programlisting>
- </example>
- <para>Si vous n'indiquez pas de base de données, c'est celle utilisée par l'adaptateur qui sera
- utilisée.</para>
- </sect3>
- <sect3 id="zend.db.table.defining.primary-key">
- <title>Définir la clé primaire d'une table</title>
- <para>Toute table doit posséder une clé primaire. <classname>Zend_Db_Table</classname> ne fonctionne pas avec les
- tables sans clé primaire. Vous pouvez les déclarer la(les) colonne servant de clé primaire grâce à la
- propriété protégée de la classe <code>$_primary</code>. Celle-ci peut être soit une chaîne, dans le cas
- d'une clé sur une colonne, ou un tableau de chaînes pour une clé sur plusieurs colonnes (clé primaire
- composée).</para>
- <example id="zend.db.table.defining.primary-key.example">
- <title>Exemple de spécification de la clé primaire</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_primary = 'bug_id';
- }
- ]]></programlisting>
- </example>
- <para>Si vous ne spécifiez pas explicitement de clé primaire, alors <classname>Zend_Db_Table_Abstract</classname> va
- essayer de la trouver lui-même en utilisant les informations renvoyées par
- <code>describeTable()</code>.</para>
- <note>
- <para>Toute classe de table doit, par un moyen ou un autre, connaître la clé primaire de la table
- ciblée. Si la clé primaire ne peut être trouvée ( spécifiée dans la classe, ou découverte par
- <code>describeTable()</code>), alors la table ne va pas pouvoir être utilisée avec
- <classname>Zend_Db_Table</classname>.</para>
- </note>
- </sect3>
- <sect3 id="zend.db.table.defining.setup">
- <title>Redéfinir les méthodes de configuration de la classe de Table</title>
- <para>Lorsque vous créez votre instance de classe <classname>Zend_Db_Table</classname>, le constructeur décompose le
- processus via plusieurs méthodes permettant l'initialisation des métadonnées de la table. Chacune de ces
- étapes est matérialisée par une méthode de la classe, surchargeable. N'oubliez cependant pas d'appeler la
- méthode parente respective à la fin de votre traitement.</para>
- <example id="zend.db.table.defining.setup.example">
- <title>Exemple de redéfinition de la méthode <code>_setupTableName()</code></title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected function _setupTableName()
- {
- $this->_name = 'bugs';
- parent::_setupTableName();
- }
- }
- ]]></programlisting>
- </example>
- <para>Les méthodes de configuration que vous pouvez redéfinir sont :</para>
- <itemizedlist>
- <listitem>
- <para><code>_setupDatabaseAdapter()</code> vérifie si un adaptateur a été passé à la classe,
- éventuellement en récupère un depuis le registre. En redéfinissant cette méthode, vous pouvez
- ajouter une source de recherche pour l'adaptateur.</para>
- </listitem>
- <listitem>
- <para><code>_setupTableName()</code> donne le nom de la table par défaut comme étant le nom de la
- classe. En redéfinissant cette méthode, vous pouvez spécifier le nom de la table avant son
- intervention.</para>
- </listitem>
- <listitem>
- <para><code>_setupMetadata()</code> définit le nom de la base de données si le nom de la table est
- de la forme "base.table"; appelle <code>describeTable()</code> pour récupérer les méta-données;
- remplir le tableau <code>$_cols</code> avec les noms des colonnes reçus via
- <code>describeTable()</code>. La redéfinition de cette méthode permet de spécifier soi-même les noms
- des colonnes de la table.</para>
- </listitem>
- <listitem>
- <para><code>_setupPrimaryKey()</code> donne le nom de la clé primaire par défaut en cherchant dans
- <code>describeTable()</code>; vérifie que la clé primaire fait bien partie du tableau
- <code>$_cols</code>. En redéfinissant cette méthode, vous pouvez spécifier une clé primaire
- manuellement.</para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.table.initialization">
- <title>Initialisation de la Table</title>
- <para>Si lors de la construction de l'objet représentant votre Table, vous avez besoin d'implémenter une
- logique spécifique, vous devriez utiliser la méthode <code>init()</code>, qui est appelée juste après le
- constructeur, donc une fois la table correctement créée. <example
- id="zend.db.table.defining.init.usage.example">
- <title>Exemple d'utilisation de la méthode <code>init()</code></title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_observer;
- public function init()
- {
- $this->_observer = new MyObserverClass();
- }
- }
- ]]></programlisting>
- </example></para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.constructing">
- <title>Créer une instance de la classe de Table</title>
- <para>Avant d'utiliser votre classe de Table, il faut en créer une instance, via son constructeur. Celui-ci
- accepte un tableau d'options. La plus importante d'entre elles est l'adaptateur de base de données, qui
- représente la connexion au SGBD. Il y a trois façon de le spécifier :</para>
- <sect3 id="zend.db.table.constructing.adapter">
- <title>Spécifier l'adaptateur de base de données</title>
- <para>La première manière de spécifier l'objet d'adaptateur à la classe de Table, est de le passer dans le
- tableau d'options, à l'index <code>"db"</code>.</para>
- <example id="zend.db.table.constructing.adapter.example">
- <title>Exemple de construction d'un objet Table avec l'objet adaptateur</title>
- <programlisting role="php"><![CDATA[
- $db = Zend_Db::factory('PDO_MYSQL', $options);
- $table = new Bugs(array('db' => $db));
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.constructing.default-adapter">
- <title>Spécifier un adaptateur par défaut</title>
- <para>La deuxième manière de donner un objet adaptateur à la classe de Table est de le déclarer comme étant
- l'objet adaptateur par défaut pour toutes les classes de Table. Vous pouvez faire ceci en utilisant la
- méthode statique <classname>Zend_Db_Table_Abstract::setDefaultAdapter()</classname>. Son argument est un objet de type
- <classname>Zend_Db_Adapter_Abstract</classname>.</para>
- <example id="zend.db.table.constructing.default-adapter.example">
- <title>Exemple de construction d'un objet Table en utilisant l'adaptateur par défaut</title>
- <programlisting role="php"><![CDATA[
- $db = Zend_Db::factory('PDO_MYSQL', $options);
- Zend_Db_Table_Abstract::setDefaultAdapter($db);
- // Plus tard...
- $table = new Bugs();
- ]]></programlisting>
- </example>
- <para>Il peut être intéressant de créer son objet adaptateur de base de données en un lieu approprié, comme
- le fichier d'amorçage ("bootstrap"), et ensuite de le spécifier comme adaptateur par défaut pour toutes les
- tables, à travers toute l'application. Attention toutefois, ce procédé fixe un et un seul adaptateur, pour
- toutes les classes de table (héritant de <classname>Zend_Db_Table_Abstract</classname>).</para>
- </sect3>
- <sect3 id="zend.db.table.constructing.registry">
- <title>Stocker l'objet adaptateur dans le registre</title>
- <para>La troisième manière de passer l'objet adaptateur de base de données à votre classe de Table, est de
- passer une chaîne de caractères dans la clé <code>"db"</code> du tableau de configuration accepté par le
- constructeur. Cette chaîne représente alors l'index auquel est stocké l'adaptateur, dans le registre
- statique.</para>
- <example id="zend.db.table.constructing.registry.example">
- <title>Exemple de construction de l'objet Table avec le registre</title>
- <programlisting role="php"><![CDATA[
- $db = Zend_Db::factory('PDO_MYSQL', $options);
- Zend_Registry::set('my_db', $db);
- // Plus tard...
- $table = new Bugs(array('db' => 'my_db'));
- ]]></programlisting>
- </example>
- <para>Cette option est très semblable à celle qui consiste à définir un adaptateur par défaut à toutes les
- classes. Le registre est en revanche plus flexible, car vous pouvez y stocker plusieurs adaptateurs,
- correspondants à plusieurs SGBD différents. Changer de SGBD pour ses classes de Table est alors aussi simple
- que de changer de valeur de registre.</para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.insert">
- <title>Insérer des enregistrement dans une table</title>
- <para>Vous pouvez utiliser votre objet de Table pour insérer des données dans la table sur laquelle l'objet se
- base. Utilisez sa méthode <code>insert()</code> qui accepte un seul paramètre : c'est un tableau dont les clés
- sont les noms des colonnes de la table, et les valeurs les valeurs souhaitées pour insertions.</para>
- <example id="zend.db.table.insert.example">
- <title>Exemple d'insertion de données dans la table</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $data = array(
- 'created_on' => '2007-03-22',
- 'bug_description' => 'Something wrong',
- 'bug_status' => 'NEW'
- );
- $table->insert($data);
- ]]></programlisting>
- </example>
- <para>Par défaut les paramètres sont traités comme des valeurs littérales. Si vous souhaitez utiliser une
- expression SQL à la place, manipulez un objet <classname>Zend_Db_Expr</classname> plutôt.</para>
- <example id="zend.db.table.insert.example-expr">
- <title>Exemple d'insertion d'expressions dans une table</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $data = array(
- 'created_on' => new Zend_Db_Expr('CURDATE()'),
- 'bug_description' => 'Something wrong',
- 'bug_status' => 'NEW'
- );
- ]]></programlisting>
- </example>
- <para>Dans les exemples ci-dessus, il est supposé que la table possède une clé primaire auto-incrémentée. C'est
- le comportement par défaut que gère <classname>Zend_Db_Table_Abstract</classname>, mais il y a d'autres comportements
- valides, qui sont détaillés ci-dessous.</para>
- <sect3 id="zend.db.table.insert.key-auto">
- <title>Utiliser une table avec une clé primaire auto-incrémentée</title>
- <para>Une clé primaire auto-incrémentée génère une valeur entière unique si vous omettez la colonne de la
- clé primaire dans une requête SQL de type <code>INSERT</code>.</para>
- <para>Dans <classname>Zend_Db_Table_Abstract</classname>, si vous définissez la variable protégée
- <code>$_sequence</code> à un booléen <code>true</code> (défaut), alors la classe va supposer que la table
- qu'elle représente possède une clé primaire auto-incrémentée.</para>
- <example id="zend.db.table.insert.key-auto.example">
- <title>Exemple de déclaration d'une clé primaire auto-incrémentée</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- // Ce comportement est celui par défaut, il est noté ici
- // uniquement pour l'exemple, mais non necéssaire
- protected $_sequence = true;
- }
- ]]></programlisting>
- </example>
- <para>MySQL, MSSQL, et SQLite sont des exemples de SGBD supportant les clé primaires
- auto-incrémentées.</para>
- <para>PostgreSQL a une propriété <code>SERIAL</code> qui définit une séquence automatiquement, basée sur le
- nom de la table et d'une colonne, et utilise cette séquence pour générer des valeurs de clés pour les
- nouveaux enregistrements. IBM DB2 a une propriété <code>IDENTITY</code> qui fonctionne de la même manière.
- Si vous utilisez ces propriétés d'automatisme, considérez votre classe de Table (<classname>Zend_Db_Table</classname>)
- comme si elle avait une clé primaire auto-incrémentée. Déclarez ainsi <code>$_sequence</code> à
- <code>true</code>.</para>
- </sect3>
- <sect3 id="zend.db.table.insert.key-sequence">
- <title>Utiliser une Table avec une séquence</title>
- <para>Une séquence est un objet de base de données qui génère des valeurs uniques pouvant être utilisées
- comme clés primaires dans une ou plusieurs tables de la base de données.</para>
- <para>Si vous définissez <code>$_sequence</code> avec une chaîne de caractères,
- <classname>Zend_Db_Table_Abstract</classname> va alors supposer que cette chaîne représente le nom de l'objet de
- séquence. Elle sera donc utilisée pour générer une valeur lors de requêtes <code>INSERT</code> le
- nécessitant.</para>
- <example id="zend.db.table.insert.key-sequence.example">
- <title>Exemple de déclaration d'une séquence dans une classe de Table</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_sequence = 'bug_sequence';
- }
- ]]></programlisting>
- </example>
- <para>Oracle, PostgreSQL, et IBM DB2 sont des SGBDs qui supportent les séquences.</para>
- <para>PostgreSQL et IBM DB2 ont aussi des mécanismes définissant implicitement la séquence et les colonnes
- associées. Si vous utilisez un de ces procédés, considérez votre classe de table comme ayant une clé
- primaire auto-incrémentée. N'utilisez la chaîne de la séquence dans $_sequence que si vous voulez
- explicitement utiliser cette séquence pour générer la valeur suivante de clé.</para>
- </sect3>
- <sect3 id="zend.db.table.insert.key-natural">
- <title>Utiliser une classe de Table avec une clé naturelle</title>
- <para>Certaines tables ont des clé naturelles, c'est à dire que vous devez fournir vous même, manuellement,
- la valeur de la clé concernée. Aucun mécanisme automatique (auto-incrémentation ou séquence) ne le fait pour
- vous.</para>
- <para>Si vous utilisez <code>$_sequence</code> avec la valeur booléenne <code>false</code>, alors
- <classname>Zend_Db_Table_Abstract</classname> se comportera comme si une clé naturelle est utilisée. Ainsi, lors de
- l'appel de la méthode <code>insert()</code>, vous devrez spécifier la valeur de la clé primaire vous même,
- autrement une <classname>Zend_Db_Table_Exception</classname> sera levée.</para>
- <example id="zend.db.table.insert.key-natural.example">
- <title>Exemple de déclaration d'une clé naturelle</title>
- <programlisting role="php"><![CDATA[
- class BugStatus extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_status';
- protected $_sequence = false;
- }
- ]]></programlisting>
- </example>
- <note>
- <para>Tous les SGBDs gère ce cas. Les tables d'intersection dans les relations de type "plusieurs à
- plusieurs" sont de bons exemples de clés naturelles, souvent composées d'autres clés étrangères.</para>
- </note>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.update">
- <title>Mettre à jour des enregistrements dans une table</title>
- <para>Vous pouvez mettre à jour des enregistrements de votre table en utilisant la méthode <code>update</code>
- de votre classe de Table. Elle accepte deux paramètres. Le premier est un tableau associatifs des colonnes
- concernées, et de leurs valeurs respectives. Le deuxième est une expression SQL qui sera utiliser comme clause
- <code>WHERE</code> dans la requête <code>UPDATE</code>.</para>
- <example id="zend.db.table.update.example">
- <title>Exemple de mise à jour d'enregistrements dans une table</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $data = array(
- 'updated_on' => '2007-03-23',
- 'bug_status' => 'FIXED'
- );
- $where = $table->getAdapter()->quoteInto('bug_id = ?', 1234);
- $table->update($data, $where);
- ]]></programlisting>
- </example>
- <para>La méthode de la classe de Table <code>update()</code> est proxiées vers la méthode <link
- linkend="zend.db.adapter.write.update"><code>update()</code></link> de l'adaptateur. Le deuxième paramètre peut
- donc être un tableau d'arguments pour la clause WHERE. Chaque élément du tableau sera joint au suivant avec une
- opération <code>AND</code>.</para>
- <note>
- <para>Les valeurs et les identifiants SQL ne sont pas échappés automatiquement. Si vous voulez échapper des
- valeurs, vous devrez utiliser <code>quote()</code>, <code>quoteInto()</code>, et
- <code>quoteIdentifier()</code> de l'adaptateur.</para>
- </note>
- </sect2>
- <sect2 id="zend.db.table.delete">
- <title>Supprimer des enregistrements d'une Table</title>
- <para>Pour effacer des enregistrements de votre table en utilisant sa classe de Table, utilisez sa méthode
- <code>delete()</code>. Son seul paramètre est une chaîne ou un tableau définissant la clause <code>WHERE</code>
- à utiliser lors de la requête <code>DELETE</code>.</para>
- <example id="zend.db.table.delete.example">
- <title>Exemple de suppression d'enregistrements</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $where = $table->getAdapter()->quoteInto('bug_id = ?', 1235);
- $table->delete($where);
- ]]></programlisting>
- </example>
- <para>Cette méthode est proxiée vers <link linkend="zend.db.adapter.write.delete"><code>delete()</code></link>
- de l'adaptateur. Si le paramètre est un tableau, chacun des éléments du tableau sera joint au suivant avec
- l'opération <code>AND</code> pour former la clause WHERE.</para>
- <note>
- <para>Les valeurs et les identifiants SQL ne sont pas échappés automatiquement. Si vous voulez échapper des
- valeurs, vous devrez utiliser <code>quote()</code>, <code>quoteInto()</code>, et
- <code>quoteIdentifier()</code> de l'adaptateur.</para>
- </note>
- </sect2>
- <sect2 id="zend.db.table.find">
- <title>Récupérer des enregistrements par clé primaire</title>
- <para>Vous pouvez interroger votre table afin de récupérer des enregistrements en spécifiant une ou plusieurs
- valeurs de clé primaire. La méthode <code>find()</code> permet ceci, elle prend comme premier paramètre une
- valeur ou un tableau de valeurs de clé primaire.</para>
- <example id="zend.db.table.find.example">
- <title>Exemple de récupération d'enregistrements par clé primaire</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- // Récupère un enregistrement, mais
- // retourne un Rowset
- $rows = $table->find(1234);
- // Récupère plusieurs enregistrement
- // retourne un Rowset
- $rows = $table->find(array(1234, 5678));
- ]]></programlisting>
- </example>
- <para>Si une seule clé est passée en paramètre, la méthode retournera au plus un résultat (car par définition,
- une clé primaire assure l'unicité d'un enregistrement). Si vous passez plusieurs valeurs de clés, alors la
- méthode pourra retourner plusieurs enregistrements. Cette méthode pourra aussi retourner zéro enregistrement.
- Quoiqu'il en soit, l'objet de retour est bien un <classname>Zend_Db_Table_Rowset_Abstract</classname></para>
- <para>Si votre clé primaire est une clé composée de plusieurs colonnes, passez alors les autres valeurs de
- colonne comme paramètres à la méthode <code>find()</code>. Il doit y avoir autant de paramètres passés à la
- méthode, que de colonnes composant la clé.</para>
- <para>Ainsi, pour trouver plusieurs enregistrements en passant plusieurs valeurs de clés primaires composées,
- passez autant de tableaux composés, que de colonnes représentant les clés. Les tableaux doivent donc, comporter
- le même nombre de valeurs. Celles-ci vont ainsi fonctionner par tuples : tous les premiers éléments des tableaux
- seront évalués pour la première recherche, et chacun représentera une colonne composant la clé primaire. Puis
- ainsi de suite, jusqu'à la fin des tableaux.</para>
- <example id="zend.db.table.find.example-compound">
- <title>Exemple de recherche avec une clé primaire composée</title>
- <para>L'exemple suivant appelle <code>find()</code> pour récupérer deux enregistrements en se basant sur une
- clé à deux colonnes. Le premier enregistrement aura une clé primaire (1234, 'ABC'), et le second une valeur
- de clé primaire (5678, 'DEF').</para>
- <programlisting role="php"><![CDATA[
- class BugsProducts extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs_products';
- protected $_primary = array('bug_id', 'product_id');
- }
- $table = new BugsProducts();
- // Retourne un enregistrement unique, basé sur une clé
- // primaire à deux colonnes
- $rows = $table->find(1234, 'ABC');
- // Retourne deux enregistrements, basés sur une clé
- // primaire à deux colonnes
- $rows = $table->find(array(1234, 5678), array('ABC', 'DEF'));
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.table.fetch-all">
- <title>Requêter pour plusieurs enregistrements</title>
- <sect3 id="zend.db.table.fetch-all.select">
- <title>API de l'objet Select</title>
- <para><warning>
- <para>L'API pour les opérations de récupération d'enregistrements a été améliorée afin d'autoriser
- un objet <classname>Zend_Db_Table_Select</classname> à modifier la requête. Les anciens comportements de
- <code>fetchRow()</code> et <code>fetchAll()</code> sont désormais dépréciés, mais toujours
- fonctionnels à ce jour.</para>
- <para>Les requêtes suivantes sont sémantiquement identiques et fonctionnent. Il est conseillé
- cependant d'utiliser l'implémentation avec l'objet select.</para>
- <para><programlisting role="php"><![CDATA[
- // Récupérer un rowset
- $rows = $table->fetchAll('bug_status = "NEW"', 'bug_id ASC', 10, 0);
- $rows = $table->fetchAll($table->select()->where('bug_status = ?', 'NEW')
- ->order('bug_id ASC')
- ->limit(10, 0));
- // Récupérer un row
- $row = $table->fetchRow('bug_status = "NEW"', 'bug_id ASC');
- $row = $table->fetchRow($table->select()->where('bug_status = ?', 'NEW')
- ->order('bug_id ASC'));
- ]]></programlisting></para>
- </warning></para>
- <para>L'objet <classname>Zend_Db_Table_Select</classname> est une extension de
- <classname>Zend_Db_Select</classname> mais qui applique des restrictions particulières à la requête. Les
- restrictions sont :</para>
- <itemizedlist>
- <listitem>
- <para>Vous <emphasis>pouvez</emphasis> utiliser l'objet pour ne sélectionner que certaines colonnes
- de l'enregistrement à retourner. Ceci est pratique dans le cas où vous n'avez pas besoin
- spécifiquement de toutes les colonnes d'une table.</para>
- </listitem>
- <listitem>
- <para>Vous <emphasis>pouvez</emphasis> spécifier des colonnes avec des évaluations envers des
- expressions SQL. Cependant, l'enregistrement résultant sera alors en mode lecture seule
- (<property>readOnly</property>) et ne pourra pas être propagé en base de données
- (<code>save()</code>). Un appel à <code>save()</code> lèvera une exception.</para>
- </listitem>
- <listitem>
- <para>Vous <emphasis>pouvez</emphasis> utiliser des jointures JOIN vers d'autres tables, mais
- uniquement pour des critères de jointure, et non sélectionner des colonnes jointes.</para>
- </listitem>
- <listitem>
- <para>Vous <emphasis>ne pouvez pas</emphasis> spécifier de colonnes JOINtes comme faisant partie du
- résultat de la requête. L'objet row/rowset serait alors corrompu, et contiendrait des données d'une
- table étrangère à sa table originale. Une erreur sera renvoyée dans un tel cas.</para>
- </listitem>
- </itemizedlist>
- <para><example id="zend.db.table.qry.rows.set.simple.usage.example">
- <title>Utilisation simple</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example></para>
- <para>L'objet <code>Select</code> utilise une interface fluide (fluent interface), permettant le chaînage
- des méthodes.</para>
- <para><example id="zend.db.table.qry.rows.set.fluent.interface.example">
- <title>Exemple d'interface fluide</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $rows = $table->fetchAll($table->select()
- ->where('bug_status = ?', 'NEW'));
- ]]></programlisting>
- </example></para>
- </sect3>
- <sect3 id="zend.db.table.fetch-all.usage">
- <title>Récupérer un jeu d'enregistrements :</title>
- <para>Vous pouvez demander une requête qui retourne plusieurs enregistrements. La méthode
- <code>fetchAll()</code> de votre classe de Table permet ceci. Elle retourne un objet de type
- <classname>Zend_Db_Table_Rowset_Abstract</classname>, même si aucun enregistrement ne correspond à la requête.</para>
- <example id="zend.db.table.qry.rows.set.finding.row.example">
- <title>Exemple de récupération d'enregistrements</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select()->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- <para>Vous pouvez aussi définir les clauses SQL <code>ORDER BY</code> ou encore <code>LIMIT</code> (ou autre
- équivalent comme OFFSET).</para>
- <example id="zend.db.table.fetch-all.example2">
- <title>Exemple de récupération d'enregistrements avec des clauses SQL</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $order = 'bug_id';
- // Retourne les enregistrements du 21ème au 30ème
- $count = 10;
- $offset = 20;
- $select = $table->select()->where(array('bug_status = ?' => 'NEW'))
- ->order($order)
- ->limit($count, $offset);
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- <para>Tous les arguments de requêtes sont optionnels. Vous pouvez écrire une requête sans clause WHERE ni
- LIMIT ou encore ORDER.</para>
- </sect3>
- <sect3 id="zend.db.table.advanced.usage">
- <title>Utilisation avancée</title>
- <para>Pour une utilisation plus avancée, vous pourriez vouloir spécifier une à une les colonnes que les
- enregistrements trouvés doivent comporter. Ceci se fait au moyen de la clause FROM de l'objet select. Le
- premier paramètre dans la clause FROM est le même que celui d'un objet Zend_Db_Select, cependant l'objet
- Zend_Db_Table_Select admet une instance de Zend_Db_Table_Abstract pour définir le nom de la table.</para>
- <para><example id="zend.db.table.qry.rows.set.retrieving.a.example">
- <title>Récupérer des colonnes spécifiques sur les enregistrements</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->from($table, array('bug_id', 'bug_description'))
- ->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example></para>
- <para><important>
- <para>Le jeu de résultats retourné est tout de même valide. Il ne possède en revanche que certaines
- colonnes de la table. La méthode <code>save()</code> est appelable, mais elle ne mettre à jour que
- ces colonnes.</para>
- </important> Il est aussi possible de spécifier des expressions dans une clause FROM, et donc récupérer
- un objet row/rowset en lecture seule. Dans l'exemple ci-après, nous retournons un enregistrement de la table
- "bugs" qui représente un agrégat du nombre de nouveaux bugs reportés. Regardez la clause GROUP. L'alias SQL
- "count" sera accessible dans le row/rowset résultant, comme si il faisait parti de la table en tant que
- colonne.</para>
- <para><example id="zend.db.table.qry.rows.set.retrieving.b.example">
- <title>Récupérer des enregistrements avec des requêtes incluant des expressions</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->from($table,
- array('COUNT(reported_by) as `count`', 'reported_by'))
- ->where('bug_status = ?', 'NEW')
- ->group('reported_by');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example> Vous pouvez aussi utiliser une table de jointure comme partie de votre requête. Dans
- l'exemple ci-dessous, nous utilisons la table "accounts" comme partie de la recherche, pour tous les bugs
- reportés par "Bob".</para>
- <para><example id="zend.db.table.qry.rows.set.refine.example">
- <title>Utiliser une table intermédiaire par jointure avec <code>fetchAll()</code></title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->where('bug_status = ?', 'NEW')
- ->join('accounts', 'accounts.account_name = bugs.reported_by')
- ->where('accounts.account_name = ?', 'Bob');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example></para>
- <para>L'objet <classname>Zend_Db_Table_Select</classname> est destiné à sélectionner des données sur une
- table précise. Des jointures peuvent être faites, mais il n'est pas possible de sélectionner des colonnes ne
- faisant pas partie de la table sous-jacente. Cependant, ceci aurait pu être utile dans certains cas, et
- l'objet <classname>Zend_Db_Table_Select</classname> possède une clause spéciale déverrouillant cette
- limitation. Passez la valeur <code>false</code> à sa méthode <code>setIntegrityCheck</code>. Il est alors
- possible de sélectionner des colonnes hors table. Attention toutefois, l'objet row/rowset résultant sera
- verrouillé. Impossible d'y appeler <code>save()</code>, <code>delete()</code> ou même d'affecter une valeur
- à certains de ses champs. Une exception sera systématiquement levée.</para>
- <example id="zend.db.table.qry.rows.set.integrity.example">
- <title>Déverrouiller un objet Zend_Db_Table_Select pour récupérer des colonnes JOINtes</title>
- <programlisting><![CDATA[
- $table = new Bugs();
- $select = $table->select()->setIntegrityCheck(false);
- $select->where('bug_status = ?', 'NEW')
- ->join('accounts',
- 'accounts.account_name = bugs.reported_by',
- 'account_name')
- ->where('accounts.account_name = ?', 'Bob');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.fetch-row">
- <title>Récupérer un seul enregistrement</title>
- <para>Vous pouvez demander à ne récupérer qu'un seul résultat, en requêtant de manière similaire à la méthode
- <code>fetchAll()</code>.</para>
- <example id="zend.db.table.fetch-row.example1">
- <title>Exemple de récupération d'un seul enregistrement</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select()->where('bug_status = ?', 'NEW')
- ->order('bug_id');
- $row = $table->fetchRow($select);
- ]]></programlisting>
- </example>
- <para>Cette méthode retourne un objet de type Zend_Db_Table_Row_Abstract. Si la requête ne trouve aucun
- enregistrement, alors <code>fetchRow()</code> retournera <code>null</code>.</para>
- </sect2>
- <sect2 id="zend.db.table.info">
- <title>Récupérer les méta données d'une Table</title>
- <para>La classe Zend_Db_Table_Abstract propose des informations concernant ses méta données.La méthode
- <code>info()</code> retourne un tableau d'informations sur les colonnes, la clé primaire, etc. de la
- table.</para>
- <example id="zend.db.table.info.example">
- <title>Exemple de récupération du nom de la table</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $info = $table->info();
- echo "The table name is " . $info['name'] . "\n";
- ]]></programlisting>
- </example>
- <para>Les clés du tableau retourné par <code>info()</code> sont les suivantes :</para>
- <itemizedlist>
- <listitem>
- <para><emphasis role="strong">name</emphasis> => nom de la table.</para>
- </listitem>
- <listitem>
- <para><emphasis role="strong">cols</emphasis> => un tableau contenant les colonnes de la
- table.</para>
- </listitem>
- <listitem>
- <para><emphasis role="strong">primary</emphasis> => un tableau contenant la(les) colonnes utilisée(s)
- pour définir la clé primaire de la table.</para>
- </listitem>
- <listitem>
- <para><emphasis role="strong">metadata</emphasis> => un tableau associatif, associant les noms des
- colonnes de la tables, à leurs informations intrinsèques. Les données sont les mêmes que celles
- retournée par <code>describeTable()</code>.</para>
- </listitem>
- <listitem>
- <para><emphasis role="strong">rowClass</emphasis> => le nom de la classe concrète servant les objets
- représentants les enregistrements de la table. Par défaut : Zend_Db_Table_Row.</para>
- </listitem>
- <listitem>
- <para><emphasis role="strong">rowsetClass</emphasis> => le nom de la classe concrète servant de
- conteneur d'objets représentants les enregistrements de la table. Par défaut :
- Zend_Db_Table_Rowset.</para>
- </listitem>
- <listitem>
- <para><emphasis role="strong">referenceMap</emphasis> => un tableau associatif. Il représente les
- références de cette table vers ses parents éventuelles. Voyez <xref
- linkend="zend.db.table.relationships.defining" />.</para>
- </listitem>
- <listitem>
- <para><emphasis role="strong">dependentTables</emphasis> => un tableau de noms de classes de tables
- qui référencent cette table. Voyez <xref linkend="zend.db.table.relationships.defining" />.</para>
- </listitem>
- <listitem>
- <para><emphasis role="strong">schema</emphasis> => Le nom de la base de données comportant cette
- table.</para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.db.table.metadata.caching">
- <title>Cacher les méta données de la table</title>
- <para>Par défaut, <classname>Zend_Db_Table_Abstract</classname> demande à la base de données les <link
- linkend="zend.db.table.info">méta données de table</link>, à chaque instanciation d'objet de table. L'objet de
- table analyse les métadonnées de la table dans le SGDB en utilisant la méthode <code>describeTable()</code> de
- l'adaptateur. Les opérations nécessitant cette introspection incluent :</para>
- <itemizedlist>
- <listitem>
- <para><code>insert()</code></para>
- </listitem>
- <listitem>
- <para><code>find()</code></para>
- </listitem>
- <listitem>
- <para><code>info()</code></para>
- </listitem>
- </itemizedlist>
- <para>Cependant, il peut être dégradant pour les performances du SGBD de lui demander ces informations à chaque
- instanciation de chaque objet de chaque table. Ainsi, un système de cache pour les méta données a été mis en
- place.</para>
- <para>La mise en cache des méta données des tables peut être contrôlée de deux manières: <itemizedlist>
- <listitem>
- <para><emphasis role="strong">Un appel à la méthode statique
- Zend_Db_Table_Abstract::setDefaultMetadataCache()</emphasis> - Ceci permet d'enregistrer une fois
- pour toutes l'objet de cache que toutes les tables devront utiliser.</para>
- </listitem>
- <listitem>
- <para><emphasis role="strong">L'appel au constructeur
- Zend_Db_Table_Abstract::__construct()</emphasis> - Il va permettre de spécifier l'objet de cache
- pour une table en particulier.</para>
- </listitem>
- </itemizedlist> Dans tous les cas, vous devrez passer soit <code>null</code> (et ainsi désactiver le cache
- des méta données des tables), soit une instance de <link
- linkend="zend.cache.frontends.core"><classname>Zend_Cache_Core</classname></link>. Il est possible d'utiliser à la fois
- <code>setDefaultMetadataCache</code> et le constructeur afin d'avoir un objet de cache par défaut, puis un
- spécifique pour certaines classes.</para>
- <example id="zend.db.table.metadata.caching-default">
- <title>Utiliser un objet de cache de méta données pour toutes les classes</title>
- <para>L'exemple qui suit illustre la manière de passer un objet de cache de méta données général, pour
- toutes les classes de table :</para>
- <programlisting role="php"><![CDATA[
- // D'abord, configurons le cache
- $frontendOptions = array(
- 'automatic_serialization' => true
- );
- $backendOptions = array(
- 'cache_dir' => 'cacheDir'
- );
- $cache = Zend_Cache::factory('Core',
- 'File',
- $frontendOptions,
- $backendOptions);
- // Puis passons le comme objet de cache par défaut
- Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
- // Testons avec une classe
- class Bugs extends Zend_Db_Table_Abstract
- {
- // ...
- }
- // Chaque instance utilise l'objet par défaut
- $bugs = new Bugs();
- ]]></programlisting>
- </example>
- <example id="zend.db.table.metadata.caching-instance">
- <title>Utiliser un objet de cache de métadonnées pour une instance précise</title>
- <para>L'exemple qui suit illustre la manière de passer un objet de cache de méta données spécifique, pour
- une instance précise :</para>
- <programlisting role="php"><![CDATA[
- // D'abord, configurons le cache
- $frontendOptions = array(
- 'automatic_serialization' => true
- );
- $backendOptions = array(
- 'cache_dir' => 'cacheDir'
- );
- $cache = Zend_Cache::factory('Core',
- 'File',
- $frontendOptions,
- $backendOptions);
- // Testons avec une classe
- class Bugs extends Zend_Db_Table_Abstract
- {
- // ...
- }
- // Lors de son instanciation, il est possible
- // de lui passer l'objet de cache
- $bugs = new Bugs(array('metadataCache' => $cache));
- ]]></programlisting>
- </example>
- <note>
- <title>Sérialisation automatique avec Cache Frontend</title>
- <para>Étant donné que les informations retournées par <classname>describeTable()</classname> le sont sous
- forme de tableau, assurez vous que le paramètre <code>automatic_serialization</code> est à <code>true</code>
- pour l'objet de la classe <classname>Zend_Cache_Core</classname>.</para>
- </note>
- <para>Dans nos exemples, nous utilisons <classname>Zend_Cache_Backend_File</classname>, mais vous pouvez utiliser le
- backend que vous souhaitez, voyez <link linkend="zend.cache">Zend_Cache</link> pour plus d'informations.</para>
- <sect3 id="zend.db.table.metadata.caching.hardcoding">
- <title>Coder en dur les métadonnées de tables</title>
- <para>Pour cacher les métadonnées une étape plus avant, vous pouvez aussi choisir de coder en dur ces
- métadonnées. Dans ce cas particulier, cependant, tout changement au schéma de la table requerra un
- changement dans votre code. Ainsi, il est seulement recommandé pour ceux qui sont dans la phase
- d'optimisation pour un usage en production.</para>
- <para>La structure des métadonnées est comme ceci :</para>
- <programlisting role="php"><![CDATA[
- protected $_metadata = array(
- '<column_name>' => array(
- 'SCHEMA_NAME' => <string>,
- 'TABLE_NAME' => <string>,
- 'COLUMN_NAME' => <string>,
- 'COLUMN_POSITION' => <int>,
- 'DATA_TYPE' => <string>,
- 'DEFAULT' => NULL|<value>,
- 'NULLABLE' => <bool>,
- 'LENGTH' => <string - length>,
- 'SCALE' => NULL|<value>,
- 'PRECISION' => NULL|<value>,
- 'UNSIGNED' => NULL|<bool>,
- 'PRIMARY' => <bool>,
- 'PRIMARY_POSITION' => <int>,
- 'IDENTITY' => <bool>,
- ),
- // additional columns...
- );
- ]]></programlisting>
- <para>Une manière simple de récupérer les valeurs appropriées est d'activer le cache des métadonnées et
- d'utiliser celles présentes dans votre cache.</para>
- <para>Vous pouvez désactiver cette optimisation en mettant à <code>false</code> le paramètre
- <code>metadataCacheInClass</code> :</para>
- <programlisting role="php"><![CDATA[
- // Lors de l'instanciation :
- $bugs = new Bugs(array('metadataCacheInClass' => false));
- // Ou plus tard :
- $bugs->setMetadataCacheInClass(false);
- ]]></programlisting>
- <para>Ce paramètre est activé par défaut, ce qui assure que le tableau <code>$_metadata</code> n'est chargé
- qu'une seule fois par instance</para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.extending">
- <title>Personnaliser et étendre une classe de Table</title>
- <sect3 id="zend.db.table.extending.row-rowset">
- <title>Utiliser des objets Row ou Rowset personnalisés</title>
- <para>Par défaut, les méthodes de la classe de Table retourne des jeux d'enregistrements comme étant des
- instances de la classe <classname>Zend_Db_Table_Rowset</classname>, ces "Rowsets" contiennent des enregistrements de
- la table, représentés par des objets instances de <classname>Zend_Db_Table_Row</classname>. Vous pouvez spécifier vos
- propres classes pour row/rowset, mais elles doivent étendre <classname>Zend_Db_Table_Rowset_Abstract</classname> ou
- <classname>Zend_Db_Table_Row_Abstract</classname>, respectivement.</para>
- <para>Vous pouvez spécifier vos classes row/rowset en utilisant le constructeur de la classe de Table, via
- le tableau d'options, aux clés <code>"rowClass"</code> et <code>"rowsetClass"</code>. Indiquez les noms des
- classes sous forme de chaînes de caractères.</para>
- <example id="zend.db.table.extending.row-rowset.example">
- <title>Exemple de spécification de ses propres classes Row et Rowset</title>
- <programlisting role="php"><![CDATA[
- class My_Row extends Zend_Db_Table_Row_Abstract
- {
- ...
- }
- class My_Rowset extends Zend_Db_Table_Rowset_Abstract
- {
- ...
- }
- $table = new Bugs(
- array(
- 'rowClass' => 'My_Row',
- 'rowsetClass' => 'My_Rowset'
- )
- );
- $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
- // Retourne un objet de type My_Rowset,
- // contenant des objets de type My_Row.
- $rows = $table->fetchAll($where);
- ]]></programlisting>
- </example>
- <para>Vous pouvez aussi utiliser les méthodes <code>setRowClass()</code> et <code>setRowsetClass()</code>.
- Ceci s'applique alors de manière ponctuelle, et non plus globale pour toute la classe de Table en tout
- point.</para>
- <example id="zend.db.table.extending.row-rowset.example2">
- <title>Exemple de changement ponctuel des classes de Row et Rowset</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
- // Retourne un objet de type Zend_Db_Table_Rowset
- // contenant des objets de type Zend_Db_Table_Row.
- $rowsStandard = $table->fetchAll($where);
- $table->setRowClass('My_Row');
- $table->setRowsetClass('My_Rowset');
- // Retourne un objet de type My_Rowset,
- // contenant des objets de type My_Row.
- $rowsCustom = $table->fetchAll($where);
- // L'objet $rowsStandard existe toujours et n'a pas changé d'état.
- ]]></programlisting>
- </example>
- <para>Pour des informations détaillées concernant les classes Row et Rowset, voyez <xref
- linkend="zend.db.table.row" /> et <xref linkend="zend.db.table.rowset" />.</para>
- </sect3>
- <sect3 id="zend.db.table.extending.insert-update">
- <title>Personnaliser les logiques Insert, Update, et Delete</title>
- <para>Vous pouvez redéfinir les méthodes <code>insert()</code> et <code>update()</code> afin d'y ajouter
- votre propre logique. Assurez vous d'appeler les méthodes parentes une fois votre code écrit.</para>
- <example id="zend.db.table.extending.insert-update.example">
- <title>Exemple d'implémentation d'une logique personnalisée gérant des timestamps</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- public function insert(array $data)
- {
- // Ajout d'un timestamp
- if (empty($data['created_on'])) {
- $data['created_on'] = time();
- }
- return parent::insert($data);
- }
- public function update(array $data, $where)
- {
- // Ajout d'un timestamp
- if (empty($data['updated_on'])) {
- $data['updated_on'] = time();
- }
- return parent::update($data, $where);
- }
- }
- ]]></programlisting>
- </example>
- <para>Il est aussi possible de redéfinir la méthode <code>delete()</code>.</para>
- </sect3>
- <sect3 id="zend.db.table.extending.finders">
- <title>Définir des méthodes de recherches personnalisées dans Zend_Db_Table</title>
- <para>Bien que <code>fetchAll()</code> fonctionne très bien, si vous avez plusieurs appels similaires à
- cette méthode (ou une autre), il peut être intéressant de factoriser du code en créant votre propre méthode
- de récupération d'enregistrements, utilisant <code>fetchAll()</code> ou une autre méthode.</para>
- <example id="zend.db.table.extending.finders.example">
- <title>Méthode personnalisée de récupération d'enregistrements "bugs" par critère "status"</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- public function findByStatus($status)
- {
- $where = $this->getAdapter()->quoteInto('bug_status = ?',
- $status);
- return $this->fetchAll($where, 'bug_id');
- }
- }
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.extending.inflection">
- <title>Utiliser l'inflexion dans Zend_Db_Table</title>
- <para>L'<emphasis>inflexion</emphasis> est un processus de transformations de caractères. Par défaut, si
- vous ne définissez pas de nom à votre table via la propriété protégée <code>$_name</code>,
- <classname>Zend_Db_Table_Abstract</classname> va utiliser le nom de la classe comme nom de table, sans effectuer
- aucune transformation.</para>
- <para>Certaines personnes peuvent vouloir utiliser un mécanisme d'inflexion pour transformer le nom de la
- classe d'une manière bien spécifique, afin de retrouver le nom de la table.</para>
- <para>Par exemple, une classe nommée "<code>BugsProducts</code>", peut vouloir refléter une table s'appelant
- "<code>bugs_products</code>," sans utiliser la propriété de classe <code>$_name</code>. Dans cette règle
- d'inflexion, les mots composant le nom de la classe sont écrits en "CamelCase", et seraient transformés en
- mots en minuscules, et séparés par des tirets bas.</para>
- <para>Vous pouvez aussi spécifier le nom de la table indépendamment du nom de la classe. Utilisez pour cela
- la propriété <code>$_name</code> de la classe de Table.</para>
- <para>Si vous voulez utiliser l'inflexion, vous devrez créer une classe (abstraite) étendant
- <classname>Zend_Db_Table_Abstract</classname>, et redéfinissant sa méthode protégée <code>_setupTableName()</code>.
- Toutes les classes de Table devront alors hériter de cette nouvelle classe abstraite.</para>
- <example id="zend.db.table.extending.inflection.example">
- <title>Exemple d'une classe abstraite utilisant l'inflexion</title>
- <programlisting role="php"><![CDATA[
- abstract class MyAbstractTable extends Zend_Db_Table_Abstract
- {
- protected function _setupTableName()
- {
- if (!$this->_name) {
- $this->_name = myCustomInflector(get_class($this));
- }
- parent::_setupTableName();
- }
- }
- class BugsProducts extends MyAbstractTable
- {
- }
- ]]></programlisting>
- </example>
- <para>C'est à vous d'écrire les fonctions qui vont établir le mécanisme d'inflexion.</para>
- </sect3>
- </sect2>
- </sect1>
|