| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 21877 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.db.adapter">
- <title>Zend_Db_Adapter</title>
- <para>
- <classname>Zend_Db</classname> et ses autres sous classes proposent une interface de
- connexion aux bases de données avec Zend Framework. <classname>Zend_Db_Adapter</classname>
- est la classe de base que vous utilisez pour vous connecter aux bases de données (SGBDs). Il
- y a différentes classes d'adaptateur par SGBD.
- </para>
- <para>
- Les classes <code>Adapters</code> de <classname>Zend_Db</classname> créent un pont
- entre les extensions <acronym>PHP</acronym> et une interface commune. Ceci vous aide à écrire des applications
- déployables avec de multiples SGBDs, demandant peu d'efforts.
- </para>
- <para>
- L'interface de la classe d'adaptateur est semblable à celle de l'extension <ulink
- url="http://www.php.net/pdo">PHP Data Objects</ulink>. <classname>Zend_Db</classname>
- propose des classes d'adaptateurs vers les drivers <acronym>PDO</acronym> pour les SGBDs suivants :
- </para>
- <itemizedlist>
- <listitem>
- <para>
- IBM DB2 et Informix Dynamic Server (IDS), en utilisant l'extension <acronym>PHP</acronym> <ulink
- url="http://www.php.net/pdo-ibm">pdo_ibm</ulink>.
- </para>
- </listitem>
- <listitem>
- <para>
- MySQL, utilisant l'extension <acronym>PHP</acronym> <ulink
- url="http://www.php.net/pdo-mysql">pdo_mysql</ulink>.
- </para>
- </listitem>
- <listitem>
- <para>
- Microsoft <acronym>SQL</acronym> Server, utilisant l'extension <acronym>PHP</acronym> <ulink
- url="http://www.php.net/pdo-dblib">pdo_dblib</ulink>.
- </para>
- </listitem>
- <listitem>
- <para>
- Oracle, utilisant l'extension <acronym>PHP</acronym> <ulink
- url="http://www.php.net/pdo-oci">pdo_oci</ulink>.
- </para>
- </listitem>
- <listitem>
- <para>
- PostgreSQL, grâce à l'extension <acronym>PHP</acronym> <ulink
- url="http://www.php.net/pdo-pgsql">pdo_pgsql</ulink>.
- </para>
- </listitem>
- <listitem>
- <para>
- SQLite, avec l'extension <acronym>PHP</acronym> <ulink
- url="http://www.php.net/pdo-sqlite">pdo_sqlite</ulink>.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- De plus, <classname>Zend_Db</classname> fournit aussi des classes se connectant avec
- les extensions <acronym>PHP</acronym> propres aux SGBDs (hors <acronym>PDO</acronym> donc), pour les SGBDs suivants :
- </para>
- <itemizedlist>
- <listitem>
- <para>
- MySQL, utilisant l'extension <acronym>PHP</acronym> <ulink
- url="http://www.php.net/mysqli">mysqli</ulink>.
- </para>
- </listitem>
- <listitem>
- <para>
- Oracle, utilisant l'extension <acronym>PHP</acronym> <ulink
- url="http://www.php.net/oci8">oci8</ulink>.
- </para>
- </listitem>
- <listitem>
- <para>
- IBM DB2, utilisant l'extension <acronym>PHP</acronym> <ulink
- url="http://www.php.net/ibm_db2">ibm_db2</ulink>.
- </para>
- </listitem>
- <listitem>
- <para>
- Firebird (Interbase), utilisant l'extension <acronym>PHP</acronym> <ulink
- url="http://www.php.net/ibase">php_interbase</ulink>
- </para>
- </listitem>
- </itemizedlist>
- <note>
- <para>
- Chaque <classname>Zend_Db_Adapter</classname> utilise une extension <acronym>PHP</acronym>. Vous
- devez donc les avoir activées pour utiliser les classes en question. Par exemple, si
- vous voulez utiliser une classe <classname>Zend_Db_Adapter</classname> basée sur <acronym>PDO</acronym>,
- vous devrez alors avoir l'extension <acronym>PDO</acronym> d'installée, ainsi que l'extension représentant
- le driver spécifique à votre SGBD.
- </para>
- </note>
- <sect2 id="zend.db.adapter.connecting">
- <title>Se connecter à un SGBD en utilisant un adaptateur</title>
- <para>
- Cette section décrit comment créer une instance d'un adaptateur
- <classname>Zend_Db</classname> de base de données.
- </para>
- <sect3 id="zend.db.adapter.connecting.constructor">
- <title>Utilisation du constructeur du Zend_Db Adapter</title>
- <para>
- Vous pouvez créer une instance d'un adaptateur en utilisant son constructeur.
- Celui-ci accepte un paramètre représentant un tableau d'options.
- </para>
- <example id="zend.db.adapter.connecting.constructor.example">
- <title>Utiliser le constructeur de l'adaptateur</title>
- <programlisting language="php"><![CDATA[
- $db = new Zend_Db_Adapter_Pdo_Mysql(array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test'
- ));
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.connecting.factory">
- <title>Utiliser la fabrique (Factory) de Zend_Db</title>
- <para>
- Alternativement, il est possible d'utiliser la méthode statique
- <methodname>Zend_Db::factory()</methodname>. Celle-ci charge dynamiquement la classe
- d'adaptateur correspondant en utilisant <link
- linkend="zend.loader.load.class">Zend_Loader::loadClass()</link>.
- </para>
- <para>
- Le premier argument est une chaîne désignant l'adaptateur souhaité. Par
- exemple, "<classname>Pdo_Mysql</classname>" va correspondre à la classe
- <classname>Zend_Db_Adapter_Pdo_Mysql</classname>. Le second paramètre est un tableau
- d'options. C'est le même que celui que vous auriez passé au constructeur de la
- classe directement.
- </para>
- <example id="zend.db.adapter.connecting.factory.example">
- <title>Utilisation de la méthode statique de fabrique de Zend_Db</title>
- <programlisting language="php"><![CDATA[
- // Nous n'avons pas besoin de la ligne suivante car Zend_Db_Adapter_Pdo_Mysql
- // sera automatiquement chargé par la fabrique Zend_Db.
- // require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
- // Charge automatiquement la classe Zend_Db_Adapter_Pdo_Mysql
- // et en créer une instance.
- $db = Zend_Db::factory('Pdo_Mysql', array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test'
- ));
- ]]></programlisting>
- </example>
- <para>
- Si vous créez votre propre classe d'adaptateur qui étend
- <classname>Zend_Db_Adapter_Abstract</classname> et que celle-ci ne respecte pas la
- syntaxe du préfixe package "<classname>Zend_Db_Adapter</classname>", utilisez alors
- la clé "<code>adapterNamespace</code>" dans le tableau de configuration passé à la
- méthode <methodname>factory()</methodname> afin de charger votre adaptateur.
- </para>
- <example id="zend.db.adapter.connecting.factory.example2">
- <title>Utilisation de la fabrique avec une classe personnalisée</title>
- <programlisting language="php"><![CDATA[
- // Charge automatiquement la classe MyProject_Db_Adapter_Pdo_Mysql
- // et l'instantie.
- $db = Zend_Db::factory('Pdo_Mysql', array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'adapterNamespace' => 'MyProject_Db_Adapter'
- ));
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.connecting.factory-config">
- <title>Utiliser Zend_Config avec la fabrique Zend_Db</title>
- <para>
- Optionnellement, vous pouvez passer un objet de type <link
- linkend="zend.config">Zend_Config</link> en tant qu'argument de la méthode
- <methodname>factory()</methodname>, concernant la configuration.
- </para>
- <para>
- Il est alors nécessaire que l'objet de configuration contienne une propriété
- <code>adapter</code>, qui représente une chaîne de caractères décrivant l'adaptateur
- à utiliser. De plus, l'objet peut aussi contenir une propriété nommée
- <code>params</code>, avec toutes les sous propriétés requises pour la configuration
- de l'adaptateur.
- </para>
- <example id="zend.db.adapter.connecting.factory.example1">
- <title>Utilisation de la fabrique avec un objet de type Zend_Config</title>
- <para>
- Dans l'exemple qui va suivre, l'objet <classname>Zend_Config</classname>
- est crée à partir d'un tableau. Il eut été possible de le créer à partir de
- fichiers externes, grâce à <link
- linkend="zend.config.adapters.ini">Zend_Config_Ini</link> ou <link
- linkend="zend.config.adapters.xml">Zend_Config_Xml</link>.
- </para>
- <programlisting language="php"><![CDATA[
- $config = new Zend_Config(
- array(
- 'database' => array(
- 'adapter' => 'Mysqli',
- 'params' => array(
- 'host' => '127.0.0.1',
- 'dbname' => 'test',
- 'username' => 'webuser',
- 'password' => 'secret',
- )
- )
- )
- );
- $db = Zend_Db::factory($config->database);
- ]]></programlisting>
- </example>
- <para>
- Le second paramètre de la méthode <methodname>factory()</methodname> doit être un tableau
- associatif décrivant les paramètres de l'adaptateur à utiliser. Cet argument est
- optionnel, si un objet de type <classname>Zend_Config</classname> est utilisé en
- premier paramètre, alors il est supposé contenir les paramètres, et le second
- paramètre de <methodname>factory()</methodname> est alors ignoré.
- </para>
- </sect3>
- <sect3 id="zend.db.adapter.connecting.parameters">
- <title>Paramètres de l'adaptateur (Adapter)</title>
- <para>
- La liste ci dessous explique les différents paramètres acceptés par les
- classes d'adaptateur <classname>Zend_Db</classname>.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>host</emphasis> : le nom de l'hôte hébergeant le SGBD. Vous
- pouvez aussi spécifier une adresse IP. Si le SGBD se situe sur la même
- machine que l'application <acronym>PHP</acronym>, "localhost" ou "127.0.0.1" devraient alors
- être utilisés.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>username </emphasis> : nom d'utilisateur du compte de
- connexion au SGBD.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>password</emphasis> : mot de passe de l'utilisateur du
- compte de connexion au SGBD.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>dbname</emphasis> : nom de la base de données située dans le
- SGBD.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>port</emphasis> : Certains SGBDs acceptent que l'on spécifie
- un port pour d'y connecter. Indiquez le alors ici.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>charset</emphasis> : encodage utilisé pour la connexion.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>options</emphasis> : Ce paramètre est un tableau associatif
- d'options génériques à toutes les classes
- <classname>Zend_Db_Adapter</classname>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>driver_options</emphasis> : Ce paramètre est un tableau
- associatif d'options spécifiques à une extension de SGBD spécifique.
- Typiquement, il est possible avec ce paramètre de passer des options
- (attributs) au driver <acronym>PDO</acronym>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>adapterNamespace</emphasis> : fournit le commencement du nom
- de la classe d'adaptateur, à utiliser la place de
- "<classname>Zend_Db_Adapter</classname>". Utilisez ceci si vous désirez que
- <methodname>factory()</methodname> charge une classe non Zend.
- </para>
- </listitem>
- </itemizedlist>
- <example id="zend.db.adapter.connecting.parameters.example1">
- <title>Passer l'option de gestion de la casse à la fabrique</title>
- <para>
- Vous pouvez spécifier cette option avec la constante
- <classname>Zend_Db::CASE_FOLDING</classname>. Ceci correspond à l'attribut
- <constant>ATTR_CASE</constant> dans les drivers <acronym>PDO</acronym> et IBM DB2, ce qui ajuste la casse
- des clés dans les jeux de résultats. Les valeurs possibles possibles sont
- <classname>Zend_Db::CASE_NATURAL</classname> (défaut),
- <classname>Zend_Db::CASE_UPPER</classname>, et
- <classname>Zend_Db::CASE_LOWER</classname>.
- </para>
- <programlisting language="php"><![CDATA[
- $options = array(
- Zend_Db::CASE_FOLDING => Zend_Db::CASE_UPPER
- );
- $params = array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'options' => $options
- );
- $db = Zend_Db::factory('Db2', $params);
- ]]></programlisting>
- </example>
- <example id="zend.db.adapter.connecting.parameters.example2">
- <title>Passer l'option d'auto-échappement à la fabrique</title>
- <para>
- Vous pouvez spécifier cette option avec le paramètre
- <classname>Zend_Db::AUTO_QUOTE_IDENTIFIERS</classname>. Si la valeur passée est
- <constant>TRUE</constant> (par défaut), alors les identifiants tels que les noms de
- tables, de colonnes, ou encore les alias <acronym>SQL</acronym>, sont échappés (délimités) dans la
- syntaxe de la requête <acronym>SQL</acronym> générée par l'objet d'adaptateur. Ceci rend
- l'utilisation de mots <acronym>SQL</acronym> contenant des identifiant spéciaux plus simple. Dans
- le cas de <constant>FALSE</constant>, vous devrez vous-même délimiter ces identifiant
- avec la méthode <methodname>quoteIdentifier()</methodname>.
- </para>
- <programlisting language="php"><![CDATA[
- $options = array(
- Zend_Db::AUTO_QUOTE_IDENTIFIERS => false
- );
- $params = array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'options' => $options
- );
- $db = Zend_Db::factory('Pdo_Mysql', $params);
- ]]></programlisting>
- </example>
- <example id="zend.db.adapter.connecting.parameters.example3">
- <title>Passer des options de driver PDO à la fabrique</title>
- <programlisting language="php"><![CDATA[
- $pdoParams = array(
- PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
- );
- $params = array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'driver_options' => $pdoParams
- );
- $db = Zend_Db::factory('Pdo_Mysql', $params);
- echo $db->getConnection()
- ->getAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY);
- ]]></programlisting>
- </example>
- <example id="zend.db.adapter.connecting.parameters.example4">
- <title>Passer des options de sérialisation à la fabrique</title>
- <programlisting language="php"><![CDATA[
- $options = array(
- Zend_Db::ALLOW_SERIALIZATION => false
- );
- $params = array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'options' => $options
- );
- $db = Zend_Db::factory('Pdo_Mysql', $params);
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.connecting.getconnection">
- <title>Gestion des connexions dites paresseuses</title>
- <para>
- La création d'une instance d'une classe d'adaptateur ne crée pas physiquement
- une connexion au SGBD. L'adaptateur sauvegarde les paramètres et se connectera
- physiquement à la demande, la première fois que vous aurez besoin d'exécuter une
- requête. Ceci permet d'assurer que la création de l'instance elle-même est rapide,
- et ne coûte rien en performances. Vous pouvez donc créer une instance de
- l'adaptateur, même si vous ne savez pas si vous allez l'utiliser. Ainsi, si vos
- paramètres sont incorrects, il faudra attendre la tentative de connexion au SGBD
- pour le vérifier réellement.
- </para>
- <para>
- Si vous voulez forcer l'adaptateur à se connecter au SGBD, utilisez sa méthode
- <methodname>getConnection()</methodname>. Elle retournera alors un objet représentant la
- connexion, en fonction de l'extension <acronym>PHP</acronym> utilisée, ou une exception si la connexion
- n'a pas été réalisée. Par exemple, si votre adaptateur utilise <acronym>PDO</acronym>, le retour sera
- un objet <acronym>PDO</acronym>. La connexion physique au SGBD est alors réalisée.
- </para>
- <para>
- Afin de vérifier si les paramètres de connexion au SGBD sont corrects,
- surveillez les exceptions envoyées par la méthode
- <methodname>getConnection()</methodname>.
- </para>
- <para>
- De plus, un adaptateur peut être sérialisé pour être stocké, par exemple, dans
- une variable de session. Ceci peut être utile non seulement pour l'adaptateur
- lui-même, mais aussi pour les autres objets qui l'agrègent, comme un objet
- <classname>Zend_Db_Select</classname>. Par défaut, les adaptateurs sont autorisés à
- être sérialisés, si vous ne le voulez pas, vous devez passer l'option
- <classname>Zend_Db::ALLOW_SERIALIZATION=false</classname>, regardez l'exemple
- ci-dessus. Afin de respecter le principe de connexions paresseuses, l'adaptateur ne
- se reconnectera pas après la désérialisation. Vous devez appeler vous-même
- <methodname>getConnection()</methodname>. Vous pouvez permettre à l'adaptateur de se reconnecter
- automatiquement en utilisant l'option d'adaptateur
- <classname>Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE=true</classname>.
- </para>
- <example id="zend.db.adapter.connecting.getconnection.example">
- <title>Gérer les exceptions de connexion</title>
- <programlisting language="php"><![CDATA[
- try {
- $db = Zend_Db::factory('Pdo_Mysql', $parameters);
- $db->getConnection();
- } catch (Zend_Db_Adapter_Exception $e) {
- // probablement mauvais identifiants,
- // ou alors le SGBD n'est pas joignable
- } catch (Zend_Exception $e) {
- // probablement que factory() n'a pas réussi à charger
- // la classe de l'adaptateur demandé
- }
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.adapter.example-database">
- <title>La base de données d'exemple</title>
- <para>
- Dans cette documentation concernant <classname>Zend_Db</classname>, nous utilisons
- un exemple simple de tables pour illustrer nos exemples. Ces tables peuvent servir à
- stocker des informations sur la gestion des bugs dans une application. La base de
- données contient quatre tables :
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>accounts</emphasis> correspond aux informations sur les
- utilisateurs qui gèrent les bugs.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>products</emphasis> enregistre les produits pour lesquels des
- bugs vont être relevés.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>bugs</emphasis> est la table qui contient les bugs, à savoir
- leur état actuel, la personne ayant relevé le bug, la personne en charge de le
- corriger, et la personne chargée de vérifier le correctif.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>bugs_products</emphasis> enregistre les relations entre les
- bugs, et les produits. C'est une relation plusieurs à plusieurs car un même bug
- peut faire partie de plusieurs produits, et un produit peut évidemment posséder
- plusieurs bugs.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Le pseudo-code <acronym>SQL</acronym> suivant représente les tables de notre base de données
- d'exemple. Ces tables sont utilisées aussi pour les tests unitaires automatisés de
- <classname>Zend_Db</classname>.
- </para>
- <programlisting language="sql"><![CDATA[
- CREATE TABLE accounts (
- account_name VARCHAR(100) NOT NULL PRIMARY KEY
- );
- CREATE TABLE products (
- product_id INTEGER NOT NULL PRIMARY KEY,
- product_name VARCHAR(100)
- );
- CREATE TABLE bugs (
- bug_id INTEGER NOT NULL PRIMARY KEY,
- bug_description VARCHAR(100),
- bug_status VARCHAR(20),
- reported_by VARCHAR(100) REFERENCES accounts(account_name),
- assigned_to VARCHAR(100) REFERENCES accounts(account_name),
- verified_by VARCHAR(100) REFERENCES accounts(account_name)
- );
- CREATE TABLE bugs_products (
- bug_id INTEGER NOT NULL REFERENCES bugs,
- product_id INTEGER NOT NULL REFERENCES products,
- PRIMARY KEY (bug_id, product_id)
- );
- ]]></programlisting>
- <para>
- Notez aussi que la table <code>bugs</code> contient plusieurs référence (clés
- étrangères) vers la table <code>accounts</code>. Chacune de ces clés peut référencer un
- enregistrement différent de la table <code>accounts</code>, pour un bug donné.
- </para>
- <para>Le diagramme qui suit illustre le modèle physique des données.</para>
- <para>
- <inlinegraphic align="center"
- fileref="figures/zend.db.adapter.example-database.png" format="PNG" scale="100"
- valign="middle" width="387" />
- </para>
- </sect2>
- <sect2 id="zend.db.adapter.select">
- <title>Lecture de résultats de requête</title>
- <para>
- Cette section décrit des méthodes de la classe d'adaptateur permettant l'obtention
- de résultats suivants une requête SELECT.
- </para>
- <sect3 id="zend.db.adapter.select.fetchall">
- <title>Récupérer tous les résultats</title>
- <para>
- Vous pouvez à la fois exécuter une requête SELECT et récupérer tous ses
- résultats en une seule manipulation, grâce à la méthode
- <methodname>fetchAll()</methodname>.
- </para>
- <para>
- Le premier paramètre de cette méthode est une chaîne représentant la requête
- SELECT à exécuter. Aussi, ce premier paramètre peut être un objet <link
- linkend="zend.db.select">Zend_Db_Select</link>, qui sera alors converti en une
- chaîne automatiquement.
- </para>
- <para>
- Le second paramètre de de <methodname>fetchAll()</methodname> est un tableau de
- substitutions des éventuels jokers présents dans la syntaxe <acronym>SQL</acronym>.
- </para>
- <example id="zend.db.adapter.select.fetchall.example">
- <title>Utiliser fetchAll()</title>
- <programlisting language="php"><![CDATA[
- $sql = 'SELECT * FROM bugs WHERE bug_id = ?';
- $result = $db->fetchAll($sql, 2);
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetch-mode">
- <title>Changer le mode de récupération (Fetch Mode)</title>
- <para>
- Par défaut, <methodname>fetchAll()</methodname> retourne un tableau d'enregistrements.
- Chaque enregistrement étant un tableau associatif dont les clés sont les noms des
- colonnes <acronym>SQL</acronym> désirées, ou leurs alias.
- </para>
- <para>
- Vous pouvez spécifier un mode de récupération de résultats différent, ceci par
- la méthode <methodname>setFetchMode()</methodname>. Les modes supportés sont identifiés par des
- constantes :
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_ASSOC</emphasis> : Retourne un tableau
- d'enregistrements. Chaque enregistrement étant un tableau associatif dont
- les clés sont les noms des colonnes <acronym>SQL</acronym> désirées, ou leurs alias. Il s'agit
- du mode par défaut utilisé par les classes Zend_Db_Adapter.
- </para>
- <para>
- Notez que si votre résultat comporte plusieurs colonnes avec le même
- nom, par exemple lors d'une jointure, il ne peut y avoir qu'un clé avec un
- nom définit dans le tableau de résultat. Vous devriez toujours utiliser des
- alias avec le mode FETCH_ASSOC.
- </para>
- <para>
- Les noms des clés des tableaux correspondants aux noms des colonnes
- <acronym>SQL</acronym> telles que retournées par le SGBD, vous pouvez spécifier la casse pour
- ces noms, grâce à l'option <classname>Zend_Db::CASE_FOLDING</classname>.
- Spécifiez ceci lors de l'instanciation de votre adaptateur. Voyez <xref
- linkend="zend.db.adapter.connecting.parameters.example1" />.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_NUM</emphasis> : Retourne les enregistrements
- dans un tableau de tableaux. Les tableaux nichés sont indexés par des
- entiers correspondants à la position du champ dans la syntaxe <acronym>SQL</acronym>
- SELECT.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_BOTH</emphasis> : Retourne les enregistrements
- dans un tableau de tableaux. Les tableaux nichés sont indexés à la fois
- numériquement et lexicalement. C'est un mode qui réunit FETCH_ASSOC et
- FETCH_NUM. Ainsi, vous avez deux fois plus d'enregistrements, chacun d'entre
- eux étant doublé.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_COLUMN</emphasis>: Retourne les
- enregistrements dans un tableau de valeurs. Les valeurs correspondent à une
- des colonnes utilisées dans la requête <acronym>SQL</acronym> SELECT. Par défaut, il s'agit de
- la colonne à l'index 0.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_OBJ</emphasis> : Retourne les enregistrements
- dans un tableau d'objets. La classe de ces objets par défaut est la classe
- intégrée à <acronym>PHP</acronym> : <code>stdClass</code>. Les colonnes des enregistrements
- sont représentées par les propriétés publiques des objets.
- </para>
- </listitem>
- </itemizedlist>
- <example id="zend.db.adapter.select.fetch-mode.example">
- <title>Utiliser setFetchMode()</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchAll('SELECT * FROM bugs WHERE bug_id = ?', 2);
- // $result est un tableau d'objets
- echo $result[0]->bug_description;
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchassoc">
- <title>Récupérer un enregistrement comme tableau associatif</title>
- <para>
- La méthode <methodname>fetchAssoc()</methodname> retourne des enregistrements sous
- forme de tableau de tableaux associatifs, quelque soit la valeur de "fetch mode"
- en utilisant la première colonne comme index.
- </para>
- <example id="zend.db.adapter.select.fetchassoc.example">
- <title>Utiliser f<methodname>etchAssoc()</methodname></title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchAssoc('SELECT bug_id, bug_description, bug_status FROM bugs');
- // $result est un tableau de tableaux associatifs
- echo $result[2]['bug_description']; // Description du bug #2
- echo $result[1]['bug_description']; // Description du bug #1
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchcol">
- <title>Récupérer une seule colonne d'un enregistrement</title>
- <para>
- La méthode <methodname>fetchCol()</methodname> retourne les enregistrements dans un
- tableau de valeurs. Les valeurs correspondent à une des colonnes utilisées dans la
- requête <acronym>SQL</acronym> SELECT, par défaut : la première. Toute autre colonne sera ignorée. Si
- vous avez besoin de retourner une autre colonne, voyez <xref
- linkend="zend.db.statement.fetching.fetchcolumn" />. Cette méthode est indépendante
- de la valeur de "fetch mode".
- </para>
- <example id="zend.db.adapter.select.fetchcol.example">
- <title>Utiliser fetchCol()</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $sql = 'SELECT bug_description, bug_id FROM bugs WHERE bug_id = ?';
- $result = $db->fetchCol($sql, 2);
- // Contient bug_description ; bug_id n'est pas retourné
- echo $result[0];
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchpairs">
- <title>Récupérer des paires Clé-Valeur d'enregistrements</title>
- <para>
- La méthode <methodname>fetchPairs()</methodname> retourne un tableau de paires
- clés/valeurs. La clé est le résultat de la première colonne sélectionnée dans la
- requête, la valeur est le résultat de la deuxième colonne sélectionnée dans la
- requête. Il est donc inutile de sélectionner plus de deux colonnes avec cette
- méthode. De même, vous devez sélectionner exactement deux colonnes avec cette
- méthode, pas moins. Si des clés ont des doublons, alors ils seront écrasés.
- </para>
- <para>
- Vous devriez réfléchir votre requête SELECT de manière à ce que la première
- colonne sélectionnée, correspondant à la clé du tableau de résultat, soit unique
- (une clé primaire par exemple). Cette méthode est indépendante de "fetch mode"
- éventuellement précédemment défini.
- </para>
- <example id="zend.db.adapter.select.fetchpairs.example">
- <title>Utilisation de fetchPairs()</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchPairs('SELECT bug_id, bug_status FROM bugs');
- echo $result[2]; // le bug_status correspondant au bug_id numéro 2
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchrow">
- <title>Récupérer un seul enregistrement complet</title>
- <para>
- La méthode <methodname>fetchRow()</methodname> retourne un et un seul enregistrement (le
- premier si plusieurs correspondent), en fonction de "fetch mode" que vous aurez
- précédemment défini. Cette méthode ressemble donc à <methodname>fetchAll()</methodname> si ce
- n'est qu'elle ne retournera jamais plus d'un seul enregistrement. Arrangez vous donc
- pour que votre SELECT possède une clause WHERE sur une clé primaire.
- </para>
- <example id="zend.db.adapter.select.fetchrow.example">
- <title>Utiliser fetchRow()</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchRow('SELECT * FROM bugs WHERE bug_id = 2');
- // Ce résultat sera un objet, car le fetch mode en a décidé ainsi
- echo $result->bug_description;
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchone">
- <title>Récupérer une colonne d'un enregistrement</title>
- <para>
- La méthode <methodname>fetchOne()</methodname> est une combinaison des méthodes
- <methodname>fetchRow()</methodname> et <methodname>fetchCol()</methodname>, ainsi elle ne retourne que la
- première colonne, du premier enregistrement retourné. La valeur de retour est donc
- une chaîne de caractères. Toute requête retournant plusieurs colonnes et/ou
- plusieurs résultats est donc inutile avec cette méthode.
- </para>
- <example id="zend.db.adapter.select.fetchone.example">
- <title>Utiliser fetchOne()</title>
- <programlisting language="php"><![CDATA[
- $result = $db->fetchOne('SELECT bug_status FROM bugs WHERE bug_id = 2');
- // ceci est une chaine
- echo $result;
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.adapter.write">
- <title>Effectuer des changements dans la base de données</title>
- <para>
- Il est bien entendu possible d'utiliser la classe d'adaptateur pour effectuer des
- changements dans vos données. Cette section décrit les manières de procéder.
- </para>
- <sect3 id="zend.db.adapter.write.insert">
- <title>Insérer des données</title>
- <para>
- Vous pouvez ajouter de nouveaux enregistrements dans une table, grâce à la
- méthode <methodname>insert()</methodname>. Son premier paramètre est une chaîne qui représente
- le nom de la table ciblée, le second paramètre est un tableau associatif liant les
- noms des colonnes de la table, aux valeurs souhaitées.
- </para>
- <example id="zend.db.adapter.write.insert.example">
- <title>Insertion dans une table</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'created_on' => '2007-03-22',
- 'bug_description' => 'Something wrong',
- 'bug_status' => 'NEW'
- );
- $db->insert('bugs', $data);
- ]]></programlisting>
- </example>
- <para>
- Les colonnes non citées dans le tableau associatif sont laissées telles
- quelles. Ainsi, si le SGBD possède une valeur DEFAULT pour les colonnes concernées,
- celle-ci sera utilisée, autrement, NULL sera utilisé.
- </para>
- <para>
- Par défaut, les valeurs insérées avec cette méthode sont automatiquement
- échappées. Ceci pour des raisons de sécurité, vous n'avez donc pas besoin de vous
- occuper de ce point là.
- </para>
- <para>
- Si vous avez besoin d'écrire de la syntaxe <acronym>SQL</acronym>, comme des mots réservés, des
- noms de fonctions <acronym>SQL</acronym>, vous voulez que ceux-ci ne soient pas échappés, et ne soient
- pas traités comme de vulgaires chaînes de caractères, mais plutôt comme des
- expressions. Pour ceci, vous devriez passer ces valeurs dans votre tableau de
- données, en tant qu'objets de type <classname>Zend_Db_Expr</classname> au lieu de
- chaînes de caractères banales.
- </para>
- <example id="zend.db.adapter.write.insert.example2">
- <title>Insérer des expressions dans une table</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'created_on' => new Zend_Db_Expr('CURDATE()'),
- 'bug_description' => 'Something wrong',
- 'bug_status' => 'NEW'
- );
- $db->insert('bugs', $data);
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.write.lastinsertid">
- <title>Récupérer une valeur générée</title>
- <para>
- Certains SGBDs supportent les clé primaires auto-incrémentées. Une table qui
- utilise un tel procédé génère la valeur de la clé automatiquement lors d'une
- insertion (INSERT). La valeur de retour de la méthode <methodname>insert()</methodname>
- <emphasis>n'est pas</emphasis> le dernier ID inséré car la table peut ne pas avoir
- de clé auto-incrémentée. La valeur de retour est le nombres d'enregistrements
- affectés (théoriquement 1).
- </para>
- <para>
- Si votre table a été définie avec une clé auto-incrémentée, alors vous pouvez
- appeler la méthode <methodname>lastInsertId()</methodname> après une opération d'insertion.
- Cette méthode retourne la valeur auto-incrémentée, générée dans le cadre de la
- connexion au SGBD.
- </para>
- <example id="zend.db.adapter.write.lastinsertid.example-1">
- <title>Utiliser lastInsertId() pour les clés auto-incrémentées</title>
- <programlisting language="php"><![CDATA[
- $db->insert('bugs', $data);
- // retourne la dernière valeur générée par la clé auto-incrémentée
- $id = $db->lastInsertId();
- ]]></programlisting>
- </example>
- <para>
- Certains SGBD supporte un objet de séquence, qui sert à générer des valeurs
- uniques qui vont servir pour les clé primaires. Pour supporter ce procédé, la
- méthode <methodname>lastInsertId()</methodname> accepte deux paramètres optionnels (chaînes de
- caractères). Ces paramètres nomment la table et la colonne en supposant que vous
- ayez respecté la convention qui définit que la séquence est nommée en utilisant le
- nom de la table et des colonnes utilisées, avec le suffixe "_seq". Ces conventions
- sont celles de PostgreSQL pour les colonnes de type SERIAL. Par exemple, une table
- "bugs" avec une clé primaire "bug_id" utilisera une séquence nommée
- "bugs_bug_id_seq".
- </para>
- <example id="zend.db.adapter.write.lastinsertid.example-2">
- <title>Utiliser lastInsertId() avec une séquence</title>
- <programlisting language="php"><![CDATA[
- $db->insert('bugs', $data);
- // retourne la dernière valeur générée par la séquence 'bugs_bug_id_seq'.
- $id = $db->lastInsertId('bugs', 'bug_id');
- // ceci retourne la dernière valeur générée par la séquence 'bugs_seq'.
- $id = $db->lastInsertId('bugs');
- ]]></programlisting>
- </example>
- <para>
- Si le nom de votre objet de séquence ne suit pas ces conventions de nommage,
- utilisez alors <methodname>lastSequenceId()</methodname>. Cette méthode prend un paramètre qui
- nomme la séquence explicitement.
- </para>
- <example id="zend.db.adapter.write.lastinsertid.example-3">
- <title>Utilisation de lastSequenceId()</title>
- <programlisting language="php"><![CDATA[
- $db->insert('bugs', $data);
- // retourne la dernière valeur générée par la séquence 'bugs_id_gen'.
- $id = $db->lastSequenceId('bugs_id_gen');
- ]]></programlisting>
- </example>
- <para>
- Pour les SGBDs ne supportant pas les séquences, comme MySQL, Microsoft <acronym>SQL</acronym>
- Server, et SQLite, les arguments passés à la méthode <methodname>lastInsertId()</methodname>
- sont ignorés. La valeur retournée est la dernière valeur générée pour la dernière
- requête INSERT, quelque soit la table concernée (pour cette connexion). Aussi, pour
- ces SGBDs, la méthode <methodname>lastSequenceId()</methodname> retournera toujours
- <constant>NULL</constant>.
- </para>
- <note>
- <title>Pourquoi ne pas utiliser "SELECT MAX(id) FROM table"?</title>
- <para>
- Quelques fois, cette requête retourne la valeur la plus récente de clé
- primaire insérée dans la table en question. Cependant, cette technique n'est pas
- pertinente dans un environnement où beaucoup de clients insèrent beaucoup de
- données dans une même table. Il est donc possible qu'un client insère une donnée
- entre le moment où la dernière insertion est effectuée, et l'appel de MAX(id),
- aboutissant ainsi à un résultat erroné. Il est très difficile de se rendre
- compte d'un tel comportement.
- </para>
- <para>
- Utiliser un mode d'isolation transactionnelle très élevé, comme
- "repeatable read" peut mitiger plus ou moins les risques, mais certains SGBDs ne
- supportent pas ce mode de transactions.
- </para>
- <para>
- De plus, utiliser une requête du type "MAX(id)+1" pour générer une
- nouvelle valeur de clé primaire n'est pas sécurisé non plus, car deux client
- peuvent se connecter simultanément et créer des effets indésirables.
- </para>
- <para>
- Tous les SGBDs fournissent un mécanisme de génération de valeurs uniques,
- et une méthode pour les récupérer. Ces mécanismes travaillent en dehors du mode
- transactionnel, et empêchent ainsi deux clients de générer la même valeur, ou de
- "se marcher dessus".
- </para>
- </note>
- </sect3>
- <sect3 id="zend.db.adapter.write.update">
- <title>Mettre à jour des données</title>
- <para>
- Vous pouvez mettre à jour des données dans une table en utilisant la méthode
- <methodname>update()</methodname> de l'adaptateur. Cette méthode accepte trois arguments :
- le premier est le nom de la table, le deuxième est un tableau faisant correspondre
- les noms des colonnes <acronym>SQL</acronym> à leurs valeurs désirées.
- </para>
- <para>
- Les valeurs dans ce tableau sont traitées comme des chaînes. Voyez <xref
- linkend="zend.db.adapter.write.insert" /> pour plus d'informations sur la gestion
- des expressions <acronym>SQL</acronym> dans ce tableau.
- </para>
- <para>
- Le troisième argument est une chaîne contenant l'expression <acronym>SQL</acronym> utilisée comme
- critère pour la mise à jour des données dans la table. Les valeurs et les arguments
- dans ce paramètre ne sont pas échappés pour vous. Vous devez donc vous assurer de
- l'éventuel bon échappement des caractères. Voyez <xref
- linkend="zend.db.adapter.quoting" /> pour plus d'informations.
- </para>
- <para>
- La valeur de retour de cette méthode est le nombre d'enregistrements affectés
- par l'opération de mise à jour (UPDATE).
- </para>
- <example id="zend.db.adapter.write.update.example">
- <title>Mettre à jour des enregistrements</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'updated_on' => '2007-03-23',
- 'bug_status' => 'FIXED'
- );
- $n = $db->update('bugs', $data, 'bug_id = 2');
- ]]></programlisting>
- </example>
- <para>
- Si vous oubliez le troisième paramètre, alors tous les enregistrements de la
- table sont mis à jour avec les valeurs spécifiées dans le tableau de données.
- </para>
- <para>
- Si vous spécifiez un tableau de chaîne en tant que troisième paramètre, alors
- ces chaînes sont jointes entre elles avec une opération <constant>AND</constant>.
- </para>
- <para>
- Si vous fournissez un tableau de tableaux en tant que troisième argument, les
- valeurs seront automatiquement échappées dans les clés. Elles seront ensuite
- jointes ensemble, séparées par des opérateurs <constant>AND</constant>.
- </para>
- <example id="zend.db.adapter.write.update.example-array">
- <title>Mettre à jour des enregistrements avec un tableau de données</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'updated_on' => '2007-03-23',
- 'bug_status' => 'FIXED'
- );
- $where[] = "reported_by = 'goofy'";
- $where[] = "bug_status = 'OPEN'";
- $n = $db->update('bugs', $data, $where);
- // la requête SQL executée est :
- // UPDATE "bugs" SET "update_on" = '2007-03-23', "bug_status" = 'FIXED'
- // WHERE ("reported_by" = 'goofy') AND ("bug_status" = 'OPEN')
- ]]></programlisting>
- </example>
- <example id="zend.db.adapter.write.update.example-arrayofarrays">
- <title>UMettre à jour des enregistrements avec un tableau de tableaux</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'updated_on' => '2007-03-23',
- 'bug_status' => 'FIXED'
- );
- $where['reported_by = ?'] = 'goofy';
- $where['bug_status = ?'] = 'OPEN';
- $n = $db->update('bugs', $data, $where);
- // la requête SQL executée est :
- // UPDATE "bugs" SET "update_on" = '2007-03-23', "bug_status" = 'FIXED'
- // WHERE ("reported_by" = 'goofy') AND ("bug_status" = 'OPEN')
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.write.delete">
- <title>Supprimer des enregistrements</title>
- <para>
- Il est possible de supprimer des enregistrements dans une table. La méthode
- <methodname>delete()</methodname> est faite pour cela. Elle accepte deux paramètres, le premier
- est une chaîne désignant la table.
- </para>
- <para>
- Le second paramètre est une chaîne contenant l'expression <acronym>SQL</acronym> utilisée comme
- critère pour effacer les enregistrements. Les valeurs de cette expression de sont
- pas échappées automatiquement, vous devez donc vous en occuper le cas échéant. Voyez
- <xref linkend="zend.db.adapter.quoting" /> pour les méthodes concernant
- l'échappement.
- </para>
- <para>
- La valeur retournée par la méthode <methodname>delete()</methodname> est le nombre
- d'enregistrements affectés (effacés).
- </para>
- <example id="zend.db.adapter.write.delete.example">
- <title>Supprimer des enregistrements</title>
- <programlisting language="php"><![CDATA[
- $n = $db->delete('bugs', 'bug_id = 3');
- ]]></programlisting>
- </example>
- <para>
- Si vous ne spécifiez pas le second paramètres, tous les enregistrements de la
- table seront alors supprimés.
- </para>
- <para>
- Si le second paramètre est un tableau de chaînes, alors celles ci seront
- jointe en une expression <acronym>SQL</acronym>, séparées par l'opérateur
- <constant>AND</constant>.
- </para>
- <para>
- Si vous fournissez un tableau de tableaux en tant que troisième argument, les
- valeurs seront automatiquement échappées dans les clés. Elles seront ensuite
- jointes ensemble, séparées par des opérateurs <constant>AND</constant>.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.adapter.quoting">
- <title>Échapper des valeurs ou des identifiants</title>
- <para>
- Lorsque vous envoyez des requêtes SQL au SGBD, il est souvent nécessaire d'y
- inclure des paramètres dynamiques, PHP. Ceci est risqué car si un des paramètres
- contient certains caractères, comme l'apostrophe ('), alors la requête résultante risque
- d'être mal formée. Par exemple, notez le caractère indésirable dans la requête
- suivante :
- <programlisting language="php"><![CDATA[
- $name = "O'Reilly";
- $sql = "SELECT * FROM bugs WHERE reported_by = '$name'";
- echo $sql;
- // SELECT * FROM bugs WHERE reported_by = 'O'Reilly'
- ]]></programlisting>
- </para>
- <para>
- Pire encore est le cas où de telles erreurs <acronym>SQL</acronym> peuvent être utilisées
- délibérément par une personne afin de manipuler la logique de votre requête. Si une
- personne peut manipuler un paramètre de votre requête, par exemple via un paramètre <acronym>HTTP</acronym>
- ou une autre méthode, alors il peut y avoir une fuite de données, voire même une
- corruption totale de votre base de données. Cette technique très préoccupante de
- violation de la sécurité d'un SGBD, est appelée "injection <acronym>SQL</acronym>" (voyez <ulink
- url="http://en.wikipedia.org/wiki/SQL_Injection">http://en.wikipedia.org/wiki/SQL_Injection</ulink>).
- </para>
- <para>
- La classe Zend_Db Adapter possède des méthodes adaptées pour vous aider à faire
- face à de telles vulnérabilités. La solution proposée est l'échappement de tels
- caractères (comme la "quote" = ') dans les valeurs <acronym>PHP</acronym> avant leur passage dans la chaîne
- de requête. Ceci vous protège de l'insertion malveillante ou involontaires, de
- caractères spéciaux dans les variables <acronym>PHP</acronym> faisant partie d'une requête <acronym>SQL</acronym>.
- </para>
- <sect3 id="zend.db.adapter.quoting.quote">
- <title>Utilisation de quote()</title>
- <para>
- La méthode <methodname>quote()</methodname> accepte un seul paramètre, une chaîne de
- caractère. Elle retourne une chaîne dont les caractères spéciaux ont été échappés
- d'une manière convenable en fonction du SGBD sous-jacent. De plus, la chaîne
- échappée est entourée d'apostrophes ("<code>'</code>").C'est la valeur standard de
- délimitations des chaînes en <acronym>SQL</acronym>.
- </para>
- <example id="zend.db.adapter.quoting.quote.example">
- <title>Utiliser quote()</title>
- <programlisting language="php"><![CDATA[
- $name = $db->quote("O'Reilly");
- echo $name;
- // 'O\'Reilly'
- $sql = "SELECT * FROM bugs WHERE reported_by = $name";
- echo $sql;
- // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
- ]]></programlisting>
- </example>
- <para>
- Notez que la valeur de retour contient les apostrophes de délimitation autour
- de la chaîne. Ceci est différent de certaines fonctions qui se contentent juste
- d'échapper les caractères spéciaux, telle que <ulink
- url="http://www.php.net/mysqli_real_escape_string">mysql_real_escape_string()</ulink>.
- </para>
- <para>
- Certaines valeurs en revanche n'ont pas besoin d'être délimitées. Certains
- SGBDs n'acceptent pas que les valeurs correspondant à des champs de type entier,
- soient délimitées. Autrement dit, l'exemple suivant est erroné dans certaines
- implémentations de SQL. Nous supposons <code>intColumn</code> ayant un type SQL
- <constant>INTEGER</constant> : <programlisting language="php"><![CDATA[
- SELECT * FROM atable WHERE intColumn = '123'
- ]]></programlisting></para>
- <para>
- Le second paramètre optionnel de <methodname>quote()</methodname> permet de spécifier un
- type <acronym>SQL</acronym>.
- </para>
- <example id="zend.db.adapter.quoting.quote.example-2">
- <title>Utiliser quote() avec un type SQL</title>
- <programlisting language="php"><![CDATA[
- $value = '1234';
- $sql = 'SELECT * FROM atable WHERE intColumn = '
- . $db->quote($value, 'INTEGER');
- ]]></programlisting>
- </example>
- <para>
- De plus, chaque classe Zend_Db_Adapter possèdent des constantes représentant
- les différents type <acronym>SQL</acronym> des SGBDs respectifs qu'elles représentent. Ainsi, les
- constantes <classname>Zend_Db::INT_TYPE</classname>,
- <classname>Zend_Db::BIGINT_TYPE</classname>, et
- <classname>Zend_Db::FLOAT_TYPE</classname> peuvent vous permettre d'écrire un code
- portable entre différents SGBDs.
- </para>
- <para>
- Zend_Db_Table fournit les types <acronym>SQL</acronym> à <methodname>quote()</methodname> automatiquement en
- fonction des colonnes utilisées par la table référencée.
- </para>
- </sect3>
- <sect3 id="zend.db.adapter.quoting.quote-into">
- <title>Utilisation de quoteInto()</title>
- <para>
- Une autre manière est d'échapper une expression <acronym>SQL</acronym> contenant une variable
- <acronym>PHP</acronym>. Vous pouvez utiliser <methodname>quoteInto()</methodname> pour cela. Cette méthode accepte
- trois arguments. Le premier est la chaîne représentant l'expression <acronym>SQL</acronym> dont les
- paramètres variables sont remplacés par un joker(<code>?</code>), et le second
- argument est la variable <acronym>PHP</acronym> à utiliser pour le remplacement du joker.
- </para>
- <para>
- Le joker est le même symbole que celui utilisé par beaucoup de SGBDs pour la
- substitution de paramètre dans une requête préparée.<methodname>quoteInto()</methodname> ne fait
- qu'émuler ce comportement : la méthode ne fait que remplacer le joker par la
- valeur <acronym>PHP</acronym>, en lui appliquant la méthode <code>quote</code>. De vrais paramètres de
- requêtes préparées conservent une réelle isolation entre la requête et ses
- paramètres.
- </para>
- <example id="zend.db.adapter.quoting.quote-into.example">
- <title>Utiliser quoteInto()</title>
- <programlisting language="php"><![CDATA[
- $sql = $db->quoteInto("SELECT * FROM bugs WHERE reported_by = ?",
- "O'Reilly");
- echo $sql;
- // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
- ]]></programlisting>
- </example>
- <para>
- Le troisième paramètre optionnel s'utilise comme avec la méthode
- <code>quote</code>. Il sert à spécifier un type <acronym>SQL</acronym>, les types numériques ne sont
- pas délimités.
- </para>
- <example id="zend.db.adapter.quoting.quote-into.example-2">
- <title>Utiliser quoteInto() avec un type SQL</title>
- <programlisting language="php"><![CDATA[
- $sql = $db->quoteInto("SELECT * FROM bugs WHERE bug_id = ?",
- '1234',
- 'INTEGER');
- echo $sql;
- // SELECT * FROM bugs WHERE reported_by = 1234
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.quoting.quote-identifier">
- <title>Utilisation de quoteIdentifier()</title>
- <para>
- Les valeurs ne sont pas les seuls données qui peuvent être dynamiques dans une
- requête <acronym>SQL</acronym>,et donc passées par des variables <acronym>PHP</acronym>. Les noms des tables, des
- colonnes, ou tout autre identifiant <acronym>SQL</acronym> spécial de la requête peuvent aussi être
- dynamiques. En général, les identifiant spéciaux d'une requête ont une syntaxe
- identique à celle des variables <acronym>PHP</acronym> : pas d'espaces dans les noms, certains
- autres caractères interdits, la ponctuation est interdite, etc... Aussi, les
- identifiants ne peuvent valoir certaines valeurs de mots réservés : une table
- ne peut s'appeler "FROM". Il se peut donc que vous ayez besoin aussi d'échapper des
- paramètres voués à être substitués à des identifiant dans la requête <acronym>SQL</acronym>, et non
- plus à des valeurs.
- </para>
- <para>
- Le langage <acronym>SQL</acronym> possède une caractéristique appelée <emphasis>identifiant
- délimités</emphasis>. Si vous entourez un identifiant <acronym>SQL</acronym> dans un type spécial de
- délimiteurs, alors vous pouvez écrire des requêtes qui auraient été invalides
- autrement. Ainsi, vous pouvez inclure des espaces, de la ponctuation ou des
- caractères internationaux dans vos identifiant, et aussi utiliser des mots
- réservés.
- </para>
- <para>
- La méthode <methodname>quoteIdentifier()</methodname> fonctionne comme
- <methodname>quote()</methodname>, mais elle utilise un caractère de délimitation spécial, en
- fonction du SGBD sous-jacent. Par exemple, le standard <acronym>SQL</acronym> spécifie des doubles
- quotes (<code>"</code>) et beaucoup de SGBDs utilisent ceci. MySQL utilise les
- apostrophes inverses (back-quotes) (<code>`</code>) par défaut. Les caractères
- spéciaux sont aussi échappés.
- </para>
- <example id="zend.db.adapter.quoting.quote-identifier.example">
- <title>Utiliser quoteIdentifier()</title>
- <programlisting language="php"><![CDATA[
- // nous possédons une table ayant un nom correspondant
- // à un mot reservé en SQL
- $tableName = $db->quoteIdentifier("order");
- $sql = "SELECT * FROM $tableName";
- echo $sql
- // SELECT * FROM "order"
- ]]></programlisting>
- </example>
- <para>
- Les identifiant <acronym>SQL</acronym> délimités sont sensibles à la casse. Vous devriez toujours
- utiliser la casse telle qu'elle est utilisée dans votre base de données (nom des
- tables, des colonnes ...).
- </para>
- <para>
- Dans les cas où le <acronym>SQL</acronym> est généré à l'intérieur des classes
- <classname>Zend_Db</classname>, alors les identifiant <acronym>SQL</acronym> seront automatiquement
- échappés. Vous pouvez changer ce comportement avec l'option
- <classname>Zend_Db::AUTO_QUOTE_IDENTIFIERS</classname>.Spécifiez la lors de
- l'instanciation de l'adaptateur. Voyez <xref
- linkend="zend.db.adapter.connecting.parameters.example2" />.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.adapter.transactions">
- <title>Gérer les transactions dans une base de données</title>
- <para>
- Les bases de données définissent les transactions comme étant des unités logiques
- de travail qui peuvent êtres validées ("commit") ou annulées ("rollback") en tant qu'une
- seule opération, même sur de multiples tables. Toutes les requêtes aux bases de données
- sont considérées comme faisant partie d'une transaction, même si le driver de base de
- données fait ceci implicitement. Ceci s'appelle le mode
- <emphasis>auto-commit</emphasis>, dans lequel le driver de base de données créer une
- transaction pour chaque requête exécutée et la valide. Par défaut toutes les classes
- <classname>Zend_Db_Adapter</classname> fonctionnent en mode auto-commit.
- </para>
- <para>
- Vous pouvez manuellement spécifier lorsque vous voulez démarrer une transaction.
- Vous contrôler ainsi combien de requêtes doivent y être exécutées, et valider ou annuler
- ce groupe de requêtes. Utilisez <methodname>beginTransaction()</methodname> pour démarrer une
- transaction. Toutes les requêtes suivantes seront alors exécutées dans cette transaction
- avant que vous ne l'annuliez, ou validiez.
- </para>
- <para>
- Pour terminer une transaction, utilisez les méthodes <methodname>commit()</methodname> ou
- <methodname>rollBack()</methodname>. <methodname>commit()</methodname> validera et appliquera les changements de
- la transaction au SGBD, ils deviendront alors visibles dans les autres
- transactions.
- </para>
- <para>
- <methodname>rollBack()</methodname> fait le contraire : elle annule les changements qu'ont
- générés les requêtes dans la transaction. L'annulation n'a aucun effet sur les
- changements qui ont été opérés par d'autres transactions parallèles.
- </para>
- <para>
- Après qu'une transaction soit terminées, <classname>Zend_Db_Adapter</classname>
- retourne en mode auto-commit jusqu'à un nouvel appel à
- <methodname>beginTransaction()</methodname>.
- </para>
- <example id="zend.db.adapter.transactions.example">
- <title>Manipuler les transactions pour assurer l'intégrité de la logique</title>
- <programlisting language="php"><![CDATA[
- // Démarre explicitement une transaction.
- $db->beginTransaction();
- try {
- // Essaye d'executer une ou plusieurs requêtes :
- $db->query(...);
- $db->query(...);
- $db->query(...);
- // Si toutes ont réussi, valide les changements en une seule passe.
- $db->commit();
- } catch (Exception $e) {
- // Si une des requête s'est mal déroulée, alors nous voulons
- // annuler les changements de toutes les requêtes faisant partie
- // de la transaction, même celles qui se sont bien déroulées.
- // Tous les changements sont annulés d'un seul coup.
- $db->rollBack();
- echo $e->getMessage();
- }
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.adapter.list-describe">
- <title>Lister et décrire les tables</title>
- <para>
- La méthode <methodname>listTables()</methodname> retourne un tableau de chaînes décrivant les
- tables de la base de données courante.
- </para>
- <para>
- La méthode <methodname>describeTable()</methodname> retourne un tableau associatif de
- métadonnées sur une table. Spécifiez en le nom en paramètre. Le second paramètre est
- optionnel et définit la base de données à utiliser, comme par exemple si aucune n'a été
- sélectionnée précédemment.
- </para>
- <para>
- Les clés de ce tableau représentent les noms des colonnes, les valeurs sont un
- tableau avec les clés suivantes :
- </para>
- <table cellpadding="5" frame="all" id="zend.db.adapter.list-describe.metadata">
- <title>Champs de métadonnées retournés par describeTable()</title>
- <tgroup align="left" cols="3" colsep="1" rowsep="1">
- <thead>
- <row>
- <entry>clé</entry>
- <entry>type</entry>
- <entry>description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><constant>SCHEMA_NAME</constant></entry>
- <entry>(chaîne)</entry>
- <entry>Nom de la base de données dans laquelle la table existe.</entry>
- </row>
- <row>
- <entry><constant>TABLE_NAME</constant></entry>
- <entry>(chaîne)</entry>
- <entry>Nom de la table dans laquelle la colonne existe.</entry>
- </row>
- <row>
- <entry><constant>COLUMN_NAME</constant></entry>
- <entry>(chaîne)</entry>
- <entry>Nom de la colonne.</entry>
- </row>
- <row>
- <entry><constant>COLUMN_POSITION</constant></entry>
- <entry>(entier)</entry>
- <entry>Position de la colonne dans la table.</entry>
- </row>
- <row>
- <entry><constant>DATA_TYPE</constant></entry>
- <entry>(chaîne)</entry>
- <entry>Nom du type de données tel que renvoyé par le <acronym>SGBD</acronym>.</entry>
- </row>
- <row>
- <entry><constant>DEFAULT</constant></entry>
- <entry>(chaîne)</entry>
- <entry>Valeur par défaut de la colonne, si une existe.</entry>
- </row>
- <row>
- <entry><constant>NULLABLE</constant></entry>
- <entry>(booléen)</entry>
- <entry><constant>TRUE</constant> si la colonne accepte la valeur <acronym>SQL</acronym>
- '<constant>NULL</constant>', <constant>FALSE</constant> sinon.</entry>
- </row>
- <row>
- <entry><constant>LENGTH</constant></entry>
- <entry>(entier)</entry>
- <entry>Longueur ou taille de la colonne telle que reportée par le
- <acronym>SGBD</acronym>.</entry>
- </row>
- <row>
- <entry><constant>SCALE</constant></entry>
- <entry>(entier)</entry>
- <entry>Échelle du type <acronym>SQL</acronym> <constant>NUMERIC</constant> ou <constant>DECIMAL</constant>.</entry>
- </row>
- <row>
- <entry><constant>PRECISION</constant></entry>
- <entry>(entier)</entry>
- <entry>Précision du type <acronym>SQL</acronym> <constant>NUMERIC</constant> ou <constant>DECIMAL</constant>.</entry>
- </row>
- <row>
- <entry><constant>UNSIGNED</constant></entry>
- <entry>(booléen)</entry>
- <entry><constant>TRUE</constant> si le type est un entier non signé, défini par
- <constant>UNSIGNED</constant>.</entry>
- </row>
- <row>
- <entry><constant>PRIMARY</constant></entry>
- <entry>(booléen)</entry>
- <entry><constant>TRUE</constant> si la colonne fait partie d'une clé
- primaire.</entry>
- </row>
- <row>
- <entry><constant>PRIMARY_POSITION</constant></entry>
- <entry>(entier)</entry>
- <entry>Position de la colonne dans la clé primaire.</entry>
- </row>
- <row>
- <entry><constant>IDENTITY</constant></entry>
- <entry>(booléen)</entry>
- <entry><constant>TRUE</constant> si la colonne utilise une valeur
- auto-générée.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <note>
- <title>A quoi correspond le champs de métadonnées "IDENTITY" en fonction du SGBD
- ?</title>
- <para>
- Le champs de métadonnées "IDENTITY" a été choisi en tant que terme idiomatique
- pour représenter une relation de substitution de clés. Ce champ est généralement
- connu par les valeurs suivantes :
- </para>
- <itemizedlist>
- <listitem>
- <para><constant>IDENTITY</constant> - DB2, MSSQL</para>
- </listitem>
- <listitem>
- <para><constant>AUTO_INCREMENT</constant> - MySQL</para>
- </listitem>
- <listitem>
- <para><constant>SERIAL</constant> - PostgreSQL</para>
- </listitem>
- <listitem>
- <para><constant>SEQUENCE</constant> - Oracle</para>
- </listitem>
- </itemizedlist>
- </note>
- <para>
- Si aucune table ne correspond à votre demande, alors <methodname>describeTable()</methodname>
- retourne un tableau vide.
- </para>
- </sect2>
- <sect2 id="zend.db.adapter.closing">
- <title>Fermer une connexion</title>
- <para>
- Normalement, il n'est pas nécessaire de fermer explicitement sa connexion. <acronym>PHP</acronym>
- nettoie automatiquement les ressources laissées ouvertes en fin de traitement. Les
- extensions des SGBDs ferment alors les connexions respectives pour les ressources
- détruites par <acronym>PHP</acronym>.
- </para>
- <para>
- Cependant, il se peut que vous trouviez utile de fermer la connexion manuellement.
- Vous pouvez alors utiliser la méthode de l'adaptateur <methodname>closeConnection()</methodname>
- afin de fermer explicitement la connexion vers le SGBD.
- </para>
- <para>
- A partir de la version 1.7.2, vous pouvez vérifier si vous êtes actuellement
- connecté au serveur SGBD grâce à la méthode <methodname>isConnected()</methodname>. Ceci correspond
- à une ressource de connexion qui a été initiée et qui n'est pas close. Cette fonction ne
- permet pas actuellement de tester la fermeture de la connexion au niveau du SGBD par
- exemple. Cette fonction est utilisée en interne pour fermer la connexion. Elle vous
- permet entre autres de fermer plusieurs fois une connexion sans erreurs. C'était déjà le
- cas avant la version 1.7.2 pour les adaptateurs de type <acronym>PDO</acronym> mais pas pour les
- autres.
- </para>
- <example id="zend.db.adapter.closing.example">
- <title>Fermer une connexion à un SGBD</title>
- <programlisting language="php"><![CDATA[
- $db->closeConnection();
- ]]></programlisting>
- </example>
- <note>
- <title>Zend_Db supporte-t-il les connexions persistantes ?</title>
- <para>
- Oui, la persistance est supportée grace à l'addition de l'option
- <code>persistent</code> quand il est à une valeur true dans la configuration
- (pas celle du driver) d'un adaptateur de <classname>Zend_Db</classname>.
- </para>
- <example id="zend.db.adapter.connecting.persistence.example">
- <title>Utiliser l'option de persistance avec l'adaptateur Oracle</title>
- <programlisting language="php"><![CDATA[
- $db = Zend_Db::factory('Oracle', array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'persistent' => true
- ));
- ]]></programlisting>
- </example>
- <para>
- Notez cependant qu'utiliser des connexions persistantes peut mener à un trop grand
- nombre de connexions en attente (idle), ce qui causera plus de problème que cela
- n'est sensé en résoudre.
- </para>
- <para>
- Les connexions aux bases de données possède un état. Dans cet état sont
- mémorisés des objets propres au SGBD. Par exemples des verrous, des variables
- utilisateur, des tables temporaires, des informations sur les requêtes récentes, les
- derniers enregistrements affectés, les dernières valeurs auto-générées, etc. Avec
- des connexions persistantes, il se peut que vous accédiez à des données ne faisant
- pas partie de votre session de travail avec le SGBD, ce qui peut s'avérer
- dangereux.
- </para>
- <para>
- Actuellement, seuls les adpatateurs Oracle, DB2 et <acronym>PDO</acronym> (si spécifiés par <acronym>PHP</acronym>)
- supportent la persistance avec Zend_Db.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.db.adapter.other-statements">
- <title>Exécuter des requêtes sur le driver directement</title>
- <para>
- Il peut y avoir des cas où vous souhaitez accéder directement à la connexion 'bas
- niveau', sous <classname>Zend_Db_Adapter</classname>.
- </para>
- <para>
- Par exemple, toute requête effectuée par <classname>Zend_Db</classname> est
- préparée, et exécutée. Cependant, certaines caractéristiques des bases de données ne
- sont pas compatibles avec les requêtes préparées. Par exemple, des requêtes du type
- CREATE ou ALTER ne peuvent pas être préparées sous MySQL. De même, les requêtes
- préparées ne bénéficient pas du <ulink
- url="http://dev.mysql.com/doc/refman/5.1/en/query-cache-how.html"> cache de
- requêtes</ulink>, avant MySQL 5.1.17.
- </para>
- <para>
- La plupart des extensions <acronym>PHP</acronym> pour les bases de données proposent une méthode
- permettant d'envoyer une requête directe, sans préparation. Par exemple, <acronym>PDO</acronym> propose
- pour ceci la méthode <methodname>exec()</methodname>. Vous pouvez récupérer l'objet de connexion
- "bas niveau" grâce à la méthode de l'adaptateur <methodname>getConnection()</methodname>.
- </para>
- <example id="zend.db.adapter.other-statements.example">
- <title>Envoyer une requête directe dans un adaptateur PDO</title>
- <programlisting language="php"><![CDATA[
- $result = $db->getConnection()->exec('DROP TABLE bugs');
- ]]></programlisting>
- </example>
- <para>
- De la même manière, vous pouvez accéder à toutes les propriétés ou méthodes de
- l'objet "bas niveau", utilisé par <classname>Zend_Db</classname>. Attention toutefois en
- utilisant ce procédé, vous risquez de rendre votre application dépendante du SGBD
- qu'elle utilise, en manipulant des méthodes propres à l'extension utilisée.
- </para>
- <para>
- Dans de futures versions de <classname>Zend_Db</classname>, il sera possible
- d'ajouter des méthodes pour des fonctionnalités communes aux extensions de bases de
- données de <acronym>PHP</acronym>. Ceci ne rompra pas la compatibilité.
- </para>
- </sect2>
- <sect2 id="zend.db.adapter.server-version">
- <title>Récupérer la version du serveur SGBD</title>
- <para>
- A partir de la version 1.7.2, vous pouvez récupérer la version du serveur avec le
- style de syntaxe <acronym>PHP</acronym> ce qui permet d'utiliser <methodname>version_compare()</methodname>. Si cette
- information n'est pas disponible, vous recevrez un <constant>NULL</constant>.
- </para>
- <example id="zend.db.adapter.server-version.example">
- <title>Vérifier la version du serveur avant de lancer une requête</title>
- <programlisting language="php"><![CDATA[
- $version = $db->getServerVersion();
- if (!is_null($version)) {
- if (version_compare($version, '5.0.0', '>=')) {
- // faire quelquechose
- } else {
- // faire autre chose
- }
- } else {
- // impossible de lire la version du serveur
- }
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.adapter.adapter-notes">
- <title>Notes sur des adaptateur spécifiques</title>
- <para>
- Cette section liste des différences entre les adaptateurs, que vous devriez
- considérer.
- </para>
- <sect3 id="zend.db.adapter.adapter-notes.ibm-db2">
- <title>IBM DB2</title>
- <itemizedlist>
- <listitem>
- <para>Passez le paramètre 'Db2' à la méthode <methodname>factory()</methodname>.</para>
- </listitem>
- <listitem>
- <para>Cet adaptateur utilise l'extension <acronym>PHP</acronym> ibm_db2.</para>
- </listitem>
- <listitem>
- <para>
- IBM DB2 supporte les séquences et les clés auto-incrémentées. Les
- arguments de <methodname>lastInsertId()</methodname> sont donc optionnels. Si vous ne
- passez pas de paramètres, alors l'adaptateur retourne la dernière valeur de
- clé auto- incrémentée. Sinon, il retourne la dernière valeur de la séquence
- passée en paramètre, en se référant à la convention
- '<emphasis>table</emphasis>_<emphasis>colonne</emphasis>_seq'.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.mysqli">
- <title>MySQLi</title>
- <itemizedlist>
- <listitem>
- <para>
- Passez le paramètre 'Mysqli' à la méthode
- <methodname>factory()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>Cet adaptateur utilise l'extension <acronym>PHP</acronym> mysqli.</para>
- </listitem>
- <listitem>
- <para>
- MySQL ne supporte pas les séquences, donc <methodname>lastInsertId()</methodname>
- ignore tout paramètre qu'on lui passe. Elle retourne toujours la valeur de
- la dernière clé auto-incrémentée. <methodname>lastSequenceId()</methodname>, elle,
- retourne toujours <constant>NULL</constant>.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.oracle">
- <title>Oracle</title>
- <itemizedlist>
- <listitem>
- <para>
- Passez le paramètre 'Oracle' à la méthode
- <methodname>factory()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>Cet adaptateur utilise l'extension <acronym>PHP</acronym> oci8.</para>
- </listitem>
- <listitem>
- <para>
- Oracle ne supporte pas les clé auto-incrémentées, donc vous devriez
- spécifier un paramètre de séquence à <methodname>lastInsertId()</methodname> ou
- <methodname>lastSequenceId()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>
- L'extension Oracle ne supporte pas les paramètres positionnés (?).
- Vous devez utiliser des paramètres nommés (:name).
- </para>
- </listitem>
- <listitem>
- <para>
- Actuellement l'option <classname>Zend_Db::CASE_FOLDING</classname>
- n'est pas supportée par l'adaptateur Oracle. Pour l'utiliser, vous devez
- utiliser l'adaptateur basé sur <acronym>PDO</acronym> et OCI.
- </para>
- </listitem>
- <listitem>
- <para>
- Par défaut les champs LOB ("Large Objet Binaire") sont retournés sous
- la forme d'objets OCI-Lob. Vous pouvez les récupérer sous forme de chaînes
- pour toutes les requêtes en utilisant l'option de driver
- <code>'lob_as_string'</code> ou pour une requête en particulier en utilisant
- la méthode <methodname>setLobAsString(boolean)</methodname> de l'adaptateur ou de
- l'objet statement.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.sqlsrv">
- <title>Microsoft SQL Server</title>
- <itemizedlist>
- <listitem>
- <para>
- Specify this Adapter to the <methodname>factory()</methodname> method with
- the name 'Sqlsrv'.
- </para>
- </listitem>
- <listitem>
- <para>
- This Adapter uses the <acronym>PHP</acronym> extension sqlsrv
- </para>
- </listitem>
- <listitem>
- <para>
- Only Microsoft <acronym>SQL</acronym> Server 2005 or greater is supported.
- </para>
- </listitem>
- <listitem>
- <para>
- Microsoft <acronym>SQL</acronym> Server does not support sequences, so
- <methodname>lastInsertId()</methodname> ignores primary key argument and
- returns the last value generated for an auto-increment key if a table name
- is specified or a last insert query returned id. The
- <methodname>lastSequenceId()</methodname> method returns
- <constant>NULL</constant>.
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Db_Adapter_Sqlsrv</classname> sets
- <constant>QUOTED_IDENTIFIER ON</constant> immediately after connecting to
- a <acronym>SQL</acronym> Server database. This makes the driver use the
- standard <acronym>SQL</acronym> identifier delimiter symbol
- (<emphasis>"</emphasis>) instead of the proprietary square-brackets
- syntax <acronym>SQL</acronym> Server uses for delimiting identifiers.
- </para>
- </listitem>
- <listitem>
- <para>
- You can specify <property>driver_options</property> as a key in the options
- array. The value can be a anything from here <ulink
- url="http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx">http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx</ulink>.
- </para>
- </listitem>
- <listitem>
- <para>
- You can use <methodname>setTransactionIsolationLevel()</methodname> to set
- isolation level for current connection. The value can be
- <constant>SQLSRV_TXN_READ_UNCOMMITTED</constant>,
- <constant>SQLSRV_TXN_READ_COMMITTED</constant>,
- <constant>SQLSRV_TXN_REPEATABLE_READ</constant>,
- <constant>SQLSRV_TXN_SNAPSHOT</constant> or
- <constant>SQLSRV_TXN_SERIALIZABLE</constant>.
- </para>
- </listitem>
- <listitem>
- <para>
- As of Zend Framework 1.9, the minimal supported build of the
- <acronym>PHP</acronym> <acronym>SQL</acronym> Server extension from
- Microsoft is 1.0.1924.0. and the <acronym>MSSQL</acronym> Server Native
- Client version 9.00.3042.00.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-ibm">
- <title>PDO pour IBM DB2 et Informix Dynamic Server (IDS)</title>
- <itemizedlist>
- <listitem>
- <para>
- Passez le paramètre 'Pdo_Ibm' à la méthode
- <methodname>factory()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>Cet adaptateur utilise les extensions <acronym>PHP</acronym> pdo et pdo_ibm.</para>
- </listitem>
- <listitem>
- <para>
- Vous devez possédez l'extension PDO_IBM en version 1.2.2 minimum. Si
- ce n'est pas le cas, vous devrez la mettre à jour via <acronym>PECL</acronym>.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-mssql">
- <title>PDO Microsoft SQL Server</title>
- <itemizedlist>
- <listitem>
- <para>
- Passez le paramètre 'Pdo_Mssql' à la méthode
- <methodname>factory()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>Cet adaptateur utilise les extensions <acronym>PHP</acronym> pdo et pdo_dblib.</para>
- </listitem>
- <listitem>
- <para>
- Microsoft <acronym>SQL</acronym> Server ne supporte pas les séquences, ainsi
- <methodname>lastInsertId()</methodname> ignore les paramètres qu'on lui passe et
- retourne toujours la valeur de la dernière clé auto-incrémentée.
- <methodname>lastSequenceId()</methodname> retourne toujours <constant>NULL</constant>.
- </para>
- </listitem>
- <listitem>
- <para>
- Si vous travaillez avec des chaînes Unicode avec un encodage autre que
- UCS-2 (comme UTF-8), vous devrez peut-être réaliser une conversion dans
- votre code d'application ou stocker les données dans un champs binaire.
- Reportez vous à la <ulink url="http://support.microsoft.com/kb/232580"> base
- de connaissance Microsoft</ulink> pour plus d'informations.
- </para>
- </listitem>
- <listitem>
- <para>
- Zend_Db_Adapter_Pdo_Mssql met <constant>QUOTED_IDENTIFIER</constant> à ON dès
- que la connexion a été effectuée. Le driver utilise donc le délimiteur
- d'identifiant <acronym>SQL</acronym> <code>"</code> au lieu de son délimiteur habituel.
- </para>
- </listitem>
- <listitem>
- <para>
- Vous pouvez spécifier la clé <code>pdoType</code> dans le tableau
- d'options de construction de l'adaptateur. La valeur peut être "mssql"
- (défaut), "dblib", "freetds", ou "sybase". Cette option affecte la syntaxe
- du préfixe DSN que l'adaptateur utilisera. "freetds" et "sybase" impliquent
- un préfixe "sybase:", qui est utilisé par les librairies <ulink
- url="http://www.freetds.org/">FreeTDS</ulink>.Voyez aussi <ulink
- url="http://www.php.net/manual/en/ref.pdo-dblib.connection.php">
- http://www.php.net/manual/en/ref.pdo-dblib.connection.php</ulink> pour plus
- d'informations sur les DSN pour ce driver.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-mysql">
- <title>PDO MySQL</title>
- <itemizedlist>
- <listitem>
- <para>
- Passez le paramètre 'Pdo_Mysql' à la méthode
- <methodname>factory()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>Cet adaptateur utilise les extensions <acronym>PHP</acronym> pdo et pdo_mysql.</para>
- </listitem>
- <listitem>
- <para>
- MySQL ne supporte pas les séquences, ainsi <methodname>lastInsertId()</methodname>
- ignore les paramètres qu'on lui passe et retourne toujours la valeur de la
- dernière clé auto-incrémentée. <methodname>lastSequenceId()</methodname> retourne
- toujours <constant>NULL</constant>.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-oci">
- <title>PDO Oracle</title>
- <itemizedlist>
- <listitem>
- <para>
- Passez le paramètre 'Pdo_Oci' à la méthode
- <methodname>factory()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>Cet adaptateur utilise les extensions <acronym>PHP</acronym> pdo et pdo_oci.</para>
- </listitem>
- <listitem>
- <para>
- Oracle ne supporte pas les clé auto-incrémentées, donc vous devriez
- spécifier un paramètre de séquence à <methodname>lastInsertId()</methodname> ou
- <methodname>lastSequenceId()</methodname>.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-pgsql">
- <title>PDO PostgreSQL</title>
- <itemizedlist>
- <listitem>
- <para>
- Passez le paramètre 'PDO_Pgsql' à la méthode
- <methodname>factory()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>Cet adaptateur utilise les extensions <acronym>PHP</acronym> pdo et pdo_pgsql.</para>
- </listitem>
- <listitem>
- <para>
- PostgreSQL supporte les séquences et les clés auto-incrémentées. Les
- arguments de <methodname>lastInsertId()</methodname> sont donc optionnels. Si vous ne
- passez pas de paramètres, alors l'adaptateur retourne la dernière valeur de
- clé auto- incrémentée. Sinon, il retourne la dernière valeur de la séquence
- passée en paramètre, en se référant à la convention
- '<emphasis>table</emphasis>_<emphasis>colonne</emphasis>_seq'.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-sqlite">
- <title>PDO SQLite</title>
- <itemizedlist>
- <listitem>
- <para>
- Passez le paramètre 'PDO_Sqlite' à la méthode
- <methodname>factory()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>Cet adaptateur utilise les extensions <acronym>PHP</acronym> pdo et pdo_sqlite.</para>
- </listitem>
- <listitem>
- <para>
- SQLite ne supporte pas les séquences, ainsi
- <methodname>lastInsertId()</methodname> ignore les paramètres qu'on lui passe et
- retourne toujours la valeur de la dernière clé auto-incrémentée.
- <methodname>lastSequenceId()</methodname> retourne toujours <constant>NULL</constant>.
- </para>
- </listitem>
- <listitem>
- <para>
- Pour vous connecter à une base de données SQLite2, spécifiez le
- paramètre <code>'sqlite2'=>true</code> dans le tableau d'options passé à
- l'adaptateur, lors de la création de l'instance de Pdo_Sqlite
- Adapter.
- </para>
- </listitem>
- <listitem>
- <para>
- Pour vous connecter à une base de données SQLite en mémoire, spécifiez
- le paramètre <code>'dsnprefix'=>':memory:'</code> dans le tableau
- d'options passé à l'adaptateur, lors de la création de l'instance de
- Pdo_Sqlite Adapter.
- </para>
- </listitem>
- <listitem>
- <para>
- Les anciennes versions du driver SQLite pour <acronym>PHP</acronym> ne semblent pas
- supporter les commandes PRAGMA nécessaires pour s'assurer que les colonnes
- ayant un nom court soient utilisées dans les résultats. Si vous avez des
- problèmes, tels que vos enregistrements sont retournés avec une forme
- "nomtable.nomcolonne" lors de vos jointures, vous devriez alors mettre à
- jour votre version de <acronym>PHP</acronym>.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.firebird">
- <title>Firebird (Interbase)</title>
- <itemizedlist>
- <listitem>
- <para>Cet adaptateur utilise l'extension <acronym>PHP</acronym> php_interbase.</para>
- </listitem>
- <listitem>
- <para>
- Firebird (Interbase) ne supporte pas les clé auto-incrémentées, donc
- vous devez spécifier un paramètre de séquence à <methodname>lastInsertId()</methodname>
- ou <methodname>lastSequenceId()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>
- Pour l'instant l'option <classname>Zend_Db::CASE_FOLDING</classname>
- n'est pas supportée par l'adaptateur Firebird (Interbase). Tout identificateur
- non échappé sera automatiquement retourné en majuscules.
- </para>
- </listitem>
- <listitem>
- <para>Le nom de l'adaptateur est ZendX_Db_Adapter_Firebird.</para>
- <para>
- Rappelez vous qu'il est nécessaire d'utiliser le paramètre
- 'adapterNamespace' avec la valeur ZendX_Db_Adapter.
- </para>
- <para>
- Nous recommandons de mettre à jour gds32.dll (ou l'équivalent linux)
- embarqué avec <acronym>PHP</acronym>, à la même version que celle du serveur. Pour Firebird
- l'équivalent à <filename>gds32.dll</filename> est
- <filename>fbclient.dll</filename>.
- </para>
- <para>
- Par défaut tous les identifiants (nomde tables, de cahmps) sont retournés en
- majuscules.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- </sect2>
- </sect1>
|