| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- 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 <varname>$_name</varname>. 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 language="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 language="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 :
- <varname>$_schema</varname>, ou avec le nom de la base précédant le nom de la table dans
- la propriété <varname>$_name</varname>. Si vous choisissez de définir le nom de la base de
- données dans la propriété <varname>$_name</varname>, alors ce choix sera prioritaire sur
- celui utilisant <varname>$_schema</varname>.
- </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 language="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 <varname>$_name</varname> et
- <varname>$_schema</varname>).
- </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 language="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 <varname>$_primary</varname>. 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 language="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 <methodname>describeTable()</methodname>.
- </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 <methodname>describeTable()</methodname>), 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 _setupTableName()</title>
- <programlisting language="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>
- <methodname>_setupDatabaseAdapter()</methodname> 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>
- <methodname>_setupTableName()</methodname> 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>
- <methodname>_setupMetadata()</methodname> définit le nom de la base de données si
- le nom de la table est de la forme "base.table"; appelle
- <methodname>describeTable()</methodname> pour récupérer les méta-données; remplir le
- tableau <varname>$_cols</varname> avec les noms des colonnes reçus via
- <methodname>describeTable()</methodname>. 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>
- <methodname>_setupPrimaryKey()</methodname> donne le nom de la clé primaire par
- défaut en cherchant dans <methodname>describeTable()</methodname>; vérifie que la clé
- primaire fait bien partie du tableau <varname>$_cols</varname>. 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
- <methodname>init()</methodname>, qui est appelée juste après le constructeur, donc une fois la
- table correctement créée.
- </para>
- <example id="zend.db.table.defining.init.usage.example">
- <title>Exemple d'utilisation de la méthode init()</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_observer;
- public function init()
- {
- $this->_observer = new MyObserverClass();
- }
- }
- ]]></programlisting>
- </example>
- </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 language="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
- <methodname>Zend_Db_Table_Abstract::setDefaultAdapter()</methodname>. 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 language="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 language="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 <methodname>insert()</methodname> 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 language="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 <acronym>SQL</acronym> à 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 language="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 <acronym>SQL</acronym> de type
- <constant>INSERT</constant>.
- </para>
- <para>
- Dans <classname>Zend_Db_Table_Abstract</classname>, si vous définissez la
- variable protégée <varname>$_sequence</varname> à un booléen <constant>TRUE</constant> (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 language="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é <constant>SERIAL</constant> 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é <constant>IDENTITY</constant> 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 <varname>$_sequence</varname> à <constant>TRUE</constant>.
- </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 <varname>$_sequence</varname> 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 <constant>INSERT</constant> 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 language="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 <varname>$_sequence</varname> avec la valeur booléenne
- <constant>FALSE</constant>, 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 <methodname>insert()</methodname>, 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 language="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 <acronym>SQL</acronym> qui sera utiliser comme clause
- <constant>WHERE</constant> dans la requête <constant>UPDATE</constant>.
- </para>
- <example id="zend.db.table.update.example">
- <title>Exemple de mise à jour d'enregistrements dans une table</title>
- <programlisting language="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 <methodname>update()</methodname> est proxiées vers la
- méthode <link linkend="zend.db.adapter.write.update"><methodname>update()</methodname></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
- <constant>AND</constant>.
- </para>
- <note>
- <para>
- Les valeurs et les identifiants <acronym>SQL</acronym> ne sont pas échappés automatiquement. Si
- vous voulez échapper des valeurs, vous devrez utiliser <methodname>quote()</methodname>,
- <methodname>quoteInto()</methodname>, et <methodname>quoteIdentifier()</methodname> 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 <methodname>delete()</methodname>. Son seul paramètre est une chaîne ou un
- tableau définissant la clause <constant>WHERE</constant> à utiliser lors de la requête
- <constant>DELETE</constant>.
- </para>
- <example id="zend.db.table.delete.example">
- <title>Exemple de suppression d'enregistrements</title>
- <programlisting language="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"><methodname>delete()</methodname></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 <constant>AND</constant> pour former la clause WHERE.
- </para>
- <note>
- <para>
- Les valeurs et les identifiants <acronym>SQL</acronym> ne sont pas échappés automatiquement. Si
- vous voulez échapper des valeurs, vous devrez utiliser <methodname>quote()</methodname>,
- <methodname>quoteInto()</methodname>, et <methodname>quoteIdentifier()</methodname> 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 <methodname>find()</methodname>
- 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 language="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 <methodname>find()</methodname>. 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 <methodname>find()</methodname> 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 language="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 <methodname>fetchRow()</methodname> et <methodname>fetchAll()</methodname>
- 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 language="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));
- // ou avec liaison :
- $rows = $table->fetchAll(
- $table->select()
- ->where('bug_status = :status')
- ->bind(array(':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'));
- // ou avec liaison :
- $row = $table->fetchRow(
- $table->select()
- ->where('bug_status = :status')
- ->bind(array(':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 <acronym>SQL</acronym>. 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 (<methodname>save()</methodname>). Un
- appel à <methodname>save()</methodname> 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 language="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 language="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 <methodname>fetchAll()</methodname> 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 language="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 <acronym>SQL</acronym> <code>ORDER BY</code> ou encore
- <constant>LIMIT</constant> (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 language="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('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 language="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 <methodname>save()</methodname>
- 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 language="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
- <methodname>fetchAll()</methodname></title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- // Récupération avec la partie from déjà spécifié, important lors des jointures
- $select = $table->select(Zend_Db_Table::SELECT_WITH_FROM_PART);
- $select->setIntegrityCheck(false)
- ->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 <constant>FALSE</constant> à 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 <methodname>save()</methodname>, <methodname>delete()</methodname> 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(Zend_Db_Table::SELECT_WITH_FROM_PART)
- ->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 <methodname>fetchAll()</methodname>.
- </para>
- <example id="zend.db.table.fetch-row.example1">
- <title>Exemple de récupération d'un seul enregistrement</title>
- <programlisting language="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 <methodname>fetchRow()</methodname> retournera
- <constant>NULL</constant>.
- </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 <methodname>info()</methodname> 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 language="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 <methodname>info()</methodname> sont les suivantes :</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>name</emphasis> => nom de la table.</para>
- </listitem>
- <listitem>
- <para>
- <emphasis>cols</emphasis> => un tableau contenant les colonnes de la
- table.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>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>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 <methodname>describeTable()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>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>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>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>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>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 <methodname>describeTable()</methodname> de l'adaptateur. Les
- opérations nécessitant cette introspection incluent :
- </para>
- <itemizedlist>
- <listitem>
- <para><methodname>insert()</methodname></para>
- </listitem>
- <listitem>
- <para><methodname>find()</methodname></para>
- </listitem>
- <listitem>
- <para><methodname>info()</methodname></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>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>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 <constant>NULL</constant> (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 language="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 language="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
- <methodname>describeTable()</methodname> le sont sous forme de tableau, assurez vous
- que le paramètre <code>automatic_serialization</code> est à <constant>TRUE</constant> 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 language="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 à <constant>FALSE</constant> le
- paramètre <code>metadataCacheInClass</code> :
- </para>
- <programlisting language="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
- <varname>$_metadata</varname> 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 language="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 <methodname>setRowClass()</methodname> et
- <methodname>setRowsetClass()</methodname>. 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 language="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 <methodname>insert()</methodname> et
- <methodname>update()</methodname> 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 language="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 <methodname>delete()</methodname>.</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 <methodname>fetchAll()</methodname> 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 <methodname>fetchAll()</methodname> 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 language="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 <varname>$_name</varname>,
- <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 <varname>$_name</varname>. 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é <varname>$_name</varname> 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 <methodname>_setupTableName()</methodname>. 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 language="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>
|