| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271 |
- <!-- EN-Revision: 14084 -->
- <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>
|