1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- EN-Revision: 20115 -->
4 <sect1 id="zend.db.adapter">
6 <title>Zend_Db_Adapter</title>
9 <classname>Zend_Db</classname> y sus clases relacionadas proporcionan
10 una interfaz simple de base de datos <acronym>SQL</acronym> para Zend
11 Framework. El <classname>Zend_Db_Adapter</classname> es la clase base
12 que se utiliza para conectar su aplicación <acronym>PHP</acronym> A una
13 base de datos ( <acronym>RDBMS</acronym> ). Existen diferentes clases
14 Adapters(Adaptador) para cada tipo de base de datos (
15 <acronym>RDBMS</acronym> ). </para>
17 <para> Las clases Adapters de <classname>Zend_Db</classname> crean un puente
18 entre las extensiones de base de datos de <acronym>PHP</acronym> hacia
19 una interfaz común, para ayudarle a escribir aplicaciones
20 <acronym>PHP</acronym> una sola vez y poder desplegar múltiples
21 tipos de base de datos ( <acronym>RDBMS</acronym> ) con muy poco
24 <para> La Interfaz de la clase adaptador (adapter) es similar a la intefaz
25 de la extensión <ulink url="http://www.php.net/pdo">PHP Data
26 Objects</ulink> . <classname>Zend_Db</classname> proporciona clases
27 Adaptadoras para los drivers <acronym>PDO</acronym> de los siguientes
28 tipos de <acronym>RDBMS</acronym> : </para>
32 <para> IBM DB2 e Informix Dynamic Server (IDS), usando la extensión
33 <acronym>PHP</acronym>
34 <ulink url="http://www.php.net/pdo-ibm">pdo_ibm</ulink>
38 <para> MySQL, usando la extensión <acronym>PHP</acronym>
39 <ulink url="http://www.php.net/pdo-mysql"> pdo_mysql </ulink>
43 <para> Microsoft SQL Server, usando la extensión
44 <acronym>PHP</acronym>
45 <ulink url="http://www.php.net/pdo-mssql"> pdo_mssql </ulink>
49 <para> Oracle, usando la extensión <acronym>PHP</acronym>
50 <ulink url="http://www.php.net/pdo-oci">pdo_oci</ulink>
54 <para> PostgreSQL, usando la extensión <acronym>PHP</acronym>
55 <ulink url="http://www.php.net/pdo-pgsql"> pdo_pgsql </ulink>
59 <para> SQLite, usando la extensión <acronym>PHP</acronym>
60 <ulink url="http://www.php.net/pdo-sqlite"> pdo_sqlite </ulink>
66 <para> Ademas, <classname>Zend_Db</classname> proporciona clases Adaptadoras
67 que utilizan las extensiones de base de datos de <acronym>PHP</acronym>
68 de los siguientes tipos: </para>
72 <para> MySQL, usando la extensión <acronym>PHP</acronym>
73 <ulink url="http://www.php.net/mysqli">mysqli</ulink>
77 <para> Oracle, usando la extensión <acronym>PHP</acronym>
78 <ulink url="http://www.php.net/oci8">oci8</ulink>
82 <para> IBM DB2, usando la extensión <acronym>PHP</acronym>
83 <ulink url="http://www.php.net/ibm_db2">ibm_db2</ulink>
87 <para> Firebird/Interbase, usando la extensión
88 <acronym>PHP</acronym>
89 <ulink url="http://www.php.net/ibase"> php_interbase </ulink>
95 <para> Cada Zend_Db_Adaptador utiliza una extensión
96 <acronym>PHP</acronym> . Se debe de tener habilitada la
97 respectiva extensión en su entorno <acronym>PHP</acronym> para
98 utilizar un <classname>Zend_Db_Adapter</classname> . Por ejemplo, si
99 se utiliza una clase <classname>Zend_Db_Adapter</classname> basada
100 en <acronym>PDO</acronym> , tiene que habilitar tanto la extensión
101 <acronym>PDO</acronym> como el driver <acronym>PDO</acronym> del
102 tipo de base de datos que se utiliza. </para>
105 <sect2 id="zend.db.adapter.connecting">
107 <title> Conexión a una Base de Datos utilizando un Adaptador </title>
109 <para> Esta sección describe cómo crear una instancia de un Adaptador de
110 base de datos. Esto corresponde a establecer una conexión a un
111 servidor de Base de Datos ( <acronym>RDBMS</acronym> ) desde su
112 aplicación <acronym>PHP</acronym> . </para>
114 <sect3 id="zend.db.adapter.connecting.constructor">
116 <title>Usando un Constructor de Zend_Db Adapter</title>
118 <para> Se puede crear una instancia de un Adaptador utilizando su
119 constructor. Un constructor de adaptador toma un argumento, que
120 es un conjunto de parámetros utilizados para declarar la
123 <example id="zend.db.adapter.connecting.constructor.example">
124 <title>Usando el Constructor de un Adaptador</title>
125 <programlisting language="php"><![CDATA[
126 $db = new Zend_Db_Adapter_Pdo_Mysql(array(
127 'host' => '127.0.0.1',
128 'username' => 'webuser',
129 'password' => 'xxxxxxxx',
137 <sect3 id="zend.db.adapter.connecting.factory">
139 <title>Usando el Zend_Db Factory</title>
141 <para> Como alternativa a la utilización directa del constructor de
142 un adaptador, se puede crear una instancia del adaptador que use
143 el método estático <methodname>Zend_Db::factory()</methodname> .
144 Este método carga dinámicamente el archivo de clase Adaptador
145 bajo demanda, usando <link linkend="zend.loader.load.class">
146 Zend_Loader::loadClass() </link> . </para>
148 <para> El primer argumento es una cadena que nombra al nombre base
149 de la clase Adaptador. Por ejemplo, la cadena '
150 <classname>Pdo_Mysql</classname> ' corresponde a la clase
151 <classname>Zend_Db_Adapter_Pdo_Mysql</classname> . El
152 segundo argumento es el mismo array de parámetros que hubiera
153 enviado al constructor del adaptador. </para>
155 <example id="zend.db.adapter.connecting.factory.example">
156 <title>Usando el Adaptador del método factory</title>
157 <programlisting language="php"><![CDATA[
158 // No necesitamos la siguiente declaración, porque
159 // el archivo Zend_Db_Adapter_Pdo_Mysql será cargado para nosotros por el método
160 // factory de Zend_Db.
162 // require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
164 // carga automaticamente la clase Zend_Db_Adapter_Pdo_Mysql
165 // y crea una instancia de la misma
166 $db = Zend_Db::factory('Pdo_Mysql', array(
167 'host' => '127.0.0.1',
168 'username' => 'webuser',
169 'password' => 'xxxxxxxx',
175 <para> Si crea su propia clase que extiende a
176 <classname>Zend_Db_Adapter_Abstract</classname> , pero no
177 nombra su clase con el prefijo de paquete "
178 <classname>Zend_Db_Adapter</classname> ", se puede utilizar
179 el método <methodname>factory()</methodname> para cargar su
180 adaptador si se especifica la parte principal de la clase del
181 adaptador con la clave "adapterNamespace" en el conjunto de
184 <example id="zend.db.adapter.connecting.factory.example2">
185 <title> Usando el método factory para una clase Adaptador
186 personalizada </title>
187 <programlisting language="php"><![CDATA[
188 // No tenemos que cargar el archivo de clase Adaptador
189 // porque será cargado para nosotros por el método factory de Zend_Db.
191 // Automáticamente carga la clase MyProject_Db_Adapter_Pdo_Mysql
192 // y crea una instancia de ella.
194 $db = Zend_Db::factory('Pdo_Mysql', array(
195 'host' => '127.0.0.1',
196 'username' => 'webuser',
197 'password' => 'xxxxxxxx',
199 'adapterNamespace' => 'MyProject_Db_Adapter'
206 <sect3 id="zend.db.adapter.connecting.factory-config">
208 <title>Uso de Zend_Config con Zend_Db Factory</title>
210 <para> Opcionalmente, se puede especificar cualquier argumento del
211 método <methodname>factory()</methodname> como un objeto de tipo
212 <link linkend="zend.config">Zend_Config</link> . </para>
214 <para> Si el primer argumento es un objeto de configuración, se
215 espera que contenga una propiedad llamada
216 <property>adapter</property> , conteniendo la cadena que da
217 nombre al nombre base de la clase de adaptador. Opcionalmente,
218 el objeto puede contener una propiedad llamada
219 <property>params</property> , con subpropiedades
220 correspondientes a nombres de parámetros del adaptador. Esto es
221 usado sólo si el segundo argumento del método
222 <methodname>factory()</methodname> se ha omitido. </para>
224 <example id="zend.db.adapter.connecting.factory.example1">
225 <title> Uso del método factory del Adaptador con un objeto
227 <para> En el siguiente ejemplo, un objeto
228 <classname>Zend_Config</classname> es creado usando un
229 array. También puedes cargar los datos de un archivo
230 externo, por ejemplo con <link
231 linkend="zend.config.adapters.ini"> Zend_Config_Ini
232 </link> o <link linkend="zend.config.adapters.xml">
233 Zend_Config_Xml </link> . </para>
234 <programlisting language="php"><![CDATA[
235 $config = new Zend_Config(
238 'adapter' => 'Mysqli',
241 'username' => 'webuser',
242 'password' => 'secret',
248 $db = Zend_Db::factory($config->database);
252 <para> El segundo argumento del método
253 <methodname>factory()</methodname> puede ser un array
254 asociativo con entradas correspondientes a los parámetros del
255 adaptador. Este argumento es opcional. Si el primer argumento es
256 de tipo <classname>Zend_Config</classname> , se asume que tiene
257 todos los parametros, y el segundo argumento es ignorado. </para>
261 <sect3 id="zend.db.adapter.connecting.parameters">
263 <title>Parámetros del Adaptador</title>
265 <para> El siguiente listado explica parámetros comunes reconocidos
266 por Adaptador de clases <classname>Zend_Db</classname> . </para>
271 <emphasis>host</emphasis> : una string conteniendo un
272 nombre de host o dirección IP del servidor de base de
273 datos. Si la base de datos está corriendo sobre el mismo
274 host que la aplicación <acronym>PHP</acronym> , usted
275 puede utilizar 'localhost' o '127.0.0.1'. </para>
279 <emphasis>username</emphasis> : identificador de cuenta
280 para autenticar una conexión al servidor
281 <acronym>RDBMS</acronym> . </para>
285 <emphasis>password</emphasis> : la contraseña de la
286 cuenta para la autenticación de credenciales de conexión
287 con el servidor <acronym>RDBMS</acronym>
292 <emphasis>dbname</emphasis> : nombre de la base de datos
293 en el servidor <acronym>RDBMS</acronym> . </para>
297 <emphasis>port</emphasis> : algunos servidores
298 <acronym>RDBMS</acronym> pueden aceptar conexiones
299 de red sobre un número de puerto específico. El
300 parámetro del puerto le permite especificar el puerto al
301 que su aplicación <acronym>PHP</acronym> se conecta,
302 para que concuerde el puerto configurado en el servidor
303 <acronym>RDBMS</acronym> . </para>
307 <emphasis>charset</emphasis> : specify the charset used
308 for the connection. </para>
313 <emphasis>options</emphasis> : : este parámetro es un
314 array asociativo de opciones que son genéricas a todas
315 las clases <classname>Zend_Db_Adapter</classname> .
320 <emphasis> driver_options </emphasis> : este parámetro
321 es un array asociativo de opciones adicionales para una
322 extensión de base de datos dada. un uso típico de este
323 parámetro es establecer atributos de un driver
324 <acronym>PDO</acronym> . </para>
328 <emphasis> adapterNamespace </emphasis> : nombre de la
329 parte inicial del nombre de las clase para el adaptador,
330 en lugar de ' <classname>Zend_Db_Adapter</classname> '.
331 Utilice esto si usted necesita usar el método
332 <methodname>factory()</methodname> para cargar un
333 adaptador de clase de base de datos que no sea de Zend.
338 <example id="zend.db.adapter.connecting.parameters.example1">
339 <title> Passing the case-folding option to the factory </title>
340 <para> Usted puede pasar esta opción específica por la constante
341 <constant>Zend_Db::CASE_FOLDING</constant> . Este
342 corresponde al atributo <constant>ATTR_CASE</constant> en
343 los drivers de base de datos <acronym>PDO</acronym> e IBM
344 DB2, ajustando la sensibilidad de las claves tipo cadena en
345 los resultados de consultas. La opción toma los valores
346 <constant>Zend_Db::CASE_NATURAL</constant> (el
347 predeterminado), <constant>Zend_Db::CASE_UPPER</constant> ,
348 y <constant>Zend_Db::CASE_LOWER</constant> . </para>
349 <programlisting language="php"><![CDATA[
351 Zend_Db::CASE_FOLDING => Zend_Db::CASE_UPPER
355 'host' => '127.0.0.1',
356 'username' => 'webuser',
357 'password' => 'xxxxxxxx',
359 'options' => $options
362 $db = Zend_Db::factory('Db2', $params);
366 <example id="zend.db.adapter.connecting.parameters.example2">
367 <title> Passing the auto-quoting option to the factory </title>
368 <para> Usted puede especificar esta opción por la constante
369 <constant>Zend_Db::AUTO_QUOTE_IDENTIFIERS</constant> .
370 Si el valor es <constant>TRUE</constant> (el
371 predeterminado), los identificadores como nombres de tabla,
372 nombres de columna, e incluso los alias son delimitados en
373 la sintaxis <acronym>SQL</acronym> generada por el Adatador
374 del objeto. Esto hace que sea sencillo utilizar
375 identificadores que contengan palabras reservadas de
376 <acronym>SQL</acronym> , o caracteres especiales. Si el
377 valor es <constant>FALSE</constant> , los identificadores no
378 son delimitados automáticamente. Si usted necesita delimitar
379 identificadores, debe hacer usted mismo utilizando el método
380 <methodname>quoteIdentifier()</methodname> . </para>
381 <programlisting language="php"><![CDATA[
383 Zend_Db::AUTO_QUOTE_IDENTIFIERS => false
387 'host' => '127.0.0.1',
388 'username' => 'webuser',
389 'password' => 'xxxxxxxx',
391 'options' => $options
394 $db = Zend_Db::factory('Pdo_Mysql', $params);
398 <example id="zend.db.adapter.connecting.parameters.example3">
399 <title>Passing PDO driver options to the factory</title>
400 <programlisting language="php"><![CDATA[
402 PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
406 'host' => '127.0.0.1',
407 'username' => 'webuser',
408 'password' => 'xxxxxxxx',
410 'driver_options' => $pdoParams
413 $db = Zend_Db::factory('Pdo_Mysql', $params);
415 echo $db->getConnection()
416 ->getAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY);
420 <example id="zend.db.adapter.connecting.parameters.example4">
421 <title>Passing Serialization Options to the Factory</title>
422 <programlisting language="php"><![CDATA[
424 Zend_Db::ALLOW_SERIALIZATION => false
428 'host' => '127.0.0.1',
429 'username' => 'webuser',
430 'password' => 'xxxxxxxx',
432 'options' => $options
435 $db = Zend_Db::factory('Pdo_Mysql', $params);
441 <sect3 id="zend.db.adapter.connecting.getconnection">
442 <title>Managing Lazy Connections</title>
444 <para> Creating an instance of an Adapter class does not immediately
445 connect to the <acronym>RDBMS</acronym> server. The Adapter
446 saves the connection parameters, and makes the actual connection
447 on demand, the first time you need to execute a query. This
448 ensures that creating an Adapter object is quick and
449 inexpensive. You can create an instance of an Adapter even if
450 you are not certain that you need to run any database queries
451 during the current request your application is serving. </para>
453 <para> If you need to force the Adapter to connect to the
454 <acronym>RDBMS</acronym> , use the
455 <methodname>getConnection()</methodname> method. This method
456 returns an object for the connection as represented by the
457 respective <acronym>PHP</acronym> database extension. For
458 example, if you use any of the Adapter classes for
459 <acronym>PDO</acronym> drivers, then
460 <methodname>getConnection()</methodname> returns the
461 <acronym>PDO</acronym> object, after initiating it as a live
462 connection to the specific database. </para>
464 <para> It can be useful to force the connection if you want to catch
465 any exceptions it throws as a result of invalid account
466 credentials, or other failure to connect to the
467 <acronym>RDBMS</acronym> server. These exceptions are not
468 thrown until the connection is made, so it can help simplify
469 your application code if you handle the exceptions in one place,
470 instead of at the time of the first query against the database. </para>
472 <para> Additionally, an adapter can get serialized to store it, for
473 example, in a session variable. This can be very useful not only
474 for the adapter itself, but for other objects that aggregate it,
475 like a <classname>Zend_Db_Select</classname> object. By default,
476 adapters are allowed to be serialized, if you don't want it, you
477 should consider passing the
478 <constant>Zend_Db::ALLOW_SERIALIZATION</constant> option
479 with <constant>FALSE</constant> , see the example above. To
480 respect lazy connections principle, the adapter won't reconnect
481 itself after being unserialized. You must then call
482 <methodname>getConnection()</methodname> yourself. You can
483 make the adapter auto-reconnect by passing the
484 <constant>Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE</constant>
485 with <constant>TRUE</constant> as an adapter option. </para>
487 <example id="zend.db.adapter.connecting.getconnection.example">
488 <title>Handling connection exceptions</title>
489 <programlisting language="php"><![CDATA[
491 $db = Zend_Db::factory('Pdo_Mysql', $parameters);
492 $db->getConnection();
493 } catch (Zend_Db_Adapter_Exception $e) {
494 // perhaps a failed login credential, or perhaps the RDBMS is not running
495 } catch (Zend_Exception $e) {
496 // perhaps factory() failed to load the specified Adapter class
505 <sect2 id="zend.db.adapter.example-database">
507 <title>La base de datos de ejemplo</title>
509 <para> En la documentación de las clases <classname>Zend_Db</classname>
510 , usamos un conjunto sencillo de tablas para ilustrar el uso de las
511 clases y métodos. Estas tablas de ejemplo permiten almacenar
512 información para localizar bugs en un proyecto de desarrollo de
513 software. La base de datos contiene cuatro tablas: </para>
518 <emphasis>accounts</emphasis> almacena información sobre
519 cada usuario que hace el seguimiento de bugs. </para>
523 <emphasis>products</emphasis> almacena información sobre
524 cada producto para el que pueden registrarse bugs. </para>
528 <emphasis>bugs</emphasis> almacena información sobre bugs,
529 incluyendo el estado actual del bug, la persona que informó
530 sobre el bug, la persona que está asignada para corregir el
531 bug, y la persona que está asignada para verificar la
536 <emphasis>bugs_products</emphasis> stores a relationship
537 between bugs and products. This implements a many-to-many
538 relationship, because a given bug may be relevant to
539 multiple products, and of course a given product can have
540 multiple bugs. </para>
544 <para> La siguiente definición de datos <acronym>SQL</acronym> en
545 lenguaje pseudocódigo describe las tablas de esta base de datos de
546 ejemplo. Estas tablas de ejemplo son usadas ampliamente por los
547 tests unitarios automatizados de <classname>Zend_Db</classname> . </para>
549 <programlisting language="sql"><![CDATA[
550 CREATE TABLE accounts (
551 account_name VARCHAR(100) NOT NULL PRIMARY KEY
554 CREATE TABLE products (
555 product_id INTEGER NOT NULL PRIMARY KEY,
556 product_name VARCHAR(100)
560 bug_id INTEGER NOT NULL PRIMARY KEY,
561 bug_description VARCHAR(100),
562 bug_status VARCHAR(20),
563 reported_by VARCHAR(100) REFERENCES accounts(account_name),
564 assigned_to VARCHAR(100) REFERENCES accounts(account_name),
565 verified_by VARCHAR(100) REFERENCES accounts(account_name)
568 CREATE TABLE bugs_products (
569 bug_id INTEGER NOT NULL REFERENCES bugs,
570 product_id INTEGER NOT NULL REFERENCES products,
571 PRIMARY KEY (bug_id, product_id)
575 <para> Also notice that the <code>bugs</code> table contains multiple
576 foreign key references to the <code>accounts</code> table. Each of
577 these foreign keys may reference a different row in the
578 <code>accounts</code> table for a given bug. </para>
580 <para> The diagram below illustrates the physical data model of the
581 example database. </para>
584 <inlinegraphic width="387" scale="100" align="center"
586 fileref="figures/zend.db.adapter.example-database.png"
592 <sect2 id="zend.db.adapter.select">
594 <title>Reading Query Results</title>
596 <para> This section describes methods of the Adapter class with which
597 you can run SELECT queries and retrieve the query results. </para>
599 <sect3 id="zend.db.adapter.select.fetchall">
601 <title>Fetching a Complete Result Set</title>
603 <para> You can run a <acronym>SQL</acronym> SELECT query and
604 retrieve its results in one step using the
605 <methodname>fetchAll()</methodname> method. </para>
607 <para> The first argument to this method is a string containing a
608 SELECT statement. Alternatively, the first argument can be an
609 object of class <link linkend="zend.db.select"
610 >Zend_Db_Select</link> . The Adapter automatically converts
611 this object to a string representation of the SELECT statement. </para>
613 <para> The second argument to <methodname>fetchAll()</methodname> is
614 an array of values to substitute for parameter placeholders in
615 the <acronym>SQL</acronym> statement. </para>
617 <example id="zend.db.adapter.select.fetchall.example">
618 <title>Using fetchAll()</title>
619 <programlisting language="php"><![CDATA[
620 $sql = 'SELECT * FROM bugs WHERE bug_id = ?';
622 $result = $db->fetchAll($sql, 2);
628 <sect3 id="zend.db.adapter.select.fetch-mode">
630 <title>Changing the Fetch Mode</title>
632 <para> By default, <methodname>fetchAll()</methodname> returns an
633 array of rows, each of which is an associative array. The keys
634 of the associative array are the columns or column aliases named
635 in the select query. </para>
637 <para> You can specify a different style of fetching results using
638 the <methodname>setFetchMode()</methodname> method. The modes
639 supported are identified by constants: </para>
644 <constant>Zend_Db::FETCH_ASSOC</constant> : return data
645 in an array of associative arrays. The array keys are
646 column names, as strings. This is the default fetch mode
647 for <classname>Zend_Db_Adapter</classname> classes. </para>
648 <para> Note that if your select-list contains more than one
649 column with the same name, for example if they are from
650 two different tables in a JOIN, there can be only one
651 entry in the associative array for a given name. If you
652 use the FETCH_ASSOC mode, you should specify column
653 aliases in your SELECT query to ensure that the names
654 result in unique array keys. </para>
655 <para> By default, these strings are returned as they are
656 returned by the database driver. This is typically the
657 spelling of the column in the <acronym>RDBMS</acronym>
658 server. You can specify the case for these strings,
659 using the <constant>Zend_Db::CASE_FOLDING</constant>
660 option. Specify this when instantiating the Adapter. See
662 linkend="zend.db.adapter.connecting.parameters.example1"
667 <constant>Zend_Db::FETCH_NUM</constant> : return data in
668 an array of arrays. The arrays are indexed by integers,
669 corresponding to the position of the respective field in
670 the select-list of the query. </para>
674 <constant>Zend_Db::FETCH_BOTH</constant> : return data
675 in an array of arrays. The array keys are both strings
676 as used in the FETCH_ASSOC mode, and integers as used in
677 the FETCH_NUM mode. Note that the number of elements in
678 the array is double that which would be in the array if
679 you used either FETCH_ASSOC or FETCH_NUM. </para>
683 <constant>Zend_Db::FETCH_COLUMN</constant> : return data
684 in an array of values. The value in each array is the
685 value returned by one column of the result set. By
686 default, this is the first column, indexed by 0. </para>
690 <constant>Zend_Db::FETCH_OBJ</constant> : return data in
691 an array of objects. The default class is the
692 <acronym>PHP</acronym> built-in class stdClass.
693 Columns of the result set are available as public
694 properties of the object. </para>
698 <example id="zend.db.adapter.select.fetch-mode.example">
699 <title>Using setFetchMode()</title>
700 <programlisting language="php"><![CDATA[
701 $db->setFetchMode(Zend_Db::FETCH_OBJ);
703 $result = $db->fetchAll('SELECT * FROM bugs WHERE bug_id = ?', 2);
705 // $result is an array of objects
706 echo $result[0]->bug_description;
712 <sect3 id="zend.db.adapter.select.fetchassoc">
714 <title>Fetching a Result Set as an Associative Array</title>
716 <para> The <methodname>fetchAssoc()</methodname> method returns data
717 in an array of associative arrays, regardless of what value you
718 have set for the fetch mode. </para>
720 <example id="zend.db.adapter.select.fetchassoc.example">
721 <title>Using fetchAssoc()</title>
722 <programlisting language="php"><![CDATA[
723 $db->setFetchMode(Zend_Db::FETCH_OBJ);
725 $result = $db->fetchAssoc('SELECT * FROM bugs WHERE bug_id = ?', 2);
727 // $result is an array of associative arrays, in spite of the fetch mode
728 echo $result[0]['bug_description'];
734 <sect3 id="zend.db.adapter.select.fetchcol">
736 <title>Fetching a Single Column from a Result Set</title>
738 <para> The <methodname>fetchCol()</methodname> method returns data
739 in an array of values, regardless of the value you have set for
740 the fetch mode. This only returns the first column returned by
741 the query. Any other columns returned by the query are
742 discarded. If you need to return a column other than the first,
743 see <xref linkend="zend.db.statement.fetching.fetchcolumn"/> . </para>
745 <example id="zend.db.adapter.select.fetchcol.example">
746 <title>Using fetchCol()</title>
747 <programlisting language="php"><![CDATA[
748 $db->setFetchMode(Zend_Db::FETCH_OBJ);
750 $result = $db->fetchCol(
751 'SELECT bug_description, bug_id FROM bugs WHERE bug_id = ?', 2);
753 // contains bug_description; bug_id is not returned
760 <sect3 id="zend.db.adapter.select.fetchpairs">
762 <title>Fetching Key-Value Pairs from a Result Set</title>
764 <para> The <methodname>fetchPairs()</methodname> method returns data
765 in an array of key-value pairs, as an associative array with a
766 single entry per row. The key of this associative array is taken
767 from the first column returned by the SELECT query. The value is
768 taken from the second column returned by the SELECT query. Any
769 other columns returned by the query are discarded. </para>
771 <para> You should design the SELECT query so that the first column
772 returned has unique values. If there are duplicates values in
773 the first column, entries in the associative array will be
776 <example id="zend.db.adapter.select.fetchpairs.example">
777 <title>Using fetchPairs()</title>
778 <programlisting language="php"><![CDATA[
779 $db->setFetchMode(Zend_Db::FETCH_OBJ);
781 $result = $db->fetchPairs('SELECT bug_id, bug_status FROM bugs');
788 <sect3 id="zend.db.adapter.select.fetchrow">
790 <title>Fetching a Single Row from a Result Set</title>
792 <para> The <methodname>fetchRow()</methodname> method returns data
793 using the current fetch mode, but it returns only the first row
794 fetched from the result set. </para>
796 <example id="zend.db.adapter.select.fetchrow.example">
797 <title>Using fetchRow()</title>
798 <programlisting language="php"><![CDATA[
799 $db->setFetchMode(Zend_Db::FETCH_OBJ);
801 $result = $db->fetchRow('SELECT * FROM bugs WHERE bug_id = 2');
803 // note that $result is a single object, not an array of objects
804 echo $result->bug_description;
809 <sect3 id="zend.db.adapter.select.fetchone">
811 <title>Fetching a Single Scalar from a Result Set</title>
813 <para> The <methodname>fetchOne()</methodname> method is like a
814 combination of <methodname>fetchRow()</methodname> with
815 <methodname>fetchCol()</methodname> , in that it returns
816 data only for the first row fetched from the result set, and it
817 returns only the value of the first column in that row.
818 Therefore it returns only a single scalar value, not an array or
821 <example id="zend.db.adapter.select.fetchone.example">
822 <title>Using fetchOne()</title>
823 <programlisting language="php"><![CDATA[
824 $result = $db->fetchOne('SELECT bug_status FROM bugs WHERE bug_id = 2');
826 // this is a single string value
834 <sect2 id="zend.db.adapter.write">
836 <title>Writing Changes to the Database</title>
838 <para> You can use the Adapter class to write new data or change
839 existing data in your database. This section describes methods to do
840 these operations. </para>
842 <sect3 id="zend.db.adapter.write.insert">
844 <title>Inserting Data</title>
846 <para> You can add new rows to a table in your database using the
847 <methodname>insert()</methodname> method. The first argument
848 is a string that names the table, and the second argument is an
849 associative array, mapping column names to data values. </para>
851 <example id="zend.db.adapter.write.insert.example">
852 <title>Inserting in a Table</title>
853 <programlisting language="php"><![CDATA[
855 'created_on' => '2007-03-22',
856 'bug_description' => 'Something wrong',
857 'bug_status' => 'NEW'
860 $db->insert('bugs', $data);
864 <para> Columns you exclude from the array of data are not specified
865 to the database. Therefore, they follow the same rules that an
866 <acronym>SQL</acronym> INSERT statement follows: if the
867 column has a DEFAULT clause, the column takes that value in the
868 row created, otherwise the column is left in a <acronym>NULL</acronym> state. </para>
870 <para> By default, the values in your data array are inserted using
871 parameters. This reduces risk of some types of security issues.
872 You don't need to apply escaping or quoting to values in the
875 <para> You might need values in the data array to be treated as
876 <acronym>SQL</acronym> expressions, in which case they
877 should not be quoted. By default, all data values passed as
878 strings are treated as string literals. To specify that the
879 value is an <acronym>SQL</acronym> expression and therefore
880 should not be quoted, pass the value in the data array as an
881 object of type <classname>Zend_Db_Expr</classname> instead of a
882 plain string. </para>
884 <example id="zend.db.adapter.write.insert.example2">
885 <title>Inserting Expressions in a Table</title>
886 <programlisting language="php"><![CDATA[
888 'created_on' => new Zend_Db_Expr('CURDATE()'),
889 'bug_description' => 'Something wrong',
890 'bug_status' => 'NEW'
893 $db->insert('bugs', $data);
899 <sect3 id="zend.db.adapter.write.lastinsertid">
901 <title>Retrieving a Generated Value</title>
903 <para> Some <acronym>RDBMS</acronym> brands support
904 auto-incrementing primary keys. A table defined this way
905 generates a primary key value automatically during an INSERT of
906 a new row. The return value of the
907 <methodname>insert()</methodname> method is
908 <emphasis>not</emphasis> the last inserted ID, because the
909 table might not have an auto-incremented column. Instead, the
910 return value is the number of rows affected (usually 1). </para>
912 <para> If your table is defined with an auto-incrementing primary
913 key, you can call the <methodname>lastInsertId()</methodname>
914 method after the insert. This method returns the last value
915 generated in the scope of the current database connection. </para>
917 <example id="zend.db.adapter.write.lastinsertid.example-1">
918 <title>Using lastInsertId() for an Auto-Increment Key</title>
919 <programlisting language="php"><![CDATA[
920 $db->insert('bugs', $data);
922 // return the last value generated by an auto-increment column
923 $id = $db->lastInsertId();
927 <para> Some <acronym>RDBMS</acronym> brands support a sequence
928 object, which generates unique values to serve as primary key
929 values. To support sequences, the
930 <methodname>lastInsertId()</methodname> method accepts two
931 optional string arguments. These arguments name the table and
932 the column, assuming you have followed the convention that a
933 sequence is named using the table and column names for which the
934 sequence generates values, and a suffix "_seq". This is based on
935 the convention used by PostgreSQL when naming sequences for
936 SERIAL columns. For example, a table "bugs" with primary key
937 column "bug_id" would use a sequence named "bugs_bug_id_seq". </para>
939 <example id="zend.db.adapter.write.lastinsertid.example-2">
940 <title>Using lastInsertId() for a Sequence</title>
941 <programlisting language="php"><![CDATA[
942 $db->insert('bugs', $data);
944 // return the last value generated by sequence 'bugs_bug_id_seq'.
945 $id = $db->lastInsertId('bugs', 'bug_id');
947 // alternatively, return the last value generated by sequence 'bugs_seq'.
948 $id = $db->lastInsertId('bugs');
952 <para> If the name of your sequence object does not follow this
953 naming convention, use the
954 <methodname>lastSequenceId()</methodname> method instead.
955 This method takes a single string argument, naming the sequence
958 <example id="zend.db.adapter.write.lastinsertid.example-3">
959 <title>Using lastSequenceId()</title>
960 <programlisting language="php"><![CDATA[
961 $db->insert('bugs', $data);
963 // return the last value generated by sequence 'bugs_id_gen'.
964 $id = $db->lastSequenceId('bugs_id_gen');
968 <para> For <acronym>RDBMS</acronym> brands that don't support
969 sequences, including MySQL, Microsoft <acronym>SQL</acronym>
970 Server, and SQLite, the arguments to the lastInsertId() method
971 are ignored, and the value returned is the most recent value
972 generated for any table by INSERT operations during the current
973 connection. For these <acronym>RDBMS</acronym> brands, the
974 lastSequenceId() method always returns <constant>NULL</constant>
978 <title>Why Not Use "SELECT MAX(id) FROM table"?</title>
979 <para> Sometimes this query returns the most recent primary key
980 value inserted into the table. However, this technique is
981 not safe to use in an environment where multiple clients are
982 inserting records to the database. It is possible, and
983 therefore is bound to happen eventually, that another client
984 inserts another row in the instant between the insert
985 performed by your client application and your query for the
986 MAX(id) value. Thus the value returned does not identify the
987 row you inserted, it identifies the row inserted by some
988 other client. There is no way to know when this has
990 <para> Using a strong transaction isolation mode such as
991 "repeatable read" can mitigate this risk, but some
992 <acronym>RDBMS</acronym> brands don't support the
993 transaction isolation required for this, or else your
994 application may use a lower transaction isolation mode by
996 <para> Furthermore, using an expression like "MAX(id)+1" to
997 generate a new value for a primary key is not safe, because
998 two clients could do this query simultaneously, and then
999 both use the same calculated value for their next INSERT
1001 <para> All <acronym>RDBMS</acronym> brands provide mechanisms to
1002 generate unique values, and to return the last value
1003 generated. These mechanisms necessarily work outside of the
1004 scope of transaction isolation, so there is no chance of two
1005 clients generating the same value, and there is no chance
1006 that the value generated by another client could be reported
1007 to your client's connection as the last value generated.
1013 <sect3 id="zend.db.adapter.write.update">
1014 <title>Updating Data</title>
1016 <para> You can update rows in a database table using the
1017 <methodname>update()</methodname> method of an Adapter. This
1018 method takes three arguments: the first is the name of the
1019 table; the second is an associative array mapping columns to
1020 change to new values to assign to these columns. </para>
1022 <para> The values in the data array are treated as string literals.
1023 See <xref linkend="zend.db.adapter.write.insert"/> for
1024 information on using <acronym>SQL</acronym> expressions in the
1027 <para> The third argument is a string containing an
1028 <acronym>SQL</acronym> expression that is used as criteria
1029 for the rows to change. The values and identifiers in this
1030 argument are not quoted or escaped. You are responsible for
1031 ensuring that any dynamic content is interpolated into this
1032 string safely. See <xref linkend="zend.db.adapter.quoting"/> for
1033 methods to help you do this. </para>
1035 <para> The return value is the number of rows affected by the update
1038 <example id="zend.db.adapter.write.update.example">
1039 <title>Updating Rows</title>
1040 <programlisting language="php"><![CDATA[
1042 'updated_on' => '2007-03-23',
1043 'bug_status' => 'FIXED'
1046 $n = $db->update('bugs', $data, 'bug_id = 2');
1047 ]]></programlisting>
1050 <para> If you omit the third argument, then all rows in the database
1051 table are updated with the values specified in the data array. </para>
1053 <para> If you provide an array of strings as the third argument,
1054 these strings are joined together as terms in an expression
1055 separated by <constant>AND</constant> operators. </para>
1057 <example id="zend.db.adapter.write.update.example-array">
1058 <title>Updating Rows Using an Array of Expressions</title>
1059 <programlisting language="php"><![CDATA[
1061 'updated_on' => '2007-03-23',
1062 'bug_status' => 'FIXED'
1065 $where[] = "reported_by = 'goofy'";
1066 $where[] = "bug_status = 'OPEN'";
1068 $n = $db->update('bugs', $data, $where);
1070 // Resulting SQL is:
1071 // UPDATE "bugs" SET "update_on" = '2007-03-23', "bug_status" = 'FIXED'
1072 // WHERE ("reported_by" = 'goofy') AND ("bug_status" = 'OPEN')
1073 ]]></programlisting>
1078 <sect3 id="zend.db.adapter.write.delete">
1079 <title>Deleting Data</title>
1080 <para> You can delete rows from a database table using the
1081 <methodname>delete()</methodname> method. This method takes
1082 two arguments: the first is a string naming the table. </para>
1084 <para> The second argument is a string containing an
1085 <acronym>SQL</acronym> expression that is used as criteria
1086 for the rows to delete. The values and identifiers in this
1087 argument are not quoted or escaped. You are responsible for
1088 ensuring that any dynamic content is interpolated into this
1089 string safely. See <xref linkend="zend.db.adapter.quoting"/> for
1090 methods to help you do this. </para>
1092 <para> The return value is the number of rows affected by the delete
1095 <example id="zend.db.adapter.write.delete.example">
1096 <title>Deleting Rows</title>
1097 <programlisting language="php"><![CDATA[
1098 $n = $db->delete('bugs', 'bug_id = 3');
1099 ]]></programlisting>
1102 <para> If you omit the second argument, the result is that all rows
1103 in the database table are deleted. </para>
1105 <para> If you provide an array of strings as the second argument,
1106 these strings are joined together as terms in an expression
1107 separated by <constant>AND</constant> operators. </para>
1113 <sect2 id="zend.db.adapter.quoting">
1115 <title>Quoting Values and Identifiers</title>
1117 <para> When you form <acronym>SQL</acronym> queries, often it is the
1118 case that you need to include the values of PHP variables in
1119 <acronym>SQL</acronym> expressions. This is risky, because if
1120 the value in a PHP string contains certain symbols, such as the
1121 quote symbol, it could result in invalid <acronym>SQL</acronym> .
1122 For example, notice the imbalanced quote characters in the following
1123 query: <programlisting language="php"><![CDATA[
1125 $sql = "SELECT * FROM bugs WHERE reported_by = '$name'";
1128 // SELECT * FROM bugs WHERE reported_by = 'O'Reilly'
1129 ]]></programlisting>
1132 <para> Even worse is the risk that such code mistakes might be exploited
1133 deliberately by a person who is trying to manipulate the function of
1134 your web application. If they can specify the value of a
1135 <acronym>PHP</acronym> variable through the use of an
1136 <acronym>HTTP</acronym> parameter or other mechanism, they might
1137 be able to make your <acronym>SQL</acronym> queries do things that
1138 you didn't intend them to do, such as return data to which the
1139 person should not have privilege to read. This is a serious and
1140 widespread technique for violating application security, known as
1141 "SQL Injection" (see <ulink
1142 url="http://en.wikipedia.org/wiki/SQL_Injection"
1143 >http://en.wikipedia.org/wiki/SQL_Injection</ulink> ). </para>
1145 <para> The <classname>Zend_Db</classname> Adapter class provides
1146 convenient functions to help you reduce vulnerabilities to
1147 <acronym>SQL</acronym> Injection attacks in your
1148 <acronym>PHP</acronym> code. The solution is to escape special
1149 characters such as quotes in <acronym>PHP</acronym> values before
1150 they are interpolated into your <acronym>SQL</acronym> strings. This
1151 protects against both accidental and deliberate manipulation of
1152 <acronym>SQL</acronym> strings by <acronym>PHP</acronym>
1153 variables that contain special characters. </para>
1155 <sect3 id="zend.db.adapter.quoting.quote">
1157 <title>Using quote()</title>
1159 <para> The <methodname>quote()</methodname> method accepts a single
1160 argument, a scalar string value. It returns the value with
1161 special characters escaped in a manner appropriate for the
1162 <acronym>RDBMS</acronym> you are using, and surrounded by
1163 string value delimiters. The standard <acronym>SQL</acronym>
1164 string value delimiter is the single-quote ( <code>'</code> ). </para>
1166 <example id="zend.db.adapter.quoting.quote.example">
1167 <title>Using quote()</title>
1168 <programlisting language="php"><![CDATA[
1169 $name = $db->quote("O'Reilly");
1173 $sql = "SELECT * FROM bugs WHERE reported_by = $name";
1176 // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
1177 ]]></programlisting>
1180 <para> Note that the return value of
1181 <methodname>quote()</methodname> includes the quote
1182 delimiters around the string. This is different from some
1183 functions that escape special characters but do not add the
1184 quote delimiters, for example <ulink
1185 url="http://www.php.net/mysqli_real_escape_string"
1186 >mysql_real_escape_string()</ulink> . </para>
1188 <para> Values may need to be quoted or not quoted according to the
1189 <acronym>SQL</acronym> datatype context in which they are
1190 used. For instance, in some RDBMS brands, an integer value must
1191 not be quoted as a string if it is compared to an integer-type
1192 column or expression. In other words, the following is an error
1193 in some <acronym>SQL</acronym> implementations, assuming
1194 <code>intColumn</code> has a <acronym>SQL</acronym> datatype
1195 of <constant>INTEGER</constant>
1196 <programlisting language="php"><![CDATA[
1197 SELECT * FROM atable WHERE intColumn = '123'
1198 ]]></programlisting>
1201 <para> You can use the optional second argument to the
1202 <methodname>quote()</methodname> method to apply quoting
1203 selectively for the <acronym>SQL</acronym> datatype you specify. </para>
1205 <example id="zend.db.adapter.quoting.quote.example-2">
1206 <title>Using quote() with a SQL Type</title>
1207 <programlisting language="php"><![CDATA[
1209 $sql = 'SELECT * FROM atable WHERE intColumn = '
1210 . $db->quote($value, 'INTEGER');
1211 ]]></programlisting>
1214 <para> Each <classname>Zend_Db_Adapter</classname> class has encoded
1215 the names of numeric <acronym>SQL</acronym> datatypes for the
1216 respective brand of <acronym>RDBMS</acronym> . You can also use
1217 the constants <constant>Zend_Db::INT_TYPE</constant> ,
1218 <constant>Zend_Db::BIGINT_TYPE</constant> , and
1219 <constant>Zend_Db::FLOAT_TYPE</constant> to write code in a
1220 more <acronym>RDBMS</acronym> -independent way. </para>
1223 <classname>Zend_Db_Table</classname> specifies
1224 <acronym>SQL</acronym> types to
1225 <methodname>quote()</methodname> automatically when
1226 generating <acronym>SQL</acronym> queries that reference a
1227 table's key columns. </para>
1231 <sect3 id="zend.db.adapter.quoting.quote-into">
1233 <title>Using quoteInto()</title>
1235 <para> The most typical usage of quoting is to interpolate a
1236 <acronym>PHP</acronym> variable into a
1237 <acronym>SQL</acronym> expression or statement. You can use
1238 the <methodname>quoteInto()</methodname> method to do this in
1239 one step. This method takes two arguments: the first argument is
1240 a string containing a placeholder symbol ( <code>?</code> ), and
1241 the second argument is a value or <acronym>PHP</acronym>
1242 variable that should be substituted for that placeholder. </para>
1244 <para> The placeholder symbol is the same symbol used by many
1245 <acronym>RDBMS</acronym> brands for positional parameters,
1246 but the <methodname>quoteInto()</methodname> method only
1247 emulates query parameters. The method simply interpolates the
1248 value into the string, escapes special characters, and applies
1249 quotes around it. True query parameters maintain the separation
1250 between the <acronym>SQL</acronym> string and the parameters as
1251 the statement is parsed in the <acronym>RDBMS</acronym> server. </para>
1253 <example id="zend.db.adapter.quoting.quote-into.example">
1254 <title>Using quoteInto()</title>
1255 <programlisting language="php"><![CDATA[
1256 $sql = $db->quoteInto("SELECT * FROM bugs WHERE reported_by = ?", "O'Reilly");
1259 // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
1260 ]]></programlisting>
1263 <para> You can use the optional third parameter of
1264 <methodname>quoteInto()</methodname> to specify the
1265 <acronym>SQL</acronym> datatype. Numeric datatypes are not
1266 quoted, and other types are quoted. </para>
1268 <example id="zend.db.adapter.quoting.quote-into.example-2">
1269 <title>Using quoteInto() with a SQL Type</title>
1270 <programlisting language="php"><![CDATA[
1272 ->quoteInto("SELECT * FROM bugs WHERE bug_id = ?", '1234', 'INTEGER');
1275 // SELECT * FROM bugs WHERE reported_by = 1234
1276 ]]></programlisting>
1280 <sect3 id="zend.db.adapter.quoting.quote-identifier">
1282 <title>Using quoteIdentifier()</title>
1284 <para> Values are not the only part of <acronym>SQL</acronym> syntax
1285 that might need to be variable. If you use
1286 <acronym>PHP</acronym> variables to name tables, columns, or
1287 other identifiers in your <acronym>SQL</acronym> statements, you
1288 might need to quote these strings too. By default,
1289 <acronym>SQL</acronym> identifiers have syntax rules like
1290 <acronym>PHP</acronym> and most other programming languages.
1291 For example, identifiers should not contain spaces, certain
1292 punctuation or special characters, or international characters.
1293 Also certain words are reserved for <acronym>SQL</acronym>
1294 syntax, and should not be used as identifiers. </para>
1296 <para> However, <acronym>SQL</acronym> has a feature called
1297 <emphasis>delimited identifiers</emphasis> , which allows
1298 broader choices for the spelling of identifiers. If you enclose
1299 a <acronym>SQL</acronym> identifier in the proper types of
1300 quotes, you can use identifiers with spellings that would be
1301 invalid without the quotes. Delimited identifiers can contain
1302 spaces, punctuation, or international characters. You can also
1303 use <acronym>SQL</acronym> reserved words if you enclose them in
1304 identifier delimiters. </para>
1306 <para> The <methodname>quoteIdentifier()</methodname> method works
1307 like <methodname>quote()</methodname> , but it applies the
1308 identifier delimiter characters to the string according to the
1309 type of Adapter you use. For example, standard
1310 <acronym>SQL</acronym> uses double-quotes ( <code>"</code> )
1311 for identifier delimiters, and most <acronym>RDBMS</acronym>
1312 brands use that symbol. MySQL uses back-quotes ( <code>`</code>
1313 ) by default. The <methodname>quoteIdentifier()</methodname>
1314 method also escapes special characters within the string
1317 <example id="zend.db.adapter.quoting.quote-identifier.example">
1318 <title>Using quoteIdentifier()</title>
1319 <programlisting language="php"><![CDATA[
1320 // we might have a table name that is an SQL reserved word
1321 $tableName = $db->quoteIdentifier("order");
1323 $sql = "SELECT * FROM $tableName";
1326 // SELECT * FROM "order"
1327 ]]></programlisting>
1331 <acronym>SQL</acronym> delimited identifiers are case-sensitive,
1332 unlike unquoted identifiers. Therefore, if you use delimited
1333 identifiers, you must use the spelling of the identifier exactly
1334 as it is stored in your schema, including the case of the
1337 <para> In most cases where <acronym>SQL</acronym> is generated
1338 within <classname>Zend_Db</classname> classes, the default is
1339 that all identifiers are delimited automatically. You can change
1340 this behavior with the option
1341 <constant>Zend_Db::AUTO_QUOTE_IDENTIFIERS</constant> .
1342 Specify this when instantiating the Adapter. See <xref
1343 linkend="zend.db.adapter.connecting.parameters.example2"/> . </para>
1349 <sect2 id="zend.db.adapter.transactions">
1351 <title>Controlling Database Transactions</title>
1353 <para> Databases define transactions as logical units of work that can
1354 be committed or rolled back as a single change, even if they operate
1355 on multiple tables. All queries to a database are executed within
1356 the context of a transaction, even if the database driver manages
1357 them implicitly. This is called <emphasis>auto-commit</emphasis>
1358 mode, in which the database driver creates a transaction for every
1359 statement you execute, and commits that transaction after your
1360 <acronym>SQL</acronym> statement has been executed. By default,
1361 all <classname>Zend_Db</classname> Adapter classes operate in
1362 auto-commit mode. </para>
1364 <para> Alternatively, you can specify the beginning and resolution of a
1365 transaction, and thus control how many <acronym>SQL</acronym>
1366 queries are included in a single group that is committed (or rolled
1367 back) as a single operation. Use the
1368 <methodname>beginTransaction()</methodname> method to initiate a
1369 transaction. Subsequent <acronym>SQL</acronym> statements are
1370 executed in the context of the same transaction until you resolve it
1373 <para> To resolve the transaction, use either the
1374 <methodname>commit()</methodname> or
1375 <methodname>rollBack()</methodname> methods. The
1376 <methodname>commit()</methodname> method marks changes made
1377 during your transaction as committed, which means the effects of
1378 these changes are shown in queries run in other transactions. </para>
1380 <para> The <methodname>rollBack()</methodname> method does the opposite:
1381 it discards the changes made during your transaction. The changes
1382 are effectively undone, and the state of the data returns to how it
1383 was before you began your transaction. However, rolling back your
1384 transaction has no effect on changes made by other transactions
1385 running concurrently. </para>
1387 <para> After you resolve this transaction,
1388 <classname>Zend_Db_Adapter</classname> returns to auto-commit
1389 mode until you call <methodname>beginTransaction()</methodname>
1392 <example id="zend.db.adapter.transactions.example">
1393 <title>Managing a Transaction to Ensure Consistency</title>
1394 <programlisting language="php"><![CDATA[
1395 // Start a transaction explicitly.
1396 $db->beginTransaction();
1399 // Attempt to execute one or more queries:
1404 // If all succeed, commit the transaction and all changes
1405 // are committed at once.
1408 } catch (Exception $e) {
1409 // If any of the queries failed and threw an exception,
1410 // we want to roll back the whole transaction, reversing
1411 // changes made in the transaction, even those that succeeded.
1412 // Thus all changes are committed together, or none are.
1414 echo $e->getMessage();
1416 ]]></programlisting>
1421 <sect2 id="zend.db.adapter.list-describe">
1423 <title>Listing and Describing Tables</title>
1425 <para> The <methodname>listTables()</methodname> method returns an array
1426 of strings, naming all tables in the current database. </para>
1428 <para> The <methodname>describeTable()</methodname> method returns an
1429 associative array of metadata about a table. Specify the name of the
1430 table as a string in the first argument to this method. The second
1431 argument is optional, and names the schema in which the table
1434 <para> The keys of the associative array returned are the column names
1435 of the table. The value corresponding to each column is also an
1436 associative array, with the following keys and values: </para>
1438 <table frame="all" cellpadding="5"
1439 id="zend.db.adapter.list-describe.metadata">
1440 <title>Metadata Fields Returned by describeTable()</title>
1441 <tgroup cols="3" align="left" colsep="1" rowsep="1">
1446 <entry>Description</entry>
1452 <constant>SCHEMA_NAME</constant>
1454 <entry>(string)</entry>
1455 <entry>Name of the database schema in which this table
1460 <constant>TABLE_NAME</constant>
1462 <entry>(string)</entry>
1463 <entry>Name of the table to which this column
1468 <constant>COLUMN_NAME</constant>
1470 <entry>(string)</entry>
1471 <entry>Name of the column.</entry>
1475 <constant>COLUMN_POSITION</constant>
1477 <entry>(integer)</entry>
1478 <entry>Ordinal position of the column in the
1483 <constant>DATA_TYPE</constant>
1485 <entry>(string)</entry>
1486 <entry>RDBMS name of the datatype of the column.</entry>
1490 <constant>DEFAULT</constant>
1492 <entry>(string)</entry>
1493 <entry>Default value for the column, if any.</entry>
1497 <constant>NULLABLE</constant>
1499 <entry>(boolean)</entry>
1500 <entry> <constant>TRUE</constant> if the column accepts
1501 <acronym>SQL</acronym> <constant>NULL</constant>s, <constant>FALSE</constant> if the
1502 column has a <constant>NOT</constant> <constant>NULL</constant> constraint. </entry>
1506 <constant>LENGTH</constant>
1508 <entry>(integer)</entry>
1509 <entry> Length or size of the column as reported by the
1510 <acronym>RDBMS</acronym> . </entry>
1514 <constant>SCALE</constant>
1516 <entry>(integer)</entry>
1517 <entry> Scale of <acronym>SQL</acronym> NUMERIC or
1518 <constant>DECIMAL</constant> type. </entry>
1522 <constant>PRECISION</constant>
1524 <entry>(integer)</entry>
1525 <entry> Precision of <acronym>SQL</acronym> NUMERIC or
1526 <constant>DECIMAL</constant> type. </entry>
1530 <constant>UNSIGNED</constant>
1532 <entry>(boolean)</entry>
1533 <entry> <constant>TRUE</constant> if an integer-based type is reported as
1534 <constant>UNSIGNED</constant> . </entry>
1538 <constant>PRIMARY</constant>
1540 <entry>(boolean)</entry>
1541 <entry><constant>TRUE</constant> if the column is part of the primary key of
1546 <constant>PRIMARY_POSITION</constant>
1548 <entry>(integer)</entry>
1549 <entry>Ordinal position (1-based) of the column in the
1550 primary key.</entry>
1554 <constant>IDENTITY</constant>
1556 <entry>(boolean)</entry>
1557 <entry><constant>TRUE</constant> if the column uses an auto-generated
1565 <title>How the IDENTITY Metadata Field Relates to Specific
1567 <para> The IDENTITY metadata field was chosen as an 'idiomatic' term
1568 to represent a relation to surrogate keys. This field can be
1569 commonly known by the following values:- </para>
1573 <constant>IDENTITY</constant> - DB2, MSSQL </para>
1577 <constant>AUTO_INCREMENT</constant> - MySQL </para>
1581 <constant>SERIAL</constant> - PostgreSQL </para>
1585 <constant>SEQUENCE</constant> - Oracle </para>
1590 <para> If no table exists matching the table name and optional schema
1591 name specified, then <methodname>describeTable()</methodname>
1592 returns an empty array. </para>
1596 <sect2 id="zend.db.adapter.closing">
1598 <title>Closing a Connection</title>
1600 <para> Normally it is not necessary to close a database connection.
1601 <acronym>PHP</acronym> automatically cleans up all resources and
1602 the end of a request. Database extensions are designed to close the
1603 connection as the reference to the resource object is cleaned up. </para>
1605 <para> However, if you have a long-duration <acronym>PHP</acronym>
1606 script that initiates many database connections, you might need to
1607 close the connection, to avoid exhausting the capacity of your
1608 <acronym>RDBMS</acronym> server. You can use the Adapter's
1609 <methodname>closeConnection()</methodname> method to explicitly
1610 close the underlying database connection. </para>
1612 <para> Since release 1.7.2, you could check you are currently connected
1613 to the <acronym>RDBMS</acronym> server with the method
1614 <methodname>isConnected()</methodname> . This means that a
1615 connection resource has been initiated and wasn't closed. This
1616 function is not currently able to test for example a server side
1617 closing of the connection. This is internally use to close the
1618 connection. It allow you to close the connection multiple times
1619 without errors. It was already the case before 1.7.2 for
1620 <acronym>PDO</acronym> adapters but not for the others. </para>
1622 <example id="zend.db.adapter.closing.example">
1623 <title>Closing a Database Connection</title>
1624 <programlisting language="php"><![CDATA[
1625 $db->closeConnection();
1626 ]]></programlisting>
1630 <title>Does Zend_Db Support Persistent Connections?</title>
1631 <para> Yes, persistence is supported through the addition of the
1632 <property>persistent</property> flag set to true in the
1633 configuration (not driver_configuration) of an adapter in
1634 <classname>Zend_Db</classname> . </para>
1636 <example id="zend.db.adapter.connecting.persistence.example">
1637 <title>Using the Persitence Flag with the Oracle Adapter</title>
1638 <programlisting language="php"><![CDATA[
1639 $db = Zend_Db::factory('Oracle', array(
1640 'host' => '127.0.0.1',
1641 'username' => 'webuser',
1642 'password' => 'xxxxxxxx',
1644 'persistent' => true
1646 ]]></programlisting>
1649 <para> Please note that using persistent connections can cause an
1650 excess of idle connections on the <acronym>RDBMS</acronym>
1651 server, which causes more problems than any performance gain you
1652 might achieve by reducing the overhead of making connections. </para>
1653 <para> Database connections have state. That is, some objects in the
1654 <acronym>RDBMS</acronym> server exist in session scope.
1655 Examples are locks, user variables, temporary tables, and
1656 information about the most recently executed query, such as rows
1657 affected, and last generated id value. If you use persistent
1658 connections, your application could access invalid or privileged
1659 data that were created in a previous <acronym>PHP</acronym>
1661 <para> Currently, only Oracle, DB2, and the <acronym>PDO</acronym>
1662 adapters (where specified by <acronym>PHP</acronym> ) support
1663 persistence in <classname>Zend_Db</classname> . </para>
1668 <sect2 id="zend.db.adapter.other-statements">
1670 <title>Running Other Database Statements</title>
1672 <para> There might be cases in which you need to access the connection
1673 object directly, as provided by the <acronym>PHP</acronym> database
1674 extension. Some of these extensions may offer features that are not
1675 surfaced by methods of
1676 <classname>Zend_Db_Adapter_Abstract</classname> . </para>
1678 <para> For example, all <acronym>SQL</acronym> statements run by
1679 <classname>Zend_Db</classname> are prepared, then executed.
1680 However, some database features are incompatible with prepared
1681 statements. DDL statements like CREATE and ALTER cannot be prepared
1682 in MySQL. Also, <acronym>SQL</acronym> statements don't benefit from
1684 url="http://dev.mysql.com/doc/refman/5.1/en/query-cache-how.html"
1685 >MySQL Query Cache</ulink> , prior to MySQL 5.1.17. </para>
1687 <para> Most <acronym>PHP</acronym> database extensions provide a method
1688 to execute <acronym>SQL</acronym> statements without preparing them.
1689 For example, in <acronym>PDO</acronym> , this method is
1690 <methodname>exec()</methodname> . You can access the connection
1691 object in the <acronym>PHP</acronym> extension directly using
1692 getConnection(). </para>
1694 <example id="zend.db.adapter.other-statements.example">
1695 <title>Running a Non-Prepared Statement in a PDO Adapter</title>
1696 <programlisting language="php"><![CDATA[
1697 $result = $db->getConnection()->exec('DROP TABLE bugs');
1698 ]]></programlisting>
1701 <para> Similarly, you can access other methods or properties that are
1702 specific to <acronym>PHP</acronym> database extensions. Be aware,
1703 though, that by doing this you might constrain your application to
1704 the interface provided by the extension for a specific brand of
1705 <acronym>RDBMS</acronym> . </para>
1707 <para> In future versions of <classname>Zend_Db</classname> , there will
1708 be opportunities to add method entry points for functionality that
1709 is common to the supported <acronym>PHP</acronym> database
1710 extensions. This will not affect backward compatibility. </para>
1714 <sect2 id="zend.db.adapter.server-version">
1715 <title>Retrieving Server Version</title>
1717 <para> Since release 1.7.2, you could retrieve the server version in
1718 <acronym>PHP</acronym> syntax style to be able to use
1719 <methodname>version_compare()</methodname> . If the information
1720 isn't available, you will receive <constant>NULL</constant> . </para>
1722 <example id="zend.db.adapter.server-version.example">
1723 <title>Verifying server version before running a query</title>
1724 <programlisting language="php"><![CDATA[
1725 $version = $db->getServerVersion();
1726 if (!is_null($version)) {
1727 if (version_compare($version, '5.0.0', '>=')) {
1730 // do something else
1733 // impossible to read server version
1735 ]]></programlisting>
1739 <sect2 id="zend.db.adapter.adapter-notes">
1741 <title>Notes on Specific Adapters</title>
1743 <para> This section lists differences between the Adapter classes of
1744 which you should be aware. </para>
1746 <sect3 id="zend.db.adapter.adapter-notes.ibm-db2">
1747 <title>IBM DB2</title>
1750 <para> Specify this Adapter to the factory() method with the
1754 <para> This Adapter uses the <acronym>PHP</acronym>
1755 extension ibm_db2. </para>
1758 <para> IBM DB2 supports both sequences and auto-incrementing
1759 keys. Therefore the arguments to
1760 <methodname>lastInsertId()</methodname> are
1761 optional. If you give no arguments, the Adapter returns
1762 the last value generated for an auto-increment key. If
1763 you give arguments, the Adapter returns the last value
1764 generated by the sequence named according to the
1765 convention ' <emphasis>table</emphasis> _
1766 <emphasis>column</emphasis> _seq'. </para>
1771 <sect3 id="zend.db.adapter.adapter-notes.mysqli">
1772 <title>MySQLi</title>
1775 <para> Specify this Adapter to the
1776 <methodname>factory()</methodname> method with the
1777 name 'Mysqli'. </para>
1780 <para> This Adapter utilizes the <acronym>PHP</acronym>
1781 extension mysqli. </para>
1784 <para> MySQL does not support sequences, so
1785 <methodname>lastInsertId()</methodname> ignores its
1786 arguments and always returns the last value generated
1787 for an auto-increment key. The
1788 <methodname>lastSequenceId()</methodname> method
1789 returns <constant>NULL</constant> . </para>
1794 <sect3 id="zend.db.adapter.adapter-notes.oracle">
1795 <title>Oracle</title>
1798 <para> Specify this Adapter to the
1799 <methodname>factory()</methodname> method with the
1800 name 'Oracle'. </para>
1803 <para> This Adapter uses the <acronym>PHP</acronym>
1804 extension oci8. </para>
1807 <para> Oracle does not support auto-incrementing keys, so
1808 you should specify the name of a sequence to
1809 <methodname>lastInsertId()</methodname> or
1810 <methodname>lastSequenceId()</methodname> . </para>
1813 <para> The Oracle extension does not support positional
1814 parameters. You must use named parameters. </para>
1817 <para> Currently the
1818 <constant>Zend_Db::CASE_FOLDING</constant> option is
1819 not supported by the Oracle adapter. To use this option
1820 with Oracle, you must use the <acronym>PDO</acronym> OCI
1824 <para> By default, LOB fields are returned as OCI-Lob
1825 objects. You could retrieve them as string for all
1826 requests by using driver options
1827 <code>'lob_as_string'</code> or for particular
1829 <methodname>setLobAsString(boolean)</methodname> on
1830 adapter or on statement. </para>
1835 <sect3 id="zend.db.adapter.adapter-notes.sqlsrv">
1836 <title>Microsoft SQL Server</title>
1839 <para> Specify this Adapter to the
1840 <methodname>factory()</methodname> method with the
1841 name 'Sqlsrv'. </para>
1844 <para> This Adapter uses the <acronym>PHP</acronym>
1845 extension sqlsrv </para>
1848 <para> Microsoft <acronym>SQL</acronym> Server does not
1849 support sequences, so
1850 <methodname>lastInsertId()</methodname> ignores
1851 primary key argument and returns the last value
1852 generated for an auto-increment key if a table name is
1853 specified or a last insert query returned id. The
1854 <methodname>lastSequenceId()</methodname> method
1855 returns <constant>NULL</constant> . </para>
1859 <classname>Zend_Db_Adapter_Sqlsrv</classname> sets
1860 <constant>QUOTED_IDENTIFIER ON</constant>
1861 immediately after connecting to a <acronym>SQL</acronym>
1862 Server database. This makes the driver use the standard
1863 <acronym>SQL</acronym> identifier delimiter symbol (
1864 <emphasis>"</emphasis> ) instead of the proprietary
1865 square-brackets syntax <acronym>SQL</acronym> Server
1866 uses for delimiting identifiers. </para>
1869 <para> You can specify <property>driver_options</property>
1870 as a key in the options array. The value can be a
1871 anything from here <ulink
1872 url="http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx"
1873 >http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx</ulink>
1878 <methodname>setTransactionIsolationLevel()</methodname>
1879 to set isolation level for current connection. The value
1880 can be <constant>SQLSRV_TXN_READ_UNCOMMITTED</constant>
1881 , <constant>SQLSRV_TXN_READ_COMMITTED</constant> ,
1882 <constant>SQLSRV_TXN_REPEATABLE_READ</constant> ,
1883 <constant>SQLSRV_TXN_SNAPSHOT</constant> or
1884 <constant>SQLSRV_TXN_SERIALIZABLE</constant> .
1888 <para> As of Zend Framework 1.9, the minimal supported build
1889 of the <acronym>PHP</acronym>
1890 <acronym>SQL</acronym> Server extension from Microsoft
1891 is 1.0.1924.0. and the <acronym>MSSQL</acronym> Server
1892 Native Client version 9.00.3042.00. </para>
1897 <sect3 id="zend.db.adapter.adapter-notes.pdo-ibm">
1898 <title>PDO for IBM DB2 and Informix Dynamic Server (IDS)</title>
1901 <para> Specify this Adapter to the
1902 <methodname>factory()</methodname> method with the
1903 name 'Pdo_Ibm'. </para>
1906 <para> This Adapter uses the <acronym>PHP</acronym>
1907 extensions pdo and pdo_ibm. </para>
1910 <para> You must use at least <acronym>PDO</acronym> _IBM
1911 extension version 1.2.2. If you have an earlier version
1912 of this extension, you must upgrade the
1913 <acronym>PDO</acronym> _IBM extension from
1914 <acronym>PECL</acronym> . </para>
1919 <sect3 id="zend.db.adapter.adapter-notes.pdo-mssql">
1920 <title>PDO Microsoft SQL Server</title>
1923 <para> Specify this Adapter to the
1924 <methodname>factory()</methodname> method with the
1925 name 'Pdo_Mssql'. </para>
1928 <para> This Adapter uses the <acronym>PHP</acronym>
1929 extensions pdo and pdo_mssql. </para>
1932 <para> Microsoft <acronym>SQL</acronym> Server does not
1933 support sequences, so
1934 <methodname>lastInsertId()</methodname> ignores its
1935 arguments and always returns the last value generated
1936 for an auto-increment key. The
1937 <methodname>lastSequenceId()</methodname> method
1938 returns <constant>NULL</constant> . </para>
1941 <para> If you are working with unicode strings in an
1942 encoding other than UCS-2 (such as UTF-8), you may have
1943 to perform a conversion in your application code or
1944 store the data in a binary column. Please refer to
1945 <ulink url="http://support.microsoft.com/kb/232580"
1946 >Microsoft's Knowledge Base</ulink> for more
1947 information. </para>
1951 <classname>Zend_Db_Adapter_Pdo_Mssql</classname> sets
1952 <constant>QUOTED_IDENTIFIER ON</constant>
1953 immediately after connecting to a <acronym>SQL</acronym>
1954 Server database. This makes the driver use the standard
1955 <acronym>SQL</acronym> identifier delimiter symbol (
1956 <code>"</code> ) instead of the proprietary
1957 square-brackets syntax <acronym>SQL</acronym> Server
1958 uses for delimiting identifiers. </para>
1961 <para> You can specify <code>pdoType</code> as a key in the
1962 options array. The value can be "mssql" (the default),
1963 "dblib", "freetds", or "sybase". This option affects the
1964 DSN prefix the adapter uses when constructing the DSN
1965 string. Both "freetds" and "sybase" imply a prefix of
1966 "sybase:", which is used for the <ulink
1967 url="http://www.freetds.org/">FreeTDS</ulink> set of
1968 libraries. See also <ulink
1969 url="http://www.php.net/manual/en/ref.pdo-dblib.connection.php"
1971 http://www.php.net/manual/en/ref.pdo-dblib.connection.php</ulink>
1972 for more information on the DSN prefixes used in this
1978 <sect3 id="zend.db.adapter.adapter-notes.pdo-mysql">
1979 <title>PDO MySQL</title>
1982 <para> Specify this Adapter to the
1983 <methodname>factory()</methodname> method with the
1984 name 'Pdo_Mysql'. </para>
1987 <para> This Adapter uses the <acronym>PHP</acronym>
1988 extensions pdo and pdo_mysql. </para>
1991 <para> MySQL does not support sequences, so
1992 <methodname>lastInsertId()</methodname> ignores its
1993 arguments and always returns the last value generated
1994 for an auto-increment key. The
1995 <methodname>lastSequenceId()</methodname> method
1996 returns <constant>NULL</constant> . </para>
2001 <sect3 id="zend.db.adapter.adapter-notes.pdo-oci">
2002 <title>PDO Oracle</title>
2005 <para> Specify this Adapter to the
2006 <methodname>factory()</methodname> method with the
2007 name 'Pdo_Oci'. </para>
2010 <para> This Adapter uses the <acronym>PHP</acronym>
2011 extensions pdo and pdo_oci. </para>
2014 <para> Oracle does not support auto-incrementing keys, so
2015 you should specify the name of a sequence to
2016 <methodname>lastInsertId()</methodname> or
2017 <methodname>lastSequenceId()</methodname> . </para>
2022 <sect3 id="zend.db.adapter.adapter-notes.pdo-pgsql">
2023 <title>PDO PostgreSQL</title>
2026 <para> Specify this Adapter to the
2027 <methodname>factory()</methodname> method with the
2028 name 'Pdo_Pgsql'. </para>
2031 <para> This Adapter uses the <acronym>PHP</acronym>
2032 extensions pdo and pdo_pgsql. </para>
2035 <para> PostgreSQL supports both sequences and
2036 auto-incrementing keys. Therefore the arguments to
2037 <methodname>lastInsertId()</methodname> are
2038 optional. If you give no arguments, the Adapter returns
2039 the last value generated for an auto-increment key. If
2040 you give arguments, the Adapter returns the last value
2041 generated by the sequence named according to the
2042 convention ' <emphasis>table</emphasis> _
2043 <emphasis>column</emphasis> _seq'. </para>
2048 <sect3 id="zend.db.adapter.adapter-notes.pdo-sqlite">
2049 <title>PDO SQLite</title>
2052 <para> Specify this Adapter to the
2053 <methodname>factory()</methodname> method with the
2054 name 'Pdo_Sqlite'. </para>
2057 <para> This Adapter uses the <acronym>PHP</acronym>
2058 extensions pdo and pdo_sqlite. </para>
2061 <para> SQLite does not support sequences, so
2062 <methodname>lastInsertId()</methodname> ignores its
2063 arguments and always returns the last value generated
2064 for an auto-increment key. The
2065 <methodname>lastSequenceId()</methodname> method
2066 returns <constant>NULL</constant> . </para>
2069 <para> To connect to an SQLite2 database, specify
2070 <code>'sqlite2'=>true</code> in the array of
2071 parameters when creating an instance of the
2072 <classname>Pdo_Sqlite</classname> Adapter. </para>
2075 <para> To connect to an in-memory SQLite database, specify
2076 <code>'dbname'=>':memory:'</code> in the array of
2077 parameters when creating an instance of the
2078 <classname>Pdo_Sqlite</classname> Adapter. </para>
2081 <para> Older versions of the SQLite driver for
2082 <acronym>PHP</acronym> do not seem to support the
2083 PRAGMA commands necessary to ensure that short column
2084 names are used in result sets. If you have problems that
2085 your result sets are returned with keys of the form
2086 "tablename.columnname" when you do a join query, then
2087 you should upgrade to the current version of
2088 <acronym>PHP</acronym> . </para>
2093 <sect3 id="zend.db.adapter.adapter-notes.firebird">
2094 <title>Firebird/Interbase</title>
2097 <para> This Adapter uses the <acronym>PHP</acronym>
2098 extension php_interbase. </para>
2101 <para> Firebird/interbase does not support auto-incrementing
2102 keys, so you should specify the name of a sequence to
2103 <methodname>lastInsertId()</methodname> or
2104 <methodname>lastSequenceId()</methodname> . </para>
2107 <para> Currently the
2108 <constant>Zend_Db::CASE_FOLDING</constant> option is
2109 not supported by the Firebird/interbase adapter.
2110 Unquoted identifiers are automatically returned in upper
2115 <para> Adapter name is
2116 <classname>ZendX_Db_Adapter_Firebird</classname> . </para>
2117 <para> Remember to use the param adapterNamespace with value
2118 <classname>ZendX_Db_Adapter</classname> . </para>
2119 <para> We recommend to update the gds32.dll (or linux
2120 equivalent) bundled with php, to the same version of the
2121 server. For Firebird the equivalent gds32.dll is
2122 fbclient.dll. </para>
2123 <para> By default all identifiers (tables names, fields) are
2124 returned in upper case. </para>