| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- 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>
- MariaDB, utilisant l'extension <acronym>PHP</acronym> <ulink
- url="http://www.php.net/pdo-mysql">pdo_mysql</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>
- MariaDB, utilisant l'extension <acronym>PHP</acronym> <ulink
- url="http://www.php.net/mysqli">mysqli</ulink>.
- </para>
- </listitem>
- <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 MariaDB, 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 / MariaDB</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 et MariaDB ne supportent 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 et MariaDB ne supportent 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>
|