|
|
@@ -0,0 +1,24447 @@
|
|
|
+<?xml version="1.0" encoding="UTF-8"?>
|
|
|
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://framework.zend.com/docbook/xml/4.5/docbookx.dtd" [
|
|
|
+<!ENTITY % xinclude SYSTEM "xinclude.mod">
|
|
|
+<!-- $Id: $ --><!ELEMENT xi:include (xi:fallback)?>
|
|
|
+<!ATTLIST xi:include xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
|
|
|
+<!ATTLIST xi:include href CDATA #REQUIRED>
|
|
|
+<!ATTLIST xi:include parse (xml | text) "xml">
|
|
|
+<!ATTLIST xi:include encoding CDATA #IMPLIED>
|
|
|
+<!ELEMENT xi:fallback ANY>
|
|
|
+<!ATTLIST xi:fallback xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
|
|
|
+<!-- inside chapter or section elements --><!ENTITY % local.divcomponent.mix "| xi:include">
|
|
|
+<!-- inside para, programlisting, literallayout, etc. --><!ENTITY % local.para.char.mix "| xi:include">
|
|
|
+<!-- inside bookinfo, chapterinfo, etc. --><!ENTITY % local.info.class "| xi:include">
|
|
|
+<!ENTITY % local.chapter.class "| xi:include">
|
|
|
+]>
|
|
|
+<book id="manual" lang="es">
|
|
|
+ <bookinfo>
|
|
|
+ <title>Guía de Referencia del Programador</title>
|
|
|
+ <subtitle>Zend Framework</subtitle>
|
|
|
+ <edition>Guía de Referencia del Programador para Zend Framework</edition>
|
|
|
+ <pubdate><?dbtimestamp format="Y-m-d"?></pubdate>
|
|
|
+ <copyright>
|
|
|
+ <year>2005-<?dbtimestamp format="Y"?></year>
|
|
|
+ <holder>
|
|
|
+ Zend Technologies Inc.
|
|
|
+ (<ulink url="http://www.zend.com"/>)
|
|
|
+ </holder>
|
|
|
+ </copyright>
|
|
|
+ <!--
|
|
|
+ A Title page graphic can be included like this
|
|
|
+ <mediaobject>
|
|
|
+ <imageobject>
|
|
|
+ <imagedata fileref="../web/images/foo.jpg"/>
|
|
|
+ </imageobject>
|
|
|
+ </mediaobject>
|
|
|
+ -->
|
|
|
+ </bookinfo>
|
|
|
+
|
|
|
+ <chapter id="introduction">
|
|
|
+ <title>Introducción a Zend Framework</title>
|
|
|
+ <sect1 id="introduction.overview" xml:base="ref/overview.xml">
|
|
|
+
|
|
|
+ <title>Descripción general </title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend Framework (ZF) es un framework de código abierto para desarrollar aplicaciones web y servicios web con PHP5. ZF es una implementación que usa código 100% orientado a objetos. La estructura de los componentes de ZF es algo único; cada componente está construido con una baja dependencia de otros componentes. Esta arquitectura débilmente acoplada permite a los desarrolladores utilizar los componentes por separado. A menudo se refiere a este tipo de diseño como "use-at-will" (uso a voluntad).
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Aunque se pueden utilizar de forma individual, los componentes de la librería estándar de Zend Framework conforman un potente y extensible framework de aplicaciones web al combinarse. ZF ofrece un gran rendimiento y una robusta implementación MVC, una abstración de base de datos fácil de usar, y un componente de formularios que implementa la prestación de formularios HTML, validación y filtado para que los desarrolladores puedan consolidar todas las operaciones usando de una manera sencilla la interfaz orientada a objetos. Otros componentes, como Zend_Auth y Zend_Acl, proveen autentificación de usuarios y autorización diferentes a las tiendas de certificados comunes (REVISAR ESTO). También existen componentes que implementan librerías de cliente para acceder de forma sencilla a los web services más populares. Cualesquiera que sean las necesidades de su solicitud, usted tiene todas las posibilidades de encontrar un componente de Zend Framework que se pueda utilizar para reducir drásticamente el tiempo de desarrollo, con una base completamente sólida.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ El principal patrocinador del proyecto Zend Framework es <ulink url="http://www.zend.com">
|
|
|
+ Zend Technologies</ulink>, pero muchas empresas han contribuido con componentes o características importantes para el marco. Empresas como Google, Microsoft y StrikeIron se han asociado con Zend para proporcionar interfaces de servicios web y otras tecnologías que desean poner a disposición de los desarrolladores de Zend Framework.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Zend Framework no podría haber proporcionado y apoyado todas estas características sin la ayuda de la vibrante comunidad de ZF. Los miembros de la comunidad, incluidos los contribuyentes, están disponibles en las , <ulink url="http://framework.zend.com/archives">listas de correo</ulink>, <ulink url="http://www.zftalk.com">
|
|
|
+ canales de IRC</ulink>, y en otros foros. Cualquier duda que tenga acerca de ZF, la comunidad está siempre disponible para responder.
|
|
|
+ </para>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="introduction.installation" xml:base="ref/installation.xml">
|
|
|
+
|
|
|
+ <title> Instalación</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend Framework requiere por lo menos PHP 5.1.4 o superior, aunque Zend recomienda encarecidamente la versión 5.2.3 o superior, porque hay parches de seguridad y mejoras en el rendimiento entre estas dos versiones. Por favor, consulte el anexo sobre los <link linkend="requirements">requisitos del sistema</link>. para obtener más información.
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La instalación del Zend Framework es muy simple. Una vez que haya descargado y descomprimido el framework, deberá añadir la carpeta "/library" de la distribución al principio de su "include path". También puede mover la carpeta "library" a cualquier otra posición (compartida o no) de su sistema de archivos.
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <ulink url="http://framework.zend.com/download">Descargar la última versión estable.</ulink> Esta versión esta disponible en formatos<code>.zip</code>. <code>.tar.gz</code>, es una buena opción para aquellos que comienzan o son nuevos en Zend Framework.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <ulink url="http://framework.zend.com/download/snapshot">Download the latest nightly
|
|
|
+ snapshot.</ulink> For those who would brave the cutting edge, the nightly snapshots represent the
|
|
|
+ latest progress of Zend Framework development. Snapshots are bundled with documentation either in
|
|
|
+ English only or in all available languages. If you anticipate working with the latest Zend
|
|
|
+ Framework developments, consider using a Subversion (SVN) client.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Using a <ulink url="http://subversion.tigris.org">Subversion</ulink> (SVN) client. Zend Framework
|
|
|
+ is open source software, and the Subversion repository used for its development is publicly
|
|
|
+ available. Consider using SVN to get the Zend Framework if you already use SVN for your
|
|
|
+ application development, want to contribute back to the framework, or need to upgrade your
|
|
|
+ framework version more often than releases occur.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ <ulink url="http://svnbook.red-bean.com/nightly/en/svn.ref.svn.c.export.html">Exporting</ulink> is
|
|
|
+ useful if you want to get a particular framework revision without the <code>.svn</code>
|
|
|
+ directories as created in a working copy.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ <ulink url="http://svnbook.red-bean.com/nightly/en/svn.ref.svn.c.checkout.html">Checking out a
|
|
|
+ working copy</ulink> is good when you might contribute to Zend Framework, and a working copy can
|
|
|
+ be updated any time with
|
|
|
+ <ulink url="http://svnbook.red-bean.com/nightly/en/svn.ref.svn.c.update.html"><code>svn
|
|
|
+ update</code></ulink>.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ <ulink url="http://svnbook.red-bean.com/nightly/en/svn.advanced.externals.html">An externals
|
|
|
+ definition</ulink> is highly convenient for developers already using SVN to manage their
|
|
|
+ application working copies.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ La URL del almacén del repository SVN de Zend Framework es:
|
|
|
+ <ulink url="http://framework.zend.com/svn/framework/standard/trunk">http://framework.zend.com/svn/framework/standard/trunk</ulink>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Una vez que tenga disponible una copia de Zend Framework, su aplicación necesita poder acceder a las clases del framework. Aunque hay
|
|
|
+ <ulink url="http://www.php.net/manual/en/configuration.changes.php">
|
|
|
+ diferentes maneras de lograr esto</ulink>, su
|
|
|
+ <ulink url="http://www.php.net/manual/en/ini.core.php#ini.include-path"><code>include_path</code></ulink> de PHP necesita contener una ruta a la librería de Zend Framework.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend provides a <ulink url="http://framework.zend.com/docs/quickstart">QuickStart</ulink> to get you up and running
|
|
|
+ as quickly as possible. This is an excellent way to begin learning about the framework with an emphasis
|
|
|
+ on real world examples that you can built upon.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Ya que los componentes de Zend Framework están débilmente conectados, tiene la opción de usar cualquier combinación de ellos en sus aplicaciones. Los siguientes capítulos presentan una referencia exhaustiva de Zend Framework, componente a componente.
|
|
|
+ </para>
|
|
|
+
|
|
|
+</sect1>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.acl">
|
|
|
+ <title>Zend_Acl</title>
|
|
|
+ <sect1 id="zend.acl.introduction" xml:base="module_specs/Zend_Acl.xml">
|
|
|
+ <title>Introducción</title>
|
|
|
+ <para>
|
|
|
+ Zend_Acl provee la implementación de un sistema simple y
|
|
|
+ flexible de Listas de Control de Acceso (ACL, por sus siglas en
|
|
|
+ inglés) para la administración de privilegios. En general, una
|
|
|
+ aplicación puede utilizar las ACL para controlar el acceso a
|
|
|
+ ciertos objetos protegidos, que son requeridos por otros
|
|
|
+ objetos.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Para los propósitos de esta documentación,
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Un
|
|
|
+ <emphasis role="strong">recurso</emphasis>
|
|
|
+ es un objeto al cual el acceso esta controlado.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Un
|
|
|
+ <emphasis role="strong">rol</emphasis>
|
|
|
+ es un objeto que puede solicitar acceso a un
|
|
|
+ recurso.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ En términos generales,
|
|
|
+ <emphasis role="strong">
|
|
|
+ Los roles solicitan acceso a los recursos
|
|
|
+ </emphasis>
|
|
|
+ . Por ejemplo, si una persona solicita acceso a un automóvil,
|
|
|
+ entonces la persona se convierte en el rol solicitante, y el
|
|
|
+ automóvil en el recurso, puesto que el acceso al automóvil puede
|
|
|
+ no estar disponible a cualquiera.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A través de la especificación y uso de Listas de Control de
|
|
|
+ Acceso (ACL), una aplicación puede controlar cómo los objetos
|
|
|
+ solicitantes (roles) han obtenido acceso a objetos protegidos
|
|
|
+ (recursos).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="zend.acl.introduction.resources">
|
|
|
+ <title>Acerca de los Recursos</title>
|
|
|
+ <para>
|
|
|
+ En Zend_Acl, crear un recurso es muy sencillo. Zend_Acl
|
|
|
+ proporciona el
|
|
|
+ <code>Zend_Acl_Resource_Interface</code>
|
|
|
+ para facilitar a los desarrolladores la creacción de
|
|
|
+ recursos. Una clase solo necesita implementar su interfaz,
|
|
|
+ la cual consiste en un método único,
|
|
|
+ <code>getResourceId()</code>
|
|
|
+ , para que Zend_Acl considere el objeto como un recurso.
|
|
|
+ Adicionalmente,
|
|
|
+ <code>Zend_Acl_Resource</code>
|
|
|
+ se incluye con Zend_Acl como una implementación principal de
|
|
|
+ recursos para los desarrolladores para extenderla hasta
|
|
|
+ donde lo deseen.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Zend_Acl provee un estructura de árbol a la cual pueden ser
|
|
|
+ agregados múltiples recursos (o "Áreas con Controles de
|
|
|
+ Acceso").Ya que los recursos son almacenados en esta
|
|
|
+ estructura de árbol, estos pueden ser organizados desde lo
|
|
|
+ general (hacia la raíz del árbol) a lo específico (hacia las
|
|
|
+ ramas del árbol). Consultas sobre un recurso específico
|
|
|
+ buscarán automáticamente, en la jerarquía del
|
|
|
+ recurso, reglas asignadas a recursos anteriores a los que
|
|
|
+ el recurso actual haga referencia, permitiendo la herencia
|
|
|
+ simple de reglas. Por ejemplo, si una regla por defecto se
|
|
|
+ aplica a cada edificio en una ciudad, uno simplemente
|
|
|
+ podría asignar la regla a la ciudad, en lugar de asignar la
|
|
|
+ misma regla a cada edificio. Algunos edificios pueden
|
|
|
+ necesitar excepciones a la regla, sin embargo, y esto es
|
|
|
+ fácil de hacer en Zend_Acl asignando esta excepción a
|
|
|
+ cada edificio que necesite una excepción a la regla. Un
|
|
|
+ recurso sólo puede heredar de un recurso padre, aunque este
|
|
|
+ recurso padre puede tener a la vez su propio recurso padre,
|
|
|
+ y así; sucesivamente.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Zend_Acl también soporta privilegios sobre recursos (ej.
|
|
|
+ "crear","leer","actualizar", "borrar"), y el desarrollador
|
|
|
+ puede asignar reglas que afecten o a todos los privilegios o
|
|
|
+ a privilegios específicos sobre un recurso.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.acl.introduction.roles">
|
|
|
+ <title>Acerca de las Reglas</title>
|
|
|
+ <para>
|
|
|
+ Al igual que los recursos, la creación de un rol
|
|
|
+ también es muy simple. Zend_Acl proporciona
|
|
|
+ <code>Zend_Acl_Role_Interface</code>
|
|
|
+ para facilitar a los desarrolladores la creación de
|
|
|
+ roles. Una clase solo necesita la implementación de su
|
|
|
+ interfaz, la cual consiste en un método único,
|
|
|
+ <code>getRoleId()</code>
|
|
|
+ , para que Zend_Acl considere que el objeto es un Rol.
|
|
|
+ Adicionalmente,
|
|
|
+ <code>Zend_Acl_Role</code>
|
|
|
+ está incluido con Zend_Acl como una implementación principal
|
|
|
+ del rol para que los desarrolladores la extiendan hasta
|
|
|
+ donde lo deseen.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ En Zend_Acl, un Rol puede heredar de otro o más roles. Esto
|
|
|
+ es para soportar herencia de reglas entre roles. Por ejemplo,
|
|
|
+ un Rol de usuario, como "sally", puede estar bajo uno o más
|
|
|
+ roles padre, como "editor" y "administrador". El
|
|
|
+ desarrollador puede asignar reglas a "editor" y
|
|
|
+ "administrador" por separado, y "sally" puede heredar tales
|
|
|
+ reglas de ambos, sin tener que asignar reglas directamente a
|
|
|
+ "sally".
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Dado que la habilidad de herencia desde múltiples roles es
|
|
|
+ muy util, múltiples herencias tambien introduce cierto grado
|
|
|
+ de complejidad. El siguiente ejemplo ilustra la condición de
|
|
|
+ ambiguedad y como Zend_Acl soluciona esto.
|
|
|
+ </para>
|
|
|
+ <example id="zend.acl.introduction.roles.example.multiple_inheritance">
|
|
|
+ <title>Herencia Multiple entre Roles</title>
|
|
|
+ <para>
|
|
|
+ El siguiente código define tres roles principales - "
|
|
|
+ <code>invitado</code>
|
|
|
+ ", "
|
|
|
+ <code>miembro</code>
|
|
|
+ ", y "
|
|
|
+ <code>admin</code>
|
|
|
+ " - de los cuales otros roles pueden heredar. Entonces,
|
|
|
+ un rol identificado como "
|
|
|
+ <code>unUsuario</code>
|
|
|
+ " es colocado y hereda de los otros tres roles. El orden en
|
|
|
+ el cual estos roles aparecen en el array
|
|
|
+ <code>$parents</code>
|
|
|
+ es importante. Cuando es necesario, Zend_Acl busca por
|
|
|
+ reglas de acceso definidas no solo para el rol
|
|
|
+ solicitado (aquí, "
|
|
|
+ <code>unUsuario</code>
|
|
|
+ "), sino también sobre los roles heredados (aquí, "
|
|
|
+ <code>invitado</code>
|
|
|
+ ", "
|
|
|
+ <code>miembro</code>
|
|
|
+ ", y "
|
|
|
+ <code>admin</code>
|
|
|
+ "):
|
|
|
+ </para>
|
|
|
+ <programlisting role="php"><![CDATA[<?php
|
|
|
+require_once 'Zend/Acl.php';
|
|
|
+$acl = new Zend_Acl();
|
|
|
+
|
|
|
+require_once 'Zend/Acl/Role.php';
|
|
|
+$acl->addRole(new Zend_Acl_Role('invitado'))
|
|
|
+ ->addRole(new Zend_Acl_Role('miembro'))
|
|
|
+ ->addRole(new Zend_Acl_Role('admin'));
|
|
|
+
|
|
|
+$parents = array('invitado', 'miembro', 'admin');
|
|
|
+$acl->addRole(new Zend_Acl_Role('unUsuario'), $parents);
|
|
|
+
|
|
|
+require_once 'Zend/Acl/Resource.php';
|
|
|
+$acl->add(new Zend_Acl_Resource('unRecurso'));
|
|
|
+
|
|
|
+$acl->deny('invitado', 'unRecurso');
|
|
|
+$acl->allow('miembro', 'unRecurso');
|
|
|
+
|
|
|
+echo $acl->isAllowed('unUsuario', 'unRecurso') ? 'permitido' : 'denegado';]]>
|
|
|
+ </programlisting>
|
|
|
+ <para>
|
|
|
+ Ya que no hay reglas específicamente definidas para
|
|
|
+ el rol "
|
|
|
+ <code>unUsuario</code>
|
|
|
+ " y "
|
|
|
+ <code>unRecurso</code>
|
|
|
+ ", Zend_Acl debe buscar por reglas que puedan estar
|
|
|
+ definidas para roles "
|
|
|
+ <code>unUsuario</code>
|
|
|
+ " hereda. Primero, el rol "
|
|
|
+ <code>admin</code>
|
|
|
+ " es visitado, y no hay regla de acceso definida
|
|
|
+ para éste. Luego, el rol "
|
|
|
+ <code>miembro</code>
|
|
|
+ " es visitado, y Zend_Acl encuentra que aquí hay una
|
|
|
+ regla especificando que "
|
|
|
+ <code>miembro</code>
|
|
|
+ " tiene permiso para acceder a "
|
|
|
+ <code>unRecurso</code>
|
|
|
+ ".
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Así, Zend_Acl va a seguir examinando las reglas definidas
|
|
|
+ para otros roles padre, sin embargo, encontraría que "
|
|
|
+ <code>invitado</code>
|
|
|
+ " tiene el acceso denegado a "
|
|
|
+ <code>unRecurso</code>
|
|
|
+ ". Este hecho introduce una ambigüedad debido a que
|
|
|
+ ahora "
|
|
|
+ <code>unUsuario</code>
|
|
|
+ " está tanto denegado como permitido para acceder a "
|
|
|
+ <code>unRecurso</code>
|
|
|
+ ", por la razon de tener un conflicto de reglas
|
|
|
+ heredadas de diferentes roles padre.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Zend_Acl resuelve esta ambiguedad completando la
|
|
|
+ consulta cuando encuentra la primera regla que es
|
|
|
+ directamente aplicable a la consulta. En este caso, dado
|
|
|
+ que el rol "
|
|
|
+ <code>miembro</code>
|
|
|
+ " es examinado antes que el rol "
|
|
|
+ <code>invitado</code>
|
|
|
+ ", el código de ejemplo mostraría "
|
|
|
+ <code>permitido</code>
|
|
|
+ ".
|
|
|
+ </para>
|
|
|
+ </example>
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ Cuando se especifican múltiples padres para un Rol, se
|
|
|
+ debe tener en cuenta que el último padre listado es el
|
|
|
+ primero en ser buscado por reglas aplicables para una
|
|
|
+ solicitud de autorización.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.acl.introduction.creating">
|
|
|
+ <title>Creando las Listas de Control de Acceso (ACL)</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Una ACL puede representar cualquier grupo de objetos físicos
|
|
|
+ o virtuales que desee. Para propósitos de demostración,
|
|
|
+ sin embargo, crearemos un ACL básico para un Sistema de
|
|
|
+ Administración de Contenido que mantendrá varias escalas de
|
|
|
+ grupos sobre una amplia variedad de áreas. Para crear un
|
|
|
+ nuevo objeto ACL, iniciamos la ACL sin parámetros:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[<?php
|
|
|
+require_once 'Zend/Acl.php';
|
|
|
+
|
|
|
+$acl = new Zend_Acl();]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ Hasta que un desarrollador especifique una regla
|
|
|
+ "permitido", Zend_Acl deniega el acceso a cada privilegio
|
|
|
+ sobre cada recurso para cada rol.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.acl.introduction.role_registry">
|
|
|
+ <title>Registrando Roles</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El Sistema de Administración de Contenido casi
|
|
|
+ siempre necesita una jerarquía de permisos para determinar
|
|
|
+ la capacidad de identificación de sus usuarios. Puede haber
|
|
|
+ un grupo de 'Invitados' para permitir acceso limitado para
|
|
|
+ demostraciones, un grupo de 'Personal' para la mayoría de
|
|
|
+ usuarios del CMS quienes realizan la mayor parte de
|
|
|
+ operaciones del día a día, un grupo 'Editores' para las
|
|
|
+ responsabilidades de publicación, revisión, archivo y
|
|
|
+ eliminación de contenido, y finalmente un grupo
|
|
|
+ 'Administradores' cuyas tareas pueden incluir todas las de los
|
|
|
+ otros grupos y también el mantenimiento de la información
|
|
|
+ delicada, manejo de usuarios, configuración de los datos
|
|
|
+ básicos y su respaldo/exportación. Este grupo de permisos
|
|
|
+ pueden ser representados en un registro de roles,
|
|
|
+ permitiendo a cada grupo heredar los privilegios de los
|
|
|
+ grupos 'padre', al igual que proporcionando distintos
|
|
|
+ privilegios solo para su grupo individual. Los permisos pueden
|
|
|
+ ser expresados como:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <table id="zend.acl.introduction.role_registry.table.example_cms_access_controls">
|
|
|
+ <title>Controles de Acceso para un CMS de ejemplo</title>
|
|
|
+ <tgroup cols="3">
|
|
|
+ <thead>
|
|
|
+ <row>
|
|
|
+ <entry>Nombre</entry>
|
|
|
+ <entry>Permisos Individuales</entry>
|
|
|
+ <entry>Hereda permisos de</entry>
|
|
|
+ </row>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ <row>
|
|
|
+ <entry>Invitado</entry>
|
|
|
+ <entry>View</entry>
|
|
|
+ <entry>N/A</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>Personal</entry>
|
|
|
+ <entry>Editar, Enviar, Revisar</entry>
|
|
|
+ <entry>Invitado</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>Editor</entry>
|
|
|
+ <entry>Publicar, Archivar, Eliminar</entry>
|
|
|
+ <entry>Personal</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>Administrador</entry>
|
|
|
+ <entry>(Todos los accesos permitidos)</entry>
|
|
|
+ <entry>N/A</entry>
|
|
|
+ </row>
|
|
|
+ </tbody>
|
|
|
+ </tgroup>
|
|
|
+ </table>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para este ejemplo, se usa
|
|
|
+ <code>Zend_Acl_Role</code>
|
|
|
+ , pero cualquier objeto que implemente
|
|
|
+ <code>Zend_Acl_Role_Interface</code>
|
|
|
+ es admisible. Estos grupos pueden ser agragados al registro
|
|
|
+ de roles de la siguiente manera:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[<?php
|
|
|
+require_once 'Zend/Acl.php';
|
|
|
+
|
|
|
+$acl = new Zend_Acl();
|
|
|
+
|
|
|
+// Agregar grupos al registro de roles usando Zend_Acl_Role
|
|
|
+require_once 'Zend/Acl/Role.php';
|
|
|
+
|
|
|
+// Invitado no hereda controles de acceso
|
|
|
+$rolInvitado = new Zend_Acl_Role('invitado');
|
|
|
+$acl->addRole($rolInvitado);
|
|
|
+
|
|
|
+// Personal hereda de Invitado
|
|
|
+$acl->addRole(new Zend_Acl_Role('personal'), $rolInvitado);
|
|
|
+
|
|
|
+/* alternativamente, lo de arriba puede ser escrito así:
|
|
|
+$rolInvitado = $acl->addRole(new Zend_Acl_Role('personal'), 'invitado');
|
|
|
+//*/
|
|
|
+
|
|
|
+// Editor hereda desde personal
|
|
|
+$acl->addRole(new Zend_Acl_Role('editor'), 'personal');
|
|
|
+
|
|
|
+// Administrador no hereda controles de acceso
|
|
|
+$acl->addRole(new Zend_Acl_Role('administrador'));]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.acl.introduction.defining">
|
|
|
+ <title>Definiendo Controles de Acceso</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Ahora que la ACL contiene los roles relevantes, se pueden
|
|
|
+ establecer reglas que definan cómo los roles pueden acceder
|
|
|
+ a los recursos. Tenga en cuenta que no definiremos ningún
|
|
|
+ recurso en particular para este ejemplo, el cual está
|
|
|
+ simplificado para ilustrar que las reglas se aplican a todos
|
|
|
+ los recursos. Zend_Acl proporciona una forma práctica por la
|
|
|
+ cual las reglas solo necesitan ser asignadas de lo general a
|
|
|
+ lo especifico, minimizando el número de reglas necesarias,
|
|
|
+ porque los recursos y roles heredan reglas que están
|
|
|
+ definidas en sus padres.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Consecuentemente, podemos definir un grupo razonablemente
|
|
|
+ complejo de reglas con un mínimo de código. Para aplicar
|
|
|
+ estos permisos básicos como están definidos arriba:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[<?php
|
|
|
+require_once 'Zend/Acl.php';
|
|
|
+
|
|
|
+$acl = new Zend_Acl();
|
|
|
+
|
|
|
+require_once 'Zend/Acl/Role.php';
|
|
|
+
|
|
|
+$rolInvitado = new Zend_Acl_Role('invitado');
|
|
|
+$acl->addRole($rolInvitado);
|
|
|
+$acl->addRole(new Zend_Acl_Role('personal'), $rolInvitado);
|
|
|
+$acl->addRole(new Zend_Acl_Role('editor'), 'personal');
|
|
|
+$acl->addRole(new Zend_Acl_Role('administrador'));
|
|
|
+
|
|
|
+// Invitado solo puede ver el contenido
|
|
|
+$acl->allow($rolInvitado, null, 'ver');
|
|
|
+
|
|
|
+/* Lo de arriba puede ser escrito de la siguiente forma alternativa:
|
|
|
+$acl->allow('invitado', null, 'ver');
|
|
|
+//*/
|
|
|
+
|
|
|
+// Personal hereda el privilegio de ver de invitado, pero también necesita privilegios adicionales
|
|
|
+$acl->allow('personal', null, array('editar', 'enviar', 'revisar'));
|
|
|
+
|
|
|
+// Editor hereda los privilegios de ver, editar, enviar, y revisar de personal,
|
|
|
+// pero también necesita privilegios adicionales
|
|
|
+$acl->allow('editor', null, array('publicar', 'archivar', 'eliminar'));
|
|
|
+
|
|
|
+// Administrador no hereda nada, pero tiene todos los privilegios permitidos
|
|
|
+$acl->allow('administrador');]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El valor
|
|
|
+ <code>null</code>
|
|
|
+ en las llamadas de
|
|
|
+ <code>allow()</code>
|
|
|
+ es usado para indicar que las reglas de permiso se aplican a
|
|
|
+ todos los recursos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.acl.introduction.querying">
|
|
|
+ <title>Consultando la ACL</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Ahora tenemos una ACL flexible que puede ser usada para
|
|
|
+ determinar qué solicitantes tienen permisos para realizar
|
|
|
+ funciones a través de la aplicacion web. Ejecutar
|
|
|
+ consultas es la forma más simple de usar el método
|
|
|
+ <code>isAllowed()</code>
|
|
|
+ :
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[<?php
|
|
|
+echo $acl->isAllowed('invitado', null, 'ver') ?
|
|
|
+ "permitido" : "denegado"; // permitido
|
|
|
+
|
|
|
+echo $acl->isAllowed('personal', null, 'publicar') ?
|
|
|
+ "permitido" : "denegado"; // denegado
|
|
|
+
|
|
|
+echo $acl->isAllowed('personal', null, 'revisar') ?
|
|
|
+ "permitido" : "denegado"; // permitido
|
|
|
+
|
|
|
+echo $acl->isAllowed('editor', null, 'ver') ?
|
|
|
+ "permitido" : "denegado"; // permitido debido a la herencia de invitado
|
|
|
+
|
|
|
+echo $acl->isAllowed('editor', null, 'actualizar') ?
|
|
|
+ "permitido" : "denegado"; // denegado debido a que no hay regla de permiso para 'actualizar'
|
|
|
+
|
|
|
+echo $acl->isAllowed('administrador', null, 'ver') ?
|
|
|
+ "permitido" : "denegado"; // permitido porque administrador tiene permitidos todos los privilegios
|
|
|
+
|
|
|
+echo $acl->isAllowed('administrador') ?
|
|
|
+ "permitido" : "denegado"; // permitido porque administrador tiene permitidos todos los privilegios
|
|
|
+
|
|
|
+echo $acl->isAllowed('administrador', null, 'actualizar') ?
|
|
|
+ "permitido" : "denegado"; // permitido porque administrador tiene permitidos todos los privilegios]]>
|
|
|
+ </programlisting>
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+ vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.acl.refining" xml:base="module_specs/Zend_Acl-Refining.xml">
|
|
|
+
|
|
|
+ <title>Perfeccionamiento de los controles de acceso</title>
|
|
|
+
|
|
|
+ <sect2 id="zend.acl.refining.precise">
|
|
|
+
|
|
|
+ <title>Definir mejor los controles de acceso</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El ACL básico según lo definido en la
|
|
|
+ <link linkend="zend.acl.introduction">
|
|
|
+ sección anterior
|
|
|
+ </link>
|
|
|
+ demuestra cómo los diversos privilegios se pueden otorgar
|
|
|
+ sobre todo el ACL (todos los recursos). En la práctica, sin
|
|
|
+ embargo, los controles de acceso tienden a tener excepciones
|
|
|
+ y diversos grados de complejidad. Zend_Acl permite lograr
|
|
|
+ estos refinamientos de una manera sencilla y flexible.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para el CMS del ejemplo se ha determinado que, si bien el
|
|
|
+ grupo 'staff' cubre las necesidades de la gran mayoría de
|
|
|
+ usuarios, hay una necesidad de un nuevo grupo 'marketing'
|
|
|
+ que requiere el acceso al boletín de noticias y las últimas
|
|
|
+ noticias en el CMS. El grupo es bastante autosuficiente y
|
|
|
+ tendrá la capacidad de publicar y de archivar los boletines
|
|
|
+ de noticias y las últimas noticias.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Primero revisamos el registro del rol para reflejar estos
|
|
|
+ cambios. Hemos determinado que el grupo 'marketing' tiene
|
|
|
+ los mismos permisos básicos que 'staff', así que definimos
|
|
|
+ 'marketing' de tal manera que herede los permisos de
|
|
|
+ 'staff':
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+ // El nuevo grupo de Marketing hereda los permisos de Staff
|
|
|
+ $acl->addRole(new Zend_Acl_Role('marketing'), 'staff'); ]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A continuación, la nota que por encima de los controles de
|
|
|
+ acceso se refieren a recursos específicos (por ejemplo,
|
|
|
+ "boletín informativo", "últimas noticias", "anuncio de
|
|
|
+ noticias"). Ahora añadimos estos recursos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Crear recursos para las reglas
|
|
|
+ // newsletter
|
|
|
+ $acl->add(new Zend_Acl_Resource('newsletter'));
|
|
|
+
|
|
|
+ // news
|
|
|
+ $acl->add(new Zend_Acl_Resource('news'));
|
|
|
+
|
|
|
+ // Últimas Noticias
|
|
|
+ $acl->add(new Zend_Acl_Resource('latest'), 'news');
|
|
|
+
|
|
|
+ // anuncio de noticias
|
|
|
+ $acl->add(new Zend_Acl_Resource('announcement'), 'news'); ]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Entonces es simplemente una cuestión de la definición de
|
|
|
+ estas normas más específicas en ámbitos de la ACL:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[ //
|
|
|
+ Marketing debe ser capaz de archivar y publicar boletines informativos y
|
|
|
+ // las últimas noticias
|
|
|
+ $acl->allow('marketing',
|
|
|
+ array('newsletter', 'latest'),
|
|
|
+ array('publish', 'archive'));
|
|
|
+
|
|
|
+ // Staff (y marketing, por herencia), se le denega el permiso a
|
|
|
+ // revisar las últimas noticias
|
|
|
+ $acl->deny('staff', 'latest', 'revise');
|
|
|
+
|
|
|
+ // Todos (incluyendo los administradores) tienen permiso denegado para
|
|
|
+ // archivar anuncios y noticias
|
|
|
+ $acl->deny(null, 'announcement', 'archive'); ]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Ahora podemos consultar el ACL con respecto a los últimos
|
|
|
+ cambios:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+ echo $acl->isAllowed('staff', 'newsletter', 'publish') ?
|
|
|
+ "allowed" : "denied";
|
|
|
+ // denegado
|
|
|
+
|
|
|
+ echo $acl->isAllowed('marketing', 'newsletter', 'publish') ?
|
|
|
+ "allowed" : "denied";
|
|
|
+ // permitido
|
|
|
+
|
|
|
+ echo $acl->isAllowed('staff', 'latest', 'publish') ?
|
|
|
+ "allowed" : "denied";
|
|
|
+ // denegado
|
|
|
+
|
|
|
+ echo $acl->isAllowed('marketing', 'latest', 'publish') ?
|
|
|
+ "allowed" : "denied";
|
|
|
+ // permitido
|
|
|
+
|
|
|
+ echo $acl->isAllowed('marketing', 'latest', 'archive') ?
|
|
|
+ "allowed" : "denied";
|
|
|
+ // permitido
|
|
|
+
|
|
|
+ echo $acl->isAllowed('marketing', 'latest', 'revise') ?
|
|
|
+ "allowed" : "denied";
|
|
|
+ // denegado
|
|
|
+
|
|
|
+ echo $acl->isAllowed('editor', 'announcement', 'archive') ?
|
|
|
+ "allowed" : "denied";
|
|
|
+ // denegado
|
|
|
+
|
|
|
+ echo $acl->isAllowed('administrator', 'announcement', 'archive') ?
|
|
|
+ "allowed" : "denied";
|
|
|
+ // denegado
|
|
|
+ ]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.acl.refining.removing">
|
|
|
+
|
|
|
+ <title>Eliminar los controles de acceso</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para eliminar una o más reglas ACL, simplemente utilice el
|
|
|
+ método removeAllow() o removeDeny(). Al igual que con
|
|
|
+ allow() y deny(), puede utilizar un valor null para indicar
|
|
|
+ que el método es aplicable a todos los roles, recursos y/o
|
|
|
+ privilegios:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Elimina la prohibición de leer las últimas noticias de staff (y marketing,
|
|
|
+// por herencia)
|
|
|
+$acl->removeDeny('staff', 'latest', 'revise');
|
|
|
+
|
|
|
+echo $acl->isAllowed('marketing', 'latest', 'revise') ?
|
|
|
+ "allowed" : "denied";
|
|
|
+// permitido
|
|
|
+
|
|
|
+// Elimina la autorización para publicar y archivar los boletines
|
|
|
+// marketing
|
|
|
+$acl->removeAllow('marketing',
|
|
|
+ 'newsletter',
|
|
|
+ array('publish', 'archive'));
|
|
|
+
|
|
|
+echo $acl->isAllowed('marketing', 'newsletter', 'publish') ?
|
|
|
+ "allowed" : "denied";
|
|
|
+// denegado
|
|
|
+
|
|
|
+echo $acl->isAllowed('marketing', 'newsletter', 'archive') ?
|
|
|
+"allowed" : "denied";
|
|
|
+
|
|
|
+// denegado
|
|
|
+ ]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los privilegios pueden ser modificados de manera incremental como se
|
|
|
+ ha indicado anteriormente, pero un valor null para los
|
|
|
+ privilegios anula tales cambios incrementales:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php">
|
|
|
+ <![CDATA[
|
|
|
+//Permitir al grupo de "marketing" todos los permisos a las últimas noticias
|
|
|
+$acl->allow('marketing', 'latest');
|
|
|
+
|
|
|
+echo $acl->isAllowed('marketing', 'latest', 'publish') ?
|
|
|
+"allowed" : "denied";
|
|
|
+//permitido
|
|
|
+
|
|
|
+echo $acl->isAllowed('marketing', 'latest', 'archive') ?
|
|
|
+"allowed" : "denied";
|
|
|
+//permitido
|
|
|
+
|
|
|
+echo $acl->isAllowed('marketing', 'latest', 'anything') ?
|
|
|
+"allowed" : "denied";
|
|
|
+// permitido
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1>
|
|
|
+ <sect1 id="zend.acl.advanced" xml:base="module_specs/Zend_Acl-Advanced.xml">
|
|
|
+
|
|
|
+ <title>Uso Avanzado</title>
|
|
|
+
|
|
|
+ <sect2 id="zend.acl.advanced.storing">
|
|
|
+
|
|
|
+ <title>Almacenamiento Permanente de los Datos ACL</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Acl fue diseñado de tal manera que no requiere ninguna
|
|
|
+ tecnología particular como bases de datos o un servidor de
|
|
|
+ cache para el almacenamiento de datos ACL. Al poseer una
|
|
|
+ implementación completamente construida en PHP, es posible
|
|
|
+ contruir herramientas de administración personalizadas sobre
|
|
|
+ Zend_Acl con relativa facilidad y flexibilidad. En muchas
|
|
|
+ situaciones se requiere alguna forma de mantenimiento
|
|
|
+ interactivo de una ACL, y Zend_Acl provee métodos para
|
|
|
+ configurar, y consultar, los controles de acceso de una
|
|
|
+ aplicación.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El almacenamiento de los datos ACL es una tarea que se
|
|
|
+ delega al desarrollador, puesto que la utilización variará
|
|
|
+ exténsamente en distintas situaciones. Dado que Zend_Acl es
|
|
|
+ serializable, los objetos ACL pueden serializarse con la
|
|
|
+ función
|
|
|
+ <ulink url="http://php.net/serialize">
|
|
|
+ <code>serialize()</code>
|
|
|
+ </ulink>
|
|
|
+ de PHP, y los resultados pueden ser almacenados donde sea
|
|
|
+ que el desarrollador lo desee, en un archivo, base de datos,
|
|
|
+ o mecanismo de cache
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.acl.advanced.assertions">
|
|
|
+
|
|
|
+ <title>
|
|
|
+ Escribiendo reglas condicionales ACL con aserciones
|
|
|
+ </title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A veces, una regla para permitir o negar una función de acceso a un
|
|
|
+ recurso no debería ser absoluta sino que depende de varios criterios.
|
|
|
+ Por ejemplo, supóngase que debe permitirse cierto acceso, pero
|
|
|
+ únicamente entre las 8:00am y 5:00pm. Otro ejemplo sería negar el
|
|
|
+ acceso debido a una petición que proviene de una dirección IP que se
|
|
|
+ ha marcado como una fuente de abusos. Zend_Acl tiene soporte para la
|
|
|
+ aplicación de normas basadas en cualquier condición que el
|
|
|
+ desarrollador necesite.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Acl provee soporte para reglas condicionales con
|
|
|
+ <code>Zend_Acl_Assert_Interface</code>
|
|
|
+ . Con el fin de utilizar la regla de aserción de la interfaz,
|
|
|
+ un desarrollador escribe una clase que implemente el método
|
|
|
+ <code>assert()</code>
|
|
|
+ de la interfaz:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class CleanIPAssertion implements Zend_Acl_Assert_Interface
|
|
|
+{
|
|
|
+ public function assert(Zend_Acl $acl,
|
|
|
+ Zend_Acl_Role_Interface $role = null,
|
|
|
+ Zend_Acl_Resource_Interface $resource = null,
|
|
|
+ $privilege = null)
|
|
|
+ {
|
|
|
+ return $this->_isCleanIP($_SERVER['REMOTE_ADDR']);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function _isCleanIP($ip)
|
|
|
+ {
|
|
|
+ // ...
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Una vez la clase de aserción esta disponible, el desarrollador puede
|
|
|
+ suministrar una instancia de la clase de aserción cuando asigna reglas
|
|
|
+ condicionales. Una regla que es creada con una aserción
|
|
|
+ sólo se aplica cuando el método de la aserción devuelve true.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$acl = new Zend_Acl();
|
|
|
+$acl->allow(null, null, null, new CleanIPAssertion());
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El código anterior crea una regla condicional que permite el acceso a
|
|
|
+ todos los privilegios sobre todo, por todo el mundo, excepto cuando la IP
|
|
|
+ de quien hace la petición está en la "lista negra". Si una petición
|
|
|
+ viene desde una IP que no está considerada "limpia", entonces la regla no
|
|
|
+ se aplica. Dado que la regla se aplica a todos los roles, todos los
|
|
|
+ recursos, y todos los privilegios, una IP "no limpia" daría lugar a una
|
|
|
+ negación de acceso. Éste es un caso especial, sin embargo, y debería ser
|
|
|
+ entendido que en todos los otros casos (por ejemplo, cuando un rol
|
|
|
+ específico, recurso, o privilegio está especificado por la regla),
|
|
|
+ una aserción fallida provoca que la regla no se aplique, y otras reglas
|
|
|
+ deberían ser usadas para determinar si el acceso está permitido o
|
|
|
+ denegado.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método
|
|
|
+ <code>assert()</code>
|
|
|
+ de un objeto aserción es pasado a la ACL, regla, recurso, y privilegio
|
|
|
+ para el cual una consulta de autorización (por ejemplo,
|
|
|
+ <code>isAllowed()</code>
|
|
|
+ ) se aplica, con el fin de proporcionar un contexto para que la clase de
|
|
|
+ aserción determine sus condiciones cuando fuera necesario.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+ vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.amf">
|
|
|
+ <title>Zend_Amf</title>
|
|
|
+ <sect1 id="zend.amf.introduction" xml:base="module_specs/Zend_Amf.xml">
|
|
|
+ <title>IntroducciГіn</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Amf</code>
|
|
|
+ provee apoyo para el Formato de Mensajes de ActionScript
|
|
|
+ <ulink url="http://en.wikipedia.org/wiki/Action_Message_Format">Action
|
|
|
+ Message Format</ulink>
|
|
|
+ (AMF) de Adobe, que permite la comunicaciГіn
|
|
|
+ entre Adobe
|
|
|
+ <ulink url="http://en.wikipedia.org/wiki/Adobe_Flash_Player">Flash
|
|
|
+ Player</ulink>
|
|
|
+ y PHP. EspecР“Вficamente, proporciona una aplicaciГіn
|
|
|
+ para un
|
|
|
+ servidor gateway que tramita las solicitudes enviadas desde
|
|
|
+ Flash Player al servidor, mapeando estos requerimientos
|
|
|
+ al objeto y a sus mГ©todos de clase, como asГ tambiГ©n a llamadas
|
|
|
+ arbitrarias de comunicaciГіn.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las
|
|
|
+ <ulink>
|
|
|
+ url="http://download.macromedia.com/pub/labs/amf/amf3_spec_121207.pdf">
|
|
|
+ </ulink>
|
|
|
+ especificaciones
|
|
|
+ (en inglГ©s) de AMF3 son de libre disponibilidad y sirven como referencia
|
|
|
+ para establecer quГ© tipos de mensajes
|
|
|
+ pueden ser enviados entre Flash Player y el servidor.
|
|
|
+ </para>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.amf.server" xml:base="module_specs/Zend_Amf-Server.xml">
|
|
|
+ <title>Zend_Amf_Server</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Amf_Server</code> proporciona un servidor al estilo RPC para
|
|
|
+ tramitar solicitudes hechas desde Adobe Flash Player utilizando el protocolo AMF.
|
|
|
+ Al igual que todas las clases de servidor, Zend Framework sigue la API de
|
|
|
+ SoapServer, proporcionando una interfaz para crear servidores fácil de recordar.
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.amf.server.basic">
|
|
|
+ <title>Servidor AMF básico</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Asumamos que ha creado la clase <code>Foo</code> con una
|
|
|
+ variedad de métodos públicos. Usando el siguiente código, puede
|
|
|
+ crear un servidor AMF:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$servidor = new Zend_Amf_Server();
|
|
|
+$servidor->setClass('Foo');
|
|
|
+$respuesta = $servidor->handle();
|
|
|
+echo $respuesta;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Alternativamente, en su lugar puede elegir agregar una función simple como
|
|
|
+ llamada de retorno:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$servidor = new Zend_Amf_Server();
|
|
|
+$servidor->addFunction('myUberCoolFunction');
|
|
|
+$respuesta = $servidor->handle();
|
|
|
+echo $respuesta;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ También puede combinar y examinar la identidad de varias clases y funciones.
|
|
|
+ Al hacerlo, sugerimos darle un espacio de nombres a cada una para
|
|
|
+ garantizar que no ocurran colisiones entre nombres de métodos;
|
|
|
+ puede hacerse simplemente pasando una segunda cadena de argumentos para cualquier <code>addFunction()</code> o
|
|
|
+ <code>setClass()</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$servidor = new Zend_Amf_Server();
|
|
|
+$servidor->addFunction('myUberCoolFunction', 'my')
|
|
|
+ ->setClass('Foo', 'foo')
|
|
|
+ ->setClass('Bar', 'bar');
|
|
|
+$respuesta = $servidor->handle();
|
|
|
+echo $respuesta;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El <code>Zend_Amf_Server</code> también permite cargar servicios
|
|
|
+ dinámicamente, en función de una ruta de directorio ya suministrada.
|
|
|
+ Puede añadir al servidor tantos directorios como desee.
|
|
|
+ El orden en que se añadan los directorios al servidor será el orden en que
|
|
|
+ se realizarán las búsquedas LIFO en los directorios para coincidir
|
|
|
+ con la clase.
|
|
|
+ El método <code>addDirectory()</code> realiza la acción de añadir directorios.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$servidor->addDirectory(dirname(__FILE__) .'/../services/');
|
|
|
+$servidor->addDirectory(dirname(__FILE__) .'/../package/');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cuando se llama a servicios remotos, los nombres de los directorios que
|
|
|
+ contengan las fuentes pueden tener los delimitadores guión bajo (_) y el punto (.).
|
|
|
+ Cuando se utilize un guión bajo (_) tanto en PEAR como en Zend Framework,
|
|
|
+ se respetarán los nombres de clases de acuerdo a las convenciones de nomenclatura.
|
|
|
+ Esto significa que si usted llama al servicio com_Foo_Bar el servidor
|
|
|
+ buscará el archivo Bar.php en cada una de las rutas incluidas en <code>com/Foo/Bar.php</code>.
|
|
|
+ Si se usa la notación punto para su servicio remoto como <code>com.Foo.Bar</code>
|
|
|
+ cada ruta incluida deberá tener <code>com/Foo/Bar.php</code> agregado al final
|
|
|
+ para autocargar Bar.php.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todos las solicitudes AMF enviadas al script serán manejadas
|
|
|
+ por el servidor, y este devolverá una respuesta AMF.
|
|
|
+ </para>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Todos los métodos y las funciones agregadas requieren bloques de documentación (docblocks)</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como todos los demás componentes del servidor en Zend Framework,
|
|
|
+ debe documentar los métodos de su clase usando PHP docblocks.
|
|
|
+ Como mínimo, necesita proporcionar anotaciones para cada argumento
|
|
|
+ así como para el valor de retorno. Como ejemplos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Función que agregar:
|
|
|
+
|
|
|
+/**
|
|
|
+ * @param string $nombre
|
|
|
+ * @param string $saludo
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+function holaMundo($ombre, $saludo = 'Hola')
|
|
|
+{
|
|
|
+ return $saludo . ', ' . $nombre;
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Clase agregada
|
|
|
+
|
|
|
+class Mundo
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * @param string $nombre
|
|
|
+ * @param string $saludo
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public function hola($nombre, $saludo = 'Hola')
|
|
|
+ {
|
|
|
+ return $saludo . ', ' . $nombre;
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Pueden usarse otras anotaciones, pero serán ignoradas.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <sect2 id="zend.amf.server.flex">
|
|
|
+ <title>Conectándose al Servidor desde Flex</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Conectarse a <code>Zend_Amf_Server</code> desde su proyecto Flex
|
|
|
+ es bastante simple; solo necesita apuntar el final del URI
|
|
|
+ a su script <code>Zend_Amf_Server</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por ejemplo, digamos que usted ya ha creado su servidor y lo ha
|
|
|
+ puesto en el fichero <code>server.php</code> en el directorio raíz (root)
|
|
|
+ de su aplicación, por lo tanto la URI es <code>http://example.com/server.php</code>.
|
|
|
+ En este caso, usted debería modificar su fichero services-config.xml
|
|
|
+ poniendo este valor como atributo al punto final del canal uri.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Si nunca ha creado un fichero services-config.xml puede hacerlo
|
|
|
+ abriendo su proyecto en la ventana del navegador.
|
|
|
+ Haga clic derecho sobre el nombre del proyecto y seleccione 'properties' (propiedades).
|
|
|
+ En el cuadro de diálogo 'properties' del proyecto ir al menú ‘Flex Build Path' (Crear ruta Flex),
|
|
|
+ luego en la pestaña ‘Library path’ (ruta de biblioteca) asegúrese
|
|
|
+ de que el fichero 'rpc.swc' sea añadido a su ruta de proyectos
|
|
|
+ y pulse Ok (Aceptar) para cerrar la ventana.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ También necesitará indicarle al compilador que debe usar
|
|
|
+ services-config.xml para encontrar el punto final de RemoteObject.
|
|
|
+ Para hacerlo, abra de nuevo el panel de propiedades de su proyecto
|
|
|
+ haciendo clic en el botón derecho sobre el proyecto en la carpeta del
|
|
|
+ navegador y seleccione 'properties' (propiedades).
|
|
|
+ Ahora seleccione ‘Flex Compiler' (Compilador Flex) y añada la cadena:
|
|
|
+ -services “services-config.xml".
|
|
|
+ Presione 'Apply' (Aplicar) y luego en OK para volver a actualizar la opción.
|
|
|
+ Lo que acaba de hacer es decirle al compilador Flex que busque en el fichero
|
|
|
+ services-config.xml aquellas variables que se usarán en tiempo de
|
|
|
+ ejecución por la clase RemotingObject.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Ahora, para conectarnos a nuestros métodos remotos debemos indicarle a Flex
|
|
|
+ qué fichero de configuración de servicios utilizar.
|
|
|
+ Por esta razón creamos un nuevo fichero 'services-config.xml'
|
|
|
+ en la carpeta src del proyecto Flex.
|
|
|
+ Con click derecho sobre el proyecto y seleccionando 'new'(nuevo)
|
|
|
+ 'File' (fichero), se abrirá una nueva ventana.
|
|
|
+ Seleccione la carpeta del proyecto y luego nombre el archivo
|
|
|
+ 'services-config.xml' y presione 'finish' (finalizar).
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Flex ha creado y abierto el nuevo fichero services-config.xml.
|
|
|
+ Utilice el siguiente texto de ejemplo para su fichero services-config.xml.
|
|
|
+ Asegúrese de actualizar su punto final para que concuerde con el servidor.
|
|
|
+ Asegúrese también de guardar el fichero.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="xml"><![CDATA[
|
|
|
+<?xml version="1.0" encoding="UTF-8"?>
|
|
|
+<services-config>
|
|
|
+ <services>
|
|
|
+ <service id="zend-service"
|
|
|
+ class="flex.messaging.services.RemotingService"
|
|
|
+ messageTypes="flex.messaging.messages.RemotingMessage">
|
|
|
+ <destination id="zend">
|
|
|
+ <channels>
|
|
|
+ <channel ref="zend-endpoint"/>
|
|
|
+ </channels>
|
|
|
+ <properties>
|
|
|
+ <source>*</source>
|
|
|
+ </properties>
|
|
|
+ </destination>
|
|
|
+ </service>
|
|
|
+ </services>
|
|
|
+ <channels>
|
|
|
+ <channel-definition id="zend-endpoint"
|
|
|
+ class="mx.messaging.channels.AMFChannel">
|
|
|
+ <endpoint uri="http://example.com/server.php"
|
|
|
+ class="flex.messaging.endpoints.AMFEndpoint"/>
|
|
|
+ </channel-definition>
|
|
|
+ </channels>
|
|
|
+</services-config>
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Hay dos puntos clave en el ejemplo.
|
|
|
+ En primer lugar, pero último en el listado, creamos un canal AMF,
|
|
|
+ y especificamos el punto final como la URL a nuestro <code>Zend_Amf_Server</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="xml"><![CDATA[
|
|
|
+<channel-definition id="zend-endpoint"
|
|
|
+ <endpoint uri="http://example.com/server.php"
|
|
|
+ class="flex.messaging.endpoints.AMFEndpoint"/>
|
|
|
+</channel-definition>
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Advierta que a este canal le hemos dado un identificador, "zend-endpoint".
|
|
|
+ El ejemplo crea un servicio cuyo destino hace referencia a este canal,
|
|
|
+ asignándole también un ID, en este caso es "zend".
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Dentro de nuestros ficheros Flex MXML, necesitamos vincular un RemoteObject al servicio.
|
|
|
+ En MXML, esto podría hacerse así:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="xml"><![CDATA[
|
|
|
+<mx:RemoteObject id="myservice"
|
|
|
+ fault="faultHandler(event)"
|
|
|
+ showBusyCursor="true"
|
|
|
+ source="RoundTrip"
|
|
|
+ destination="zend">
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Aquí, hemos definido un nuevo objeto remoto identificado por "myservice"
|
|
|
+ vinculado destino de servicio "zend" que hemos definido en el fichero
|
|
|
+ <code>services-config.xml</code>. Entonces invocamos sus métodos en
|
|
|
+ nuestro ActionScript simplemente llamando a "myservice.<method>".
|
|
|
+ (En este caso, el código original "RoundTrip" es el nombre de nuestra
|
|
|
+ aplicación Flex). Un ejemplo:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="ActionScript"><![CDATA[
|
|
|
+myservice.hello("Wade");
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cuando se usan nombres-de-espacio, puede usarse
|
|
|
+ "myservice.<namespace>.<method>":
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="ActionScript"><![CDATA[
|
|
|
+myservice.world.hello("Wade");
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para más información sobre como invocar a Flex RemoteObject visite el
|
|
|
+ sitio de ayuda de Adobe Flex 3 en:<ulink url="http://livedocs.adobe.com/flex/3/html/help.html?content=data_access_4.html"/>.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.amf.server.errors">
|
|
|
+ <title>Manejo de errores</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, todas las excepciones producidas en sus
|
|
|
+ clases o funciones adjuntas serán capturados y devueltas como
|
|
|
+ mensajes de error de AMF (AMF ErrorMessages).
|
|
|
+ Sin embargo, el contenido de estos objetos de mensajes de error
|
|
|
+ variará dependiendo de si el servidor está o no en modo "producción"
|
|
|
+ (el estado por defecto).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cuando se está en modo de producción, únicamente el código de excepción será devuelto.
|
|
|
+ Si desactiva el modo de producción, algo que debe hacerse sólo
|
|
|
+ para probar -- serán devueltos más detalles de la excepción:
|
|
|
+ el mensaje de excepción (error), línea y backtrace serán adjuntados.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para desactivar el modo de producción, haga lo siguiente:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$servidor->setProduction(false);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para habilitarlo nuevamente, pase el valor true en su lugar.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$servidor->setProduction(true);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>¡Deshabilite el modo de producción racionalmente!</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Sugerimos deshabilitar el modo de producción solo cuando se está
|
|
|
+ en modo de desarrollo.
|
|
|
+ Los mensajes de excepción y los backtraces puede contener información
|
|
|
+ sensible del sistema, y no desea que se pueda acceder a ellas
|
|
|
+ desde el exterior.
|
|
|
+ Aunque AMF es un formato binario, ahora al ser abierta la especificación,
|
|
|
+ cualquiera puede potencialmente deserializar los datos.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un área en la que se debe tener especialmente mucho cuidado son los
|
|
|
+ errores propios de PHP.
|
|
|
+ Cuando la directiva INI <code>display_errors</code> está habilitada,
|
|
|
+ los errores de PHP de cualquier nivel del reporte actual serán
|
|
|
+ pasados directamente a la salida, y potencialmente se podrían hacer
|
|
|
+ estragos con las respuestas de AMF.
|
|
|
+ Para prevenir estos problemas, sugerimos deshabilitar la directiva
|
|
|
+ <code>display_errors</code> cuando se está en modo de producción.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.amf.server.response">
|
|
|
+ <title>Respuestas de AMF</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En ocasiones es posible que quiera manipular ligeramente el objeto
|
|
|
+ respuesta, es bastante usual querer devolver algunas cebeceras
|
|
|
+ de mensajes adicionales. Puede hacerlo mediante el método del servidor
|
|
|
+ <code>handle()</code> que devuelve el objeto respuesta.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.amf.server.response.messageHeaderExample">
|
|
|
+ <title>Agregar cabeceras de mensaje a la respuesta de AMF</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En este ejemplo, añadiremos la cabecera de mensaje (MessageHeader)
|
|
|
+ "foo" con el valor 'bar' a la respuesta antes de devolverla.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$respuesta = $servidor->handle();
|
|
|
+$respuesta->addAmfHeader(new Zend_Amf_Value_MessageHeader('foo', true, 'bar'))
|
|
|
+echo $respuesta;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.amf.server.typedobjects">
|
|
|
+ <title>Objetos tipados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Similarmente a SOAP, AMF permite pasar objetos entre cliente y servidor.
|
|
|
+ Esto le da una gran flexibilidad y coherencia a ambos entornos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Amf</code> ofrece tres métodos para mapear ActionScript
|
|
|
+ y objetos PHP.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Primero, usted puede crear uniones explícitas a nivel del servidor,
|
|
|
+ utilizando el método <code>setClassMap()</code>.
|
|
|
+ El primer argumento es el nombre de la clase de ActionScript,
|
|
|
+ el segundo es el nombre de la clase PHP que lo mapea:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Mapea la clase ActionScript 'ContactVO' a la clase PHP 'Contact':
|
|
|
+$servidor->setClassMap('ContactVO', 'Contact');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Segundo, en su clase PHP puede ajustar la propiedad como pública
|
|
|
+ mediante <code>$_explicitType</code>, con el valor
|
|
|
+ representativo de la clase ActionScript que mapear:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Contact
|
|
|
+{
|
|
|
+ public $_explicitType = 'ContactVO';
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Tercero, en un sentido similar, puede definir como público el método
|
|
|
+ <code>getASClassName()</code> dentro de su clase.
|
|
|
+ Este método debe devolver la clase ActionScript apropiada:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Contact
|
|
|
+{
|
|
|
+ public function getASClassName()
|
|
|
+ {
|
|
|
+ return 'ContactVO';
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Aunque hemos creado ContactVO en el servidor,
|
|
|
+ ahora tenemos que hacer su clase correspondiente en AS3
|
|
|
+ para que el servidor pueda mapear el objeto.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Haga clic derecho sobre la carpeta src del proyecto Flex y seleccione New -> ActionScript File.
|
|
|
+ Nombre el fichero como ContactVO y pulse 'finish' (finalizar) para verlo.
|
|
|
+ Copie el siguiente código en el fichero para terminar de crear la clase.
|
|
|
+ </para>
|
|
|
+ <programlisting role="as"><![CDATA[
|
|
|
+package
|
|
|
+{
|
|
|
+ [Bindable]
|
|
|
+ [RemoteClass(alias="ContactVO")]
|
|
|
+ public class ContactVO
|
|
|
+ {
|
|
|
+ public var id:int;
|
|
|
+ public var firstname:String;
|
|
|
+ public var lastname:String;
|
|
|
+ public var email:String;
|
|
|
+ public var mobile:String;
|
|
|
+ public function ProductVO():void {
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ <para>
|
|
|
+ La clase es sintácticamente equivalente a la de PHP del mismo nombre.
|
|
|
+ Los nombres de variables son exactamente los mismos y necesitan estar
|
|
|
+ en el mismo contenedor para trabajar correctamente. Hay
|
|
|
+ dos meta tags AS3 únicos en esta clase.
|
|
|
+ El primero es vinculable y dispara un evento cuando es actualizada.
|
|
|
+ El segundo es el tag RemoteClass y define que esta clase puede tener
|
|
|
+ mapeado un objeto remoto con un nombre de alias, en este caso <code>ContactVO</code>
|
|
|
+ Es obligatorio que en esta etiqueta(tag), el valor que se estableció es la clase PHP
|
|
|
+ sea estrictamente equivalente.
|
|
|
+ </para>
|
|
|
+ <programlisting role="as"><![CDATA[
|
|
|
+[Bindable]
|
|
|
+private var myContact:ContactVO;
|
|
|
+
|
|
|
+private function getContactHandler(event:ResultEvent):void {
|
|
|
+ myContact = ContactVO(event.result);
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ <para>
|
|
|
+ El siguiente resultado del evento debido a la llamada de servicio,
|
|
|
+ se incorporó instantáneamente a ContactVO de Flex.
|
|
|
+ Cualquier cosa que esté ligada a myContact será actualizada con los
|
|
|
+ datos retornados por ContactVO.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.amf.server.flash">
|
|
|
+ <title>Conectándose al servidor desde Flash</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La conexión a <code>Zend_Amf_Server</code> desde su proyecto Flash
|
|
|
+ es ligeramente distinta a la de Flex. Sin embargo una vez que la conexión
|
|
|
+ con Flash funcione con <code>Zend_Amf_Server</code> lo hará igual
|
|
|
+ modo que con Flex. El siguiente ejemplo también puede ser utilizado
|
|
|
+ desde un fichero Flex AS3. Para nuestra conexión vamos a reutilizar
|
|
|
+ la misma configuracion <code>Zend_Amf_Server</code> junto a la clase Mundo.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Abra Flash CS y cree un nuevo fichero Flash (ActionScript 3).
|
|
|
+ Nombre al documento como ZendExample.fla y guárdelo en una carpeta
|
|
|
+ que utilizará para este ejemplo. Cree una nuevo fichero AS3 en el mismo
|
|
|
+ directorio y llámelo Main.as. Abra ambos ficheros con su editor.
|
|
|
+ Ahora vamos a conectar las dos ficheros a través de la clase documento.
|
|
|
+ Seleccione ZendExample y haga clic en el escenario.
|
|
|
+ Desde el panel del escenario cambie la propiedad de la clase Document a Main.
|
|
|
+ Esto vincula al fichero Main.as con la interfaz de usuario en ZendExample.fla.
|
|
|
+ Cuando ejecute el fichero ZendExample de Flash se ejecutará ahora
|
|
|
+ la clase Main.as.
|
|
|
+ El paso siguiente será añadir ActionScript para hacer una lamada AMF.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Ahora vamos a hacer una clase Main(principal) para que podamos enviar
|
|
|
+ los datos al servidor y mostrar el resultado.
|
|
|
+ Copie el código siguiente en su fichero Main.as y luego vamos a recorrer
|
|
|
+ el código para describir cuál es el papel de cada elemento.
|
|
|
+ </para>
|
|
|
+ <programlisting role="as"><![CDATA[
|
|
|
+package {
|
|
|
+ import flash.display.MovieClip;
|
|
|
+ import flash.events.*;
|
|
|
+ import flash.net.NetConnection;
|
|
|
+ import flash.net.Responder;
|
|
|
+
|
|
|
+ public class Main extends MovieClip {
|
|
|
+ private var gateway:String = "http://example.com/server.php";
|
|
|
+ private var connection:NetConnection;
|
|
|
+ private var responder:Responder;
|
|
|
+
|
|
|
+ public function Main() {
|
|
|
+ responder = new Responder(onResult, onFault);
|
|
|
+ connection = new NetConnection;
|
|
|
+ connection.connect(gateway);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function onComplete( e:Event ):void{
|
|
|
+ var params = "Sent to Server";
|
|
|
+ connection.call("World.hello", responder, params);
|
|
|
+ }
|
|
|
+
|
|
|
+ private function onResult(result:Object):void {
|
|
|
+ // Display the returned data
|
|
|
+ trace(String(result));
|
|
|
+ }
|
|
|
+ private function onFault(fault:Object):void {
|
|
|
+ trace(String(fault.description));
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Primero tenemos que importar dos bibliotecas de ActionScript que realizan
|
|
|
+ la mayor parte del trabajo. La primera es NetConnection que actúa como un
|
|
|
+ tubo bidireccional entre el cliente y el servidor.
|
|
|
+ La segunda es un objeto Responder que maneja los valores de retorno desde
|
|
|
+ el servidor, y que están relacionados con el éxito o el fracaso de la llamada.
|
|
|
+ </para>
|
|
|
+ <programlisting role="as"><![CDATA[
|
|
|
+import flash.net.NetConnection;
|
|
|
+import flash.net.Responder;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ <para>
|
|
|
+ En la clase necesitaremos tres variables para representar a NetConnection,
|
|
|
+ Responder, y la URL del gateway a nuestra instalación <code>Zend_Amf_Server</code>.
|
|
|
+ </para>
|
|
|
+ <programlisting role="as"><![CDATA[
|
|
|
+private var gateway:String = "http://example.com/server.php";
|
|
|
+private var connection:NetConnection;
|
|
|
+private var responder:Responder;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ <para>
|
|
|
+ En el constructor Main creamos un Responder(respondedor) y una nueva conexión al
|
|
|
+ punto final de <code>Zend_Amf_Server</code>. El respondedor define dos
|
|
|
+ diferentes métodos para manejar la respuesta desde el servidor.
|
|
|
+ Por simplicidad los hemos llamado onResult y onFault.
|
|
|
+ </para>
|
|
|
+ <programlisting role="as"><![CDATA[
|
|
|
+responder = new Responder(onResult, onFault);
|
|
|
+connection = new NetConnection;
|
|
|
+connection.connect(gateway);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ <para>
|
|
|
+ La función onComplete se ejecuta tan pronto como la construcción
|
|
|
+ ha concluido, enviando los datos al servidor.
|
|
|
+ Necesitamos añadir una línea más que hace una llamada a la función
|
|
|
+ <code>Zend_Amf_Server</code> Mundo->hola.
|
|
|
+ </para>
|
|
|
+ <programlisting role="as"><![CDATA[
|
|
|
+connection.call("Mundo.hola", responder, params);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ <para>
|
|
|
+ Cuando creamos la variable responder hemos definido las funciones onResult y onFault
|
|
|
+ para manejar la respuesta proveniente del servidor.
|
|
|
+ Hemos añadido la función OnResult para el resultado exitoso desde el servidor.
|
|
|
+ Cada vez que se ejecuta apropiadamente el manejo de conexión con el
|
|
|
+ servidor, el manejador de eventos llama esta función.
|
|
|
+ </para>
|
|
|
+ <programlisting role="as"><![CDATA[
|
|
|
+private function onResult(result:Object):void {
|
|
|
+ // Muestra los datos devueltos
|
|
|
+ trace(String(result));
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ <para>
|
|
|
+ La función onFault, se llama si hubo una respuesta nula desde el servidor.
|
|
|
+ Esto ocurre cuando hay un error en el servidor, la URL al servidor es inválida,
|
|
|
+ el servicio remoto o método no existe o cualquier otra cuestión
|
|
|
+ relacionada con la conexión.
|
|
|
+ </para>
|
|
|
+ <programlisting role="as"><![CDATA[
|
|
|
+private function onFault(fault:Object):void {
|
|
|
+ trace(String(fault.description));
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ <para>
|
|
|
+ La inclusión de ActionScript para realizar la conexión remota ha finalizado.
|
|
|
+ Al ejecutar el fichero ZendExample, se establece una conexión con Zend_Amf.
|
|
|
+ En resumen, se han añadido las variables requeridas para abrir una conexión
|
|
|
+ con el servidor remoto, se han definido qué métodos se deben utilizar cuando su aplicación
|
|
|
+ recibe una respuesta desde el servidor, y finalmente se han mostrado los datos de salida
|
|
|
+ devueltos a través de trace().
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.auth">
|
|
|
+ <title>Zend_Auth</title>
|
|
|
+ <sect1 id="zend.auth.introduction" xml:base="module_specs/Zend_Auth.xml">
|
|
|
+
|
|
|
+ <title>Introduction</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Auth provides an API for authentication and includes concrete authentication adapters for
|
|
|
+ common use case scenarios.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Auth is concerned only with <emphasis role="strong">authentication</emphasis> and not with
|
|
|
+ <emphasis role="strong">authorization</emphasis>. Authentication is loosely defined as determining
|
|
|
+ whether an entity actually is what it purports to be (i.e., identification), based on some set of
|
|
|
+ credentials. Authorization, the process of deciding whether to allow an entity access to, or to
|
|
|
+ perform operations upon, other entities is outside the scope of Zend_Auth. For more information about
|
|
|
+ authorization and access control with the Zend Framework, please see
|
|
|
+ <link linkend="zend.acl">Zend_Acl</link>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ The <code>Zend_Auth</code> class implements the Singleton pattern - only one instance of the class is
|
|
|
+ available - through its static <code>getInstance()</code> method. This means that using the <code>new</code>
|
|
|
+ operator and the <code>clone</code> keyword will not work with the <code>Zend_Auth</code> class; use
|
|
|
+ <code>Zend_Auth::getInstance()</code> instead.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <sect2 id="zend.auth.introduction.adapters">
|
|
|
+
|
|
|
+ <title>Adapters</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A Zend_Auth adapter is used to authenticate against a particular type of authentication service,
|
|
|
+ such as LDAP, RDBMS, or file-based storage. Different adapters are likely to have vastly different
|
|
|
+ options and behaviors, but some basic things are common among authentication adapters. For example,
|
|
|
+ accepting authentication credentials (including a purported identity), performing queries against the
|
|
|
+ authentication service, and returning results are common to Zend_Auth adapters.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Each Zend_Auth adapter class implements <code>Zend_Auth_Adapter_Interface</code>. This interface defines one
|
|
|
+ method, <code>authenticate()</code>, that an adapter class must implement for performing an authentication
|
|
|
+ query. Each adapter class must be prepared prior to calling <code>authenticate()</code>. Such adapter
|
|
|
+ preparation includes setting up credentials (e.g., username and password) and defining values for adapter-
|
|
|
+ specific configuration options, such as database connection settings for a database table adapter.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The following is an example authentication adapter that requires a username and password to be set
|
|
|
+ for authentication. Other details, such as how the authentication service is queried, have been
|
|
|
+ omitted for brevity:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class MyAuthAdapter implements Zend_Auth_Adapter_Interface
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * Sets username and password for authentication
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function __construct($username, $password)
|
|
|
+ {
|
|
|
+ // ...
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Performs an authentication attempt
|
|
|
+ *
|
|
|
+ * @throws Zend_Auth_Adapter_Exception If authentication cannot
|
|
|
+ * be performed
|
|
|
+ * @return Zend_Auth_Result
|
|
|
+ */
|
|
|
+ public function authenticate()
|
|
|
+ {
|
|
|
+ // ...
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ As indicated in its docblock, <code>authenticate()</code> must return an instance of
|
|
|
+ <code>Zend_Auth_Result</code> (or of a class derived from <code>Zend_Auth_Result</code>). If for some
|
|
|
+ reason performing an authentication query is impossible, <code>authenticate()</code> should throw
|
|
|
+ an exception that derives from <code>Zend_Auth_Adapter_Exception</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.auth.introduction.results">
|
|
|
+
|
|
|
+ <title>Results</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Auth adapters return an instance of <code>Zend_Auth_Result</code> with
|
|
|
+ <code>authenticate()</code> in order to represent the results of an authentication attempt. Adapters
|
|
|
+ populate the <code>Zend_Auth_Result</code> object upon construction, so that the following four methods
|
|
|
+ provide a basic set of user-facing operations that are common to the results of Zend_Auth adapters:
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>isValid()</code> - returns true if and only if the result represents a
|
|
|
+ successful authentication attempt
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>getCode()</code> - returns a <code>Zend_Auth_Result</code> constant identifier for
|
|
|
+ determining the type of authentication failure or whether success has occurred. This may be
|
|
|
+ used in situations where the developer wishes to distinguish among several authentication
|
|
|
+ result types. This allows developers to maintain detailed authentication result statistics,
|
|
|
+ for example. Another use of this feature is to provide specific, customized messages to
|
|
|
+ users for usability reasons, though developers are encouraged to consider the risks of
|
|
|
+ providing such detailed reasons to users, instead of a general authentication failure
|
|
|
+ message. For more information, see the notes below.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>getIdentity()</code> - returns the identity of the authentication attempt
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>getMessages()</code> - returns an array of messages regarding a failed
|
|
|
+ authentication attempt
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A developer may wish to branch based on the type of authentication result in order to perform more
|
|
|
+ specific operations. Some operations developers might find useful are locking accounts after too many
|
|
|
+ unsuccessful password attempts, flagging an IP address after too many nonexistent identities are
|
|
|
+ attempted, and providing specific, customized authentication result messages to the user. The following
|
|
|
+ result codes are available:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+Zend_Auth_Result::SUCCESS
|
|
|
+Zend_Auth_Result::FAILURE
|
|
|
+Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND
|
|
|
+Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS
|
|
|
+Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID
|
|
|
+Zend_Auth_Result::FAILURE_UNCATEGORIZED
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The following example illustrates how a developer may branch on the result code:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// inside of AuthController / loginAction
|
|
|
+$result = $this->_auth->authenticate($adapter);
|
|
|
+
|
|
|
+switch ($result->getCode()) {
|
|
|
+
|
|
|
+ case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
|
|
|
+ /** do stuff for nonexistent identity **/
|
|
|
+ break;
|
|
|
+
|
|
|
+ case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
|
|
|
+ /** do stuff for invalid credential **/
|
|
|
+ break;
|
|
|
+
|
|
|
+ case Zend_Auth_Result::SUCCESS:
|
|
|
+ /** do stuff for successful authentication **/
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ /** do stuff for other failure **/
|
|
|
+ break;
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.auth.introduction.persistence">
|
|
|
+
|
|
|
+ <title>Identity Persistence</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Authenticating a request that includes authentication credentials is useful per se, but it is also
|
|
|
+ important to support maintaining the authenticated identity without having to present the
|
|
|
+ authentication credentials with each request.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ HTTP is a stateless protocol, however, and techniques such as cookies and sessions have been
|
|
|
+ developed in order to facilitate maintaining state across multiple requests in server-side web
|
|
|
+ applications.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.auth.introduction.persistence.default">
|
|
|
+
|
|
|
+ <title>Default Persistence in the PHP Session</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ By default, <code>Zend_Auth</code> provides persistent storage of the identity from a successful
|
|
|
+ authentication attempt using the PHP session. Upon a successful authentication attempt,
|
|
|
+ <code>Zend_Auth::authenticate()</code> stores the identity from the authentication result into
|
|
|
+ persistent storage. Unless configured otherwise, <code>Zend_Auth</code> uses a storage class named
|
|
|
+ <code>Zend_Auth_Storage_Session</code>, which, in turn, uses
|
|
|
+ <link linkend="zend.session">Zend_Session</link>. A custom class may instead be used by providing an
|
|
|
+ object that implements <code>Zend_Auth_Storage_Interface</code> to
|
|
|
+ <code>Zend_Auth::setStorage()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ If automatic persistent storage of the identity is not appropriate for a particular use case, then
|
|
|
+ developers may forgo using the <code>Zend_Auth</code> class altogether, instead using an adapter
|
|
|
+ class directly.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <example id="zend.auth.introduction.persistence.default.example">
|
|
|
+
|
|
|
+ <title>Modifying the Session Namespace</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Auth_Storage_Session</code> uses a session namespace of <code>'Zend_Auth'</code>. This
|
|
|
+ namespace may be overridden by passing a different value to the constructor of
|
|
|
+ <code>Zend_Auth_Storage_Session</code>, and this value is internally passed along to the constructor
|
|
|
+ of <code>Zend_Session_Namespace</code>. This should occur before authentication is attempted, since
|
|
|
+ <code>Zend_Auth::authenticate()</code> performs the automatic storage of the identity.
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Save a reference to the Singleton instance of Zend_Auth
|
|
|
+$auth = Zend_Auth::getInstance();
|
|
|
+
|
|
|
+// Use 'someNamespace' instead of 'Zend_Auth'
|
|
|
+$auth->setStorage(new Zend_Auth_Storage_Session('someNamespace'));
|
|
|
+
|
|
|
+/**
|
|
|
+ * @todo Set up the auth adapter, $authAdapter
|
|
|
+ */
|
|
|
+
|
|
|
+// Authenticate, saving the result, and persisting the identity on
|
|
|
+// success
|
|
|
+$result = $auth->authenticate($authAdapter);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.auth.introduction.persistence.custom">
|
|
|
+
|
|
|
+ <title>Implementing Customized Storage</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Sometimes developers may need to use different identity persistence behavior than that provided by
|
|
|
+ <code>Zend_Auth_Storage_Session</code>. For such cases developers may simply implement
|
|
|
+ <code>Zend_Auth_Storage_Interface</code> and supply an instance of the class to
|
|
|
+ <code>Zend_Auth::setStorage()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.auth.introduction.persistence.custom.example">
|
|
|
+
|
|
|
+ <title>Using a Custom Storage Class</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In order to use an identity persistence storage class other than
|
|
|
+ <code>Zend_Auth_Storage_Session</code>, a developer implements
|
|
|
+ <code>Zend_Auth_Storage_Interface</code>:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class MyStorage implements Zend_Auth_Storage_Interface
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * Returns true if and only if storage is empty
|
|
|
+ *
|
|
|
+ * @throws Zend_Auth_Storage_Exception If it is impossible to
|
|
|
+ * determine whether storage
|
|
|
+ * is empty
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
+ public function isEmpty()
|
|
|
+ {
|
|
|
+ /**
|
|
|
+ * @todo implementation
|
|
|
+ */
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Returns the contents of storage
|
|
|
+ *
|
|
|
+ * Behavior is undefined when storage is empty.
|
|
|
+ *
|
|
|
+ * @throws Zend_Auth_Storage_Exception If reading contents from
|
|
|
+ * storage is impossible
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function read()
|
|
|
+ {
|
|
|
+ /**
|
|
|
+ * @todo implementation
|
|
|
+ */
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Writes $contents to storage
|
|
|
+ *
|
|
|
+ * @param mixed $contents
|
|
|
+ * @throws Zend_Auth_Storage_Exception If writing $contents to
|
|
|
+ * storage is impossible
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function write($contents)
|
|
|
+ {
|
|
|
+ /**
|
|
|
+ * @todo implementation
|
|
|
+ */
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Clears contents from storage
|
|
|
+ *
|
|
|
+ * @throws Zend_Auth_Storage_Exception If clearing contents from
|
|
|
+ * storage is impossible
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function clear()
|
|
|
+ {
|
|
|
+ /**
|
|
|
+ * @todo implementation
|
|
|
+ */
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In order to use this custom storage class, <code>Zend_Auth::setStorage()</code> is invoked before an
|
|
|
+ authentication query is attempted:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Instruct Zend_Auth to use the custom storage class
|
|
|
+Zend_Auth::getInstance()->setStorage(new MyStorage());
|
|
|
+
|
|
|
+/**
|
|
|
+ * @todo Set up the auth adapter, $authAdapter
|
|
|
+ */
|
|
|
+
|
|
|
+// Authenticate, saving the result, and persisting the identity on
|
|
|
+// success
|
|
|
+$result = Zend_Auth::getInstance()->authenticate($authAdapter);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.auth.introduction.using">
|
|
|
+
|
|
|
+ <title>Using Zend_Auth</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ There are two provided ways to use Zend_Auth adapters:
|
|
|
+ <orderedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ indirectly, through <code>Zend_Auth::authenticate()</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ directly, through the adapter's <code>authenticate()</code> method
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </orderedlist>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The following example illustrates how to use a Zend_Auth adapter indirectly, through the use of
|
|
|
+ the <code>Zend_Auth</code> class:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Get a reference to the singleton instance of Zend_Auth
|
|
|
+$auth = Zend_Auth::getInstance();
|
|
|
+
|
|
|
+// Set up the authentication adapter
|
|
|
+$authAdapter = new MyAuthAdapter($username, $password);
|
|
|
+
|
|
|
+// Attempt authentication, saving the result
|
|
|
+$result = $auth->authenticate($authAdapter);
|
|
|
+
|
|
|
+if (!$result->isValid()) {
|
|
|
+ // Authentication failed; print the reasons why
|
|
|
+ foreach ($result->getMessages() as $message) {
|
|
|
+ echo "$message\n";
|
|
|
+ }
|
|
|
+} else {
|
|
|
+ // Authentication succeeded; the identity ($username) is stored
|
|
|
+ // in the session
|
|
|
+ // $result->getIdentity() === $auth->getIdentity()
|
|
|
+ // $result->getIdentity() === $username
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Once authentication has been attempted in a request, as in the above example, it is a simple
|
|
|
+ matter to check whether a successfully authenticated identity exists:
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$auth = Zend_Auth::getInstance();
|
|
|
+if ($auth->hasIdentity()) {
|
|
|
+ // Identity exists; get it
|
|
|
+ $identity = $auth->getIdentity();
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ To remove an identity from persistent storage, simply use the <code>clearIdentity()</code> method.
|
|
|
+ This typically would be used for implementing an application "logout" operation:
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+Zend_Auth::getInstance()->clearIdentity();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ When the automatic use of persistent storage is inappropriate for a particular use case, a
|
|
|
+ developer may simply bypass the use of the <code>Zend_Auth</code> class, using an adapter class
|
|
|
+ directly. Direct use of an adapter class involves configuring and preparing an adapter object and
|
|
|
+ then calling its <code>authenticate()</code> method. Adapter-specific details are discussed in the
|
|
|
+ documentation for each adapter. The following example directly utilizes
|
|
|
+ <code>MyAuthAdapter</code>:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Set up the authentication adapter
|
|
|
+$authAdapter = new MyAuthAdapter($username, $password);
|
|
|
+
|
|
|
+// Attempt authentication, saving the result
|
|
|
+$result = $authAdapter->authenticate();
|
|
|
+
|
|
|
+if (!$result->isValid()) {
|
|
|
+ // Authentication failed; print the reasons why
|
|
|
+ foreach ($result->getMessages() as $message) {
|
|
|
+ echo "$message\n";
|
|
|
+ }
|
|
|
+} else {
|
|
|
+ // Authentication succeeded
|
|
|
+ // $result->getIdentity() === $username
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Auth_Adapter_DbTable.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Auth_Adapter_Digest.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Auth_Adapter_Http.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Auth_Adapter_Ldap.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Auth_Adapter_OpenId.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.cache">
|
|
|
+ <title>Zend_Cache</title>
|
|
|
+ <sect1 id="zend.cache.introduction" xml:base="module_specs/Zend_Cache-Introduction.xml">
|
|
|
+ <title>Introducción</title>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Cache</code>
|
|
|
+ provee una forma genérica para cualquier caché de datos.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ El almacenamiento en caché en Zend Framework se opera por
|
|
|
+ interfaces, mientras que los registros de caché son almacenados
|
|
|
+ a través de adapatadores del backend (
|
|
|
+ <code>Archivo</code>
|
|
|
+ ,
|
|
|
+ <code>Sqlite</code>
|
|
|
+ ,
|
|
|
+ <code>Memcache</code>
|
|
|
+ ...) mediante un sistema flexible de documentos de identidad y
|
|
|
+ etiquetas. Utilizando éstas, es fácil en el futuro eliminar
|
|
|
+ determinados tipos de registro.(Ejemplo: "eliminar todos los
|
|
|
+ registros caché de determinada etiqueta").
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ El módulo principal (
|
|
|
+ <code>Zend_Cache_Core</code>
|
|
|
+ ) es genérico, flexible y configurable. Aun para sus necesidades
|
|
|
+ específicas existen frontends de caché que extienden
|
|
|
+ <code>Zend_Cache_Core</code>
|
|
|
+ a conveniencia:
|
|
|
+ <code>Output</code>
|
|
|
+ ,
|
|
|
+ <code>File</code>
|
|
|
+ ,
|
|
|
+ <code>Function</code>
|
|
|
+ y
|
|
|
+ <code>Class</code>
|
|
|
+ .
|
|
|
+
|
|
|
+ </para>
|
|
|
+ <example id="zend.cache.introduction.example-1">
|
|
|
+ <title>
|
|
|
+ Obtener un frontend con
|
|
|
+ <code>Zend_Cache::factory()</code>
|
|
|
+ </title>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Cache::factory()</code>
|
|
|
+ ejemplifica objetos correctos y los une. En este primer
|
|
|
+ ejemplo, usaremos el frontend
|
|
|
+ <code>Core</code>
|
|
|
+ junto con el backend
|
|
|
+ <code>File</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$frontendOptions = array(
|
|
|
+ 'lifetime' => 7200, // tiempo de vida de caché de 2 horas
|
|
|
+ 'automatic_serialization' => true
|
|
|
+);
|
|
|
+
|
|
|
+$backendOptions = array(
|
|
|
+ 'cache_dir' => './tmp/' // Carpeta donde alojar los archivos de caché
|
|
|
+);
|
|
|
+
|
|
|
+// getting a Zend_Cache_Core object
|
|
|
+$cache = Zend_Cache::factory('Core',
|
|
|
+ 'File',
|
|
|
+ $frontendOptions,
|
|
|
+ $backendOptions);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>
|
|
|
+ Frontends y Backends Compuestos de Múltiples Palabras
|
|
|
+ </title>
|
|
|
+ <para>
|
|
|
+ Algunos frontends y backends se nombran usando varias
|
|
|
+ palabras, tal como 'ZenPlatform'. Al fabricarlas las
|
|
|
+ especificamos, las separamos usando un separador de
|
|
|
+ palabras, como un espacio (' '), guión ('-'), o punto ('.').
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <example id="zend.cache.introduction.example-2">
|
|
|
+ <title>Almacenando en caché un resultado de consulta a una base de datos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Ahora que tenemos un frontend, podemos almacenar en caché
|
|
|
+ cualquier tipo de dato (hemos activado la serialización). Por
|
|
|
+ ejemplo, podemos almacenar en caché un resultado de una
|
|
|
+ consulta de base de datos muy costosa. Después de ser
|
|
|
+ almacenada en caché, no es necesario ni conectar la base
|
|
|
+ de datos; los registros se obtienen del caché de forma no
|
|
|
+ serializada.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// $cache initializada en el ejemplo anterior
|
|
|
+
|
|
|
+// Verificar si la cahce existe:
|
|
|
+if(!$result = $cache->load('myresult')) {
|
|
|
+
|
|
|
+ // no existe cache; conectar a la base de datos
|
|
|
+
|
|
|
+ $db = Zend_Db::factory( [...] );
|
|
|
+
|
|
|
+ $result = $db->fetchAll('SELECT * FROM huge_table');
|
|
|
+
|
|
|
+ $cache->save($result, 'myresult');
|
|
|
+
|
|
|
+} else {
|
|
|
+
|
|
|
+ // cache existosa!, darlo a conocer
|
|
|
+ echo "Éste es de caché!\n\n";
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+print_r($result);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <example id="zend.cache.introduction.example-3">
|
|
|
+ <title>
|
|
|
+ El almacenamiento en caché de salida con la interfaz de
|
|
|
+ salida
|
|
|
+ <code>Zend_Cache</code>
|
|
|
+ </title>
|
|
|
+ <para>
|
|
|
+ ‘Resaltamos’ las secciones en las que deseamos almacenar en
|
|
|
+ caché la salida, mediante la adición de algunas condiciones lógicas,
|
|
|
+ encapsulamos la sección dentro de los métodos
|
|
|
+ <code>start()</code>
|
|
|
+ y
|
|
|
+ <code>end()</code>
|
|
|
+ (esto se parece al primer ejemplo y es la estrategia
|
|
|
+ fundamental para el almacenamiento en caché).
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Dentro, los datos de salida, como siempre – todas las salidas
|
|
|
+ serán almacenadas en caché cuando se ordene la ejecución del
|
|
|
+ método
|
|
|
+ <code>end()</code>
|
|
|
+ . En la siguiente ejecución, toda la sección se saltará a
|
|
|
+ favor de la búsqueda de datos del caché (tanto tiempo como
|
|
|
+ el registro del caché sea válido).
|
|
|
+ </para>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$frontendOptions = array(
|
|
|
+ 'lifetime' => 30, // tiempo de vida de caché de 30 segundos
|
|
|
+ 'automatic_serialization' => false // éste es el valor por defecto
|
|
|
+);
|
|
|
+
|
|
|
+$backendOptions = array('cache_dir' => './tmp/');
|
|
|
+
|
|
|
+$cache = Zend_Cache::factory('Output',
|
|
|
+ 'File',
|
|
|
+ $frontendOptions,
|
|
|
+ $backendOptions);
|
|
|
+
|
|
|
+// Pasamos un identificador único al método start()
|
|
|
+if(!$cache->start('mypage')) {
|
|
|
+ // salida como de costumbre:
|
|
|
+
|
|
|
+ echo 'Hola mundo! ';
|
|
|
+ echo 'Esto está en caché ('.time().') ';
|
|
|
+
|
|
|
+ $cache->end(); // la salida es guardada y enviada al navegador
|
|
|
+}
|
|
|
+
|
|
|
+echo 'Esto no estará en caché nunca ('.time().').';
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ <para>
|
|
|
+ Note que delineamos el resultado de
|
|
|
+ <code>time()</code>
|
|
|
+ dos veces; esto es algo dinámico para los propósitos de la
|
|
|
+ demostración. Trate de ejecutarlo y entonces regenérelo
|
|
|
+ muchas veces; notará que el primer número no cambia mientras
|
|
|
+ que el segundo cambia a medida que pasa el tiempo. Esto
|
|
|
+ es porque el primer número esta delineado en la sección
|
|
|
+ caché y esta guardado en medio de otras salidas. Después de
|
|
|
+ medio minuto (habremos establecido el tiempo de vida de 30
|
|
|
+ segundos) los números deben acoplarse nuevamente porque el
|
|
|
+ registro caché ha expirado -- sólo para ser almacenado en
|
|
|
+ caché nuevamente. Deberá probarlo en su visualizador o
|
|
|
+ consola.
|
|
|
+ </para>
|
|
|
+ </example>
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ Cuando usamos Zend_Cache, ponemos atención a la importación
|
|
|
+ del identificador caché (pasado a
|
|
|
+ <code>save()</code>
|
|
|
+ y
|
|
|
+ <code>start()</code>
|
|
|
+ ). Éste deberá ser único para cada recurso que se almacene
|
|
|
+ en caché, de otra manera los registros almacenados en caché
|
|
|
+ que no se vinculan podrían borrarse unos a otros, o peor
|
|
|
+ aún, mostrarse uno en lugar del otro.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+</sect1><!--
|
|
|
+ vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Cache-Theory.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Cache-Frontends.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Cache-Backends.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.captcha">
|
|
|
+ <title>Zend_Captcha</title>
|
|
|
+ <sect1 id="zend.captcha.introduction" xml:base="module_specs/Zend_Captcha.xml">
|
|
|
+ <title>Introducción</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <ulink url="http://en.wikipedia.org/wiki/Captcha">
|
|
|
+ CAPTCHA
|
|
|
+ </ulink>
|
|
|
+ es el acrónimo de "Completely Automated Public Turing test to
|
|
|
+ tell Computers and Humans Apart" (Prueba de Turing pública y
|
|
|
+ automática para diferenciar a máquinas y humanos). Es usado como un
|
|
|
+ desafío-respuesta para asegurar que la información individual suministrada
|
|
|
+ viene de un humano y no de un proceso automatizado. Típicamente,
|
|
|
+ un captcha es usado con envío de formularios donde no es necesario que el
|
|
|
+ usuario se haya autenticado, pero se desea prevenir el envío de spam.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los Captchas pueden presentarse en multitud de formas, incluyendo
|
|
|
+ preguntas lógicas, caracteres trastocados o presentar imágenes y preguntar
|
|
|
+ cómo se relacionan. Zend_Captcha intenta proveer una amalgama de backends
|
|
|
+ que pueden ser utilizados por separado o en conjunción con
|
|
|
+ <code>Zend_Form</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+</sect1><!--
|
|
|
+ vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Captcha-Operation.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Captcha-Adapters.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.config">
|
|
|
+ <title>Zend_Config</title>
|
|
|
+ <sect1 id="zend.config.introduction" xml:base="module_specs/Zend_Config-Introduction.xml">
|
|
|
+ <title>Introducción</title>
|
|
|
+ <para>
|
|
|
+
|
|
|
+ <code class="code">Zend_Config</code>
|
|
|
+ está diseñado para simplificar el acceso y el uso de datos de
|
|
|
+ configuración dentro de aplicaciones. Provee una interfaz de
|
|
|
+ usuario basada en propiedades de objetos anidadas para acceder a
|
|
|
+ datos de configuración dentro del código de la aplicación. Los
|
|
|
+ datos de configuración pueden venir de multitud de medios que
|
|
|
+ soporten almacenamiento de datos de forma jerárquica.
|
|
|
+ Actualmente
|
|
|
+ <code class="code">Zend_Config</code>
|
|
|
+ provee adaptadores para datos de configuración que están
|
|
|
+ almacenados en archivos de texto con
|
|
|
+ <link linkend="zend.config.adapters.ini">
|
|
|
+ <code>Zend_Config_Ini</code>
|
|
|
+ </link>
|
|
|
+ y
|
|
|
+ <link linkend="zend.config.adapters.xml">
|
|
|
+ <code>Zend_Config_Xml</code>
|
|
|
+ </link>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ <example id="zend.config.introduction.example.using">
|
|
|
+ <title>Usando Zend_Config Per Se</title>
|
|
|
+ <para>
|
|
|
+ Normalmente, se espera que los usuarios usen
|
|
|
+ una de las clases adaptadoras como
|
|
|
+ <link linkend="zend.config.adapters.ini">
|
|
|
+ <code>Zend_Config_Ini</code>
|
|
|
+ </link>
|
|
|
+ o
|
|
|
+ <link linkend="zend.config.adapters.xml">
|
|
|
+ <code>Zend_Config_Xml</code>
|
|
|
+ </link>
|
|
|
+ , pero si los datos de configuración están disponibles
|
|
|
+ en un array PHP, se puede simplemente pasar los datos al
|
|
|
+ constructor
|
|
|
+ <code>Zend_Config</code>
|
|
|
+ para utilizar una interfaz simple orientada a objetos:
|
|
|
+ </para>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Dado un array de datos de configuración
|
|
|
+$configArray = array(
|
|
|
+ 'webhost' => 'www.example.com',
|
|
|
+ 'database' => array(
|
|
|
+ 'adapter' => 'pdo_mysql',
|
|
|
+ 'params' => array(
|
|
|
+ 'host' => 'db.example.com',
|
|
|
+ 'username' => 'dbuser',
|
|
|
+ 'password' => 'secret',
|
|
|
+ 'dbname' => 'mydatabase'
|
|
|
+ )
|
|
|
+ )
|
|
|
+);
|
|
|
+
|
|
|
+// Crea el objeto a partir de los datos de configuración
|
|
|
+$config = new Zend_Config($configArray);
|
|
|
+
|
|
|
+// Muestra un dato de configuración (resultado: 'www.example.com')
|
|
|
+echo $config->webhost;
|
|
|
+
|
|
|
+// Use los datos de configuración para conectarse a la base de datos
|
|
|
+$db = Zend_Db::factory($config->database->adapter,
|
|
|
+ $config->database->params->toArray());
|
|
|
+
|
|
|
+// Uso alternativo: simplemente pase el objeto Zend_Config.
|
|
|
+// La Zend_Db factory sabe cómo interpretarlo.
|
|
|
+$db = Zend_Db::factory($config->database);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+ <para>
|
|
|
+ Como se ilustra en el ejemplo de arriba,
|
|
|
+ <code>Zend_Config</code>
|
|
|
+ provee una sintáxis de propiedades de objetos anidados para acceder a datos de configuración
|
|
|
+ pasados a su constructor.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Junto al acceso a valores de datos orientado a objetos,
|
|
|
+ <code>Zend_Config</code>
|
|
|
+ también tiene el método
|
|
|
+ <code>get()</code>
|
|
|
+ que devolverá el valor por defecto suministrado si el elemento
|
|
|
+ de datos no existe. Por ejemplo:
|
|
|
+ </para>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$host = $config->database->get('host', 'localhost');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ <example id="zend.config.introduction.example.file.php">
|
|
|
+ <title>Usando Zend_Config con un Archivo de Configuración PHP</title>
|
|
|
+ <para>
|
|
|
+ A veces, es deseable usar un archivo de configuración
|
|
|
+ puramente PHP. El código siguiente ilustra cómo podemos conseguir
|
|
|
+ esto fácilmente:
|
|
|
+ </para>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// config.php
|
|
|
+return array(
|
|
|
+ 'webhost' => 'www.example.com',
|
|
|
+ 'database' => array(
|
|
|
+ 'adapter' => 'pdo_mysql',
|
|
|
+ 'params' => array(
|
|
|
+ 'host' => 'db.example.com',
|
|
|
+ 'username' => 'dbuser',
|
|
|
+ 'password' => 'secret',
|
|
|
+ 'dbname' => 'mydatabase'
|
|
|
+ )
|
|
|
+ )
|
|
|
+);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Lectura de la configuración
|
|
|
+$config = new Zend_Config(require 'config.php');
|
|
|
+
|
|
|
+// Muestra un dato de configuración (resultado: 'www.example.com')
|
|
|
+echo $config->webhost;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+</sect1><!--
|
|
|
+ vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.config.theory_of_operation" xml:base="module_specs/Zend_Config-TheoryOfOperation.xml">
|
|
|
+ <title>Aspectos Teóricos</title>
|
|
|
+ <para>
|
|
|
+ Los datos de configuración se hacen accesibles al constructor <code>Zend_Config</code>
|
|
|
+ a través de un array asociativo, que puede ser multidimensional, para permitir
|
|
|
+ organizar los datos desde lo general a lo específico. Las clases de adaptador concretas
|
|
|
+ permiten construir una tabla asociativa para el constructor de <code>Zend_Config</code>
|
|
|
+ a partir de un sistema de almacenamiento de datos de configuración. Algunos scripts
|
|
|
+ de usuario pueden proveer esos arrays directamente al constructor Zend_Config,
|
|
|
+ sin usar una clase adaptador, lo cual puede ser apropiado en ciertas ocasiones.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Cada valor del array de datos de configuración se convierte en una propiedad del objeto <code>Zend_Config</code>.
|
|
|
+ La clave es usada como el nombre de la propiedad. Si un valor es un array por sí solo, entonces la propiedad
|
|
|
+ de objeto resultante es creada como un nuevo objeto
|
|
|
+ <code>Zend_Config</code>, cargado con los datos del array. Esto ocurre recursivamente, de forma
|
|
|
+ que una jerarquía de datos de configuración puede ser creada con cualquier número de niveles.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Config</code> implementa las interfaces <code>Countable</code> e <code>Iterator</code>
|
|
|
+ para facilitar el aceso sencillo a los datos de configuración.
|
|
|
+ Así, uno puede usar la función <ulink url="http://php.net/count"><code>count()</code></ulink>
|
|
|
+ y constructores PHP como
|
|
|
+ <ulink url="http://php.net/foreach"><code>foreach</code></ulink> sobre objetos
|
|
|
+ <code>Zend_Config</code>.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Por defecto, los datos de configuración permitidos a través de <code>Zend_Config</code>
|
|
|
+ son de sólo lectura, y una asignación (e.g.,
|
|
|
+ <code>$config->database->host = 'example.com'</code>)
|
|
|
+ provoca que se lance una excepción. Este comportamiento por defecto puede ser sobrescrito a través
|
|
|
+ del constructor, sin embargo, para permitir la modificación de valores de datos. Además, cuando
|
|
|
+ las modificaciones están permitidas, <code>Zend_Config</code> soporta el borrado de elementos (unset) (i.e. <code>unset($config->database->host);</code>). El método
|
|
|
+ <code>readOnly()</code> puede ser usado para determinar si las modificaciones a un objeto <code>Zend_Config</code>
|
|
|
+ están permitidas y el método <code>setReadOnly()</code> puede ser usado para evitar cualquier modificación
|
|
|
+ posterior a un objeto <code>Zend_Config</code> que fue creado con permiso de modificaciones.
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ Es importante no confundir tales modificaciones en memoria con guardar los datos de configuración a un
|
|
|
+ medio de almacenamiento específico. Las herramientas para crear y modificar datos de configuración para
|
|
|
+ distintos medios de almacenamiento están fuera del alcance de <code>Zend_Config</code>.
|
|
|
+ Existen soluciones third-party de código abierto con el propósito de crear y modificar
|
|
|
+ datos de configuración de distintos medios de almacenamiento.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Las clases del adaptador heredan de la clase <code>Zend_Config</code> debido a que utilizan su funcionalidad.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ La familia de clases <code>Zend_Config</code> permite organizar en secciones
|
|
|
+ los datos de configuración. Los objetos de adaptador <code>Zend_Config</code>
|
|
|
+ pueden ser cargados con una sola sección especificada, múltiples secciones especificadas,
|
|
|
+ o todas las secciones (si no se especifica ninguna).
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Las clases del adaptador <code>Zend_Config</code> soportan un modelo de herencia única
|
|
|
+ que permite que los datos de configuración hereden de una sección de datos de configuración a otra.
|
|
|
+ Esto es provisto con el fin de reducir o eliminar la necesidad de duplicar datos de configuración por
|
|
|
+ distintos motivos. Una sección heredada puede también sobrescribir los valores que hereda de su sección
|
|
|
+ padre. Al igual que la herencia de clases PHP, una sección puede heredar de una sección padre,
|
|
|
+ la cual puede heredar de una sección abuela, etc..., pero la herencia múltiple
|
|
|
+ (i.e., la sección C heredando directamente de las secciones padre A y B) no está permitida.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Si tiene dos objetos <code>Zend_Config</code>, puede combinarlos en un único
|
|
|
+ objeto usando la función <code>merge()</code>. Por ejemplo, dados <code>$config</code> y
|
|
|
+ <code>$localConfig</code>, puede fusionar datos de <code>$localConfig</code> a <code>$config</code> usando
|
|
|
+ <code>$config->merge($localConfig);</code>. Los ítemes en <code>$localConfig</code> sobrescribirán
|
|
|
+ cualquier item con el mismo nombre en <code>$config</code>.
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ El objeto <code>Zend_Config</code> que está ejecutando el merge debe haber sido construido
|
|
|
+ para permitir modificaciones, pasando <code>true</code> como el segundo parámetro del constructor.
|
|
|
+ El método <code>setReadOnly()</code> puede entonces ser usado para evitar cualquier
|
|
|
+ modificación posterior después de que el merge se haya completado.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+ </para>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.config.adapters.ini" xml:base="module_specs/Zend_Config_Ini.xml">
|
|
|
+ <title>Zend_Config_Ini</title>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Config_Ini</code>
|
|
|
+ permite a los desarrolladores almacenar datos de configuración
|
|
|
+ en un formato de datos INI familiar, y leer de ellos en la
|
|
|
+ aplicación usando una sintáxis de propiedades de objetos
|
|
|
+ anidados. El formato INI se especializa en proveer tanto la
|
|
|
+ habilidad de mantener una jerarquía de claves de datos (data
|
|
|
+ keys) de configuración como la de mantener una jerarquía entre
|
|
|
+ secciones de datos de configuración. Las jerarquías de datos de
|
|
|
+ configuración son provistas separando las claves mediante el
|
|
|
+ carácter punto (
|
|
|
+ <code>.</code>
|
|
|
+ ). Una sección puede extender o heredar de otra sección
|
|
|
+ indicando el nombre de la sección seguido de dos puntos (
|
|
|
+ <code>:</code>
|
|
|
+ ) y el nombre de la sección desde la cual se quieren heredar los
|
|
|
+ datos.
|
|
|
+ </para>
|
|
|
+ <note>
|
|
|
+ <title>parse_ini_file</title>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Config_Ini</code>
|
|
|
+ utiliza la función
|
|
|
+ <ulink url="http://php.net/parse_ini_file">
|
|
|
+ <code>parse_ini_file()</code>
|
|
|
+ </ulink>
|
|
|
+ de PHP. Por favor, revise esta documentación para observar
|
|
|
+ sus comportamientos específicos, que se propagan a
|
|
|
+ <code>Zend_Config_Ini</code>
|
|
|
+ , tales como la forma en que los valores especiales:
|
|
|
+ <code>true</code>
|
|
|
+ ,
|
|
|
+ <code>false</code>
|
|
|
+ ,
|
|
|
+ <code>yes</code>
|
|
|
+ ,
|
|
|
+ <code>no</code>
|
|
|
+ , y
|
|
|
+ <code>null</code>
|
|
|
+ son manejados.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+ <note>
|
|
|
+ <title>Separador de clave</title>
|
|
|
+ <para>
|
|
|
+ Por defecto, el carácter separador de clave es el punto (
|
|
|
+ <code>.</code>
|
|
|
+ ). Puede ser reemplazado, no obstante,cambiando la clave de
|
|
|
+ <code>$options</code>
|
|
|
+ llamada
|
|
|
+ <code>'nestSeparator'</code>
|
|
|
+ al construir el objeto
|
|
|
+ <code>Zend_Config_Ini</code>
|
|
|
+ . Por ejemplo:
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$options['nestSeparator'] = ':';
|
|
|
+$config = new Zend_Config_Ini('/path/to/config.ini',
|
|
|
+ 'pruebas',
|
|
|
+ $options);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+ <example id="zend.config.adapters.ini.example.using">
|
|
|
+ <title>Utilizando Zend_Config_Ini</title>
|
|
|
+ <para>
|
|
|
+ Este ejemplo muestra una forma de uso básica de
|
|
|
+ <code>Zend_Config_Ini</code>
|
|
|
+ para cargar datos de configuración de un archivo INI. En
|
|
|
+ este ejemplo hay datos de configuración tanto para un
|
|
|
+ sistema de producción como para un sistema en fase de
|
|
|
+ pruebas. Debido a que los datos de la fase de pruebas son
|
|
|
+ muy parecidos a los de producción, la sección de pruebas
|
|
|
+ hereda de la sección de producción. En este caso, la
|
|
|
+ decisión es arbitraria y podría haberse escrito a la
|
|
|
+ inversa, con la sección de producción heredando de la
|
|
|
+ sección de pruebas, a pesar de que éste no sería el caso
|
|
|
+ para situaciones más complejas. Supongamos, entonces, que
|
|
|
+ los siguientes datos de configuración están contenidos en
|
|
|
+ <code>/path/to/config.ini</code>
|
|
|
+ :
|
|
|
+ </para>
|
|
|
+ <programlisting role="ini"><![CDATA[
|
|
|
+; Datos de configuración de la web de producción
|
|
|
+[produccion]
|
|
|
+webhost = www.example.com
|
|
|
+database.adapter = pdo_mysql
|
|
|
+database.params.host = db.example.com
|
|
|
+database.params.username = dbuser
|
|
|
+database.params.password = secret
|
|
|
+database.params.dbname = dbname
|
|
|
+
|
|
|
+; Los datos de configuración de la fase de pruebas heredan de la producción
|
|
|
+; y sobreescribren valores si es necesario
|
|
|
+[pruebas : produccion]
|
|
|
+database.params.host = dev.example.com
|
|
|
+database.params.username = devuser
|
|
|
+database.params.password = devsecret
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ <para>
|
|
|
+ Ahora, asuma que el desarrollador de aplicaciones necesita
|
|
|
+ los datos de configuración de la etapa de pruebas del
|
|
|
+ archivo INI. Resulta fácil cargar estos datos especificando
|
|
|
+ el archivo INI en la sección de la etapa de pruebas:
|
|
|
+ </para>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$config = new Zend_Config_Ini('/path/to/config.ini', 'pruebas');
|
|
|
+
|
|
|
+echo $config->database->params->host; // muestra "dev.example.com"
|
|
|
+echo $config->database->params->dbname; // muestra "dbname"
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+ <note>
|
|
|
+ <table id="zend.config.adapters.ini.table">
|
|
|
+ <title>Parámetros del constructor Zend_Config_Ini</title>
|
|
|
+ <tgroup cols="2">
|
|
|
+ <thead>
|
|
|
+ <row>
|
|
|
+ <entry>Parámetros</entry>
|
|
|
+ <entry>Notas</entry>
|
|
|
+ </row>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ <row>
|
|
|
+ <entry>
|
|
|
+ <code>$filename</code>
|
|
|
+ </entry>
|
|
|
+ <entry>
|
|
|
+ El archivo INI que se va a cargar.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>
|
|
|
+ <code>$section</code>
|
|
|
+ </entry>
|
|
|
+ <entry>
|
|
|
+ La [sección] contenida en el archivo ini que
|
|
|
+ se va a cargar. Fijar este parámetro a null
|
|
|
+ cargará todas las secciones.
|
|
|
+ Alternativamente, se puede introducir un
|
|
|
+ array de nombres de sección para cargar
|
|
|
+ multiples secciones.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>
|
|
|
+ <code>$options = false</code>
|
|
|
+ </entry>
|
|
|
+ <entry>
|
|
|
+ Array de opciones. Las siguientes claves
|
|
|
+ están aceptadas:
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis>
|
|
|
+ allowModifications
|
|
|
+ </emphasis>
|
|
|
+ : Fijar a
|
|
|
+ <emphasis>true</emphasis>
|
|
|
+ para permitir modificaciones
|
|
|
+ subsiguientes del archivo
|
|
|
+ cargado. Por defecto es
|
|
|
+ <emphasis>false</emphasis>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis>
|
|
|
+ nestSeparator
|
|
|
+ </emphasis>
|
|
|
+ : Carácter que utilizar como
|
|
|
+ separador de anidamiento. Por
|
|
|
+ defecto es "."
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ </tbody>
|
|
|
+ </tgroup>
|
|
|
+ </table>
|
|
|
+ </note>
|
|
|
+</sect1><!--
|
|
|
+ vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.config.adapters.xml" xml:base="module_specs/Zend_Config_Xml.xml">
|
|
|
+ <title>Zend_Config_Xml</title>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Config_Xml</code> permite a los desarrolladores almacenar
|
|
|
+ datos de configuración en un formato sencillo XML y leerlos a través de
|
|
|
+ una sintáxis de propiedades de objetos anidados. El elemento raíz del
|
|
|
+ archivo XML es irrelevante y puede ser nombrado arbitrariamente.
|
|
|
+ El primer nivel de elementos XML corresponde con las secciones de datos
|
|
|
+ de configuración. El formato XML admite organización jerárquica a
|
|
|
+ través del anidamiento de elementos XML bajo los elementos a nivel de
|
|
|
+ sección. El contenido de un elemento XML a nivel de hoja corresponde al
|
|
|
+ valor de un dato de configuración. La herencia de sección está permitida
|
|
|
+ por un atributo XML especial llamado <code>extends</code>, y el valor de
|
|
|
+ este atributo se corresponde con la sección de la cual los datos son
|
|
|
+ heredados por la sección extendida..
|
|
|
+ </para>
|
|
|
+ <note>
|
|
|
+ <title>Tipo devuelto</title>
|
|
|
+ <para>
|
|
|
+ Los datos de configuración que se leen en <code>Zend_Config_Xml</code>
|
|
|
+ son siempre devueltos como strings.
|
|
|
+ La conversión de datos de string a otros tipos se deja en manos de los
|
|
|
+ desarrolladores para que se ajuste a sus necesidades particulares.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+ <example id="zend.config.adapters.xml.example.using">
|
|
|
+ <title>Usando Zend_Config_Xml</title>
|
|
|
+ <para>
|
|
|
+ Este ejemplo ilustra un uso básico de <code>Zend_Config_Xml</code>
|
|
|
+ para cargar datos de configuración de un archivo XML. En este ejemplo
|
|
|
+ hay datos de configuración tanto para un sistema de producción como
|
|
|
+ para un sistema de pruebas. Debido a que los datos de configuración del
|
|
|
+ sistema de pruebas son muy similares a los de producción, la sección de
|
|
|
+ pruebas hereda de la sección de producción. En este caso, la decisión
|
|
|
+ es arbitraria y podría haberse escrito a la inversa, con la sección de
|
|
|
+ producción heredando de la sección de pruebas, a pesar de que éste no
|
|
|
+ sería el caso para situaciones más complejas. Suponga, pues, que los
|
|
|
+ datos de configuración siguientes están contenidos
|
|
|
+ en <code>/ruta/de/config.xml</code>:
|
|
|
+ </para>
|
|
|
+ <programlisting role="xml"><![CDATA[
|
|
|
+<?xml version="1.0"?>
|
|
|
+<configdata>
|
|
|
+ <production>
|
|
|
+ <webhost>www.example.com</webhost>
|
|
|
+ <database>
|
|
|
+ <adapter>pdo_mysql</adapter>
|
|
|
+ <params>
|
|
|
+ <host>db.example.com</host>
|
|
|
+ <username>dbuser</username>
|
|
|
+ <password>secret</password>
|
|
|
+ <dbname>dbname</dbname>
|
|
|
+ </params>
|
|
|
+ </database>
|
|
|
+ </production>
|
|
|
+ <staging extends="production">
|
|
|
+ <database>
|
|
|
+ <params>
|
|
|
+ <host>dev.example.com</host>
|
|
|
+ <username>devuser</username>
|
|
|
+ <password>devsecret</password>
|
|
|
+ </params>
|
|
|
+ </database>
|
|
|
+ </staging>
|
|
|
+</configdata>
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+ <para>
|
|
|
+ Ahora, asuma que el desarrollador de aplicaciones necesita los datos
|
|
|
+ de configuración de la fase de pruebas del archivo XML. Es una tarea
|
|
|
+ sencilla cargar estos datos, especificando el archivo XML y la
|
|
|
+ sección de pruebas:
|
|
|
+ </para>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$config = new Zend_Config_Xml('/ruta/de/config.xml', 'pruebas');
|
|
|
+
|
|
|
+echo $config->database->params->host; // muestra "dev.example.com"
|
|
|
+echo $config->database->params->dbname; // muestra "dbname"
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+ <example id="zend.config.adapters.xml.example.attributes">
|
|
|
+ <title>Usando atributos de etiqueta en Zend_Config_Xml</title>
|
|
|
+ <para>
|
|
|
+ Zend_Config_Xml también soporta dos formas adicionales de definir
|
|
|
+ nodos en la configuración. Ambas hacen uso de atributos. Dado que
|
|
|
+ los atributos <code>extends</code> y <code>value</code> son palabras
|
|
|
+ reservadas (la última por la segunda manera de usar atributos),
|
|
|
+ pueden no ser utilizadas.
|
|
|
+ La primera manera de utilizar atributos es añadir atributos en un
|
|
|
+ nodo padre, el cual será interpretado como hijo de ese nodo:
|
|
|
+ </para>
|
|
|
+ <programlisting role="xml"><![CDATA[
|
|
|
+<?xml version="1.0"?>
|
|
|
+<configdata>
|
|
|
+ <production webhost="www.example.com">
|
|
|
+ <database adapter="pdo_mysql">
|
|
|
+ <params host="db.example.com" username="dbuser" password="secret" dbname="dbname"/>
|
|
|
+ </database>
|
|
|
+ </production>
|
|
|
+ <staging extends="production">
|
|
|
+ <database>
|
|
|
+ <params host="dev.example.com" username="devuser" password="devsecret"/>
|
|
|
+ </database>
|
|
|
+ </staging>
|
|
|
+</configdata>
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+ <para>
|
|
|
+ La otra forma no reduce la configuración, sino que permite mantenerla de
|
|
|
+ forma más fácil dado que no es necesario escribir el nombre de la
|
|
|
+ etiqueta dos veces. Simplemente, cree una etiqueta vacía con el valor en
|
|
|
+ el atributo <code>value</code>:
|
|
|
+ </para>
|
|
|
+ <programlisting role="xml"><![CDATA[
|
|
|
+<?xml version="1.0"?>
|
|
|
+<configdata>
|
|
|
+ <production>
|
|
|
+ <webhost>www.example.com</webhost>
|
|
|
+ <database>
|
|
|
+ <adapter value="pdo_mysql"/>
|
|
|
+ <params>
|
|
|
+ <host value="db.example.com"/>
|
|
|
+ <username value="dbuser"/>
|
|
|
+ <password value="secret"/>
|
|
|
+ <dbname value="dbname"/>
|
|
|
+ </params>
|
|
|
+ </database>
|
|
|
+ </production>
|
|
|
+ <staging extends="production">
|
|
|
+ <database>
|
|
|
+ <params>
|
|
|
+ <host value="dev.example.com"/>
|
|
|
+ <username value="devuser"/>
|
|
|
+ <password value="devsecret"/>
|
|
|
+ </params>
|
|
|
+ </database>
|
|
|
+ </staging>
|
|
|
+</configdata>
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+ </example>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.config.writer">
|
|
|
+ <title>Zend_Config_Writer</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Config_Writer.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.console.getopt">
|
|
|
+ <title>Zend_Console_Getopt</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Console_Getopt-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Console_Getopt-Rules.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Console_Getopt-Fetching.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Console_Getopt-Configuration.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.controller">
|
|
|
+ <title>Zend_Controller</title>
|
|
|
+ <sect1 id="zend.controller.quickstart" xml:base="module_specs/Zend_Controller-QuickStart.xml">
|
|
|
+ <title>Zend_Controller Quick Start</title>
|
|
|
+
|
|
|
+ <sect2 id="zend.controller.quickstart.introduction">
|
|
|
+ <title>Introducción</title>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Controller</code>
|
|
|
+ es el corazón del sistema de MVC de Zend Framework MVC. MVC
|
|
|
+ son las siglas de
|
|
|
+ <ulink url="http://en.wikipedia.org/wiki/Model-view-controller">
|
|
|
+ Modelo-Vista-Controlador
|
|
|
+ </ulink>
|
|
|
+ y es un patrón de diseño con el objetivo de separar la
|
|
|
+ lógica de la aplicación de la lógica de visualización.
|
|
|
+ <code>Zend_Controller_Front</code>
|
|
|
+ implementa el patrón
|
|
|
+ <ulink url="http://www.martinfowler.com/eaaCatalog/frontController.html">
|
|
|
+ Front Controller (Controlador Frontal)
|
|
|
+ </ulink>
|
|
|
+ en el cual todas las transacciones HTTP (requests) son
|
|
|
+ interceptadas por el controlador frontal y despachado a una
|
|
|
+ Acción particular de un Controlador según la URL pedida.
|
|
|
+
|
|
|
+
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ El sistema
|
|
|
+ <code>Zend_Controller</code>
|
|
|
+ fue construido con la extensibilidad en mente, ya sea
|
|
|
+ heredando las clases existentes, escribiendo nuevas clases
|
|
|
+ que implementan varias interfaces o clases abstractas que
|
|
|
+ forman la base de la familia de clases del controlador, o
|
|
|
+ escribiendo plugins o helpers de las acciones para aumentar
|
|
|
+ o manipular la funcionalidad del sistema.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.controller.quickstart.go">
|
|
|
+ <title>Quick Start</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si necesita información más detallada, mire las secciones
|
|
|
+ siguientes. Si solamente quiere inicializar y ejecutar una
|
|
|
+ aplicación rápidamente, siga leyendo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.controller.quickstart.go.directory">
|
|
|
+ <title>Cree su estructura de archivos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El primer paso es crear su estructura de archivos. La
|
|
|
+ estructura típica es la siguiente:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+application/
|
|
|
+ controllers/
|
|
|
+ IndexController.php
|
|
|
+ models/
|
|
|
+ views/
|
|
|
+ scripts/
|
|
|
+ index/
|
|
|
+ index.phtml
|
|
|
+ helpers/
|
|
|
+ filters/
|
|
|
+html/
|
|
|
+ .htaccess
|
|
|
+ index.php
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.controller.quickstart.go.docroot">
|
|
|
+ <title>Establezca su document root</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Apunte su document root en su servidor web hacia el
|
|
|
+ directorio
|
|
|
+ <code>html</code>
|
|
|
+ de la estrctura de archivos de arriba.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.controller.quickstart.go.rewrite">
|
|
|
+ <title>Cree sus reglas de reescritura</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Edite el archivo
|
|
|
+ <code>html/.htaccess</code>
|
|
|
+ que aparece arriba de la siguiente forma:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+RewriteEngine On
|
|
|
+RewriteCond %{REQUEST_FILENAME} -s [OR]
|
|
|
+RewriteCond %{REQUEST_FILENAME} -l [OR]
|
|
|
+RewriteCond %{REQUEST_FILENAME} -d
|
|
|
+RewriteRule ^.*$ - [NC,L]
|
|
|
+RewriteRule ^.*$ index.php [NC,L]
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La regla de arriba redigirá las peticiones a recuros existentes
|
|
|
+ (enlaces simbólicos existentes, archivos no vacíos, o directorios no vacíos)
|
|
|
+ en consecuencia, y todas las otras peticiones al front controller.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ Las reglas de arriba pertenecen a Apache. Para ejemplos de reglas
|
|
|
+ de rewrite para otros servidores web, mire la
|
|
|
+ <link linkend="zend.controller.router.introduction">
|
|
|
+ documentación de router
|
|
|
+ </link>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.controller.quickstart.go.bootstrap">
|
|
|
+ <title>Cree su archivo bootstrap</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El archivo bootstrap es la página a la que todas las peticiones
|
|
|
+ son redirigidas a través de --
|
|
|
+ <code>html/index.php</code>
|
|
|
+ en este caso. Abra el archivo
|
|
|
+ <code>html/index.php</code>
|
|
|
+ en el editor de su elección y añada lo siguiente:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+Zend_Controller_Front::run('/path/to/app/controllers');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esto instanciará y hará un dispatch del front controller, que
|
|
|
+ redigirá las peticiones a los action controllers.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.controller.quickstart.go.controller">
|
|
|
+ <title>Cree su action controller por defecto</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Antes de tratar los action controllers, debe primero
|
|
|
+ entender cómo las peticiones son redirigidas en Zend Framework.
|
|
|
+ Por defecto, el primero segmento de una ruta URL apunta
|
|
|
+ a un controlador, y el segundo a una acción. Por ejemplo,
|
|
|
+ dada la URL
|
|
|
+ <code>
|
|
|
+ http://framework.zend.com/roadmap/components
|
|
|
+ </code>
|
|
|
+ , la ruta es
|
|
|
+ <code>/roadmap/components</code>
|
|
|
+ , que apuntará al controlador
|
|
|
+ <code>roadmap</code>
|
|
|
+ y la acción
|
|
|
+ <code>components</code>
|
|
|
+ . Si no se suministra una acción, se asume la acción
|
|
|
+ <code>index</code>
|
|
|
+ , y si no se suministra un controlador, se asume el controlador
|
|
|
+ <code>index</code>
|
|
|
+ (siguiendo la convención de Apache de apuntar a
|
|
|
+ <code>DirectoryIndex</code>
|
|
|
+ automáticamente).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El dispatcher de <code>Zend_Controller</code>
|
|
|
+ toma entonces el valor del controlador y lo apunta
|
|
|
+ a una clase. Por defecto, pone en mayúsculas la primera letra
|
|
|
+ del nombre de controlador y agrega la palabra
|
|
|
+ <code>Controller</code>
|
|
|
+ . De esta forma, en nuestro ejemplo de arriba, el controlador
|
|
|
+ <code>roadmap</code>
|
|
|
+ es dirigido a la clase
|
|
|
+ <code>RoadmapController</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ De la misma forma, el valor de action es dirigido
|
|
|
+ a un método de la clase controladora. Por defecto, el valor se
|
|
|
+ pasa a minúsculas, y la palabra
|
|
|
+ <code>Action</code>
|
|
|
+ es añadida. De esta forma, en nuestro ejemplo de arriba, la acción
|
|
|
+ <code>components</code>
|
|
|
+ se convierte en
|
|
|
+ <code>componentsAction</code>
|
|
|
+ , y el método final llamado es
|
|
|
+ <code>RoadmapController::componentsAction()</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Continuando, creemos ahora un action controller
|
|
|
+ y un método de acción por defecto. Como se ha dicho antes,
|
|
|
+ el controlador por defecto y la acción llamada son ambos
|
|
|
+ <code>index</code>
|
|
|
+ . Abra el archivo
|
|
|
+ <code>application/controllers/IndexController.php</code>
|
|
|
+ , e introduzca lo siguiente:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+/** Zend_Controller_Action */
|
|
|
+class IndexController extends Zend_Controller_Action
|
|
|
+{
|
|
|
+ public function indexAction()
|
|
|
+ {
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, el action helper
|
|
|
+ <link linkend="zend.controller.actionhelpers.viewrenderer">
|
|
|
+ ViewRenderer
|
|
|
+ </link>
|
|
|
+ está activado. Esto significa que simplemente
|
|
|
+ definiendo un action method y un view script correspondiente,
|
|
|
+ tendrá su contenido generado inmediatamente.
|
|
|
+ Por defecto,
|
|
|
+ <code>Zend_View</code>
|
|
|
+ es usado como la capa Vista en el patrón MVC. El
|
|
|
+ <code>ViewRenderer</code>
|
|
|
+ hace algo de magia, y usa el nombre de controlador (e.g.,
|
|
|
+ <code>index</code>
|
|
|
+ ) y el nombre de acción actual (e.g.,
|
|
|
+ <code>index</code>
|
|
|
+ ) para determinar qué plantilla traer. Por defecto,
|
|
|
+ las plantillas terminan con la extensión
|
|
|
+ <code>.phtml</code>
|
|
|
+ , lo que significa que en el ejemplo de arriba, la
|
|
|
+ plantilla
|
|
|
+ <code>index/index.phtml</code>
|
|
|
+ será generada. Adicionalmente, el
|
|
|
+ <code>ViewRenderer</code>
|
|
|
+ asume automáticamente que la carpeta
|
|
|
+ <code>views</code>
|
|
|
+ al mismo nivel que la carpeta controller será
|
|
|
+ la carpeta raíz de la vista, y que el script de vista actual
|
|
|
+ estará en la subcarpeta
|
|
|
+ <code>views/scripts/</code>.
|
|
|
+ De esta forma, la plantilla generada será encontrada en
|
|
|
+ <code>application/views/scripts/index/index.phtml</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.controller.quickstart.go.view">
|
|
|
+ <title>Cree su view script</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como hemos mencionado
|
|
|
+ <link linkend="zend.controller.quickstart.go.controller">
|
|
|
+ en la sección anterior
|
|
|
+ </link>
|
|
|
+ , los scripts de vista se encuentran en
|
|
|
+ <code>application/views/scripts/</code>
|
|
|
+ ; el view script para el controlador y la acción por defecto
|
|
|
+ está en
|
|
|
+ <code>application/views/scripts/index/index.phtml</code>
|
|
|
+ . Cree este archivo, y escriba un poco de HTML:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+<!DOCTYPE html
|
|
|
+PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
|
|
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
|
+<html>
|
|
|
+<head>
|
|
|
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
|
+ <title>Mi primera aplicación Zend Framework</title>
|
|
|
+</head>
|
|
|
+<body>
|
|
|
+ <h1>>¡Hola, Mundo!</h1>
|
|
|
+</body>
|
|
|
+</html>
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.controller.quickstart.go.errorhandler">
|
|
|
+ <title>Cree su controlador de errores</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, está registrado
|
|
|
+ <link linkend="zend.controller.plugins.standard.errorhandler">
|
|
|
+ el plugin 'error handler'
|
|
|
+ </link>. Este plugin espera que exista
|
|
|
+ un controlador para manejar los errores.
|
|
|
+ Por defecto, asume un
|
|
|
+ <code>ErrorController</code>
|
|
|
+ en el módulo default con un método
|
|
|
+ <code>errorAction</code>
|
|
|
+ :
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class ErrorController extends Zend_Controller_Action
|
|
|
+{
|
|
|
+ public function errorAction()
|
|
|
+ {
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Asumiendo el sistema de carpetas discutido anteriormente,
|
|
|
+ este archivo irá en
|
|
|
+ <code>application/controllers/ErrorController.php</code>
|
|
|
+ . También necesitará crear un view script en
|
|
|
+ <code>application/views/scripts/error/error.phtml</code>
|
|
|
+ ; el contenido de ejemplo será parecido a:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+<!DOCTYPE html
|
|
|
+PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
|
|
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
|
+<html>
|
|
|
+<head>
|
|
|
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
|
+ <title>Error</title>
|
|
|
+</head>
|
|
|
+<body>
|
|
|
+ <h1>Ocurrió un error</h1>
|
|
|
+ <p>Ocurrió un error; Por favor, inténtelo de nuevo más tarde.</p>
|
|
|
+</body>
|
|
|
+</html>
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.controller.quickstart.go.finish">
|
|
|
+ <title>¡Vea el sitio!</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Con su primer controlador y vista, ya puede arrancar su navegador y acceder a su sitio.
|
|
|
+ Asumiendo que
|
|
|
+ <code>example.com</code>
|
|
|
+ es su dominio, cualquiera de las siguientes URLs le llevará a
|
|
|
+ la página que acaba de crear:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>http://example.com/</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>http://example.com/index</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>http://example.com/index/index</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Ya está listo para empezar a crear más métodos de controladores y acciones. ¡Felicidades!
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+ vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Controller-Basics.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Controller-FrontController.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Controller-Request.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Controller-Router.xml" parse="xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Controller-Dispatcher.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Controller-ActionController.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Controller-ActionHelpers.xml" parse="xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Controller-Response.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Controller-Plugins.xml" parse="xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Controller-Modular.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Controller-Exceptions.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Controller-Migration.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.currency">
|
|
|
+ <title>Zend_Currency</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Currency-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Currency-Usage.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Currency-Migrating.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.date">
|
|
|
+ <title>Zend_Date</title>
|
|
|
+ <sect1 id="zend.date.introduction" xml:base="module_specs/Zend_Date-Introduction.xml">
|
|
|
+
|
|
|
+ <title>Introducción</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El componente
|
|
|
+ <code>Zend_Date</code>
|
|
|
+ ofrece una API detallada pero simple para manipular fechas y
|
|
|
+ horas. Sus métodos aceptan una gran variedad de tipos de
|
|
|
+ información, incluyendo partes de fecha, en numerosas
|
|
|
+ combinaciones provocando muchas características y posibilidades
|
|
|
+ más allá de las funciones de fecha PHP relacionadas. Para
|
|
|
+ las últimas actualizaciones manuales, por favor ver el siguiente
|
|
|
+ link <ulink>
|
|
|
+ url="http://framework.zend.com/wiki/display/ZFDOCDEV/Home">our
|
|
|
+ online manual (sincronizado frecuentemente con Subversion)
|
|
|
+ </ulink>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Aunque la simplicidad sea el objetivo, trabajar con fechas y
|
|
|
+ tiempos localizados mientras se modifican, combinan y comparan
|
|
|
+ partes, provoca una complejidad inevitable. Las fechas, así como
|
|
|
+ los tiempos, a menudo son escritos de forma diferente en
|
|
|
+ zonas locales distintas. Por ejemplo, algunos colocan primero el
|
|
|
+ mes, mientras otros escriben el año en primer lugar cuando
|
|
|
+ expresan fechas del calendario. Para más información relacionada
|
|
|
+ con manejo de localizaciones y normalización, por favor
|
|
|
+ vea el manual de
|
|
|
+ <link linkend="zend.locale.date.datesandtimes">
|
|
|
+ <code>Zend_Locale</code>
|
|
|
+ </link>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Date</code>
|
|
|
+ también soporta nombres de meses abreviados en varios idiomas.
|
|
|
+ <code>Zend_Locale</code>
|
|
|
+ facilita la normalización de meses localizados y nombres de días
|
|
|
+ de la semana a timestamps, los cuales pueden, a su vez, ser
|
|
|
+ mostrados localizados a otras regiones.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="zend.date.setdefaulttimezone">
|
|
|
+
|
|
|
+ <title>Asigne Siempre una Zona Horaria por Defecto</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Antes de utilizar funciones relacionadas con fechas en PHP o
|
|
|
+ en el Zend Framework, primero debe asegurarse que su
|
|
|
+ aplicación tiene una zona horaria correcta por defecto,
|
|
|
+ configurando la variable de entorno TZ, usando el
|
|
|
+ parametro del php.ini
|
|
|
+ <code>date.timezone</code>
|
|
|
+ , o usando
|
|
|
+ <ulink url="http://php.net/date_default_timezone_set">
|
|
|
+ date_default_timezone_set()
|
|
|
+ </ulink>
|
|
|
+ . En PHP, podemos ajustar todas las funciones relacionadas
|
|
|
+ con fechas y hora para trabajar para un usuario particular
|
|
|
+ configurando por defecto una zona horaria de acuerdo a las
|
|
|
+ expectativas del usuario. Para una lista completa de
|
|
|
+ configuraciones de zona horaria, vea el siguiente link
|
|
|
+ <ulink url="http://unicode.org/cldr/data/diff/supplemental/territory_containment_un_m_49.html">
|
|
|
+ Lista de Identificadores de Zonas Horarias CLDR
|
|
|
+ </ulink>
|
|
|
+ .
|
|
|
+ <example id="zend.date.setdefaulttimezone.example-1">
|
|
|
+ <title>Configurando una Zona Horaria por Defecto</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+ // zona horaria para un estadounidense en California
|
|
|
+date_default_timezone_set('America/Los_Angeles');
|
|
|
+// zona horaria para un alemán en Alemania
|
|
|
+date_default_timezone_set('Europe/Berlin');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+ <emphasis role="strong">¡Al crear instancias de Zend_Date, su zona horaria se convertirá automáticamente
|
|
|
+ en la zona horaria por defecto actual!</emphasis> De esta forma, la configuración de zona horaria tendrá
|
|
|
+ en cuenta cualquier cambio de hora de invierno/verano (Daylight Saving Time, DST), eliminando la necesidad
|
|
|
+ de especificarlo explícitamente.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Tenga en cuenta que las zonas horarias <emphasis role="strong">UTC</emphasis> y
|
|
|
+ <emphasis role="strong">GMT</emphasis> no incluyen el cambio de hora de invierno/verano (Daylight Saving Time, DST).
|
|
|
+ Esto significa que aunque defina a mano que <code>Zend_Date</code> deba trabajar con DST, podría
|
|
|
+ ser anulado por las instancias de <code>Zend_Date</code> que han sido fijadas a
|
|
|
+ UTC o GMT.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.date.why">
|
|
|
+
|
|
|
+ <title>¿Por Qué Usar Zend_Date?</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Date</code> ofrece las siguientes prestaciones, las cuales extienden el alcance de las funciones de fecha de PHP:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist mark="opencircle">
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ API sencilla
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Date</code> aporta una API muy sencilla, que combina lo mejor de la funcionalidad
|
|
|
+ fecha/hora de cuatro lenguajes de programación. Es posible, por ejemplo, añadir o comparar dos horas
|
|
|
+ dentro de una misma columna.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Completamente internacionalizado
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Todos los nombres de meses y días de la semana completos y abreviados están incluidos para más de 130 idiomas.
|
|
|
+ Los métodos admiten tanto entrada como salida de fechas usando los nombres localizados de meses y días de la semana.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Timestamps ilimitados
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ A pesar de que la documentación de PHP 5.2 indice: "El intervalo de valores admitidos de timestamps es
|
|
|
+ desde el 13 Dec 1901 20:45:54 GMT al 19 Ene 2038 03:14:07 GMT," <code>Zend_Date</code> admite un rango
|
|
|
+ casi ilimitado, con la ayuda de la extensión BCMath. Si BCMath no está disponible, Zend_Date tendrá una
|
|
|
+ funcionalidad de timestamps reducida al rango del tipo <code>float</code> soportado por su servidor.
|
|
|
+ El tamaño de un float es dependiente de la plataforma, aunque un máximo de ~1.8e308 con una precisión
|
|
|
+ de cerca de 14 dígitos decimales es un valor habitual (formato 64 bit IEEE)." [
|
|
|
+ <ulink url="http://www.php.net/float">http://www.php.net/float</ulink>
|
|
|
+ ]. Adicionalmente, las limitaciones heredadas de los tipos de dato float, y errores de redondeo de números
|
|
|
+ flotantes pueden introducir errores en los cálculos. Para evitar estos problemas, los componentes ZF I18n
|
|
|
+ usan la extensión BCMath, si está disponible.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Soporte para especificaciones de fecha ISO_8601
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Las especificaciones de fecha ISO_8601 están aceptadas. Incluso las especificaciones de fecha ISO_8601
|
|
|
+ parcialmente autorizadas serán identificadas. Estos formatos de fecha son particularmente útiles al
|
|
|
+ trabajar con bases de datos. Por ejemplo, aunque MsSQL y
|
|
|
+ <ulink url="http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html">MySQL</ulink>
|
|
|
+ difieren ligeramente uno de otro, ambos tienen soporte por parte de <code>Zend_Date</code> usando la constante
|
|
|
+ de especificación de formato
|
|
|
+ <link linkend="zend.date.constants.list">Zend_Date::ISO_8601</link>.
|
|
|
+ Cuando las cadenas de fecha sean del tipo "Y/m/d" o "Y-m-d H:i:s", de acuerdo con los tokens de formato
|
|
|
+ PHP date(), use el soporte integrado de Zend_Date para fechas formateadas ISO 8601.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Calcular amanecer y puesta de sol
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Las horas de amanecer y puesta de sol pueden mostrarse para cualquier lugar y día, para que no pierda ni un segundo de luz diurna
|
|
|
+ para trabajar en su proyecto PHP favorito :)
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+ vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Date-Theory.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Date-Basic.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Date-Overview.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Date-Creation.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Date-Constants.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Date-Additional.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.db">
|
|
|
+ <title>Zend_Db</title>
|
|
|
+ <sect1 id="zend.db.adapter" xml:base="module_specs/Zend_Db_Adapter.xml">
|
|
|
+
|
|
|
+ <title>Zend_Db_Adapter</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Db y sus clases relacionadas proporcionan una interfaz
|
|
|
+ simple de base de datos SQL para Zend Framework. El
|
|
|
+ Zend_Db_Adapter es la clase base que se utiliza para conectar su
|
|
|
+ aplicación PHP A una base de datos (RDBMS). Existen diferentes
|
|
|
+ clases Adapters(Adaptador) para cada tipo de base de datos
|
|
|
+ (RDBMS).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las clases
|
|
|
+ <code>Adapters</code>
|
|
|
+ de Zend_Db crean un puente entre las extensiones de base de
|
|
|
+ datos de PHP hacia una interfaz común, para ayudarle a escribir
|
|
|
+ aplicaciones PHP una sola vez y poder desplegar múltiples
|
|
|
+ tipos de base de datos (RDBMS) con muy poco esfuerzo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La Interfaz de la clase adaptador (adapter) es similar a la
|
|
|
+ intefaz de la extensión
|
|
|
+ <ulink url="http://www.php.net/pdo">PHP Data Objects</ulink>
|
|
|
+ . Zend_Db proporciona clases Adaptadoras para los drivers PDO de
|
|
|
+ los siguientes tipos de RDBMS:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ IBM DB2 e Informix Dynamic Server (IDS), usando la
|
|
|
+ extensión PHP
|
|
|
+ <ulink url="http://www.php.net/pdo-ibm">pdo_ibm</ulink>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ MySQL, usando la extensión PHP
|
|
|
+ <ulink url="http://www.php.net/pdo-mysql">
|
|
|
+ pdo_mysql
|
|
|
+ </ulink>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Microsoft SQL Server, usando la extensión PHP
|
|
|
+ <ulink url="http://www.php.net/pdo-mssql">
|
|
|
+ pdo_mssql
|
|
|
+ </ulink>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Oracle, usando la extensión PHP
|
|
|
+ <ulink url="http://www.php.net/pdo-oci">pdo_oci</ulink>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ PostgreSQL, usando la extensión PHP
|
|
|
+ <ulink url="http://www.php.net/pdo-pgsql">
|
|
|
+ pdo_pgsql
|
|
|
+ </ulink>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ SQLite, usando la extensión PHP
|
|
|
+ <ulink url="http://www.php.net/pdo-sqlite">
|
|
|
+ pdo_sqlite
|
|
|
+ </ulink>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Ademas, Zend_Db proporciona clases Adaptadoras que utilizan las
|
|
|
+ extensiones de base de datos de PHP de los siguientes tipos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ MySQL, usando la extensión PHP
|
|
|
+ <ulink url="http://www.php.net/mysqli">mysqli</ulink>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Oracle, usando la extensión PHP
|
|
|
+ <ulink url="http://www.php.net/oci8">oci8</ulink>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ IBM DB2, usando la extensión PHP
|
|
|
+ <ulink url="http://www.php.net/ibm_db2">ibm_db2</ulink>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Firebird/Interbase, usando la extensión PHP
|
|
|
+ <ulink url="http://www.php.net/ibase">
|
|
|
+ php_interbase
|
|
|
+ </ulink>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ Cada Zend_Db_Adaptador utiliza una extensión PHP. Se debe de
|
|
|
+ tener habilitada la respectiva extensión en su entorno PHP
|
|
|
+ para utilizar un Zend_Db_Adapter. Por ejemplo, si se utiliza
|
|
|
+ una clase Zend_Db_Adapter basada en PDO, tiene que
|
|
|
+ habilitar tanto la extensión PDO como el driver PDO del tipo
|
|
|
+ de base de datos que se utiliza.
|
|
|
+
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.adapter.connecting">
|
|
|
+
|
|
|
+ <title>
|
|
|
+ Conexión a una Base de Datos utilizando un Adaptador
|
|
|
+ </title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esta sección describe cómo crear una instancia de un
|
|
|
+ Adaptador de base de datos. Esto corresponde a establecer
|
|
|
+ una conexión a un servidor de Base de Datos (RDBMS) desde su
|
|
|
+ aplicación PHP.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.connecting.constructor">
|
|
|
+
|
|
|
+ <title>Usando un Constructor de Zend_Db Adapter</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Se puede crear una instancia de un Adaptador utilizando
|
|
|
+ su constructor. Un constructor de adaptador toma un
|
|
|
+ argumento, que es un conjunto de parámetros utilizados
|
|
|
+ para declarar la conexión.
|
|
|
+ </para>
|
|
|
+
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.connecting.constructor.example">
|
|
|
+ <title>Usando el Constructor de un Adaptador</title>
|
|
|
+ <programlisting role="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>Usando el Factory de Zend_Db</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como alternativa a la utilización directa del
|
|
|
+ constructor de un adaptador, se puede crear una
|
|
|
+ instancia del adaptador que use el método estático
|
|
|
+ <code>Zend_Db::factory()</code>
|
|
|
+ . Este método carga dinámicamente el archivo de clase
|
|
|
+ Adaptador bajo demanda, usando
|
|
|
+ <link linkend="zend.loader.load.class">
|
|
|
+ Zend_Loader::loadClass()
|
|
|
+ </link>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El primer argumento es una cadena que nombra al nombre base
|
|
|
+ de la clase Adaptador. Por ejemplo, la cadena
|
|
|
+ 'Pdo_Mysql' corresponde a la clase
|
|
|
+ Zend_Db_Adapter_Pdo_Mysql. El segundo argumento es el
|
|
|
+ mismo array de parámetros que hubiera enviado al
|
|
|
+ constructor del adaptador.
|
|
|
+ </para>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.connecting.factory.example">
|
|
|
+ <title>Usando el Adaptador del método factory</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// No necesitamos la siguiente declaración, porque
|
|
|
+// el archivo Zend_Db_Adapter_Pdo_Mysql será cargado para nosotros por el método
|
|
|
+// factory de Zend_Db.
|
|
|
+
|
|
|
+// require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
|
|
|
+
|
|
|
+// carga automaticamente la clase Zend_Db_Adapter_Pdo_Mysql
|
|
|
+// y crea una instancia de la misma
|
|
|
+$db = Zend_Db::factory('Pdo_Mysql', array(
|
|
|
+ 'host' => '127.0.0.1',
|
|
|
+ 'username' => 'webuser',
|
|
|
+ 'password' => 'xxxxxxxx',
|
|
|
+ 'dbname' => 'test'
|
|
|
+));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si crea su propia clase que extiende a
|
|
|
+ Zend_Db_Adapter_Abstract, pero no nombra su clase con el prefijo
|
|
|
+ de paquete "Zend_Db_Adapter", se puede utilizar el método
|
|
|
+ <code>factory()</code>
|
|
|
+ para cargar su adaptador si se especifica la parte principal
|
|
|
+ de la clase del adaptador con la clave "adapterNamespace" en
|
|
|
+ el conjunto de parámetros
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.connecting.factory.example2">
|
|
|
+ <title>
|
|
|
+ Usando el método factory para una clase Adaptador
|
|
|
+ personalizada
|
|
|
+ </title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// No tenemos que cargar el archivo de clase Adaptador
|
|
|
+// porque será cargado para nosotros por el método factory de Zend_Db.
|
|
|
+
|
|
|
+// Automáticamente carga la clase MyProject_Db_Adapter_Pdo_Mysql
|
|
|
+// y crea una instancia de ella.
|
|
|
+
|
|
|
+$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>Uso de Zend_Config con Zend_Db Factory</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Opcionalmente, se puede especificar cualquier
|
|
|
+ argumento del método
|
|
|
+ <code>factory()</code>
|
|
|
+ como un objeto de tipo
|
|
|
+ <link linkend="zend.config">Zend_Config</link>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si el primer argumento es un objeto de configuración, se
|
|
|
+ espera que contenga una propiedad llamada
|
|
|
+ <code>adapter</code>
|
|
|
+ , conteniendo la cadena que da nombre al nombre base de la
|
|
|
+ clase de adaptador. Opcionalmente, el objeto puede
|
|
|
+ contener una propiedad llamada
|
|
|
+ <code>params</code>
|
|
|
+ , con subpropiedades correspondientes a nombres de parámetros
|
|
|
+ del adaptador. Esto es usado sólo si el segundo
|
|
|
+ argumento del método <code>factory()</code> se ha omitido.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.connecting.factory.example1">
|
|
|
+ <title>
|
|
|
+ Uso del método factory del Adaptador con un objeto Zend_Config
|
|
|
+ </title>
|
|
|
+ <para>
|
|
|
+ En el siguiente ejemplo, un objeto Zend_Config es
|
|
|
+ creado usando un array. También puedes cargar los datos de
|
|
|
+ un archivo externo, por ejemplo con
|
|
|
+ <link linkend="zend.config.adapters.ini">
|
|
|
+ Zend_Config_Ini
|
|
|
+ </link>
|
|
|
+ o
|
|
|
+ <link linkend="zend.config.adapters.xml">
|
|
|
+ Zend_Config_Xml
|
|
|
+ </link>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$config = new Zend_Config(
|
|
|
+ array(
|
|
|
+ 'database' => array(
|
|
|
+ 'adapter' => 'Mysqli',
|
|
|
+ 'params' => array(
|
|
|
+ 'dbname' => 'test',
|
|
|
+ 'username' => 'webuser',
|
|
|
+ 'password' => 'secret',
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+);
|
|
|
+
|
|
|
+$db = Zend_Db::factory($config->database);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El segundo argumento del método
|
|
|
+ <code>factory()</code>
|
|
|
+ puede ser un array asociativo con entradas
|
|
|
+ correspondientes a los parámetros del adaptador. Este argumento es
|
|
|
+ opcional. Si el primer argumento es de tipo Zend_Config,
|
|
|
+ se asume que tiene todos los parametros, y el segundo
|
|
|
+ argumento es ignorado.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.connecting.parameters">
|
|
|
+
|
|
|
+ <title>Parámetros del Adaptador</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El siguiente listado explica parámetros comunes reconocidos por
|
|
|
+ Adaptador de clases Zend_Db.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">host</emphasis>
|
|
|
+ : una string conteniendo un nombre de host o dirección IP
|
|
|
+ del servidor de base de datos. Si la base de datos está corriendo
|
|
|
+ sobre el mismo host que la aplicación PHP,
|
|
|
+ usted puede utilizar 'localhost' o '127.0.0.1'.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">username</emphasis>
|
|
|
+ : identificador de cuenta para autenticar una conexión al
|
|
|
+ servidor RDBMS.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">password</emphasis>
|
|
|
+ : la contraseña de la cuenta para la autenticación de credenciales
|
|
|
+ de conexión con el servidor RDBMS
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">dbname</emphasis>
|
|
|
+ : nombre de la base de datos en el servidor RDBMS.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">port</emphasis>
|
|
|
+ : algunos servidores RDBMS pueden aceptar conexiones de red
|
|
|
+ sobre un número de puerto específico.
|
|
|
+ El parámetro del puerto le permite especificar el puerto al
|
|
|
+ que su aplicación PHP se conecta, para que concuerde el puerto
|
|
|
+ configurado en el servidor RDBMS.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">options</emphasis>
|
|
|
+ : este parámetro es un array asociativo de
|
|
|
+ opciones que son genéricas a todas las clases Zend_Db_Adapter.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">
|
|
|
+ driver_options
|
|
|
+ </emphasis>
|
|
|
+ : este parámetro es un array asociativo de opciones adicionales
|
|
|
+ para una extensión de base de datos dada.
|
|
|
+ un uso típico de este parámetro es establecer atributos
|
|
|
+ de un driver PDO.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">
|
|
|
+ adapterNamespace
|
|
|
+ </emphasis>
|
|
|
+ : nombre de la parte inicial del nombre de las clase para el
|
|
|
+ adaptador, en lugar de 'Zend_Db_Adapter'. Utilice
|
|
|
+ esto si usted necesita usar el método
|
|
|
+ <code>factory()</code>
|
|
|
+ para cargar un adaptador de clase de base de datos que no sea
|
|
|
+ de Zend.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.connecting.parameters.example1">
|
|
|
+ <title>
|
|
|
+ Passing the case-folding option to the factory
|
|
|
+ </title>
|
|
|
+ <para>
|
|
|
+ Usted puede pasar esta opción específica por la constante
|
|
|
+ <code>Zend_Db::CASE_FOLDING</code>
|
|
|
+ . Este corresponde al atributo
|
|
|
+ <code>ATTR_CASE</code>
|
|
|
+ en los drivers de base de datos PDO e IBM DB2,
|
|
|
+ ajustando la sensibilidad de las claves tipo cadena en los resultados
|
|
|
+ de consultas. La opción toma los valores
|
|
|
+ <code>Zend_Db::CASE_NATURAL</code>
|
|
|
+ (el predeterminado),
|
|
|
+ <code>Zend_Db::CASE_UPPER</code>
|
|
|
+ , y
|
|
|
+ <code>Zend_Db::CASE_LOWER</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ <programlisting role="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>
|
|
|
+ Passing the auto-quoting option to the factory
|
|
|
+ </title>
|
|
|
+ <para>
|
|
|
+ Usted puede especificar esta opción por la constante
|
|
|
+ <code>Zend_Db::AUTO_QUOTE_IDENTIFIERS</code>
|
|
|
+ . Si el valor es
|
|
|
+ <code>true</code>
|
|
|
+ (el predeterminado), los identificadores como nombres de tabla,
|
|
|
+ nombres de columna, e incluso los alias son delimitados en la
|
|
|
+ sintaxis SQL generada por el Adatador del objeto.
|
|
|
+ Esto hace que sea sencillo utilizar identificadores que contengan
|
|
|
+ palabras reservadas de SQL, o caracteres especiales. Si el valor es
|
|
|
+ <code>false</code>
|
|
|
+ , los identificadores no son delimitados automáticamente. Si
|
|
|
+ usted necesita delimitar identificadores, debe hacer usted mismo
|
|
|
+ utilizando el método
|
|
|
+ <code>quoteIdentifier()</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ <programlisting role="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>Passing PDO driver options to the factory</title>
|
|
|
+ <programlisting role="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>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.connecting.getconnection">
|
|
|
+ <title>Managing Lazy Connections</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Creating an instance of an Adapter class does not
|
|
|
+ immediately connect to the RDBMS server. The Adapter
|
|
|
+ saves the connection parameters, and makes the actual
|
|
|
+ connection on demand, the first time you need to execute
|
|
|
+ a query. This ensures that creating an Adapter object is
|
|
|
+ quick and inexpensive. You can create an instance of an
|
|
|
+ Adapter even if you are not certain that you need to run
|
|
|
+ any database queries during the current request your
|
|
|
+ application is serving.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you need to force the Adapter to connect to the
|
|
|
+ RDBMS, use the
|
|
|
+ <code>getConnection()</code>
|
|
|
+ method. This method returns an object for the connection
|
|
|
+ as represented by the respective PHP database extension.
|
|
|
+ For example, if you use any of the Adapter classes for
|
|
|
+ PDO drivers, then
|
|
|
+ <code>getConnection()</code>
|
|
|
+ returns the PDO object, after initiating it as a live
|
|
|
+ connection to the specific database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ It can be useful to force the connection if you want to
|
|
|
+ catch any exceptions it throws as a result of invalid
|
|
|
+ account credentials, or other failure to connect to the
|
|
|
+ RDBMS server. These exceptions are not thrown until the
|
|
|
+ connection is made, so it can help simplify your
|
|
|
+ application code if you handle the exceptions in one
|
|
|
+ place, instead of at the time of the first query against
|
|
|
+ the database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.connecting.getconnection.example">
|
|
|
+ <title>Handling connection exceptions</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+try {
|
|
|
+ $db = Zend_Db::factory('Pdo_Mysql', $parameters);
|
|
|
+ $db->getConnection();
|
|
|
+} catch (Zend_Db_Adapter_Exception $e) {
|
|
|
+ // perhaps a failed login credential, or perhaps the RDBMS is not running
|
|
|
+} catch (Zend_Exception $e) {
|
|
|
+ // perhaps factory() failed to load the specified Adapter class
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.adapter.example-database">
|
|
|
+
|
|
|
+ <title>La base de datos de ejemplo</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En la documentación de las clases Zend_Db, usamos un
|
|
|
+ conjunto sencillo de tablas para ilustrar el uso de las
|
|
|
+ clases y métodos. Estas tablas de ejemplo permiten almacenar
|
|
|
+ información para localizar bugs en un proyecto de desarrollo
|
|
|
+ de software. La base de datos contiene cuatro tablas:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">accounts</emphasis>
|
|
|
+ almacena información sobre cada usuario que hace el
|
|
|
+ seguimiento de bugs.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">products</emphasis>
|
|
|
+ almacena información sobre cada producto para el que
|
|
|
+ pueden registrarse bugs.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">bugs</emphasis>
|
|
|
+ almacena información sobre bugs, incluyendo el
|
|
|
+ estado actual del bug, la persona que informó sobre
|
|
|
+ el bug, la persona que está asignada para corregir
|
|
|
+ el bug, y la persona que está asignada para
|
|
|
+ verificar la corrección.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">bugs_products</emphasis>
|
|
|
+ stores a relationship between bugs and products.
|
|
|
+ This implements a many-to-many relationship, because
|
|
|
+ a given bug may be relevant to multiple products,
|
|
|
+ and of course a given product can have multiple
|
|
|
+ bugs.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La siguiente definición de datos SQL en lenguaje
|
|
|
+ pseudocódigo describe las tablas de esta base de datos de
|
|
|
+ ejemplo. Estas tablas de ejemplo son usadas ampliamente por
|
|
|
+ los tests unitarios automatizados de Zend_Db.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="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>
|
|
|
+ Also notice that the
|
|
|
+ <code>bugs</code>
|
|
|
+ table contains multiple foreign key references to the
|
|
|
+ <code>accounts</code>
|
|
|
+ table. Each of these foreign keys may reference a different
|
|
|
+ row in the
|
|
|
+ <code>accounts</code>
|
|
|
+ table for a given bug.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The diagram below illustrates the physical data model of the
|
|
|
+ example database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <inlinegraphic width="387" scale="100" align="center" valign="middle" fileref="figures/zend.db.adapter.example-database.png" format="PNG"/>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.adapter.select">
|
|
|
+
|
|
|
+ <title>Reading Query Results</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This section describes methods of the Adapter class with
|
|
|
+ which you can run SELECT queries and retrieve the query
|
|
|
+ results.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.select.fetchall">
|
|
|
+
|
|
|
+ <title>Fetching a Complete Result Set</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can run a SQL SELECT query and retrieve its results
|
|
|
+ in one step using the
|
|
|
+ <code>fetchAll()</code>
|
|
|
+ method.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The first argument to this method is a string containing
|
|
|
+ a SELECT statement. Alternatively, the first argument
|
|
|
+ can be an object of class
|
|
|
+ <link linkend="zend.db.select">Zend_Db_Select</link>
|
|
|
+ . The Adapter automatically converts this object to a
|
|
|
+ string representation of the SELECT statement.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The second argument to
|
|
|
+ <code>fetchAll()</code>
|
|
|
+ is an array of values to substitute for parameter
|
|
|
+ placeholders in the SQL statement.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.select.fetchall.example">
|
|
|
+ <title>Using fetchAll()</title>
|
|
|
+ <programlisting role="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>Changing the Fetch Mode</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ By default,
|
|
|
+ <code>fetchAll()</code>
|
|
|
+ returns an array of rows, each of which is an
|
|
|
+ associative array. The keys of the associative array are
|
|
|
+ the columns or column aliases named in the select query.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can specify a different style of fetching results
|
|
|
+ using the
|
|
|
+ <code>setFetchMode()</code>
|
|
|
+ method. The modes supported are identified by constants:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">
|
|
|
+ Zend_Db::FETCH_ASSOC
|
|
|
+ </emphasis>
|
|
|
+ : return data in an array of associative arrays.
|
|
|
+ The array keys are column names, as strings.
|
|
|
+ This is the default fetch mode for
|
|
|
+ Zend_Db_Adapter classes.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Note that if your select-list contains more than
|
|
|
+ one column with the same name, for example if
|
|
|
+ they are from two different tables in a JOIN,
|
|
|
+ there can be only one entry in the associative
|
|
|
+ array for a given name. If you use the
|
|
|
+ FETCH_ASSOC mode, you should specify column
|
|
|
+ aliases in your SELECT query to ensure that the
|
|
|
+ names result in unique array keys.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ By default, these strings are returned as they
|
|
|
+ are returned by the database driver. This is
|
|
|
+ typically the spelling of the column in the
|
|
|
+ RDBMS server. You can specify the case for these
|
|
|
+ strings, using the
|
|
|
+ <code>Zend_Db::CASE_FOLDING</code>
|
|
|
+ option. Specify this when instantiating the
|
|
|
+ Adapter. See
|
|
|
+ <xref linkend="zend.db.adapter.connecting.parameters.example1"/>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">
|
|
|
+ Zend_Db::FETCH_NUM
|
|
|
+ </emphasis>
|
|
|
+ : return data in an array of arrays. The arrays
|
|
|
+ are indexed by integers, corresponding to the
|
|
|
+ position of the respective field in the
|
|
|
+ select-list of the query.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">
|
|
|
+ Zend_Db::FETCH_BOTH
|
|
|
+ </emphasis>
|
|
|
+ : return data in an array of arrays. The array
|
|
|
+ keys are both strings as used in the FETCH_ASSOC
|
|
|
+ mode, and integers as used in the FETCH_NUM
|
|
|
+ mode. Note that the number of elements in the
|
|
|
+ array is double that which would be in the array
|
|
|
+ if you used either FETCH_ASSOC or FETCH_NUM.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">
|
|
|
+ Zend_Db::FETCH_COLUMN
|
|
|
+ </emphasis>
|
|
|
+ : return data in an array of values. The value
|
|
|
+ in each array is the value returned by one
|
|
|
+ column of the result set. By default, this is
|
|
|
+ the first column, indexed by 0.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">
|
|
|
+ Zend_Db::FETCH_OBJ
|
|
|
+ </emphasis>
|
|
|
+ : return data in an array of objects. The
|
|
|
+ default class is the PHP built-in class
|
|
|
+ stdClass. Columns of the result set are
|
|
|
+ available as public properties of the object.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.select.fetch-mode.example">
|
|
|
+ <title>Using setFetchMode()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db->setFetchMode(Zend_Db::FETCH_OBJ);
|
|
|
+
|
|
|
+$result = $db->fetchAll('SELECT * FROM bugs WHERE bug_id = ?', 2);
|
|
|
+
|
|
|
+// $result is an array of objects
|
|
|
+echo $result[0]->bug_description;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.select.fetchassoc">
|
|
|
+
|
|
|
+ <title>Fetching a Result Set as an Associative Array</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The
|
|
|
+ <code>fetchAssoc()</code>
|
|
|
+ method returns data in an array of associative arrays,
|
|
|
+ regardless of what value you have set for the fetch
|
|
|
+ mode.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.select.fetchassoc.example">
|
|
|
+ <title>Using fetchAssoc()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db->setFetchMode(Zend_Db::FETCH_OBJ);
|
|
|
+
|
|
|
+$result = $db->fetchAssoc('SELECT * FROM bugs WHERE bug_id = ?', 2);
|
|
|
+
|
|
|
+// $result is an array of associative arrays, in spite of the fetch mode
|
|
|
+echo $result[0]['bug_description'];
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.select.fetchcol">
|
|
|
+
|
|
|
+ <title>Fetching a Single Column from a Result Set</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The
|
|
|
+ <code>fetchCol()</code>
|
|
|
+ method returns data in an array of values, regardless of
|
|
|
+ the value you have set for the fetch mode. This only
|
|
|
+ returns the first column returned by the query. Any
|
|
|
+ other columns returned by the query are discarded. If
|
|
|
+ you need to return a column other than the first, see
|
|
|
+ <xref linkend="zend.db.statement.fetching.fetchcolumn"/>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.select.fetchcol.example">
|
|
|
+ <title>Using fetchCol()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db->setFetchMode(Zend_Db::FETCH_OBJ);
|
|
|
+
|
|
|
+$result = $db->fetchCol(
|
|
|
+ 'SELECT bug_description, bug_id FROM bugs WHERE bug_id = ?', 2);
|
|
|
+
|
|
|
+// contains bug_description; bug_id is not returned
|
|
|
+echo $result[0];
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.select.fetchpairs">
|
|
|
+
|
|
|
+ <title>Fetching Key-Value Pairs from a Result Set</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The
|
|
|
+ <code>fetchPairs()</code>
|
|
|
+ method returns data in an array of key-value pairs, as
|
|
|
+ an associative array with a single entry per row. The
|
|
|
+ key of this associative array is taken from the first
|
|
|
+ column returned by the SELECT query. The value is taken
|
|
|
+ from the second column returned by the SELECT query. Any
|
|
|
+ other columns returned by the query are discarded.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You should design the SELECT query so that the first
|
|
|
+ column returned has unique values. If there are
|
|
|
+ duplicates values in the first column, entries in the
|
|
|
+ associative array will be overwritten.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.select.fetchpairs.example">
|
|
|
+ <title>Using fetchPairs()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db->setFetchMode(Zend_Db::FETCH_OBJ);
|
|
|
+
|
|
|
+$result = $db->fetchPairs('SELECT bug_id, bug_status FROM bugs');
|
|
|
+
|
|
|
+echo $result[2];
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.select.fetchrow">
|
|
|
+
|
|
|
+ <title>Fetching a Single Row from a Result Set</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The
|
|
|
+ <code>fetchRow()</code>
|
|
|
+ method returns data using the current fetch mode, but it
|
|
|
+ returns only the first row fetched from the result set.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.select.fetchrow.example">
|
|
|
+ <title>Using fetchRow()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db->setFetchMode(Zend_Db::FETCH_OBJ);
|
|
|
+
|
|
|
+$result = $db->fetchRow('SELECT * FROM bugs WHERE bug_id = 2');
|
|
|
+
|
|
|
+// note that $result is a single object, not an array of objects
|
|
|
+echo $result->bug_description;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.select.fetchone">
|
|
|
+
|
|
|
+ <title>Fetching a Single Scalar from a Result Set</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The
|
|
|
+ <code>fetchOne()</code>
|
|
|
+ method is like a combination of
|
|
|
+ <code>fetchRow()</code>
|
|
|
+ with
|
|
|
+ <code>fetchCol()</code>
|
|
|
+ , in that it returns data only for the first row fetched
|
|
|
+ from the result set, and it returns only the value of
|
|
|
+ the first column in that row. Therefore it returns only
|
|
|
+ a single scalar value, not an array or an object.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.select.fetchone.example">
|
|
|
+ <title>Using fetchOne()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$result = $db->fetchOne('SELECT bug_status FROM bugs WHERE bug_id = 2');
|
|
|
+
|
|
|
+// this is a single string value
|
|
|
+echo $result;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.adapter.write">
|
|
|
+
|
|
|
+ <title>Writing Changes to the Database</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can use the Adapter class to write new data or change
|
|
|
+ existing data in your database. This section describes
|
|
|
+ methods to do these operations.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.write.insert">
|
|
|
+
|
|
|
+ <title>Inserting Data</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can add new rows to a table in your database using
|
|
|
+ the
|
|
|
+ <code>insert()</code>
|
|
|
+ method. The first argument is a string that names the
|
|
|
+ table, and the second argument is an associative array,
|
|
|
+ mapping column names to data values.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.write.insert.example">
|
|
|
+ <title>Inserting to a table</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$data = array(
|
|
|
+ 'created_on' => '2007-03-22',
|
|
|
+ 'bug_description' => 'Something wrong',
|
|
|
+ 'bug_status' => 'NEW'
|
|
|
+);
|
|
|
+
|
|
|
+$db->insert('bugs', $data);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Columns you exclude from the array of data are not
|
|
|
+ specified to the database. Therefore, they follow the
|
|
|
+ same rules that an SQL INSERT statement follows: if the
|
|
|
+ column has a DEFAULT clause, the column takes that value
|
|
|
+ in the row created, otherwise the column is left in a
|
|
|
+ NULL state.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ By default, the values in your data array are inserted
|
|
|
+ using parameters. This reduces risk of some types of
|
|
|
+ security issues. You don't need to apply escaping or
|
|
|
+ quoting to values in the data array.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You might need values in the data array to be treated as
|
|
|
+ SQL expressions, in which case they should not be
|
|
|
+ quoted. By default, all data values passed as strings
|
|
|
+ are treated as string literals. To specify that the
|
|
|
+ value is an SQL expression and therefore should not be
|
|
|
+ quoted, pass the value in the data array as an object of
|
|
|
+ type Zend_Db_Expr instead of a plain string.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.write.insert.example2">
|
|
|
+ <title>Inserting expressions to a table</title>
|
|
|
+ <programlisting role="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>Retrieving a Generated Value</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Some RDBMS brands support auto-incrementing primary
|
|
|
+ keys. A table defined this way generates a primary key
|
|
|
+ value automatically during an INSERT of a new row. The
|
|
|
+ return value of the
|
|
|
+ <code>insert()</code>
|
|
|
+ method is
|
|
|
+ <emphasis>not</emphasis>
|
|
|
+ the last inserted ID, because the table might not have
|
|
|
+ an auto-incremented column. Instead, the return value is
|
|
|
+ the number of rows affected (usually 1).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If your table is defined with an auto-incrementing
|
|
|
+ primary key, you can call the
|
|
|
+ <code>lastInsertId()</code>
|
|
|
+ method after the insert. This method returns the last
|
|
|
+ value generated in the scope of the current database
|
|
|
+ connection.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.write.lastinsertid.example-1">
|
|
|
+ <title>
|
|
|
+ Using lastInsertId() for an auto-increment key
|
|
|
+ </title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db->insert('bugs', $data);
|
|
|
+
|
|
|
+// return the last value generated by an auto-increment column
|
|
|
+$id = $db->lastInsertId();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Some RDBMS brands support a sequence object, which
|
|
|
+ generates unique values to serve as primary key values.
|
|
|
+ To support sequences, the
|
|
|
+ <code>lastInsertId()</code>
|
|
|
+ method accepts two optional string arguments. These
|
|
|
+ arguments name the table and the column, assuming you
|
|
|
+ have followed the convention that a sequence is named
|
|
|
+ using the table and column names for which the sequence
|
|
|
+ generates values, and a suffix "_seq". This is based on
|
|
|
+ the convention used by PostgreSQL when naming sequences
|
|
|
+ for SERIAL columns. For example, a table "bugs" with
|
|
|
+ primary key column "bug_id" would use a sequence named
|
|
|
+ "bugs_bug_id_seq".
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.write.lastinsertid.example-2">
|
|
|
+ <title>Using lastInsertId() for a sequence</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db->insert('bugs', $data);
|
|
|
+
|
|
|
+// return the last value generated by sequence 'bugs_bug_id_seq'.
|
|
|
+$id = $db->lastInsertId('bugs', 'bug_id');
|
|
|
+
|
|
|
+// alternatively, return the last value generated by sequence 'bugs_seq'.
|
|
|
+$id = $db->lastInsertId('bugs');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If the name of your sequence object does not follow this
|
|
|
+ naming convention, use the
|
|
|
+ <code>lastSequenceId()</code>
|
|
|
+ method instead. This method takes a single string
|
|
|
+ argument, naming the sequence literally.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.write.lastinsertid.example-3">
|
|
|
+ <title>Using lastSequenceId()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db->insert('bugs', $data);
|
|
|
+
|
|
|
+// return the last value generated by sequence 'bugs_id_gen'.
|
|
|
+$id = $db->lastSequenceId('bugs_id_gen');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ For RDBMS brands that don't support sequences, including
|
|
|
+ MySQL, Microsoft SQL Server, and SQLite, the arguments
|
|
|
+ to the lastInsertId() method are ignored, and the value
|
|
|
+ returned is the most recent value generated for any
|
|
|
+ table by INSERT operations during the current
|
|
|
+ connection. For these RDBMS brands, the lastSequenceId()
|
|
|
+ method always returns
|
|
|
+ <code>null</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Why not use "SELECT MAX(id) FROM table"?</title>
|
|
|
+ <para>
|
|
|
+ Sometimes this query returns the most recent primary
|
|
|
+ key value inserted into the table. However, this
|
|
|
+ technique is not safe to use in an environment where
|
|
|
+ multiple clients are inserting records to the
|
|
|
+ database. It is possible, and therefore is bound to
|
|
|
+ happen eventually, that another client inserts
|
|
|
+ another row in the instant between the insert
|
|
|
+ performed by your client application and your query
|
|
|
+ for the MAX(id) value. Thus the value returned does
|
|
|
+ not identify the row you inserted, it identifies the
|
|
|
+ row inserted by some other client. There is no way
|
|
|
+ to know when this has happened.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Using a strong transaction isolation mode such as
|
|
|
+ "repeatable read" can mitigate this risk, but some
|
|
|
+ RDBMS brands don't support the transaction isolation
|
|
|
+ required for this, or else your application may use
|
|
|
+ a lower transaction isolation mode by design.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Furthermore, using an expression like "MAX(id)+1" to
|
|
|
+ generate a new value for a primary key is not safe,
|
|
|
+ because two clients could do this query
|
|
|
+ simultaneously, and then both use the same
|
|
|
+ calculated value for their next INSERT operation.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ All RDBMS brands provide mechanisms to generate
|
|
|
+ unique values, and to return the last value
|
|
|
+ generated. These mechanisms necessarily work outside
|
|
|
+ of the scope of transaction isolation, so there is
|
|
|
+ no chance of two clients generating the same value,
|
|
|
+ and there is no chance that the value generated by
|
|
|
+ another client could be reported to your client's
|
|
|
+ connection as the last value generated.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.write.update">
|
|
|
+ <title>Updating Data</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can update rows in a database table using the
|
|
|
+ <code>update()</code>
|
|
|
+ method of an Adapter. This method takes three arguments:
|
|
|
+ the first is the name of the table; the second is an
|
|
|
+ associative array mapping columns to change to new
|
|
|
+ values to assign to these columns.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The values in the data array are treated as string
|
|
|
+ literals. See
|
|
|
+ <xref linkend="zend.db.adapter.write.insert"/>
|
|
|
+ for information on using SQL expressions in the data
|
|
|
+ array.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The third argument is a string containing an SQL
|
|
|
+ expression that is used as criteria for the rows to
|
|
|
+ change. The values and identifiers in this argument are
|
|
|
+ not quoted or escaped. You are responsible for ensuring
|
|
|
+ that any dynamic content is interpolated into this
|
|
|
+ string safely. See
|
|
|
+ <xref linkend="zend.db.adapter.quoting"/>
|
|
|
+ for methods to help you do this.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The return value is the number of rows affected by the
|
|
|
+ update operation.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.write.update.example">
|
|
|
+ <title>Updating rows</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$data = array(
|
|
|
+ 'updated_on' => '2007-03-23',
|
|
|
+ 'bug_status' => 'FIXED'
|
|
|
+);
|
|
|
+
|
|
|
+$n = $db->update('bugs', $data, 'bug_id = 2');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you omit the third argument, then all rows in the
|
|
|
+ database table are updated with the values specified in
|
|
|
+ the data array.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you provide an array of strings as the third
|
|
|
+ argument, these strings are joined together as terms in
|
|
|
+ an expression separated by
|
|
|
+ <code>AND</code>
|
|
|
+ operators.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.write.update.example-array">
|
|
|
+ <title>
|
|
|
+ Updating rows using an array of expressions
|
|
|
+ </title>
|
|
|
+ <programlisting role="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);
|
|
|
+
|
|
|
+// Resulting SQL is:
|
|
|
+// 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>Deleting Data</title>
|
|
|
+ <para>
|
|
|
+ You can delete rows from a database table using the
|
|
|
+ <code>delete()</code>
|
|
|
+ method. This method takes two arguments: the first is a
|
|
|
+ string naming the table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The second argument is a string containing an SQL
|
|
|
+ expression that is used as criteria for the rows to
|
|
|
+ delete. The values and identifiers in this argument are
|
|
|
+ not quoted or escaped. You are responsible for ensuring
|
|
|
+ that any dynamic content is interpolated into this
|
|
|
+ string safely. See
|
|
|
+ <xref linkend="zend.db.adapter.quoting"/>
|
|
|
+ for methods to help you do this.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The return value is the number of rows affected by the
|
|
|
+ delete operation.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.write.delete.example">
|
|
|
+ <title>Deleting rows</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$n = $db->delete('bugs', 'bug_id = 3');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you omit the second argument, the result is that all
|
|
|
+ rows in the database table are deleted.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you provide an array of strings as the second
|
|
|
+ argument, these strings are joined together as terms in
|
|
|
+ an expression separated by
|
|
|
+ <code>AND</code>
|
|
|
+ operators.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.adapter.quoting">
|
|
|
+
|
|
|
+ <title>Quoting Values and Identifiers</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ When you form SQL queries, often it is the case that you
|
|
|
+ need to include the values of PHP variables in SQL
|
|
|
+ expressions. This is risky, because if the value in a PHP
|
|
|
+ string contains certain symbols, such as the quote symbol,
|
|
|
+ it could result in invalid SQL. For example, notice the
|
|
|
+ imbalanced quote characters in the following query:
|
|
|
+ <programlisting role="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>
|
|
|
+ Even worse is the risk that such code mistakes might be
|
|
|
+ exploited deliberately by a person who is trying to
|
|
|
+ manipulate the function of your web application. If they can
|
|
|
+ specify the value of a PHP variable through the use of an
|
|
|
+ HTTP parameter or other mechanism, they might be able to
|
|
|
+ make your SQL queries do things that you didn't intend them
|
|
|
+ to do, such as return data to which the person should not
|
|
|
+ have privilege to read. This is a serious and widespread
|
|
|
+ technique for violating application security, known as "SQL
|
|
|
+ Injection" (see
|
|
|
+ <ulink url="http://en.wikipedia.org/wiki/SQL_Injection">
|
|
|
+ http://en.wikipedia.org/wiki/SQL_Injection
|
|
|
+ </ulink>
|
|
|
+ ).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The Zend_Db Adapter class provides convenient functions to
|
|
|
+ help you reduce vulnerabilities to SQL Injection attacks in
|
|
|
+ your PHP code. The solution is to escape special characters
|
|
|
+ such as quotes in PHP values before they are interpolated
|
|
|
+ into your SQL strings. This protects against both accidental
|
|
|
+ and deliberate manipulation of SQL strings by PHP variables
|
|
|
+ that contain special characters.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.quoting.quote">
|
|
|
+
|
|
|
+ <title>
|
|
|
+ Using
|
|
|
+ <code>quote()</code>
|
|
|
+ </title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The
|
|
|
+ <code>quote()</code>
|
|
|
+ method accepts a single argument, a scalar string value.
|
|
|
+ It returns the value with special characters escaped in
|
|
|
+ a manner appropriate for the RDBMS you are using, and
|
|
|
+ surrounded by string value delimiters. The standard SQL
|
|
|
+ string value delimiter is the single-quote (
|
|
|
+ <code>'</code>
|
|
|
+ ).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.quoting.quote.example">
|
|
|
+ <title>Using quote()</title>
|
|
|
+ <programlisting role="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>
|
|
|
+ Note that the return value of
|
|
|
+ <code>quote()</code>
|
|
|
+ includes the quote delimiters around the string. This is
|
|
|
+ different from some functions that escape special
|
|
|
+ characters but do not add the quote delimiters, for
|
|
|
+ example
|
|
|
+ <ulink url="http://www.php.net/mysqli_real_escape_string">
|
|
|
+ mysql_real_escape_string()
|
|
|
+ </ulink>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Values may need to be quoted or not quoted according to
|
|
|
+ the SQL datatype context in which they are used. For
|
|
|
+ instance, in some RDBMS brands, an integer value must
|
|
|
+ not be quoted as a string if it is compared to an
|
|
|
+ integer-type column or expression. In other words, the
|
|
|
+ following is an error in some SQL implementations,
|
|
|
+ assuming
|
|
|
+ <code>intColumn</code>
|
|
|
+ has a SQL datatype of
|
|
|
+ <code>INTEGER</code>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+SELECT * FROM atable WHERE intColumn = '123'
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can use the optional second argument to the
|
|
|
+ <code>quote()</code>
|
|
|
+ method to apply quoting selectively for the SQL datatype
|
|
|
+ you specify.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.quoting.quote.example-2">
|
|
|
+ <title>Using quote() with a SQL type</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$value = '1234';
|
|
|
+$sql = 'SELECT * FROM atable WHERE intColumn = '
|
|
|
+ . $db->quote($value, 'INTEGER');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Each Zend_Db_Adapter class has encoded the names of
|
|
|
+ numeric SQL datatypes for the respective brand of RDBMS.
|
|
|
+ You can also use the constants
|
|
|
+ <code>Zend_Db::INT_TYPE</code>
|
|
|
+ ,
|
|
|
+ <code>Zend_Db::BIGINT_TYPE</code>
|
|
|
+ , and
|
|
|
+ <code>Zend_Db::FLOAT_TYPE</code>
|
|
|
+ to write code in a more RDBMS-independent way.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Db_Table specifies SQL types to
|
|
|
+ <code>quote()</code>
|
|
|
+ automatically when generating SQL queries that reference
|
|
|
+ a table's key columns.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.quoting.quote-into">
|
|
|
+
|
|
|
+ <title>
|
|
|
+ Using
|
|
|
+ <code>quoteInto()</code>
|
|
|
+ </title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The most typical usage of quoting is to interpolate a
|
|
|
+ PHP variable into a SQL expression or statement. You can
|
|
|
+ use the
|
|
|
+ <code>quoteInto()</code>
|
|
|
+ method to do this in one step. This method takes two
|
|
|
+ arguments: the first argument is a string containing a
|
|
|
+ placeholder symbol (
|
|
|
+ <code>?</code>
|
|
|
+ ), and the second argument is a value or PHP variable
|
|
|
+ that should be substituted for that placeholder.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The placeholder symbol is the same symbol used by many
|
|
|
+ RDBMS brands for positional parameters, but the
|
|
|
+ <code>quoteInto()</code>
|
|
|
+ method only emulates query parameters. The method simply
|
|
|
+ interpolates the value into the string, escapes special
|
|
|
+ characters, and applies quotes around it. True query
|
|
|
+ parameters maintain the separation between the SQL
|
|
|
+ string and the parameters as the statement is parsed in
|
|
|
+ the RDBMS server.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.quoting.quote-into.example">
|
|
|
+ <title>Using quoteInto()</title>
|
|
|
+ <programlisting role="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>
|
|
|
+ You can use the optional third parameter of
|
|
|
+ <code>quoteInto()</code>
|
|
|
+ to specify the SQL datatype. Numeric datatypes are not
|
|
|
+ quoted, and other types are quoted.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.quoting.quote-into.example-2">
|
|
|
+ <title>Using quoteInto() with a SQL type</title>
|
|
|
+ <programlisting role="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>
|
|
|
+ Using
|
|
|
+ <code>quoteIdentifier()</code>
|
|
|
+ </title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Values are not the only part of SQL syntax that might
|
|
|
+ need to be variable. If you use PHP variables to name
|
|
|
+ tables, columns, or other identifiers in your SQL
|
|
|
+ statements, you might need to quote these strings too.
|
|
|
+ By default, SQL identifiers have syntax rules like PHP
|
|
|
+ and most other programming languages. For example,
|
|
|
+ identifiers should not contain spaces, certain
|
|
|
+ punctuation or special characters, or international
|
|
|
+ characters. Also certain words are reserved for SQL
|
|
|
+ syntax, and should not be used as identifiers.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ However, SQL has a feature called
|
|
|
+ <emphasis>delimited identifiers</emphasis>
|
|
|
+ , which allows broader choices for the spelling of
|
|
|
+ identifiers. If you enclose a SQL identifier in the
|
|
|
+ proper types of quotes, you can use identifiers with
|
|
|
+ spellings that would be invalid without the quotes.
|
|
|
+ Delimited identifiers can contain spaces, punctuation,
|
|
|
+ or international characters. You can also use SQL
|
|
|
+ reserved words if you enclose them in identifier
|
|
|
+ delimiters.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The
|
|
|
+ <code>quoteIdentifier()</code>
|
|
|
+ method works like
|
|
|
+ <code>quote()</code>
|
|
|
+ , but it applies the identifier delimiter characters to
|
|
|
+ the string according to the type of Adapter you use. For
|
|
|
+ example, standard SQL uses double-quotes (
|
|
|
+ <code>"</code>
|
|
|
+ ) for identifier delimiters, and most RDBMS brands use
|
|
|
+ that symbol. MySQL uses back-quotes (
|
|
|
+ <code>`</code>
|
|
|
+ ) by default. The
|
|
|
+ <code>quoteIdentifier()</code>
|
|
|
+ method also escapes special characters within the string
|
|
|
+ argument.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.quoting.quote-identifier.example">
|
|
|
+ <title>Using quoteIdentifier()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// we might have a table name that is an SQL reserved word
|
|
|
+$tableName = $db->quoteIdentifier("order");
|
|
|
+
|
|
|
+$sql = "SELECT * FROM $tableName";
|
|
|
+
|
|
|
+echo $sql
|
|
|
+// SELECT * FROM "order"
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ SQL delimited identifiers are case-sensitive, unlike
|
|
|
+ unquoted identifiers. Therefore, if you use delimited
|
|
|
+ identifiers, you must use the spelling of the identifier
|
|
|
+ exactly as it is stored in your schema, including the
|
|
|
+ case of the letters.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In most cases where SQL is generated within Zend_Db
|
|
|
+ classes, the default is that all identifiers are
|
|
|
+ delimited automatically. You can change this behavior
|
|
|
+ with the option
|
|
|
+ <code>Zend_Db::AUTO_QUOTE_IDENTIFIERS</code>
|
|
|
+ . Specify this when instantiating the Adapter. See
|
|
|
+ <xref linkend="zend.db.adapter.connecting.parameters.example2"/>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.adapter.transactions">
|
|
|
+
|
|
|
+ <title>Controlling Database Transactions</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Databases define transactions as logical units of work that
|
|
|
+ can be committed or rolled back as a single change, even if
|
|
|
+ they operate on multiple tables. All queries to a database
|
|
|
+ are executed within the context of a transaction, even if
|
|
|
+ the database driver manages them implicitly. This is called
|
|
|
+ <emphasis>auto-commit</emphasis>
|
|
|
+ mode, in which the database driver creates a transaction for
|
|
|
+ every statement you execute, and commits that transaction
|
|
|
+ after your SQL statement has been executed. By default, all
|
|
|
+ Zend_Db Adapter classes operate in auto-commit mode.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Alternatively, you can specify the beginning and resolution
|
|
|
+ of a transaction, and thus control how many SQL queries are
|
|
|
+ included in a single group that is committed (or rolled
|
|
|
+ back) as a single operation. Use the
|
|
|
+ <code>beginTransaction()</code>
|
|
|
+ method to initiate a transaction. Subsequent SQL statements
|
|
|
+ are executed in the context of the same transaction until
|
|
|
+ you resolve it explicitly.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ To resolve the transaction, use either the
|
|
|
+ <code>commit()</code>
|
|
|
+ or
|
|
|
+ <code>rollBack()</code>
|
|
|
+ methods. The
|
|
|
+ <code>commit()</code>
|
|
|
+ method marks changes made during your transaction as
|
|
|
+ committed, which means the effects of these changes are
|
|
|
+ shown in queries run in other transactions.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The
|
|
|
+ <code>rollBack()</code>
|
|
|
+ method does the opposite: it discards the changes made
|
|
|
+ during your transaction. The changes are effectively undone,
|
|
|
+ and the state of the data returns to how it was before you
|
|
|
+ began your transaction. However, rolling back your
|
|
|
+ transaction has no effect on changes made by other
|
|
|
+ transactions running concurrently.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ After you resolve this transaction,
|
|
|
+ <code>Zend_Db_Adapter</code>
|
|
|
+ returns to auto-commit mode until you call
|
|
|
+ <code>beginTransaction()</code>
|
|
|
+ again.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.transactions.example">
|
|
|
+ <title>Managing a transaction to ensure consistency</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Start a transaction explicitly.
|
|
|
+$db->beginTransaction();
|
|
|
+
|
|
|
+try {
|
|
|
+ // Attempt to execute one or more queries:
|
|
|
+ $db->query(...);
|
|
|
+ $db->query(...);
|
|
|
+ $db->query(...);
|
|
|
+
|
|
|
+ // If all succeed, commit the transaction and all changes
|
|
|
+ // are committed at once.
|
|
|
+ $db->commit();
|
|
|
+
|
|
|
+} catch (Exception $e) {
|
|
|
+ // If any of the queries failed and threw an exception,
|
|
|
+ // we want to roll back the whole transaction, reversing
|
|
|
+ // changes made in the transaction, even those that succeeded.
|
|
|
+ // Thus all changes are committed together, or none are.
|
|
|
+ $db->rollBack();
|
|
|
+ echo $e->getMessage();
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.adapter.list-describe">
|
|
|
+
|
|
|
+ <title>Listing and Describing Tables</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The
|
|
|
+ <code>listTables()</code>
|
|
|
+ method returns an array of strings, naming all tables in the
|
|
|
+ current database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The
|
|
|
+ <code>describeTable()</code>
|
|
|
+ method returns an associative array of metadata about a
|
|
|
+ table. Specify the name of the table as a string in the
|
|
|
+ first argument to this method. The second argument is
|
|
|
+ optional, and names the schema in which the table exists.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The keys of the associative array returned are the column
|
|
|
+ names of the table. The value corresponding to each column
|
|
|
+ is also an associative array, with the following keys and
|
|
|
+ values:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <table frame="all" cellpadding="5" id="zend.db.adapter.list-describe.metadata">
|
|
|
+ <title>Metadata fields returned by describeTable()</title>
|
|
|
+ <tgroup cols="3" align="left" colsep="1" rowsep="1">
|
|
|
+ <thead>
|
|
|
+ <row>
|
|
|
+ <entry>Key</entry>
|
|
|
+ <entry>Type</entry>
|
|
|
+ <entry>Description</entry>
|
|
|
+ </row>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ <row>
|
|
|
+ <entry>SCHEMA_NAME</entry>
|
|
|
+ <entry>(string)</entry>
|
|
|
+ <entry>
|
|
|
+ Name of the database schema in which this
|
|
|
+ table exists.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>TABLE_NAME</entry>
|
|
|
+ <entry>(string)</entry>
|
|
|
+ <entry>
|
|
|
+ Name of the table to which this column
|
|
|
+ belongs.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>COLUMN_NAME</entry>
|
|
|
+ <entry>(string)</entry>
|
|
|
+ <entry>Name of the column.</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>COLUMN_POSITION</entry>
|
|
|
+ <entry>(integer)</entry>
|
|
|
+ <entry>
|
|
|
+ Ordinal position of the column in the table.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>DATA_TYPE</entry>
|
|
|
+ <entry>(string)</entry>
|
|
|
+ <entry>
|
|
|
+ RDBMS name of the datatype of the column.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>DEFAULT</entry>
|
|
|
+ <entry>(string)</entry>
|
|
|
+ <entry>
|
|
|
+ Default value for the column, if any.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>NULLABLE</entry>
|
|
|
+ <entry>(boolean)</entry>
|
|
|
+ <entry>
|
|
|
+ True if the column accepts SQL NULLs, false
|
|
|
+ if the column has a NOT NULL constraint.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>LENGTH</entry>
|
|
|
+ <entry>(integer)</entry>
|
|
|
+ <entry>
|
|
|
+ Length or size of the column as reported by
|
|
|
+ the RDBMS.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>SCALE</entry>
|
|
|
+ <entry>(integer)</entry>
|
|
|
+ <entry>
|
|
|
+ Scale of SQL NUMERIC or DECIMAL type.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>PRECISION</entry>
|
|
|
+ <entry>(integer)</entry>
|
|
|
+ <entry>
|
|
|
+ Precision of SQL NUMERIC or DECIMAL type.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>UNSIGNED</entry>
|
|
|
+ <entry>(boolean)</entry>
|
|
|
+ <entry>
|
|
|
+ True if an integer-based type is reported as
|
|
|
+ UNSIGNED.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>PRIMARY</entry>
|
|
|
+ <entry>(boolean)</entry>
|
|
|
+ <entry>
|
|
|
+ True if the column is part of the primary
|
|
|
+ key of this table.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>PRIMARY_POSITION</entry>
|
|
|
+ <entry>(integer)</entry>
|
|
|
+ <entry>
|
|
|
+ Ordinal position (1-based) of the column in
|
|
|
+ the primary key.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>IDENTITY</entry>
|
|
|
+ <entry>(boolean)</entry>
|
|
|
+ <entry>
|
|
|
+ True if the column uses an auto-generated
|
|
|
+ value.
|
|
|
+ </entry>
|
|
|
+ </row>
|
|
|
+ </tbody>
|
|
|
+ </tgroup>
|
|
|
+ </table>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>
|
|
|
+ How the IDENTITY metadata field relates to specific
|
|
|
+ RDBMS
|
|
|
+ </title>
|
|
|
+ <para>
|
|
|
+ The IDENTITY metadata field was chosen as an 'idiomatic'
|
|
|
+ term to represent a relation to surrogate keys. This
|
|
|
+ field can be commonly known by the following values:-
|
|
|
+ </para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>IDENTITY</code>
|
|
|
+ - DB2, MSSQL
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>AUTO_INCREMENT</code>
|
|
|
+ - MySQL
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>SERIAL</code>
|
|
|
+ - PostgreSQL
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>SEQUENCE</code>
|
|
|
+ - Oracle
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If no table exists matching the table name and optional
|
|
|
+ schema name specified, then
|
|
|
+ <code>describeTable()</code>
|
|
|
+ returns an empty array.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.adapter.closing">
|
|
|
+
|
|
|
+ <title>Closing a Connection</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Normally it is not necessary to close a database connection.
|
|
|
+ PHP automatically cleans up all resources and the end of a
|
|
|
+ request. Database extensions are designed to close the
|
|
|
+ connection as the reference to the resource object is
|
|
|
+ cleaned up.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ However, if you have a long-duration PHP script that
|
|
|
+ initiates many database connections, you might need to close
|
|
|
+ the connection, to avoid exhausting the capacity of your
|
|
|
+ RDBMS server. You can use the Adapter's
|
|
|
+ <code>closeConnection()</code>
|
|
|
+ method to explicitly close the underlying database
|
|
|
+ connection.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.closing.example">
|
|
|
+ <title>Closing a database connection</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db->closeConnection();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Does Zend_Db support persistent connections?</title>
|
|
|
+ <para>
|
|
|
+ The usage of persistent connections is not supported or
|
|
|
+ encouraged in Zend_Db.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Using persistent connections can cause an excess of idle
|
|
|
+ connections on the RDBMS server, which causes more
|
|
|
+ problems than any performance gain you might achieve by
|
|
|
+ reducing the overhead of making connections.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Database connections have state. That is, some objects
|
|
|
+ in the RDBMS server exist in session scope. Examples are
|
|
|
+ locks, user variables, temporary tables, and information
|
|
|
+ about the most recently executed query, such as rows
|
|
|
+ affected, and last generated id value. If you use
|
|
|
+ persistent connections, your application could access
|
|
|
+ invalid or privileged data that were created in a
|
|
|
+ previous PHP request.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.adapter.other-statements">
|
|
|
+
|
|
|
+ <title>Running Other Database Statements</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ There might be cases in which you need to access the
|
|
|
+ connection object directly, as provided by the PHP database
|
|
|
+ extension. Some of these extensions may offer features that
|
|
|
+ are not surfaced by methods of Zend_Db_Adapter_Abstract.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ For example, all SQL statements run by Zend_Db are prepared,
|
|
|
+ then executed. However, some database features are
|
|
|
+ incompatible with prepared statements. DDL statements like
|
|
|
+ CREATE and ALTER cannot be prepared in MySQL. Also, SQL
|
|
|
+ statements don't benefit from the
|
|
|
+ <ulink url="http://dev.mysql.com/doc/refman/5.1/en/query-cache-how.html">
|
|
|
+ MySQL Query Cache
|
|
|
+ </ulink>
|
|
|
+ , prior to MySQL 5.1.17.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Most PHP database extensions provide a method to execute SQL
|
|
|
+ statements without preparing them. For example, in PDO, this
|
|
|
+ method is
|
|
|
+ <code>exec()</code>
|
|
|
+ . You can access the connection object in the PHP extension
|
|
|
+ directly using getConnection().
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.adapter.other-statements.example">
|
|
|
+ <title>
|
|
|
+ Running a non-prepared statement in a PDO adapter
|
|
|
+ </title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$result = $db->getConnection()->exec('DROP TABLE bugs');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Similarly, you can access other methods or properties that
|
|
|
+ are specific to PHP database extensions. Be aware, though,
|
|
|
+ that by doing this you might constrain your application to
|
|
|
+ the interface provided by the extension for a specific brand
|
|
|
+ of RDBMS.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In future versions of Zend_Db, there will be opportunities
|
|
|
+ to add method entry points for functionality that is common
|
|
|
+ to the supported PHP database extensions. This will not
|
|
|
+ affect backward compatibility.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.adapter.adapter-notes">
|
|
|
+
|
|
|
+ <title>Notes on Specific Adapters</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This section lists differences between the Adapter classes
|
|
|
+ of which you should be aware.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.adapter-notes.ibm-db2">
|
|
|
+ <title>IBM DB2</title>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Specify this Adapter to the factory() method
|
|
|
+ with the name 'Db2'.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ This Adapter uses the PHP extension ibm_db2.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ IBM DB2 supports both sequences and
|
|
|
+ auto-incrementing keys. Therefore the arguments
|
|
|
+ to
|
|
|
+ <code>lastInsertId()</code>
|
|
|
+ are optional. If you give no arguments, the
|
|
|
+ Adapter returns the last value generated for an
|
|
|
+ auto-increment key. If you give arguments, the
|
|
|
+ Adapter returns the last value generated by the
|
|
|
+ sequence named according to the convention '
|
|
|
+ <emphasis>table</emphasis>
|
|
|
+ _
|
|
|
+ <emphasis>column</emphasis>
|
|
|
+ _seq'.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.adapter-notes.mysqli">
|
|
|
+ <title>MySQLi</title>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Specify this Adapter to the
|
|
|
+ <code>factory()</code>
|
|
|
+ method with the name 'Mysqli'.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ This Adapter utilizes the PHP extension mysqli.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ MySQL does not support sequences, so
|
|
|
+ <code>lastInsertId()</code>
|
|
|
+ ignores its arguments and always returns the
|
|
|
+ last value generated for an auto-increment key.
|
|
|
+ The
|
|
|
+ <code>lastSequenceId()</code>
|
|
|
+ method returns
|
|
|
+ <code>null</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.adapter-notes.oracle">
|
|
|
+ <title>Oracle</title>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Specify this Adapter to the
|
|
|
+ <code>factory()</code>
|
|
|
+ method with the name 'Oracle'.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ This Adapter uses the PHP extension oci8.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Oracle does not support auto-incrementing keys,
|
|
|
+ so you should specify the name of a sequence to
|
|
|
+ <code>lastInsertId()</code>
|
|
|
+ or
|
|
|
+ <code>lastSequenceId()</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ The Oracle extension does not support positional
|
|
|
+ parameters. You must use named parameters.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Currently the
|
|
|
+ <code>Zend_Db::CASE_FOLDING</code>
|
|
|
+ option is not supported by the Oracle adapter.
|
|
|
+ To use this option with Oracle, you must use the
|
|
|
+ PDO OCI adapter.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.adapter-notes.pdo-ibm">
|
|
|
+ <title>
|
|
|
+ PDO for IBM DB2 and Informix Dynamic Server (IDS)
|
|
|
+ </title>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Specify this Adapter to the
|
|
|
+ <code>factory()</code>
|
|
|
+ method with the name 'Pdo_Ibm'.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ This Adapter uses the PHP extensions pdo and
|
|
|
+ pdo_ibm.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ You must use at least PDO_IBM extension version
|
|
|
+ 1.2.2. If you have an earlier version of this
|
|
|
+ extension, you must upgrade the PDO_IBM
|
|
|
+ extension from PECL.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.adapter-notes.pdo-mssql">
|
|
|
+ <title>PDO Microsoft SQL Server</title>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Specify this Adapter to the
|
|
|
+ <code>factory()</code>
|
|
|
+ method with the name 'Pdo_Mssql'.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ This Adapter uses the PHP extensions pdo and
|
|
|
+ pdo_mssql.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Microsoft SQL Server does not support sequences,
|
|
|
+ so
|
|
|
+ <code>lastInsertId()</code>
|
|
|
+ ignores its arguments and always returns the
|
|
|
+ last value generated for an auto-increment key.
|
|
|
+ The
|
|
|
+ <code>lastSequenceId()</code>
|
|
|
+ method returns
|
|
|
+ <code>null</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ If you are working with unicode strings in an
|
|
|
+ encoding other than UCS-2 (such as UTF-8), you
|
|
|
+ may have to perform a conversion in your
|
|
|
+ application code or store the data in a binary
|
|
|
+ column. Please refer to
|
|
|
+ <ulink url="http://support.microsoft.com/kb/232580">
|
|
|
+ Microsoft's Knowledge Base
|
|
|
+ </ulink>
|
|
|
+ for more information.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Zend_Db_Adapter_Pdo_Mssql sets
|
|
|
+ <code>QUOTED_IDENTIFIER ON</code>
|
|
|
+ immediately after connecting to a SQL Server
|
|
|
+ database. This makes the driver use the standard
|
|
|
+ SQL identifier delimiter symbol (
|
|
|
+ <code>"</code>
|
|
|
+ ) instead of the proprietary square-brackets
|
|
|
+ syntax SQL Server uses for delimiting
|
|
|
+ identifiers.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ You can specify
|
|
|
+ <code>pdoType</code>
|
|
|
+ as a key in the options array. The value can be
|
|
|
+ "mssql" (the default), "dblib", "freetds", or
|
|
|
+ "sybase". This option affects the DSN prefix the
|
|
|
+ adapter uses when constructing the DSN string.
|
|
|
+ Both "freetds" and "sybase" imply a prefix of
|
|
|
+ "sybase:", which is used for the
|
|
|
+ <ulink url="http://www.freetds.org/">
|
|
|
+ FreeTDS
|
|
|
+ </ulink>
|
|
|
+ set of libraries. See also
|
|
|
+ <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>
|
|
|
+ for more information on the DSN prefixes used in
|
|
|
+ this driver.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.adapter-notes.pdo-mysql">
|
|
|
+ <title>PDO MySQL</title>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Specify this Adapter to the
|
|
|
+ <code>factory()</code>
|
|
|
+ method with the name 'Pdo_Mysql'.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ This Adapter uses the PHP extensions pdo and
|
|
|
+ pdo_mysql.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ MySQL does not support sequences, so
|
|
|
+ <code>lastInsertId()</code>
|
|
|
+ ignores its arguments and always returns the
|
|
|
+ last value generated for an auto-increment key.
|
|
|
+ The
|
|
|
+ <code>lastSequenceId()</code>
|
|
|
+ method returns
|
|
|
+ <code>null</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.adapter-notes.pdo-oci">
|
|
|
+ <title>PDO Oracle</title>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Specify this Adapter to the
|
|
|
+ <code>factory()</code>
|
|
|
+ method with the name 'Pdo_Oci'.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ This Adapter uses the PHP extensions pdo and
|
|
|
+ pdo_oci.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Oracle does not support auto-incrementing keys,
|
|
|
+ so you should specify the name of a sequence to
|
|
|
+ <code>lastInsertId()</code>
|
|
|
+ or
|
|
|
+ <code>lastSequenceId()</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.adapter-notes.pdo-pgsql">
|
|
|
+ <title>PDO PostgreSQL</title>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Specify this Adapter to the
|
|
|
+ <code>factory()</code>
|
|
|
+ method with the name 'Pdo_Pgsql'.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ This Adapter uses the PHP extensions pdo and
|
|
|
+ pdo_pgsql.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ PostgreSQL supports both sequences and
|
|
|
+ auto-incrementing keys. Therefore the arguments
|
|
|
+ to
|
|
|
+ <code>lastInsertId()</code>
|
|
|
+ are optional. If you give no arguments, the
|
|
|
+ Adapter returns the last value generated for an
|
|
|
+ auto-increment key. If you give arguments, the
|
|
|
+ Adapter returns the last value generated by the
|
|
|
+ sequence named according to the convention '
|
|
|
+ <emphasis>table</emphasis>
|
|
|
+ _
|
|
|
+ <emphasis>column</emphasis>
|
|
|
+ _seq'.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.adapter-notes.pdo-sqlite">
|
|
|
+ <title>PDO SQLite</title>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Specify this Adapter to the
|
|
|
+ <code>factory()</code>
|
|
|
+ method with the name 'Pdo_Sqlite'.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ This Adapter uses the PHP extensions pdo and
|
|
|
+ pdo_sqlite.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ SQLite does not support sequences, so
|
|
|
+ <code>lastInsertId()</code>
|
|
|
+ ignores its arguments and always returns the
|
|
|
+ last value generated for an auto-increment key.
|
|
|
+ The
|
|
|
+ <code>lastSequenceId()</code>
|
|
|
+ method returns
|
|
|
+ <code>null</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ To connect to an SQLite2 database, specify
|
|
|
+ <code>'sqlite2'=>true</code>
|
|
|
+ in the array of parameters when creating an
|
|
|
+ instance of the Pdo_Sqlite Adapter.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ To connect to an in-memory SQLite database,
|
|
|
+ specify
|
|
|
+ <code>'dbname'=>':memory:'</code>
|
|
|
+ in the array of parameters when creating an
|
|
|
+ instance of the Pdo_Sqlite Adapter.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Older versions of the SQLite driver for PHP do
|
|
|
+ not seem to support the PRAGMA commands
|
|
|
+ necessary to ensure that short column names are
|
|
|
+ used in result sets. If you have problems that
|
|
|
+ your result sets are returned with keys of the
|
|
|
+ form "tablename.columnname" when you do a join
|
|
|
+ query, then you should upgrade to the current
|
|
|
+ version of PHP.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.adapter.adapter-notes.firebird">
|
|
|
+ <title>Firebird/Interbase</title>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ This Adapter uses the PHP extension
|
|
|
+ php_interbase.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Firebird/interbase does not support
|
|
|
+ auto-incrementing keys, so you should specify
|
|
|
+ the name of a sequence to
|
|
|
+ <code>lastInsertId()</code>
|
|
|
+ or
|
|
|
+ <code>lastSequenceId()</code>
|
|
|
+ .
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Currently the
|
|
|
+ <code>Zend_Db::CASE_FOLDING</code>
|
|
|
+ option is not supported by the
|
|
|
+ Firebird/interbase adapter. Unquoted identifiers
|
|
|
+ are automatically returned in upper case.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+ vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.db.statement" xml:base="module_specs/Zend_Db_Statement.xml">
|
|
|
+
|
|
|
+ <title>Zend_Db_Statement</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Además de algunos métodos convenientes tales como
|
|
|
+ <code>fetchAll()</code> e <code>insert()</code> documentados en
|
|
|
+ <xref linkend="zend.db.adapter"/>, puede usarse un objeto de declaración
|
|
|
+ para obtener más opciones al ejecutar consultas y devolver conjuntos de
|
|
|
+ resultados. Esta sección describe cómo obtener una instancia de un
|
|
|
+ objeto de declaración y como usar sus métodos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Db_Statement está basado en el objeto PDOStatement en la extensión
|
|
|
+ <ulink url="http://www.php.net/pdo">PHP Data Objects</ulink>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.statement.creating">
|
|
|
+
|
|
|
+ <title>Creando una Declaración</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Típicamente, un objeto de declaración statement es devuelto por el
|
|
|
+ método <code>query()</code> de la clase de Adaptador de la base de
|
|
|
+ datos.
|
|
|
+ Este método es un modo general de preparar una declaración SQL.
|
|
|
+ El primer parámetro es un string conteniendo la declaración SQL.
|
|
|
+ El segundo parámetro (opcional) es un array de valores para
|
|
|
+ vincular posiciones de parámetros en el string SQL.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.statement.creating.example1">
|
|
|
+ <title>Crear un objeto de declaración SQL con query()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$stmt = $db->query(
|
|
|
+ 'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?',
|
|
|
+ array('goofy', 'FIXED')
|
|
|
+ );
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El objeto de declaración corresponde a una declaración SQL que ha
|
|
|
+ sido preparada, y ejecutada una vez con valores vinculados
|
|
|
+ especificados.
|
|
|
+ Si la declaración fue una consulta SELECT u otro tipo de declaración
|
|
|
+ que devuelve un conjunto de resultados, ahora estará lista para
|
|
|
+ extraer resultados.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede crear una declaración con su constructor, pero este es un
|
|
|
+ uso menos típico. No hay un método factory para crear el objeto,
|
|
|
+ así que es necesario cargar una clase de declaración específica y llamar a su constructor.
|
|
|
+ Pase el objeto Adaptador como el primer parámetro, y un string
|
|
|
+ conteniendo la declaración SQL como el segundo parámetro.
|
|
|
+ La declaración es preparada pero no ejecutada.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.statement.creating.example2">
|
|
|
+ <title>Usando un constructor de declaración SQL</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$sql = 'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?';
|
|
|
+
|
|
|
+$stmt = new Zend_Db_Statement_Mysqli($db, $sql);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.statement.executing">
|
|
|
+
|
|
|
+ <title>Ejecutando la declaración</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Necesita ejecutar un objeto de declaración si lo crea con el
|
|
|
+ constructor, o si desea ejecutar la misma declaración varias veces.
|
|
|
+ Use el método <code>execute()</code> del mismo objeto de
|
|
|
+ declaración. El único parámetro es un array de valores a vincular a
|
|
|
+ posiciones de parámetros en la declaración.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si usa <emphasis>parámetros posicionales</emphasis>, o los que
|
|
|
+ están marcados por un signo de interrogación (<code>?</code>), pase
|
|
|
+ los valores de vinculación en un array plano.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.statement.executing.example1">
|
|
|
+ <title>Ejecutar una declaración con parámetros posicionales</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$sql = 'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?';
|
|
|
+
|
|
|
+$stmt = new Zend_Db_Statement_Mysqli($db, $sql);
|
|
|
+
|
|
|
+$stmt->execute(array('goofy', 'FIXED'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si usa <emphasis>parámetros nombrados</emphasis>, o los que son
|
|
|
+ indicados por un string identificador precedido por un caracter de
|
|
|
+ dos puntos (<code>:</code>), pase el valor en un array asociativo.
|
|
|
+ Las claves de este array deben coincidir con el nombre de los
|
|
|
+ parámetros.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.statement.executing.example2">
|
|
|
+ <title>Ejecutando una declaración con parámetros nombrados</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$sql = 'SELECT * FROM bugs WHERE ' .
|
|
|
+ 'reported_by = :reporter AND bug_status = :status';
|
|
|
+
|
|
|
+$stmt = new Zend_Db_Statement_Mysqli($db, $sql);
|
|
|
+
|
|
|
+$stmt->execute(array(':reporter' => 'goofy', ':status' => 'FIXED'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las declaraciones PDO soportan tanto parámetros posicionales como
|
|
|
+ parámetros nombrados, pero no ambos tipos en la misma declaración
|
|
|
+ SQL. Algunas clases Zend_Db_Statement para extensiones no-PDO
|
|
|
+ soportan solo un tipo de parámetro o el otro.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.statement.fetching">
|
|
|
+
|
|
|
+ <title>Extrayendo Resultados de una declaración <code>SELECT</code></title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede llamar a métodos del objeto de declaración para obtener filas
|
|
|
+ desde declaraciones SQL que producen conjuntos de resultados.
|
|
|
+
|
|
|
+ SELECT, SHOW, DESCRIBE y EXPLAIN son ejemplos de declaraciones que
|
|
|
+ producen un conjunto de resultados.
|
|
|
+ INSERT, UPDATE, and DELETE son ejemplo de declaraciones que
|
|
|
+ no producen un conjunto de resultados.
|
|
|
+
|
|
|
+ Puede ejecutar las últimas declaraciones de SQL usando
|
|
|
+ Zend_Db_Statement, pero no puede llamar a los métodos que extraen
|
|
|
+ filas de resultados desde este.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.statement.fetching.fetch">
|
|
|
+
|
|
|
+ <title>Extrayendo una Fila Simple desde un Conjunto de Resultados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para extraer una fila desde el conjunto de resultados,
|
|
|
+ use el método <code>fetch()</code> del objeto de declaración.
|
|
|
+ Los tres parámetros de este método son opcionales:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">Estilo de Extracción</emphasis>
|
|
|
+ es el primer parámetro. Éste controla la estructura
|
|
|
+ en la que será devuelta la fila.
|
|
|
+ Vea <xref linkend="zend.db.adapter.select.fetch-mode"/>
|
|
|
+ para la descripción de un valor válido los
|
|
|
+ correspondientes formatos de datos.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">Orientación del Cursor</emphasis>
|
|
|
+ es el segundo parámetro. Por omisión es
|
|
|
+ Zend_Db::FETCH_ORI_NEXT, lo cual simplemente significa
|
|
|
+ que cada llamada a <code>fetch()</code> devuelve la
|
|
|
+ siguiente fila del resultado, en el orden devuelto por
|
|
|
+ el RDBMS.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">Compensación</emphasis> es el
|
|
|
+ tercer parámetro.
|
|
|
+ Si la orientación del cursor es Zend_Db::FETCH_ORI_ABS,
|
|
|
+ entonces el offset es el número ordinal
|
|
|
+ de las filas que devolver.
|
|
|
+ Si la orientación del cursor es Zend_Db::FETCH_ORI_REL,
|
|
|
+ entonces el offset es relativo a la posición del
|
|
|
+ cursor antes de que <code>fetch()</code> fuera llamado.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>fetch()</code> devuelve <code>false</code> si todas las filas
|
|
|
+ del conjunto de resultados han sido extraídas.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.statement.fetching.fetch.example">
|
|
|
+ <title>Usando fetch() en un bucle</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$stmt = $db->query('SELECT * FROM bugs');
|
|
|
+
|
|
|
+while ($row = $stmt->fetch()) {
|
|
|
+ echo $row['bug_description'];
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Vea también <ulink url="http://www.php.net/PDOStatement-fetch">PDOStatement::fetch()</ulink>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.statement.fetching.fetchall">
|
|
|
+
|
|
|
+ <title>Extrayendo un Conjunto de Resultados completo</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para extraer todas las filas de un resultado en un solo paso,
|
|
|
+ use el método <code>fetchAll()</code>. Esto es equivalente a
|
|
|
+ llamar al método <code>fetch()</code> en un bucle devolviendo
|
|
|
+ todas las filas en una array. El método <code>fetchAll()</code>
|
|
|
+ acepta 2 parámetros. El primero es el estilo de extracción,
|
|
|
+ descrito anteriormente, y el segundo indica el número de la
|
|
|
+ columa que devolver, cuando el estilo de extracción es
|
|
|
+ Zend_Db::FETCH_COLUMN.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.statement.fetching.fetchall.example">
|
|
|
+ <title>Usando fetchAll()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$stmt = $db->query('SELECT * FROM bugs');
|
|
|
+
|
|
|
+$rows = $stmt->fetchAll();
|
|
|
+
|
|
|
+echo $rows[0]['bug_description'];
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Vea también <ulink url="http://www.php.net/PDOStatement-fetchAll">PDOStatement::fetchAll()</ulink>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.statement.fetching.fetch-mode">
|
|
|
+
|
|
|
+ <title>Cambiando el Modo de extracción</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, el objeto de declaración devuelve filas de un
|
|
|
+ conjunto de resultados como array asociativo, mapeando los
|
|
|
+ nombres de columnas a los valores de la columna.
|
|
|
+ Se puede especificar un formato diferente para que la clase de
|
|
|
+ declaración devuelva las filas, tal como se puede con la clase
|
|
|
+ Adaptadora. Puede usar él método <code>setFetchMode()</code>
|
|
|
+ para establecer el modo de extracción. Especifique el modo de
|
|
|
+ extracción usando las constantes de la clase
|
|
|
+ Zend_Db: FETCH_ASSOC, FETCH_NUM, FETCH_BOTH,
|
|
|
+ FETCH_COLUMN, and FETCH_OBJ.
|
|
|
+ Vea <xref linkend="zend.db.adapter.select.fetch-mode"/>
|
|
|
+ para más información de estos modos.
|
|
|
+ Llamadas subsiguientes a los métodos de la declaración
|
|
|
+ <code>fetch()</code> o <code>fetchAll()</code> usan el modo de
|
|
|
+ extracción especificado.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.statement.fetching.fetch-mode.example">
|
|
|
+ <title>Configurando un modo de extracción</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$stmt = $db->query('SELECT * FROM bugs');
|
|
|
+
|
|
|
+$stmt->setFetchMode(Zend_Db::FETCH_NUM);
|
|
|
+
|
|
|
+$rows = $stmt->fetchAll();
|
|
|
+
|
|
|
+echo $rows[0][0];
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Vea también <ulink url="http://www.php.net/PDOStatement-setFetchMode">PDOStatement::setFetchMode()</ulink>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.statement.fetching.fetchcolumn">
|
|
|
+
|
|
|
+ <title>Extrayendo una Única Columna desde un Conjunto de Resultados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para devolver una única columna de la siguiente fila del
|
|
|
+ conjunto de resultados, use <code>fetchColumn()</code>. El
|
|
|
+ parámetro opcional es el índice de la columna (integer), y por
|
|
|
+ defecto es 0. Este método devuelve un valor escalar, o
|
|
|
+ <code>false</code> si todas las filas del conjunto de resultados
|
|
|
+ han sido extraídas.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Note que este método opera diferente que el método
|
|
|
+ <code>fetchCol()</code> de la clase Adaptadora.
|
|
|
+ El método <code>fetchColumn()</code> de una declaración devuelve
|
|
|
+ un único valor desde una fila.
|
|
|
+ El método <code>fetchCol()</code> de un adaptador devuelve un
|
|
|
+ array de valores, tomados desde la primera columa de todas las
|
|
|
+ del conjunto de resultados.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.statement.fetching.fetchcolumn.example">
|
|
|
+ <title>Usando fetchColumn()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$stmt = $db->query('SELECT bug_id, bug_description, bug_status FROM bugs');
|
|
|
+
|
|
|
+$bug_status = $stmt->fetchColumn(2);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Vea también <ulink url="http://www.php.net/PDOStatement-fetchColumn">PDOStatement::fetchColumn()</ulink>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.statement.fetching.fetchobject">
|
|
|
+
|
|
|
+ <title>Extrayendo una Fila como un Objeto</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para extraer una fila desde un conjunto de resultados
|
|
|
+ estructurado como un Objeto, use el método
|
|
|
+ <code>fetchObject()</code>. Este método tiene 2 parámetros
|
|
|
+ opcionales. El primer parámetro es un string con el nombre de
|
|
|
+ la clase del objeto que devolver; por defecto será 'stdClass'. El segundo
|
|
|
+ parámetro es un array de valores que serán pasados al
|
|
|
+ constructor de la clase.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.statement.fetching.fetchobject.example">
|
|
|
+ <title>Usando fetchObject()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$stmt = $db->query('SELECT bug_id, bug_description, bug_status FROM bugs');
|
|
|
+
|
|
|
+$obj = $stmt->fetchObject();
|
|
|
+
|
|
|
+echo $obj->bug_description;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Vea también <ulink url="http://www.php.net/PDOStatement-fetchObject">PDOStatement::fetchObject()</ulink>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <!--
|
|
|
+ @todo: binding parameters is not working yet.
|
|
|
+
|
|
|
+ <sect2 id="zend.db.statement.binding-param">
|
|
|
+
|
|
|
+ <title>Binding PHP Variables to Parameters</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.statement.binding-param.example">
|
|
|
+ <title>Binding parameters from PHP variables</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+<?php
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ See also <ulink url="http://www.php.net/PDOStatement-bindParam">PDOStatement::bindParam()</ulink>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+ -->
|
|
|
+
|
|
|
+ <!--
|
|
|
+ @todo: binding columns is not working yet.
|
|
|
+ <sect2 id="zend.db.statement.binding-column">
|
|
|
+
|
|
|
+ <title>Binding PHP Variables to Query Results</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.statement.binding-column.example">
|
|
|
+ <title>Binding results to PHP variables</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+<?php
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ See also <ulink url="http://www.php.net/PDOStatement-bindColumn">PDOStatement::bindColumn()</ulink>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+ -->
|
|
|
+
|
|
|
+</sect1>
|
|
|
+ <sect1 xmlns:xi="http://www.w3.org/2001/XInclude" id="zend.db.profiler" xml:base="module_specs/Zend_Db_Profiler.xml">
|
|
|
+
|
|
|
+ <title>Zend_Db_Profiler</title>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.profiler.introduction">
|
|
|
+
|
|
|
+ <title>Introducción</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Db_Profiler</code> puede ser habilitado para Perfilar las
|
|
|
+ consultas. Los Perfiles incluyen la consulta procesada por el adaptador como
|
|
|
+ el tiempo as transcurrido en la ejecución de las consultas, permitiendo
|
|
|
+ inspeccionar las consultas realizadas win necesidad de agregar información
|
|
|
+ de depuración extra en el código de las clases. El uso avanzado también permite
|
|
|
+ que el desarrollador filtre las consultas que desea perfilar.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Habilite el perfilador pasando una directiva al al constructor del adaptador,
|
|
|
+ o pidiendole al adaptador permitirlo más adelante.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$params = array(
|
|
|
+ 'host' => '127.0.0.1',
|
|
|
+ 'username' => 'webuser',
|
|
|
+ 'password' => 'xxxxxxxx',
|
|
|
+ 'dbname' => 'test'
|
|
|
+ 'profiler' => true // enciende el perfilador
|
|
|
+ // establezca false para deshabilitar (está deshabilitado por defecto)
|
|
|
+);
|
|
|
+
|
|
|
+$db = Zend_Db::factory('PDO_MYSQL', $params);
|
|
|
+
|
|
|
+// apagar el perfilador:
|
|
|
+$db->getProfiler()->setEnabled(false);
|
|
|
+
|
|
|
+// encender el perfilador:
|
|
|
+$db->getProfiler()->setEnabled(true);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El valor de la opción '<code>profiler</code>' es flexible. Es interpretada de distintas
|
|
|
+ formas dependiendo del tipo. Normalmente, debería usar un valor booleano simple, pero
|
|
|
+ otros tipos le permiten personalizar el comportamiento del perfilador.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un argumento booleano establece el perfilador como habilitado si el valor es
|
|
|
+ <code>true</code>, o deshabilitado si es <code>false</code>. La clase del perfilador
|
|
|
+ es el la clase de perfilador por defecto del adaptador, <code>Zend_Db_Profiler</code>.
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$params['profiler'] = true;
|
|
|
+$db = Zend_Db::factory('PDO_MYSQL', $params);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Una instancia del objeto perfilador hace que el adaptador use ese objeto.
|
|
|
+ El tipo del objeto debe ser <code>Zend_Db_Profiler</code> o una subclase de este.
|
|
|
+ Habilitar el perfilador se hace por separado.
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$profiler = MyProject_Db_Profiler();
|
|
|
+$profiler->setEnabled(true);
|
|
|
+$params['profiler'] = $profiler;
|
|
|
+$db = Zend_Db::factory('PDO_MYSQL', $params);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El argumento puede ser un array asociativo conteniendo algunas o todas las claves
|
|
|
+ '<code>enabled</code>', '<code>instance</code>', y '<code>class</code>'. Las claves
|
|
|
+ '<code>enabled</code>' e '<code>instance</code>' corresponden a los tipos booleano y
|
|
|
+ la instancia documentada previamente. La clave '<code>class</code>' es usada para nombrar
|
|
|
+ la clase que usará el perfilador personalizado. La clase debe ser
|
|
|
+ <code>Zend_Db_Profiler</code> o una subclase. La clase es instanciada sin argumentos
|
|
|
+ de constructor. La opción '<code>class</code>' es ignorada cuando la opción
|
|
|
+ '<code>instance</code>' está dada.
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$params['profiler'] = array(
|
|
|
+ 'enabled' => true,
|
|
|
+ 'class' => 'MyProject_Db_Profiler'
|
|
|
+);
|
|
|
+$db = Zend_Db::factory('PDO_MYSQL', $params);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Finalmente, el argumento puede ser un objeto de tipo <code>Zend_Config</code>
|
|
|
+ conteniendo las propiedades, que son tratadas como las claves de array descritas recién.
|
|
|
+ Por ejemplo, un archivo "config.ini" puede contener los siguientes datos:
|
|
|
+ <programlisting role="ini"><![CDATA[
|
|
|
+[main]
|
|
|
+db.profiler.class = "MyProject_Db_Profiler"
|
|
|
+db.profiler.enabled = true
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ Esta configuración puede ser aplicada con el siguiente código PHP:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$config = new Zend_Config_Ini('config.ini', 'main');
|
|
|
+$params['profiler'] = $config->db->profiler;
|
|
|
+$db = Zend_Db::factory('PDO_MYSQL', $params);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ La propiedad '<code>instance</code>' debe ser usada como el siguiente ejemplo:
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$profiler = new MyProject_Db_Profiler();
|
|
|
+$profiler->setEnabled(true);
|
|
|
+$configData = array(
|
|
|
+ 'instance' => $profiler
|
|
|
+ );
|
|
|
+$config = new Zend_Config($configData);
|
|
|
+$params['profiler'] = $config;
|
|
|
+$db = Zend_Db::factory('PDO_MYSQL', $params);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.profiler.using">
|
|
|
+
|
|
|
+ <title>Usando el Perfilador</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En este punto, obtenemos el perfilador usando el método
|
|
|
+ <code>getProfiler()</code> del adaptador:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$profiler = $db->getProfiler();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Este retorna una instancia del objeto <code>Zend_Db_Profiler</code>. Con
|
|
|
+ esta instancia, el desarrollador puede examinar las consultar usando una variedad
|
|
|
+ de métodos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>getTotalNumQueries()</code> retorna el número total
|
|
|
+ de consultas que han sido perfiladas.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>getTotalElapsedSecs()</code> retorna el número total
|
|
|
+ de segundos transcurridos en todas las consultas perfiladas.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>getQueryProfiles()</code> retorna un array con todos
|
|
|
+ los perfiles de consultas.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>getLastQueryProfile()</code> retorna el último perfil (más
|
|
|
+ reciente) de consulta, independientemente de si la consulta ha
|
|
|
+ terminado o no (si no lo ha hecho, la hora de finalización será nula).
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>clear()</code> limpia los perfiles de consulta de la pila.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El valor de retorno de <code>getLastQueryProfile()</code> y
|
|
|
+ elementos individuales de <code>getQueryProfiles()</code> son
|
|
|
+ <code>Zend_Db_Profiler_Query</code> objetos, que proporcionan la
|
|
|
+ capacidad para inspeccionar cada una de las consultas:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>getQuery()</code> retorna el texto SQL de la consulta.
|
|
|
+ El texto SQL de una declaración preparada con parámetros es el
|
|
|
+ texto al tiempo en que la consulta fué preparada, por lo que contiene
|
|
|
+ marcadores de posición, no los valores utilizados cuando la
|
|
|
+ declaración se ejecuta.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>getQueryParams()</code> retorna un array de
|
|
|
+ los valores de los parámetros usados cuando se ejecuta una consulta preparada.
|
|
|
+ Este incluye ambos parámetros y argumentos vinculados al método
|
|
|
+ <code>execute()</code> de la declaración. Las claves del array
|
|
|
+ son las posiciones (basado en 1) o indices de parámetros nombrados (string).
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>getElapsedSecs()</code> returna el número de segundos
|
|
|
+ que tuvo la consulta al correr.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La información que <code>Zend_Db_Profiler</code> provee es útil para
|
|
|
+ perfilar cuellos de botella en aplicaciones, y para depurar consultas que
|
|
|
+ han sido ejecutadas. Por instancia, para ver la consulta exacta que tuvo la
|
|
|
+ última ejecución:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$query = $profiler->getLastQueryProfile();
|
|
|
+
|
|
|
+echo $query->getQuery();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Tal vez una página se genera lentamente; use el perfilador para
|
|
|
+ determinar primero el número total de segundos de todas las consultas,
|
|
|
+ y luego recorrer paso a paso a través de las consultas para encontrar
|
|
|
+ la más lenta:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$totalTime = $profiler->getTotalElapsedSecs();
|
|
|
+$queryCount = $profiler->getTotalNumQueries();
|
|
|
+$longestTime = 0;
|
|
|
+$longestQuery = null;
|
|
|
+
|
|
|
+foreach ($profiler->getQueryProfiles() as $query) {
|
|
|
+ if ($query->getElapsedSecs() > $longestTime) {
|
|
|
+ $longestTime = $query->getElapsedSecs();
|
|
|
+ $longestQuery = $query->getQuery();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+echo 'Ejecutadas ' . $queryCount . ' consultas en ' . $totalTime .
|
|
|
+ ' segundos' . "\n";
|
|
|
+echo 'Promedio de tiempo de consulta: ' . $totalTime / $queryCount .
|
|
|
+ ' segundos' . "\n";
|
|
|
+echo 'Consultas por segundo: ' . $queryCount / $totalTime . "\n";
|
|
|
+echo 'Tardanza de la consulta más lenta: ' . $longestTime . "\n";
|
|
|
+echo "Consulta más lenta: \n" . $longestQuery . "\n";
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.profiler.advanced">
|
|
|
+
|
|
|
+ <title>Uso avanzado del Perfilador</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Además de la inspección de consultas, el perfilador también le permite
|
|
|
+ al desarrollador filtrar que consultas serán perfiladas. El siguiente método
|
|
|
+ opera en una instancia de <code>Zend_Db_Profiler</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.profiler.advanced.filtertime">
|
|
|
+ <title>Filtrar por tiempo transcurrido en consulta</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>setFilterElapsedSecs()</code> le permite al desarrolador establecer
|
|
|
+ un tiempo mínimo antes de que una consulta se perfile. Para remover el filtro,
|
|
|
+ pase un valor null al método.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Solo perfilar consultas que tardan más de 5 segundos:
|
|
|
+$profiler->setFilterElapsedSecs(5);
|
|
|
+
|
|
|
+// Perfilar todas las consultas sin importar el tiempo:
|
|
|
+$profiler->setFilterElapsedSecs(null);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.profiler.advanced.filtertype">
|
|
|
+ <title>Filtrar por tipo de consulta</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>setFilterQueryType()</code> le permite al desarrollador
|
|
|
+ establecer que tipo de consulta serán perfiladas; para perfilar multiples tipos,
|
|
|
+ use un "OR" lógico. Los tipos de consulta se definen como las siguientes
|
|
|
+ constantes de <code>Zend_Db_Profiler</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Db_Profiler::CONNECT</code>: operaciones de
|
|
|
+ conexión o selección de base de datos.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Db_Profiler::QUERY</code>: consultas generales
|
|
|
+ a la base de datos que no calzan con otros tipos.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Db_Profiler::INSERT</code>: cualquier consulta
|
|
|
+ que agrega filas a la base de datos, generalmente un SQL INSERT.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Db_Profiler::UPDATE</code>: cualquier consulta que
|
|
|
+ actualice registros existentes, usualmente un SQL UPDATE.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Db_Profiler::DELETE</code>: cualquier consulta
|
|
|
+ que elimine datos existentes, usualmente un SQL DELETE.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Db_Profiler::SELECT</code>: cualquier consulta que
|
|
|
+ retorne datos existentes, usualmente un SQL SELECT.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Db_Profiler::TRANSACTION</code>: cualquier
|
|
|
+ operación transaccional, tal como iniciar una transacción, confirmar,
|
|
|
+ o revertir.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Asi como con <code>setFilterElapsedSecs()</code>, puedes remover cualquier filtro
|
|
|
+ existente pasando un <code>null</code> como único argumento.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Perfilar solo consultas SELECT
|
|
|
+$profiler->setFilterQueryType(Zend_Db_Profiler::SELECT);
|
|
|
+
|
|
|
+// Perfila consultas SELECT, INSERT, y UPDATE
|
|
|
+$profiler->setFilterQueryType(Zend_Db_Profiler::SELECT |
|
|
|
+ Zend_Db_Profiler::INSERT |
|
|
|
+ Zend_Db_Profiler::UPDATE);
|
|
|
+
|
|
|
+// Perfilar consultas DELETE
|
|
|
+$profiler->setFilterQueryType(Zend_Db_Profiler::DELETE);
|
|
|
+
|
|
|
+// Remover todos los filtros
|
|
|
+$profiler->setFilterQueryType(null);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.profiler.advanced.getbytype">
|
|
|
+ <title>Obtener perfiles por tipo de consulta</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Usando <code>setFilterQueryType()</code> puedes reducir los
|
|
|
+ perfiles generados. Sin embargo, a veces puede ser más útil
|
|
|
+ mantener todos los perfiles, pero ver sólo los que necesita
|
|
|
+ en un determinado momento. Otra característica de
|
|
|
+ <code>getQueryProfiles()</code> es que puede este filtrado al-vuelo,
|
|
|
+ pasando un tipo de consulta(o una combinación lógica de tipos de consulta)
|
|
|
+ en el primer; vea <xref linkend="zend.db.profiler.advanced.filtertype"/>
|
|
|
+ para una lista las constantes de tipo de consulta.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Obtiene solo perfiles de consultas SELECT
|
|
|
+$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT);
|
|
|
+
|
|
|
+// Obtiene los perfiles de consultas SELECT, INSERT, y UPDATE
|
|
|
+$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT |
|
|
|
+ Zend_Db_Profiler::INSERT |
|
|
|
+ Zend_Db_Profiler::UPDATE);
|
|
|
+
|
|
|
+// Obtiene solo perfiles de consultas DELETE
|
|
|
+$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::DELETE);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.profiler.profilers">
|
|
|
+ <title>Perfiladores Especializados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un Perfilador Especializado es un objeto que hereda de
|
|
|
+ <code>Zend_Db_Profiler</code>. Los Perfiladores Especializados
|
|
|
+ tratan la información de perfilado de maneras más especificas.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.profiler.profilers.firebug">
|
|
|
+ <title>Perfilando con Firebug</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Db_Profiler_Firebug</code> envía información de
|
|
|
+perfilado a la <ulink url="http://getfirebug.com/logging.html">Consola</ulink> de
|
|
|
+ <ulink url="http://www.getfirebug.com/">Firebug</ulink>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todos los datos son enviados a través del componente
|
|
|
+ <code>Zend_Wildfire_Channel_HttpHeaders</code> que usa cabeceras HTTP
|
|
|
+ para asegurar que el contenido de la página no sea alterado.
|
|
|
+ Depurar peticiones AJAX que requieren respuestas JSON y XML
|
|
|
+ es perfectamente posible con este enfoque.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Requerimientos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ Navegador web Firefox idealmente versión 3, pero la versión 2
|
|
|
+ tambien está soportada.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem> <para>
|
|
|
+ Extensión Firebug para Firefox, la cual puede descargarse desde
|
|
|
+ <ulink url="https://addons.mozilla.org/en-US/firefox/addon/1843">https://addons.
|
|
|
+mozilla .org/en-US/firefox/addon/1843</ulink>.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Extensión FirePHP para Firefox, la cual puede descargarse desde
|
|
|
+<ulink url="https://addons.mozilla.org/en-US/firefox/addon/6149">https://addons.mozilla.org/en-US/firefox/addon/6149</ulink>.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <example id="zend.db.profiler.profilers.firebug.example.with_front_controller">
|
|
|
+ <title>Perfilando DB con <code>Zend_Controller_Front</code></title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// En tu archivo bootstrap
|
|
|
+
|
|
|
+$profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
|
|
|
+$profiler->setEnabled(true);
|
|
|
+
|
|
|
+// Anexar el perfilador a tu adaptador de base de datos
|
|
|
+$db->setProfiler($profiler)
|
|
|
+
|
|
|
+// Despachar el controlador frontal
|
|
|
+
|
|
|
+// Todas las consultas a la base de datos en tus archivos modelo, vista y controlador
|
|
|
+// ahora serán perfilados y enviados a Firebug
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <example id="zend.db.profiler.profilers.firebug.example.without_front_controller">
|
|
|
+ <title>Perfilar DB sin <code>Zend_Controller_Front</code></title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
|
|
|
+$profiler->setEnabled(true);
|
|
|
+
|
|
|
+// Anexar el perfilador a tu adaptador de base de datos
|
|
|
+$db->setProfiler($profiler)
|
|
|
+
|
|
|
+$request = new Zend_Controller_Request_Http();
|
|
|
+$response = new Zend_Controller_Response_Http();
|
|
|
+$channel = Zend_Wildfire_Channel_HttpHeaders::getInstance();
|
|
|
+$channel->setRequest($request);
|
|
|
+$channel->setResponse($response);
|
|
|
+
|
|
|
+// Iniciar un buffer de las salidas
|
|
|
+ob_start();
|
|
|
+
|
|
|
+// Ahora se pueden ejecutar las consultas a la Base de Datos para ser perfiladas
|
|
|
+
|
|
|
+// Enviar los datos de perfilado al navegador
|
|
|
+$channel->flush();
|
|
|
+$response->sendHeaders();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+</sect3><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.db.select" xml:base="module_specs/Zend_Db_Select.xml">
|
|
|
+
|
|
|
+ <title>Zend_Db_Select</title>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.select.introduction">
|
|
|
+
|
|
|
+ <title>Descripción del Objeto Select</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El objeto Zend_Db_Select object representa una declaración de consulta
|
|
|
+ <code>SELECT</code> de SQL. La clase tiene métodos para agregar partes
|
|
|
+ individuales a la consulta. Puedes especificar algunas partes de la consulta
|
|
|
+ usando los métodos en PHP y sus estructuras de datos, y la clase forma la sintaxis
|
|
|
+ SLQ correcta. Despues de construir la consulta, puedes ejecutarla como si
|
|
|
+ se hubiera escrito como un string.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El valor entregado por Zend_Db_Select incluye:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Métodos Orientados a objetos para especificar consultas SQL
|
|
|
+ de manera pieza-a-pieza;
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Abstracción de partes de las consultas SQL, independiente de la
|
|
|
+ Base de datos;
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Entrecomillado automático de identificadores de metadatos en
|
|
|
+ la mayoría de los casos, soportanto identificadores que contienen palabras
|
|
|
+ reservadas de SQL y caracteres especiales;
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Entrecomillado de identificadores y valores, para ayudar a reducir el
|
|
|
+ riesgo de ataque de inyección SQL.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El uso de Zend_Db_Select no es obligatorio. Para consultas SELECT muy simples,
|
|
|
+ es usualmente más simple especificar la consulta completa como un string
|
|
|
+ y ejecutarla usando un método del Adapter como <code>query()</code> o
|
|
|
+ <code>fetchAll()</code>. Usar Zend_Db_Select es util si se necesita ensamblar
|
|
|
+ una consulta SELECT proceduralmente, o basado en condiciones lógicas en
|
|
|
+ la aplicación.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.select.creating">
|
|
|
+
|
|
|
+ <title>Creando un Objeto Select</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puedes crear un a instancia del objeto Zend_Db_Select usando el método
|
|
|
+ <code>select()</code> de un objeto Zend_Db_Adapter_Abstract.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.creating.example-db">
|
|
|
+
|
|
|
+ <title>Ejemplo del método select() del adaptador</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db = Zend_Db::factory( ...options... );
|
|
|
+$select = $db->select();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Otra manera de crear el objeto Zend_Db_Select es con su constructor,
|
|
|
+ especificando el adaptador de base de datos como un argumento.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.creating.example-new">
|
|
|
+
|
|
|
+ <title>Ejemplo de creación de un nuevo objeto Select</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db = Zend_Db::factory( ...options... );
|
|
|
+$select = new Zend_Db_Select($db);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.select.building">
|
|
|
+
|
|
|
+ <title>Construyendo consultas Select</title>
|
|
|
+
|
|
|
+ <para>Cuando se construye una consulta, puede agregar clausulas a esta, una por una.
|
|
|
+ Hay un método separado para agregar cada al objeto Zend_Db_Select.</para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.example">
|
|
|
+
|
|
|
+ <title>Ejemplo de uso de métodos que agregan cláusulas</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Crear el objeto Zend_Db_Select
|
|
|
+$select = $db->select();
|
|
|
+
|
|
|
+// Agregar una cláusula FROM
|
|
|
+$select->from( ...specify table and columns... )
|
|
|
+
|
|
|
+// Agregar una cláusula WHERE
|
|
|
+$select->where( ...specify search criteria... )
|
|
|
+
|
|
|
+// Agregar una cláusula ORDER BY
|
|
|
+$select->order( ...specify sorting criteria... );
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>También puede utilizar la mayoría de los métodos del objeto Zend_Db_Select con una
|
|
|
+ interfaz fluida. Una interfaz fluida significa que cada método retorna una referencia
|
|
|
+ al objeto que se ha llamado, así puedes llamar inmediatamente a otro método.</para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.example-fluent">
|
|
|
+
|
|
|
+ <title>Ejemplo de uso de la interfaz fluida.</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$select = $db->select()
|
|
|
+ ->from( ...specify table and columns... )
|
|
|
+ ->where( ...specify search criteria... )
|
|
|
+ ->order( ...specify sorting criteria... );
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>Los ejemplos en esta sección muestran el uso de la interfaz fluída, pero también
|
|
|
+ puedes usar la interfaz no-fluída en todos los casos. A menudo es necesario
|
|
|
+ utilizar la interfaz no-fluída, por ejemplo, si su aplicación necesita realizar
|
|
|
+ cierta lógica antes de añadir una cláusula a la consulta.</para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.building.from">
|
|
|
+
|
|
|
+ <title>Agregando una cláusula FROM</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Especifica la tabla para esta consulta usando el método <code>from()</code>.
|
|
|
+ Puedes especificar el nombre de la tabla como un simple string. Zend_Db_Select
|
|
|
+ aplica el identificador entrecomillando el nombre de la tabla, así puedes
|
|
|
+ usar caracteres especiales.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.from.example">
|
|
|
+
|
|
|
+ <title>Ejemplo del método from()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye la consulta:
|
|
|
+// SELECT *
|
|
|
+// FROM "products"
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from( 'products' );
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puedes especificar un nombre correlacionado (también llamado a veces
|
|
|
+ "alias de tabla") para una tabla. En lugar de un simple string, se usa un
|
|
|
+ array asociativo que mapee el nombre de la correlación con el nombre de la tabla.
|
|
|
+ En otras cláusulas de consulta SQL, se usa esta correlación de nombre.
|
|
|
+ si su consulta se une con más de una tabla, Zend_Db_Select generatiza una
|
|
|
+ correlación unica de nombres basados en el nombre de la tabla, para una tabla
|
|
|
+ a la cual no se le espicifique un nombre correlacionado.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.from.example-cname">
|
|
|
+
|
|
|
+ <title>Ejemplo especificando una tabla con nombre correlacionado</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT p.*
|
|
|
+// FROM "products" AS p
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from( array('p' => 'products') );
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Algunos RDBMS apoyan el uso de un especificador de esquema para una tabla.
|
|
|
+ Puedes especificar el nombre de la tabla como
|
|
|
+ "<code>nombreDeEsquema.nombre DeTabla</code>", donde Zend_Db_Select entrecomillará
|
|
|
+ cada parte individualmente, o tambien puedes especificar el nombre de esquema
|
|
|
+ por separado. Un nombre de esquema especificado en el nombre de la tabla toma
|
|
|
+ precedencia en sobre un esquema dado por separado en el caso de que ambos
|
|
|
+ sean dados.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.from.example-schema">
|
|
|
+
|
|
|
+ <title>Ejemplo especificando un nombre de esquema</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT *
|
|
|
+// FROM "myschema"."products"
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from( 'myschema.products' );
|
|
|
+
|
|
|
+// o
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from('products', '*', 'myschema');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.building.columns">
|
|
|
+
|
|
|
+ <title>Agregando Columnas</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En el segundo argumento del método <code>from()</code>, puedes especificar
|
|
|
+ las columnas a seleccionar desde la respectiva tabla.
|
|
|
+ Si no especificas columns, por defecto será "<code>*</code>",
|
|
|
+ el comodín SQL para "todas las columnas".
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puedes listar las columnas en un simple array de strings, o en un
|
|
|
+ array asociativo mapeando los alias de columnas a su nombre de tabla.
|
|
|
+ Si solo se especifica una columna en la consulta y no necesitas especificar un
|
|
|
+ alias de columna, puedes listarla solo con un string plano de lugar de un array.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si se entrega un array vacío como el argumento de las tablas, no se incluirán
|
|
|
+ columnas en el resultado. Vea un
|
|
|
+ <link linkend="zend.db.select.building.join.example-no-columns">codigo de ejemplo</link>
|
|
|
+ bajo la sección del método <code>join()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puedes especificar el nombre de columna como
|
|
|
+ "<code>nombreCorrelacionado.nombreDeColumna</code>".
|
|
|
+ Zend_Db_Select entrecomullará cada parte individualmente. Si no especificas
|
|
|
+ un nombre correlacionado para una columna, se usará el nombre correlacionado
|
|
|
+ para la tabla nombrada en el actual método <code>from()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.columns.example">
|
|
|
+
|
|
|
+ <title>Ejemplos especificando columnas</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construir esta consulta:
|
|
|
+// SELECT p."product_id", p."product_name"
|
|
|
+// FROM "products" AS p
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('product_id', 'product_name'));
|
|
|
+
|
|
|
+// Construir la misma consulta, especificando nombres correlacionados:
|
|
|
+// SELECT p."product_id", p."product_name"
|
|
|
+// FROM "products" AS p
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('p.product_id', 'p.product_name'));
|
|
|
+
|
|
|
+// Construir esta consulta con una alias para una columna:
|
|
|
+// SELECT p."product_id" AS prodno, p."product_name"
|
|
|
+// FROM "products" AS p
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('prodno' => 'product_id', 'product_name'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.building.columns-expr">
|
|
|
+
|
|
|
+ <title>Agregando una Expresión en las Columns</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las columnas en consultas SQL a veces son expresiones, no simples columnas
|
|
|
+ de una tabla. Las expresiones no deberían tener nombres correlacionados o entrecomillado aplicado.
|
|
|
+ Si sus columnas contienen parentesis, Zend_Db_Select las reconoce como una expresión.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Tambien puedes crear un objeto de tipo Zend_Db_Expr explícitamente, para prevenir
|
|
|
+ que el string sea tratado como columna. Zend_Db_Expr es una clase mínima, que contiene
|
|
|
+ un simple string. Zend_Db_Select reconoce el objeto de tipo Zend_Db_Expr y
|
|
|
+ lo convierte de vuelta en el string, pero no le aplica ninguna alteración,
|
|
|
+ tal como el entrecomillado o la correlación de nombres.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El Uso de Zend_Db_Expr para nombres de columnas no es necesario si
|
|
|
+ la expresión de la columna contiene parentesis; Zend_Db_Select reconoce
|
|
|
+ y trata el string como expresión, saltándose el entrcomillado y la
|
|
|
+ correlación de nombres.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.columns-expr.example">
|
|
|
+
|
|
|
+ <title>Ejemplos especificando columnas que contienen expresiones</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT p."product_id", LOWER(product_name)
|
|
|
+// FROM "products" AS p
|
|
|
+// Una expresion con parentesis implicitamente se transforma en
|
|
|
+// un Zend_Db_Expr.
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('product_id', 'LOWER(product_name)'));
|
|
|
+
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT p."product_id", (p.cost * 1.08) AS cost_plus_tax
|
|
|
+// FROM "products" AS p
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('product_id',
|
|
|
+ 'cost_plus_tax' => '(p.cost * 1.08)')
|
|
|
+ );
|
|
|
+
|
|
|
+// Construye esta consulta usando Zend_Db_Expr explícitamente:
|
|
|
+// SELECT p."product_id", p.cost * 1.08 AS cost_plus_tax
|
|
|
+// FROM "products" AS p
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('product_id',
|
|
|
+ 'cost_plus_tax' =>
|
|
|
+ new Zend_Db_Expr('p.cost * 1.08'))
|
|
|
+ );
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En los casos anteriores, Zend_Db_Select no altera el string para aplicar
|
|
|
+ correlación de nombres o entrecomillado de identificadores. Si estos
|
|
|
+ cambios son necesarios para resolver ambigüedades, deberías realizar
|
|
|
+ cambios manualmente en el string.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si el nombre de su columna es alguna palabra reservada de SQL o
|
|
|
+ contiene caracteres especiales, debería usar el método
|
|
|
+ <code>quoteIdentifier()</code> del Adapdator e interpolar el resultado en un
|
|
|
+ string. El método <code>quoteIdentifier()</code> usa entrecomillado SQL para
|
|
|
+ delimitar el identificador,
|
|
|
+ the identifier, dejando en claro que es un identificador de tabla o columna y no
|
|
|
+ otra parte de la sintaxis SQL.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Su código es más independiente de la base de datos si se usa el método
|
|
|
+ <code>quoteIdentifier()</code> en vez de las excribir literalmente las comillas
|
|
|
+ en la cadena, debido a que algunos RDBMS no usan simbolos estándar para entrecomillar
|
|
|
+ identificadores.
|
|
|
+ El método <code>quoteIdentifier()</code> está diseñado para usar los símbolos
|
|
|
+ apropiados para entrecomillar basado en el tipo del adaptador.
|
|
|
+ El método <code>quoteIdentifier()</code> también escapa
|
|
|
+ cual caracter de comilla que aparezca en el nombre del identificador mismo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.columns-quoteid.example">
|
|
|
+
|
|
|
+ <title>Ejemplo de entrecomillado de columnas en una expresión</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta, entrecomillando el nombre
|
|
|
+// especial de la columna llamada "from" en la expresión:
|
|
|
+// SELECT p."from" + 10 AS origin
|
|
|
+// FROM "products" AS p
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('origin' =>
|
|
|
+ '(p.' . $db->quoteIdentifier('from') . ' + 10)')
|
|
|
+ );
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.building.columns-atomic">
|
|
|
+
|
|
|
+ <title>Agregar columnas a una tabla FROM o JOIN existente</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede haber casos en los que desea agregar columnas a una tabla FROM o JOIN
|
|
|
+ después de que estos métodos han sido llamados. El método <code>columns()</code>
|
|
|
+ permite agregar columnas en cualquier punto antes de ejecutar la consulta.
|
|
|
+ Puedes pasar las columnas bien como un string, un <code>Zend_Db_Expr</code> o
|
|
|
+ un array de estos elementos. El segundo argumento para este método puede ser omitido,
|
|
|
+ implicando que las columnas serán agregadas a una tabla FROM, en otro caso
|
|
|
+ debería usarse un nombre de correlación existente.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.columns-atomic.example">
|
|
|
+
|
|
|
+ <title>Ejemplos agregando columnas con el método<code>columns()</code></title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construir la consulta:
|
|
|
+// SELECT p."product_id", p."product_name"
|
|
|
+// FROM "products" AS p
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'), 'product_id')
|
|
|
+ ->columns('product_name');
|
|
|
+
|
|
|
+// Construir la misma consulta, especificando correlación de nombres:
|
|
|
+// SELECT p."product_id", p."product_name"
|
|
|
+// FROM "products" AS p
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'), 'p.product_id')
|
|
|
+ ->columns('product_name', 'p');
|
|
|
+ // Alternativamente puede usar columns('p.product_name')]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.building.join">
|
|
|
+
|
|
|
+ <title>Agregar Otra Tabla a la Consulta Query con JOIN</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Muchas consultas útiles involucran el uso de un <code>JOIN</code> para
|
|
|
+ combinar filas de multiples tablas. Puedes agregar tablas a una consulta Zend_Db_Select
|
|
|
+ usando el método <code>join()</code>. Usar este método, es similar
|
|
|
+ al método <code>from()</code>, excepto que puedes especificar una condición de unión
|
|
|
+ en la mayoría de los casos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.join.example">
|
|
|
+
|
|
|
+ <title>Ejemplo del método join()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT p."product_id", p."product_name", l.*
|
|
|
+// FROM "products" AS p JOIN "line_items" AS l
|
|
|
+// ON p.product_id = l.product_id
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('product_id', 'product_name'))
|
|
|
+ ->join(array('l' => 'line_items'),
|
|
|
+ 'p.product_id = l.product_id');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El segundo argumento <code>join()</code> es un string que es usado como condición de unión.
|
|
|
+ Esta es una expresión que declara un criterio por el cual las filas en una tabla concuerdan con
|
|
|
+ las filas de la otra tabla. Puedes especificar correlación de nombres en esta expresión.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ No se aplica entrecomillado en la expresión especificada para la condición de unión;
|
|
|
+ si tienes problemas con nombres que necesitan ser entrecomillados, deberás usar
|
|
|
+ <code>quoteIdentifier()</code> para formar el string de condición de unión.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El tercer argumento <code>join()</code> es un array de nombres de columnas, como
|
|
|
+ al usar el método <code>from()</code>. Este es por defecto "<code>*</code>", soporta
|
|
|
+ correlación de nombres, expresiones, y Zend_Db_Expr de la misma manera que el array de
|
|
|
+ nombres de columnas en el método <code>from()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para no seleccionar columnas de una tabla, use un array vacío para la lista de columnas.
|
|
|
+ El uso de esto trabaja con el método <code>from()</code> también, pero en general
|
|
|
+ deseará algunas columnas de la tabla primaria en sus consultas, a la vez que no se desean
|
|
|
+ columnas de la tabla unida.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.join.example-no-columns">
|
|
|
+
|
|
|
+ <title>Ejemplo especificando ninguna columna</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT p."product_id", p."product_name"
|
|
|
+// FROM "products" AS p JOIN "line_items" AS l
|
|
|
+// ON p.product_id = l.product_id
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('product_id', 'product_name'))
|
|
|
+ ->join(array('l' => 'line_items'),
|
|
|
+ 'p.product_id = l.product_id',
|
|
|
+ array() ); // empty list of columns
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Note el array vacío <code>array()</code> en el ejemplo anterior
|
|
|
+ en lugar de una lista de columnas de la tabla unida.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ SQL tiene muchos tipos de uniones. Vea una lista a continuación para los métodos
|
|
|
+ que soportan cada tipo de unión en Zend_Db_Select.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <command>INNER JOIN</command> con los métodos
|
|
|
+ <code>join(table, join, [columns])</code> o
|
|
|
+ <code>joinInner(table, join, [columns])</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esta es el tipo de unión más comun. Las filas de cada tabla son comparadas
|
|
|
+ usando la condición de unión especificada. El resultado incluye solo las filas
|
|
|
+ que satisfacen la condición. El resultado puede ser vacio si no hay filas que
|
|
|
+ satisfagan la condición.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todos los RDBMS soportan este tipo de unión.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <command>LEFT JOIN</command> con el método
|
|
|
+ <code>joinLeft(table, condition, [columns])</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todas las filas de tabla a la izquierda del operando son incluídas,
|
|
|
+ pareando las filas de la tabla a la derecha del operando,
|
|
|
+ y las columnas de la tabla a la derecha del operando son rellenadas con
|
|
|
+ NULLs si no existen filas que calcen con la tabla a la izquierda.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todos los RDBMS soportan este tipo de unión.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <command>RIGHT JOIN</command> con el método
|
|
|
+ <code>joinRight(table, condition, [columns])</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Unión exterior por la derecha es un complemento de la unión exterior por la
|
|
|
+ izquierda. Todas las filas de la tabla a la derecha del operando son incluídos,
|
|
|
+ pareando las filas de la tabla a la izquierda del operando incluídos, y las
|
|
|
+ columnas de la tabla a la izquierda del operando son rellenadas con NULLs si
|
|
|
+ no existen filas que calcen con la tabla de la derecha.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Algunos RDBMS no soportan'este tipo de join, pero en general, cualquier unión
|
|
|
+ por la derecha puede representarse por una unión por la derecha invirtiendo
|
|
|
+ el orden de las tablas.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <command>FULL JOIN</command> con el método
|
|
|
+ <code>joinFull(table, condition, [columns])</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Una unión externa total es como una combinación de una unión exterior por
|
|
|
+ la izquierda y una unión exterior por la derecha.
|
|
|
+ Todas las filas de ambas tablas son incluídas, vinculadas entre sí
|
|
|
+ en la misma fila si estos satisfacen la condición de unión, y en otro
|
|
|
+ caso se vinculan con valores nulos en lugar de columnas de la otra tabla.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Algunos RDBMS no soportan este tipo de unión.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <command>CROSS JOIN</command> con el método
|
|
|
+ <code>joinCross(table, [columns])</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Una unión cruzada es un Producto Cartesiano. Cada fila en la primera tabla
|
|
|
+ es pareada con cada una en la segunda tabla.
|
|
|
+ Por lo tanto, el número de filas en el resultado es igual al producto del
|
|
|
+ número de filas en cada tabla.
|
|
|
+ Puede filtrar el conjunto de resultados con el uso de condiciones en una
|
|
|
+ cláusula WHERE; de esta forma una unión cruzada es similar a la antigua
|
|
|
+ sintaxis de unión en SQL-89.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método <code>joinCross()</code> no tiene parámetros para especificar una
|
|
|
+ condición de unión. Algunos RDBMS no soportan este tipo de unión.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <command>NATURAL JOIN</command> con el método
|
|
|
+ <code>joinNatural(table, [columns])</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Una unión natural compara cualquier columa(s) que aparezca con el nombre
|
|
|
+ en ambas tablas. La comparación es el equivalente de todas las columna(s);
|
|
|
+ comparando las columnas usando desigualdad no es una unión natural.
|
|
|
+ Solo la unión interna natural es soportada por este API, aun cuando SQL
|
|
|
+ permita una unión externa natural.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método <code>joinNatural()</code> no tiene parámetros para especificar una condición.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Además de los métodos de unión, puedes simplificar las consultas
|
|
|
+ usando métodos JoinUsing. En vez de proveer una condición completa a la unión,
|
|
|
+ simplemente pasas el nombre de columna en la que se hará la uninón y
|
|
|
+ el objeto Zend_Db_Select completa la condición por ti.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.joinusing.example">
|
|
|
+
|
|
|
+ <title>Ejemplo de método joinUsing()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT *
|
|
|
+// FROM "table1"
|
|
|
+// JOIN "table2"
|
|
|
+// ON "table1".column1 = "table2".column1
|
|
|
+// WHERE column2 = 'foo'
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from('table1')
|
|
|
+ ->joinUsing('table2', 'column1')
|
|
|
+ ->where('column2 = ?', 'foo');]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cada uno de los métodos aplicables para uniones en el componente
|
|
|
+ Zend_Db_Select tiene su correspondiente método 'usando'.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>joinUsing(table, join, [columns])</code> y
|
|
|
+ <code>joinInnerUsing(table, join, [columns])</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>joinLeftUsing(table, join, [columns])</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>joinRightUsing(table, join, [columns])</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>joinFullUsing(table, join, [columns])</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.building.where">
|
|
|
+
|
|
|
+ <title>Agregar una cláusula WHERE</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede especificar un criterio para restringir las filas de resultado
|
|
|
+ usando el método <code>where()</code>. El primer argumento de este método
|
|
|
+ es una expresión SQL, y esta expresión es usada como una expresión SQL
|
|
|
+ <code>WHERE</code> en la consulta.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.where.example">
|
|
|
+
|
|
|
+ <title>Ejemplo del método where()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT product_id, product_name, price
|
|
|
+// FROM "products"
|
|
|
+// WHERE price > 100.00
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from('products',
|
|
|
+ array('product_id', 'product_name', 'price'))
|
|
|
+ ->where('price > 100.00');]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ No se aplica entrecomillado en una expresión dada en el método <code>where()</code> u
|
|
|
+ <code>orWhere()</code>. Si tienes nombres de columnas que necesitan ser entrecomillada,
|
|
|
+ debe usar el método <code>quoteIdentifier()</code> para formar el string de la condición.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El segundo argumento del método <code>where()</code> es opcional.
|
|
|
+ Es un valor a sustituir en la expresión. Zend_Db_Select entrecomilla el valor
|
|
|
+ y sustituye por un signo de interrogación ("<code>?</code>") en la expresión.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Este método acepta solo un parámetro. Si tienes una expresión
|
|
|
+ en la cual necesitas sustituir multiples variables, deberás formar
|
|
|
+ el string manualmente, interpolando variables y realizando entrecomillado
|
|
|
+ tu mismo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.where.example-param">
|
|
|
+
|
|
|
+ <title>Ejemplo de parámetro en el método where()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT product_id, product_name, price
|
|
|
+// FROM "products"
|
|
|
+// WHERE (price > 100.00)
|
|
|
+
|
|
|
+$minimumPrice = 100;
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from('products',
|
|
|
+ array('product_id', 'product_name', 'price'))
|
|
|
+ ->where('price > ?', $minimumPrice);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puedes invocar el método <code>where()</code> multiples veces en el mismo objeto
|
|
|
+ Zend_Db_Select. La consulta resultante combina los multiples terminos
|
|
|
+ juntos usando <code>AND</code> entre ellos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.where.example-and">
|
|
|
+
|
|
|
+ <title>Ejemplo de multiples métodos where()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT product_id, product_name, price
|
|
|
+// FROM "products"
|
|
|
+// WHERE (price > 100.00)
|
|
|
+// AND (price < 500.00)
|
|
|
+
|
|
|
+$minimumPrice = 100;
|
|
|
+$maximumPrice = 500;
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from('products',
|
|
|
+ array('product_id', 'product_name', 'price'))
|
|
|
+ ->where('price > ?', $minimumPrice)
|
|
|
+ ->where('price < ?', $maximumPrice);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si necesitas combinar terminos juntos uando <code>OR</code>, use el método
|
|
|
+ <code>orWhere()</code>. Este mñetodo se usa del mismo modo que el método
|
|
|
+ <code>where()</code>, excepto que el termino especificado es precedido por
|
|
|
+ <code>OR</code>, en lugar de <code>AND</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.where.example-or">
|
|
|
+
|
|
|
+ <title>Ejemplo del método orWhere()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT product_id, product_name, price
|
|
|
+// FROM "products"
|
|
|
+// WHERE (price < 100.00)
|
|
|
+// OR (price > 500.00)
|
|
|
+
|
|
|
+$minimumPrice = 100;
|
|
|
+$maximumPrice = 500;
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from('products',
|
|
|
+ array('product_id', 'product_name', 'price'))
|
|
|
+ ->where('price < ?', $minimumPrice)
|
|
|
+ ->orWhere('price > ?', $maximumPrice);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Db_Select automáticamente pone paréntesis alrededor de cada expresión
|
|
|
+ que especifiques usandp el método <code>where()</code> u <code>orWhere()</code>.
|
|
|
+ Esto ayuda a asegurar que la precedencia del operador Booleano no cause resultados
|
|
|
+ inesperados.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.where.example-parens">
|
|
|
+
|
|
|
+ <title>Ejemplos de Expresiones Booleanas con parentesis</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT product_id, product_name, price
|
|
|
+// FROM "products"
|
|
|
+// WHERE (price < 100.00 OR price > 500.00)
|
|
|
+// AND (product_name = 'Apple')
|
|
|
+
|
|
|
+$minimumPrice = 100;
|
|
|
+$maximumPrice = 500;
|
|
|
+$prod = 'Apple';
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from('products',
|
|
|
+ array('product_id', 'product_name', 'price'))
|
|
|
+ ->where("price < $minimumPrice OR price > $maximumPrice")
|
|
|
+ ->where('product_name = ?', $prod);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En el ejemplo anterior, los resultados deberían ser diferentes sin paréntesis,
|
|
|
+ porque <code>AND</code> tiene alta precedencia respecto a <code>OR</code>.
|
|
|
+ Zend_Db_Select aplica el parentesis con un efecto tal que la expresión en sucesivas
|
|
|
+ llamadas al método <code>where()</code> vincule más estrechamente el <code>AND</code>
|
|
|
+ que combina las expresiones.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.building.group">
|
|
|
+
|
|
|
+ <title>Agregando una cláusula GROUP BY</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En SQL, la cláusula <code>GROUP BY</code> permite reducir el número
|
|
|
+ de filas del resultado de una consulta a una fila por cada valor único
|
|
|
+ encontrado en la(s) columna(s) nombrada(s) en la cláusula
|
|
|
+ <code>GROUP BY</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En Zend_Db_Select, puedes especificar la(s) columna(s) a usar para el
|
|
|
+ cálculo de grupos de filas usando el método <code>group()</code>.
|
|
|
+ El argumento de este método es una columna o un array de columnas
|
|
|
+ que se usarán en la cláusula <code>GROUP BY</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.group.example">
|
|
|
+
|
|
|
+ <title>Ejemplo del método groups group()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT p."product_id", COUNT(*) AS line_items_per_product
|
|
|
+// FROM "products" AS p JOIN "line_items" AS l
|
|
|
+// ON p.product_id = l.product_id
|
|
|
+// GROUP BY p.product_id
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('product_id'))
|
|
|
+ ->join(array('l' => 'line_items'),
|
|
|
+ 'p.product_id = l.product_id',
|
|
|
+ array('line_items_per_product' => 'COUNT(*)'))
|
|
|
+ ->group('p.product_id');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como el array de columnas del método <code>from()</code>, peudes usar
|
|
|
+ correlación de nombres en el string de nombre de columna, y la conlumna será
|
|
|
+ entrecomillada como un identificador, salvo que el string contenga paréntesis
|
|
|
+ o sea un objeto de tipo Zend_Db_Expr.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.building.having">
|
|
|
+
|
|
|
+ <title>Agregando una cláusula HAVING</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En SQL, la cláusula <code>HAVING</code> aplica una condición de restricción
|
|
|
+ en grupos de filas. Es similar a una cláusula <code>WHERE</code>
|
|
|
+ aplicando una condición de restricción a las filas. Pero las 2 cláusulas
|
|
|
+ son diferentes porque las condiciones <code>WHERE</code>
|
|
|
+ son aplicadas antes que definan los grupos, mientras que las condiciones
|
|
|
+ <code>HAVING</code> son aplicadas después que los grupos son definidos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En Zend_Db_Select, puedes especificar condiciones para restringir
|
|
|
+ grupos usando el método <code>having()</code>. Su uso es similar al
|
|
|
+ del método <code>where()</code>. El primer agumento es un string
|
|
|
+ conteniendo una expresión SQL. El segundo argumento es un valor
|
|
|
+ que es usado para reemplazar un parámetro marcador de posición en la
|
|
|
+ expresión SQL. Las expresiones dadas en multiples invocaciones al método
|
|
|
+ <code>having()</code> son combinados usando el operador Booleano
|
|
|
+ <code>AND</code>, o el operador <code>OR</code> si usas el método
|
|
|
+ <code>orHaving()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.having.example">
|
|
|
+
|
|
|
+ <title>Ejemplo del método having()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT p."product_id", COUNT(*) AS line_items_per_product
|
|
|
+// FROM "products" AS p JOIN "line_items" AS l
|
|
|
+// ON p.product_id = l.product_id
|
|
|
+// GROUP BY p.product_id
|
|
|
+// HAVING line_items_per_product > 10
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('product_id'))
|
|
|
+ ->join(array('l' => 'line_items'),
|
|
|
+ 'p.product_id = l.product_id',
|
|
|
+ array('line_items_per_product' => 'COUNT(*)'))
|
|
|
+ ->group('p.product_id')
|
|
|
+ ->having('line_items_per_product > 10');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ No se aplica entrecomillado a expresiones dadas al método <code>having()</code> u
|
|
|
+ <code>orHaving()</code>. Si tienes nombres de columnas que deban ser
|
|
|
+ entrecomillados, deberás usar <code>quoteIdentifier()</code> para
|
|
|
+ formar el string de la condición.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.building.order">
|
|
|
+
|
|
|
+ <title>Agregar una cláusula ORDER BY</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En SQL, la cláusula <code>ORDER BY</code> especifica una o más
|
|
|
+ columnas o expresiones por el cual el resultado de la consulta
|
|
|
+ será ordenado. Si multiples columnas son listadas, las columnas secundarias
|
|
|
+ serán usadas para resolver relaciones; el orden de clasificación es determinado
|
|
|
+ por columnas secundarias si la columna anterior contiene valores identicos.
|
|
|
+ El orden por defecto es del menor valor al mayor valor. Puedes también
|
|
|
+ ordenar de mayor a menor valor para una columna dada en la lista espeificando
|
|
|
+ la palabra clave <code>DESC</code> despues de la columna.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En Zend_Db_Select, puedes usar el método el método <code>order()</code>
|
|
|
+ para especificar una columna o un array de columnas por el cual ordenar.
|
|
|
+ Cada elemento del array es un string nombrando la columna. Opcionalmente con la
|
|
|
+ palabra reservada <code>ASC</code> o <code>DESC</code> siguiendola, deparada
|
|
|
+ por un espacio.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como en el método <code>from()</code> y <code>group()</code>, los nombres de columnas
|
|
|
+ son entrecomillados como identificadores, a menos que contengan paréntesis
|
|
|
+ o sean un obheto de tipo Zend_Db_Expr.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.order.example">
|
|
|
+
|
|
|
+ <title>Ejemplo del método order()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT p."product_id", COUNT(*) AS line_items_per_product
|
|
|
+// FROM "products" AS p JOIN "line_items" AS l
|
|
|
+// ON p.product_id = l.product_id
|
|
|
+// GROUP BY p.product_id
|
|
|
+// ORDER BY "line_items_per_product" DESC, "product_id"
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('product_id'))
|
|
|
+ ->join(array('l' => 'line_items'),
|
|
|
+ 'p.product_id = l.product_id',
|
|
|
+ array('line_items_per_product' => 'COUNT(*)'))
|
|
|
+ ->group('p.product_id')
|
|
|
+ ->order(array('line_items_per_product DESC',
|
|
|
+ 'product_id'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.building.limit">
|
|
|
+
|
|
|
+ <title>Agregando una cláusula LIMIT</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Algunos RDBMS extienden una consulta SQL con una cláusula conocida como <code>LIMIT</code>.
|
|
|
+ Esta cláusuala reduce el número de filas en el resultado a no más de un número
|
|
|
+ especificado. También puedes especificar saltar el número de filas antes
|
|
|
+ de empezar la salida. Esta característica hace más fácil tomar un subconjunto de
|
|
|
+ resultados, por ejemplo cuando mostramos los resultados de una consulta en
|
|
|
+ progresivas páginas de salida.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En Zend_Db_Select, puedes usar el método <code>limit()</code> para especificar
|
|
|
+ la cantidad de filas y el número de filas a saltar. El primer argumento es
|
|
|
+ el método es el número de filas deseado. El segundo argument es el númerp de filas a saltar.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.limit.example">
|
|
|
+
|
|
|
+ <title>Ejemplo del método limit()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT p."product_id", p."product_name"
|
|
|
+// FROM "products" AS p
|
|
|
+// LIMIT 10, 20
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('product_id', 'product_name'))
|
|
|
+ ->limit(10, 20);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La sintaxis de <code>LIMIT</code> no está soportada por todos los RDBMS brands.
|
|
|
+ Algunos RDBMS requieren diferente sintaxis para soportar una funcionalidad simialr.
|
|
|
+ Cada clase Zend_Db_Adapter_Abstract incluye un método
|
|
|
+ para producir el SQL apropiado para cada RDBMS.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Use el método <code>limitPage()</code> como un modo alternativa de
|
|
|
+ especificar la cantidad de filas y compensación.
|
|
|
+ Este método permite limitar el conjunto resultado a una serie de subconjuntos
|
|
|
+ de tamaño fijo de filas del total del resultado de la consulta.
|
|
|
+ En otras palabras, puedes especificar el tamaño de una "página" de resultados,
|
|
|
+ y el número ordinal de la página simple donde se espera que retorne la consulta.
|
|
|
+ El número de página es el primer argumento del método <code>limitPage()</code>,
|
|
|
+ y la longitud de la página es el segundo argumento.
|
|
|
+ Ambos son argumentos requeridos; no tienen valores por omisión.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.limit.example2">
|
|
|
+
|
|
|
+ <title>Ejemplo del método limitPage()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT p."product_id", p."product_name"
|
|
|
+// FROM "products" AS p
|
|
|
+// LIMIT 10, 20
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products'),
|
|
|
+ array('product_id', 'product_name'))
|
|
|
+ ->limitPage(2, 10);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.building.distinct">
|
|
|
+
|
|
|
+ <title>Agregar el modificador DISTINCT a la consulta</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método <code>distinct()</code> permite agregar la palabra
|
|
|
+ clave a la consulta <code>DISTINCT</code> a su consulta SQL.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.distinct.example">
|
|
|
+
|
|
|
+ <title>Ejemplo del método distinct()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT DISTINCT p."product_name"
|
|
|
+// FROM "products" AS p
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->distinct()
|
|
|
+ ->from(array('p' => 'products'), 'product_name');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.building.for-update">
|
|
|
+
|
|
|
+ <title>Agregar el modificador FOR UPDATE</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método <code>forUpdate()</code> permite agregar el modificador
|
|
|
+ <code>FOR UPDATE</code> a su consulta SQL.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.building.for-update.example">
|
|
|
+
|
|
|
+ <title>Example of forUpdate() method</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT FOR UPDATE p.*
|
|
|
+// FROM "products" AS p
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->forUpdate()
|
|
|
+ ->from(array('p' => 'products'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.select.execute">
|
|
|
+
|
|
|
+ <title>Ejecutando consultas Select</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esta sección se describe como ejecutar una consulta representada por
|
|
|
+ un objeto Zend_Db_Select.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.execute.query-adapter">
|
|
|
+
|
|
|
+ <title>Ejecutando Consultas SelectExecuting desde el Adaptador de Base de Datos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puedes ejecutar la consulta representada por el objeto Zend_Db_Select pasandolo
|
|
|
+ como primer argumento al método <code>query()</code> de un objeto Zend_Db_Adapter_Abstract.
|
|
|
+ Use objetos Zend_Db_Select en lugar de un string de consulta.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método <code>query()</code> retorna un objeto de tipo
|
|
|
+ Zend_Db_Statement o PDOStatement, dependiendo del tipo de adaptador.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.execute.query-adapter.example">
|
|
|
+
|
|
|
+ <title>Ejemplo usando el método adaptador query() del Adaptador de Base de datos</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$select = $db->select()
|
|
|
+ ->from('products');
|
|
|
+
|
|
|
+$stmt = $db->query($select);
|
|
|
+$result = $stmt->fetchAll();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.execute.query-select">
|
|
|
+
|
|
|
+ <title>Ejecutando Consultas Select desde el Objeto</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como alternativa al uso del método <code>query()</code> del objeto adaptador,
|
|
|
+ puedes usar el método <code>query()</code> del objeto Zend_Db_Select. Ambos
|
|
|
+ métodos retornan un objeto de tipo Zend_Db_Statement o PDOStatement, dependiendo
|
|
|
+ del tipo de adaptador.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.execute.query-select.example">
|
|
|
+
|
|
|
+ <title>Ejempo usando el método query() del objeto Select</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$select = $db->select()
|
|
|
+ ->from('products');
|
|
|
+
|
|
|
+$stmt = $select->query();
|
|
|
+$result = $stmt->fetchAll();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.execute.tostring">
|
|
|
+
|
|
|
+ <title>Convertiendo un Objeto Select a un String SQL</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si necesitas acceder a una represantación en un string de la
|
|
|
+ consulta SQL correspondiente al objeto Zend_Db_Select,
|
|
|
+ use el método <code>__toString()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.execute.tostring.example">
|
|
|
+
|
|
|
+ <title>Ejemplo del método __toString()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$select = $db->select()
|
|
|
+ ->from('products');
|
|
|
+
|
|
|
+$sql = $select->__toString();
|
|
|
+echo "$sql\n";
|
|
|
+
|
|
|
+// The output is the string:
|
|
|
+// SELECT * FROM "products"
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.select.other">
|
|
|
+
|
|
|
+ <title>Otros Métodos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esta sección describe otros métodos de Zend_Db_Select que no han
|
|
|
+ sido cubiertos antes: <code>getPart()</code> y <code>reset()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.other.get-part">
|
|
|
+
|
|
|
+ <title>Obtener Partes de un Objeto Select</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método <code>getPart()</code> retorna una representación de
|
|
|
+ una parte de su consulta SQL. Por ejemplo, puedes usar este
|
|
|
+ método para retornar un array de expresiones para la cláusula
|
|
|
+ <code>WHERE</code>, o el array de columnas (o expresiones de
|
|
|
+ columnas) que estan en la lista del <code>SELECT</code>, o los
|
|
|
+ valores de la cantidad y comienzo para la cláusula
|
|
|
+ <code>LIMIT</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El valor de retorno no es un string conteniendo un fragmento
|
|
|
+ de la sintaxis SQL. El valor de retorno es una representación,
|
|
|
+ típicamente un array con una estructura que contiene valores y
|
|
|
+ expresiones. Cada parte de la consulta tiene una estructura
|
|
|
+ diferente.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El único argumento del método <code>getPart()</code> es un
|
|
|
+ string que identifica que parte del la consulta Select va a
|
|
|
+ retornar. Por ejemplo, el string <code>'from'</code> identifica
|
|
|
+ la parte del objeto Select que almacena la información de las
|
|
|
+ tablas de la cláusula <code>FROM</code>, incluyendo uniones de
|
|
|
+ tablas.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La clase Zend_Db_Select define constantes que puedes usar para
|
|
|
+ las partes de la consulta SQL.
|
|
|
+ Puedes usar estas definiciones de constantes, o los strings
|
|
|
+ literales.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <table id="zend.db.select.other.get-part.table">
|
|
|
+
|
|
|
+ <title>Constantes usedas por getPart() y reset()</title>
|
|
|
+
|
|
|
+ <tgroup cols="2">
|
|
|
+ <thead>
|
|
|
+ <row>
|
|
|
+ <entry>Constante</entry>
|
|
|
+ <entry>Valor del String</entry>
|
|
|
+ </row>
|
|
|
+ </thead>
|
|
|
+
|
|
|
+ <tbody>
|
|
|
+ <row>
|
|
|
+ <entry><code>Zend_Db_Select::DISTINCT</code></entry>
|
|
|
+ <entry><code>'distinct'</code></entry>
|
|
|
+ </row>
|
|
|
+
|
|
|
+ <row>
|
|
|
+ <entry><code>Zend_Db_Select::FOR_UPDATE</code></entry>
|
|
|
+ <entry><code>'forupdate'</code></entry>
|
|
|
+ </row>
|
|
|
+
|
|
|
+ <row>
|
|
|
+ <entry><code>Zend_Db_Select::COLUMNS</code></entry>
|
|
|
+ <entry><code>'columns'</code></entry>
|
|
|
+ </row>
|
|
|
+
|
|
|
+ <row>
|
|
|
+ <entry><code>Zend_Db_Select::FROM</code></entry>
|
|
|
+ <entry><code>'from'</code></entry>
|
|
|
+ </row>
|
|
|
+
|
|
|
+ <row>
|
|
|
+ <entry><code>Zend_Db_Select::WHERE</code></entry>
|
|
|
+ <entry><code>'where'</code></entry>
|
|
|
+ </row>
|
|
|
+
|
|
|
+ <row>
|
|
|
+ <entry><code>Zend_Db_Select::GROUP</code></entry>
|
|
|
+ <entry><code>'group'</code></entry>
|
|
|
+ </row>
|
|
|
+
|
|
|
+ <row>
|
|
|
+ <entry><code>Zend_Db_Select::HAVING</code></entry>
|
|
|
+ <entry><code>'having'</code></entry>
|
|
|
+ </row>
|
|
|
+
|
|
|
+ <row>
|
|
|
+ <entry><code>Zend_Db_Select::ORDER</code></entry>
|
|
|
+ <entry><code>'order'</code></entry>
|
|
|
+ </row>
|
|
|
+
|
|
|
+ <row>
|
|
|
+ <entry><code>Zend_Db_Select::LIMIT_COUNT</code></entry>
|
|
|
+ <entry><code>'limitcount'</code></entry>
|
|
|
+ </row>
|
|
|
+
|
|
|
+ <row>
|
|
|
+ <entry><code>Zend_Db_Select::LIMIT_OFFSET</code></entry>
|
|
|
+ <entry><code>'limitoffset'</code></entry>
|
|
|
+ </row>
|
|
|
+ </tbody>
|
|
|
+ </tgroup>
|
|
|
+ </table>
|
|
|
+
|
|
|
+ <example id="zend.db.select.other.get-part.example">
|
|
|
+
|
|
|
+ <title>Ejemplo del método getPart()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$select = $db->select()
|
|
|
+ ->from('products')
|
|
|
+ ->order('product_id');
|
|
|
+
|
|
|
+// Puedes especificar un string string literal para especificar la parte
|
|
|
+$orderData = $select->getPart( 'order' );
|
|
|
+
|
|
|
+// Puedes usar una constante para especificar la misma parte
|
|
|
+$orderData = $select->getPart( Zend_Db_Select::ORDER );
|
|
|
+
|
|
|
+// El valor de retorno puede ser una estructura en un array, no un string.
|
|
|
+// Cada parte tiene distinta estructura.
|
|
|
+print_r( $orderData );
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.select.other.reset">
|
|
|
+
|
|
|
+ <title>Restableciendo Partes de un Objeto</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método <code>reset()</code> permite limpiar una parte
|
|
|
+ específica de la consulta SQL, o limpia todas las partes de la
|
|
|
+ consulta SQL si omites el argumento.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El argumento es opcional. Puedes especificar la parte de la
|
|
|
+ consulta que será limpiada, usando los mismos strings que usa el
|
|
|
+ argumento del método <code>getPart()</code>. La parte de la
|
|
|
+ consulta que especifiques se reestablecerá a su estado por
|
|
|
+ omisión.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si omites el parámetro, <code>reset()</code> cambia todas las
|
|
|
+ partes de la consulta a su estado por omisión. Esto hace que
|
|
|
+ el objeto Zend_Db_Select sea equivalente a crear un nuevo
|
|
|
+ objeto, como si acabases de instanciarlo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.select.other.reset.example">
|
|
|
+
|
|
|
+ <title>Ejemplo del método reset()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Construye esta consulta:
|
|
|
+// SELECT p.*
|
|
|
+// FROM "products" AS p
|
|
|
+// ORDER BY "product_name"
|
|
|
+
|
|
|
+$select = $db->select()
|
|
|
+ ->from(array('p' => 'products')
|
|
|
+ ->order('product_name');
|
|
|
+
|
|
|
+// Requisito cambiado, en su lugar un orden diferente de columnas:
|
|
|
+// SELECT p.*
|
|
|
+// FROM "products" AS p
|
|
|
+// ORDER BY "product_id"
|
|
|
+
|
|
|
+// Limpia una parte para poder redefinirla
|
|
|
+$select->reset( Zend_Db_Select::ORDER );
|
|
|
+
|
|
|
+// Y especificar una columna diferente
|
|
|
+$select->order('product_id');
|
|
|
+
|
|
|
+// Limpia todas las partes de la consulta
|
|
|
+$select->reset();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.db.table" xml:base="module_specs/Zend_Db_Table.xml">
|
|
|
+
|
|
|
+ <title>Zend_Db_Table</title>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.introduction">
|
|
|
+
|
|
|
+ <title>Introduction to Table Class</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The Zend_Db_Table class is an object-oriented interface to database tables. It provides
|
|
|
+ methods for many common operations on tables. The base class is extensible, so you can
|
|
|
+ add custom logic.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The Zend_Db_Table solution is an implementation of the
|
|
|
+ <ulink url="http://www.martinfowler.com/eaaCatalog/tableDataGateway.html">Table Data
|
|
|
+ Gateway</ulink> pattern. The solution also includes a class that implements the
|
|
|
+ <ulink url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data
|
|
|
+ Gateway</ulink> pattern.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.defining">
|
|
|
+
|
|
|
+ <title>Defining a Table Class</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ For each table in your database that you want to access, define a class that extends
|
|
|
+ Zend_Db_Table_Abstract.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.defining.table-schema">
|
|
|
+
|
|
|
+ <title>Defining the Table Name and Schema</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Declare the database table for which this class is defined, using the protected
|
|
|
+ variable <code>$_name</code>. This is a string, and must contain the name of the
|
|
|
+ table spelled as it appears in the database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.defining.table-schema.example1">
|
|
|
+
|
|
|
+ <title>Declaring a table class with explicit table name</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bugs';
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you don't specify the table name, it defaults to the name of the class. If you
|
|
|
+ rely on this default, the class name must match the spelling of the table name as
|
|
|
+ it appears in the database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.defining.table-schema.example">
|
|
|
+
|
|
|
+ <title>Declaring a table class with implicit table name</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ // table name matches class name
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can also declare the schema for the table, either with the protected variable
|
|
|
+ <code>$_schema</code>, or with the schema prepended to the table name in the
|
|
|
+ <code>$_name</code> property. Any schema specified with the <code>$_name</code>
|
|
|
+ property takes precedence over a schema specified with the <code>$_schema</code>
|
|
|
+ property. In some RDBMS brands, the term for schema is "database" or "tablespace,"
|
|
|
+ but it is used similarly.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.defining.table-schema.example3">
|
|
|
+
|
|
|
+ <title>Declaring a table class with schema</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// First alternative:
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_schema = 'bug_db';
|
|
|
+ protected $_name = 'bugs';
|
|
|
+}
|
|
|
+
|
|
|
+// Second alternative:
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bug_db.bugs';
|
|
|
+}
|
|
|
+
|
|
|
+// If schemas are specified in both $_name and $_schema, the one
|
|
|
+// specified in $_name takes precedence:
|
|
|
+
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bug_db.bugs';
|
|
|
+ protected $_schema = 'ignored';
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The schema and table names may also be specified via constructor configuration
|
|
|
+ directives, which override any default values specified with the
|
|
|
+ <code>$_name</code> and <code>$_schema</code> properties. A schema specification
|
|
|
+ given with the <code>name</code> directive overrides any value provided with the
|
|
|
+ <code>schema</code> option.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.defining.table-schema.example.constructor">
|
|
|
+
|
|
|
+ <title>Declaring table and schema names upon instantiation</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+// First alternative:
|
|
|
+
|
|
|
+$tableBugs = new Bugs(array('name' => 'bugs', 'schema' => 'bug_db'));
|
|
|
+
|
|
|
+// Second alternative:
|
|
|
+
|
|
|
+$tableBugs = new Bugs(array('name' => 'bug_db.bugs');
|
|
|
+
|
|
|
+// If schemas are specified in both 'name' and 'schema', the one
|
|
|
+// specified in 'name' takes precedence:
|
|
|
+
|
|
|
+$tableBugs = new Bugs(array('name' => 'bug_db.bugs',
|
|
|
+ 'schema' => 'ignored');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you don't specify the schema name, it defaults to the schema to which your
|
|
|
+ database adapter instance is connected.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.defining.primary-key">
|
|
|
+
|
|
|
+ <title>Defining the Table Primary Key</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Every table must have a primary key. You can declare the column for the primary key
|
|
|
+ using the protected variable <code>$_primary</code>. This is either a string that
|
|
|
+ names the single column for the primary key, or else it is an array of column names
|
|
|
+ if your primary key is a compound key.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.defining.primary-key.example">
|
|
|
+
|
|
|
+ <title>Example of specifying the primary key</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bugs';
|
|
|
+ protected $_primary = 'bug_id';
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you don't specify the primary key, Zend_Db_Table_Abstract tries to discover the
|
|
|
+ primary key based on the information provided by the <code>describeTable()</code>´
|
|
|
+ method.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Every table class must know which column(s) can be used to address rows
|
|
|
+ uniquely. If no primary key column(s) are specified in the table class
|
|
|
+ definition or the table constructor arguments, or discovered in the table
|
|
|
+ metadata provided by <code>describeTable()</code>, then the table cannot be
|
|
|
+ used with Zend_Db_Table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.defining.setup">
|
|
|
+
|
|
|
+ <title>Overriding Table Setup Methods</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ When you create an instance of a Table class, the constructor calls a set of
|
|
|
+ protected methods that initialize metadata for the table. You can extend any of
|
|
|
+ these methods to define metadata explicitly. Remember to call the method of the
|
|
|
+ same name in the parent class at the end of your method.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.defining.setup.example">
|
|
|
+
|
|
|
+ <title>Example of overriding the _setupTableName() method</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected function _setupTableName()
|
|
|
+ {
|
|
|
+ $this->_name = 'bugs';
|
|
|
+ parent::_setupTableName();
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The setup methods you can override are the following:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>_setupDatabaseAdapter()</code> checks that an adapter has been
|
|
|
+ provided; gets a default adapter from the registry if needed. By overriding
|
|
|
+ this method, you can set a database adapter from some other source.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>_setupTableName()</code> defaults the table name to the name of the
|
|
|
+ class. By overriding this method, you can set the table name before this
|
|
|
+ default behavior runs.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>_setupMetadata()</code> sets the schema if the table name contains
|
|
|
+ the pattern "schema.table"; calls <code>describeTable()</code> to get
|
|
|
+ metadata information; defaults the <code>$_cols</code> array to the columns
|
|
|
+ reported by <code>describeTable()</code>. By overriding this method, you
|
|
|
+ can specify the columns.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>_setupPrimaryKey()</code> defaults the primary key columns to those
|
|
|
+ reported by <code>describeTable()</code>; checks that the primary key
|
|
|
+ columns are included in the <code>$_cols</code> array. By overriding this
|
|
|
+ method, you can specify the primary key columns.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.initialization">
|
|
|
+
|
|
|
+ <title>Table initialization</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If application-specific logic needs to be initialized when a Table class is
|
|
|
+ constructed, you can select to move your tasks to the <code>init()</code> method,
|
|
|
+ which is called after all Table metadata has been processed. This is recommended
|
|
|
+ over the <code>__construct</code> method if you do not need to alter the metadata
|
|
|
+ in any programmatic way.
|
|
|
+
|
|
|
+ <example id="zend.db.table.defining.init.usage.example">
|
|
|
+
|
|
|
+ <title>Example usage of init() method</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_observer;
|
|
|
+
|
|
|
+ protected function init()
|
|
|
+ {
|
|
|
+ $this->_observer = new MyObserverClass();
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.constructing">
|
|
|
+
|
|
|
+ <title>Creating an Instance of a Table</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Before you use a Table class, create an instance using its constructor. The
|
|
|
+ constructor's argument is an array of options. The most important option to a Table
|
|
|
+ constructor is the database adapter instance, representing a live connection to an
|
|
|
+ RDBMS. There are three ways of specifying the database adapter to a Table class, and
|
|
|
+ these three ways are described below:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.constructing.adapter">
|
|
|
+
|
|
|
+ <title>Specifying a Database Adapter</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The first way to provide a database adapter to a Table class is by passing it as an
|
|
|
+ object of type Zend_Db_Adapter_Abstract in the options array, identified by the key
|
|
|
+ <code>'db'</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.constructing.adapter.example">
|
|
|
+
|
|
|
+ <title>Example of constructing a Table using an Adapter object</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db = Zend_Db::factory('PDO_MYSQL', $options);
|
|
|
+
|
|
|
+$table = new Bugs(array('db' => $db));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.constructing.default-adapter">
|
|
|
+
|
|
|
+ <title>Setting a Default Database Adapter</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The second way to provide a database adapter to a Table class is by declaring an
|
|
|
+ object of type Zend_Db_Adapter_Abstract to be a default database adapter for all
|
|
|
+ subsequent instances of Tables in your application. You can do this with the static
|
|
|
+ method <code>Zend_Db_Table_Abstract::setDefaultAdapter()</code>. The argument is an
|
|
|
+ object of type Zend_Db_Adapter_Abstract.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.constructing.default-adapter.example">
|
|
|
+
|
|
|
+ <title>Example of constructing a Table using a the Default Adapter</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db = Zend_Db::factory('PDO_MYSQL', $options);
|
|
|
+Zend_Db_Table_Abstract::setDefaultAdapter($db);
|
|
|
+
|
|
|
+// Later...
|
|
|
+
|
|
|
+$table = new Bugs();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ It can be convenient to create the database adapter object in a central place of
|
|
|
+ your application, such as the bootstrap, and then store it as the default adapter.
|
|
|
+ This gives you a means to ensure that the adapter instance is the same throughout
|
|
|
+ your application. However, setting a default adapter is limited to a single adapter
|
|
|
+ instance.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.constructing.registry">
|
|
|
+
|
|
|
+ <title>Storing a Database Adapter in the Registry</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The third way to provide a database adapter to a Table class is by passing a string
|
|
|
+ in the options array, also identified by the <code>'db'</code> key. The string is
|
|
|
+ used as a key to the static Zend_Registry instance, where the entry at that key is
|
|
|
+ an object of type Zend_Db_Adapter_Abstract.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.constructing.registry.example">
|
|
|
+
|
|
|
+ <title>Example of constructing a Table using a Registry key</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$db = Zend_Db::factory('PDO_MYSQL', $options);
|
|
|
+Zend_Registry::set('my_db', $db);
|
|
|
+
|
|
|
+// Later...
|
|
|
+
|
|
|
+$table = new Bugs(array('db' => 'my_db'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Like setting the default adapter, this gives you the means to ensure that the same
|
|
|
+ adapter instance is used throughout your application. Using the registry is more
|
|
|
+ flexible, because you can store more than one adapter instance. A given adapter
|
|
|
+ instance is specific to a certain RDBMS brand and database instance. If your
|
|
|
+ application needs access to multiple databases or even multiple database brands,
|
|
|
+ then you need to use multiple adapters.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.insert">
|
|
|
+
|
|
|
+ <title>Inserting Rows to a Table</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can use the Table object to insert rows into the database table on which the Table
|
|
|
+ object is based. Use the <code>insert()</code> method of your Table object. The
|
|
|
+ argument is an associative array, mapping column names to values.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.insert.example">
|
|
|
+
|
|
|
+ <title>Example of inserting to a Table</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$data = array(
|
|
|
+ 'created_on' => '2007-03-22',
|
|
|
+ 'bug_description' => 'Something wrong',
|
|
|
+ 'bug_status' => 'NEW'
|
|
|
+);
|
|
|
+
|
|
|
+$table->insert($data);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ By default, the values in your data array are inserted as literal values, using
|
|
|
+ parameters. If you need them to be treated as SQL expressions, you must make sure they
|
|
|
+ are distinct from plain strings. Use an object of type Zend_Db_Expr to do this.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.insert.example-expr">
|
|
|
+
|
|
|
+ <title>Example of inserting expressions to a Table</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$data = array(
|
|
|
+ 'created_on' => new Zend_Db_Expr('CURDATE()'),
|
|
|
+ 'bug_description' => 'Something wrong',
|
|
|
+ 'bug_status' => 'NEW'
|
|
|
+);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In the examples of inserting rows above, it is assumed that the table has an
|
|
|
+ auto-incrementing primary key. This is the default behavior of Zend_Db_Table_Abstract,
|
|
|
+ but there are other types of primary keys as well. The following sections describe how
|
|
|
+ to support different types of primary keys.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.insert.key-auto">
|
|
|
+
|
|
|
+ <title>Using a Table with an Auto-incrementing Key</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ An auto-incrementing primary key generates a unique integer value for you if you
|
|
|
+ omit the primary key column from your SQL <code>INSERT</code> statement.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In Zend_Db_Table_Abstract, if you define the protected variable
|
|
|
+ <code>$_sequence</code> to be the Boolean value <code>true</code>, then the class
|
|
|
+ assumes that the table has an auto-incrementing primary key.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.insert.key-auto.example">
|
|
|
+
|
|
|
+ <title>Example of declaring a Table with auto-incrementing primary key</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bugs';
|
|
|
+
|
|
|
+ // This is the default in the Zend_Db_Table_Abstract class;
|
|
|
+ // you do not need to define this.
|
|
|
+ protected $_sequence = true;
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ MySQL, Microsoft SQL Server, and SQLite are examples of RDBMS brands that support
|
|
|
+ auto-incrementing primary keys.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ PostgreSQL has a <code>SERIAL</code> notation that implicitly defines a sequence
|
|
|
+ based on the table and column name, and uses the sequence to generate key values
|
|
|
+ for new rows. IBM DB2 has an <code>IDENTITY</code> notation that works similarly.
|
|
|
+ If you use either of these notations, treat your Zend_Db_Table class as having an
|
|
|
+ auto-incrementing column with respect to declaring the <code>$_sequence</code>
|
|
|
+ member as <code>true</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.insert.key-sequence">
|
|
|
+
|
|
|
+ <title>Using a Table with a Sequence</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A sequence is a database object that generates a unique value, which can be used
|
|
|
+ as a primary key value in one or more tables of the database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you define <code>$_sequence</code> to be a string, then Zend_Db_Table_Abstract
|
|
|
+ assumes the string to name a sequence object in the database. The sequence is
|
|
|
+ invoked to generate a new value, and this value is used in the <code>INSERT</code>
|
|
|
+ operation.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.insert.key-sequence.example">
|
|
|
+
|
|
|
+ <title>Example of declaring a Table with a sequence</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bugs';
|
|
|
+
|
|
|
+ protected $_sequence = 'bug_sequence';
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Oracle, PostgreSQL, and IBM DB2 are examples of RDBMS brands that support sequence
|
|
|
+ objects in the database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ PostgreSQL and IBM DB2 also have syntax that defines sequences implicitly and
|
|
|
+ associated with columns. If you use this notation, treat the table as having an
|
|
|
+ auto-incrementing key column. Define the sequence name as a string only in cases
|
|
|
+ where you would invoke the sequence explicitly to get the next key value.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.insert.key-natural">
|
|
|
+
|
|
|
+ <title>Using a Table with a Natural Key</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Some tables have a natural key. This means that the key is not automatically
|
|
|
+ generated by the table or by a sequence. You must specify the value for the primary
|
|
|
+ key in this case.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you define the <code>$_sequence</code> to be the Boolean value
|
|
|
+ <code>false</code>, then Zend_Db_Table_Abstract assumes that the table has a
|
|
|
+ natural primary key. You must provide values for the primary key columns in the
|
|
|
+ array of data to the <code>insert()</code> method, or else this method throws a
|
|
|
+ Zend_Db_Table_Exception.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.insert.key-natural.example">
|
|
|
+
|
|
|
+ <title>Example of declaring a Table with a natural key</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class BugStatus extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bug_status';
|
|
|
+
|
|
|
+ protected $_sequence = false;
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ All RDBMS brands support tables with natural keys. Examples of tables that are
|
|
|
+ often declared as having natural keys are lookup tables, intersection tables in
|
|
|
+ many-to-many relationships, or most tables with compound primary keys.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.update">
|
|
|
+
|
|
|
+ <title>Updating Rows in a Table</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can update rows in a database table using the <code>update</code> method of a Table
|
|
|
+ class. This method takes two arguments: an associative array of columns to change and
|
|
|
+ new values to assign to these columns; and an SQL expression that is used in a
|
|
|
+ <code>WHERE</code> clause, as criteria for the rows to change in the
|
|
|
+ <code>UPDATE</code> operation.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.update.example">
|
|
|
+
|
|
|
+ <title>Example of updating rows in a Table</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$data = array(
|
|
|
+ 'updated_on' => '2007-03-23',
|
|
|
+ 'bug_status' => 'FIXED'
|
|
|
+);
|
|
|
+
|
|
|
+$where = $table->getAdapter()->quoteInto('bug_id = ?', 1234);
|
|
|
+
|
|
|
+$table->update($data, $where);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Since the table <code>update()</code> method proxies to the database adapter
|
|
|
+ <link linkend="zend.db.adapter.write.update"><code>update()</code></link> method, the
|
|
|
+ second argument can be an array of SQL expressions. The expressions are combined as
|
|
|
+ Boolean terms using an <code>AND</code> operator.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The values and identifiers in the SQL expression are not quoted for you. If you
|
|
|
+ have values or identifiers that require quoting, you are responsible for doing
|
|
|
+ this. Use the <code>quote()</code>, <code>quoteInto()</code>, and
|
|
|
+ <code>quoteIdentifier()</code> methods of the database adapter.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.delete">
|
|
|
+
|
|
|
+ <title>Deleting Rows from a Table</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can delete rows from a database table using the <code>delete()</code> method. This
|
|
|
+ method takes one argument, which is an SQL expression that is used in a
|
|
|
+ <code>WHERE</code> clause, as criteria for the rows to delete.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.delete.example">
|
|
|
+
|
|
|
+ <title>Example of deleting rows from a Table</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$where = $table->getAdapter()->quoteInto('bug_id = ?', 1235);
|
|
|
+
|
|
|
+$table->delete($where);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The second argument can be an array of SQL expressions. The expressions are combined as
|
|
|
+ Boolean terms using an <code>AND</code> operator.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Since the table <code>delete()</code> method proxies to the database adapter
|
|
|
+ <link linkend="zend.db.adapter.write.delete"><code>delete()</code></link> method, the
|
|
|
+ second argument can be an array of SQL expressions. The expressions are combined as
|
|
|
+ Boolean terms using an <code>AND</code> operator.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The values and identifiers in the SQL expression are not quoted for you. If you
|
|
|
+ have values or identifiers that require quoting, you are responsible for doing
|
|
|
+ this. Use the <code>quote()</code>, <code>quoteInto()</code>, and
|
|
|
+ <code>quoteIdentifier()</code> methods of the database adapter.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.find">
|
|
|
+
|
|
|
+ <title>Finding Rows by Primary Key</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can query the database table for rows matching specific values in the primary key,
|
|
|
+ using the <code>find()</code> method. The first argument of this method is either a
|
|
|
+ single value or an array of values to match against the primary key of the table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.find.example">
|
|
|
+
|
|
|
+ <title>Example of finding rows by primary key values</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+// Find a single row
|
|
|
+// Returns a Rowset
|
|
|
+$rows = $table->find(1234);
|
|
|
+
|
|
|
+// Find multiple rows
|
|
|
+// Also returns a Rowset
|
|
|
+$rows = $table->find(array(1234, 5678));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you specify a single value, the method returns at most one row, because a primary
|
|
|
+ key cannot have duplicate values and there is at most one row in the database table
|
|
|
+ matching the value you specify. If you specify multiple values in an array, the method
|
|
|
+ returns at most as many rows as the number of distinct values you specify.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The <code>find()</code> method might return fewer rows than the number of values you
|
|
|
+ specify for the primary key, if some of the values don't match any rows in the database
|
|
|
+ table. The method even may return zero rows. Because the number of rows returned is
|
|
|
+ variable, the <code>find()</code> method returns an object of type
|
|
|
+ <classname>Zend_Db_Table_Rowset_Abstract</classname>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If the primary key is a compound key, that is, it consists of multiple columns, you can
|
|
|
+ specify the additional columns as additional arguments to the <code>find()</code>
|
|
|
+ method. You must provide as many arguments as the number of columns in the table's
|
|
|
+ primary key.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ To find multiple rows from a table with a compound primary key, provide an array for
|
|
|
+ each of the arguments. All of these arrays must have the same number of elements. The
|
|
|
+ values in each array are formed into tuples in order; for example, the first element
|
|
|
+ in all the array arguments define the first compound primary key value, then the second
|
|
|
+ elements of all the arrays define the second compound primary key value, and so on.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.find.example-compound">
|
|
|
+
|
|
|
+ <title>Example of finding rows by compound primary key values</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The call to <code>find()</code> below to match multiple rows can match two rows in
|
|
|
+ the database. The first row must have primary key value (1234, 'ABC'), and the
|
|
|
+ second row must have primary key value (5678, 'DEF').
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class BugsProducts extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bugs_products';
|
|
|
+ protected $_primary = array('bug_id', 'product_id');
|
|
|
+}
|
|
|
+
|
|
|
+$table = new BugsProducts();
|
|
|
+
|
|
|
+// Find a single row with a compound primary key
|
|
|
+// Returns a Rowset
|
|
|
+$rows = $table->find(1234, 'ABC');
|
|
|
+
|
|
|
+// Find multiple rows with compound primary keys
|
|
|
+// Also returns a Rowset
|
|
|
+$rows = $table->find(array(1234, 5678), array('ABC', 'DEF'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.fetch-all">
|
|
|
+
|
|
|
+ <title>Querying for a Set of Rows</title>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.fetch-all.select">
|
|
|
+
|
|
|
+ <title>Select API</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+
|
|
|
+ <warning>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The API for fetch operations has been superseded to allow a
|
|
|
+ <code>Zend_Db_Table_Select</code> object to modify the query. However, the
|
|
|
+ deprecated usage of the <code>fetchRow()</code> and <code>fetchAll()</code>
|
|
|
+ methods will continue to work without modification.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The following statements are all legal and functionally identical, however
|
|
|
+ it is recommended to update your code to take advantage of the new usage
|
|
|
+ where possible.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Fetching a rowset
|
|
|
+$rows = $table->fetchAll('bug_status = "NEW"', 'bug_id ASC', 10, 0);
|
|
|
+$rows = $table->fetchAll($table->select()->where('bug_status = ?', 'NEW')
|
|
|
+ ->order('bug_id ASC')
|
|
|
+ ->limit(10, 0));
|
|
|
+
|
|
|
+// Fetching a single row
|
|
|
+$row = $table->fetchRow('bug_status = "NEW"', 'bug_id ASC');
|
|
|
+$row = $table->fetchRow($table->select()->where('bug_status = ?', 'NEW')
|
|
|
+ ->order('bug_id ASC'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </warning>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The <classname>Zend_Db_Table_Select</classname> object is an extension of the
|
|
|
+ <classname>Zend_Db_Select</classname> object that applies specific restrictions to
|
|
|
+ a query. The enhancements and restrictions are:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ You <emphasis>can</emphasis> elect to return a subset of columns within a
|
|
|
+ fetchRow or fetchAll query. This can provide optimization benefits where
|
|
|
+ returning a large set of results for all columns is not desirable.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ You <emphasis>can</emphasis> specify columns that evaluate expressions from
|
|
|
+ within the selected table. However this will mean that the returned row or
|
|
|
+ rowset will be <property>readOnly</property> and cannot be used for save()
|
|
|
+ operations. A <code>Zend_Db_Table_Row</code> with
|
|
|
+ <property>readOnly</property> status will throw an exception if a
|
|
|
+ <code>save()</code> operation is attempted.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ You <emphasis>can</emphasis> allow JOIN clauses on a select to allow
|
|
|
+ multi-table lookups.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ You <emphasis>can not</emphasis> specify columns from a JOINed tabled to be
|
|
|
+ returned in a row/rowset. Doing so will trigger a PHP error. This was done
|
|
|
+ to ensure the integrity of the <code>Zend_Db_Table is retained</code>. i.e.
|
|
|
+ A <code>Zend_Db_Table_Row</code> should only reference columns derived from
|
|
|
+ its parent table.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.qry.rows.set.simple.usage.example">
|
|
|
+
|
|
|
+ <title>Simple usage</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$select = $table->select();
|
|
|
+$select->where('bug_status = ?', 'NEW');
|
|
|
+
|
|
|
+$rows = $table->fetchAll($select);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Fluent interfaces are implemented across the component, so this can be rewritten
|
|
|
+ this in a more abbreviated form.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.qry.rows.set.fluent.interface.example">
|
|
|
+
|
|
|
+ <title>Example of fluent interface</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$rows =
|
|
|
+ $table->fetchAll($table->select()->where('bug_status = ?', 'NEW'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.fetch-all.usage">
|
|
|
+
|
|
|
+ <title>Fetching a rowset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can query for a set of rows using any criteria other than the primary key
|
|
|
+ values, using the <code>fetchAll()</code> method of the Table class. This method
|
|
|
+ returns an object of type <code>Zend_Db_Table_Rowset_Abstract</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.qry.rows.set.finding.row.example">
|
|
|
+
|
|
|
+ <title>Example of finding rows by an expression</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$select = $table->select()->where('bug_status = ?', 'NEW');
|
|
|
+
|
|
|
+$rows = $table->fetchAll($select);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You may also pass sorting criteria in an <code>ORDER BY</code> clause, as well as
|
|
|
+ count and offset integer values, used to make the query return a specific subset of
|
|
|
+ rows. These values are used in a <code>LIMIT</code> clause, or in equivalent logic
|
|
|
+ for RDBMS brands that do not support the <code>LIMIT</code> syntax.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.fetch-all.example2">
|
|
|
+
|
|
|
+ <title>Example of finding rows by an expression</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$order = 'bug_id';
|
|
|
+
|
|
|
+// Return the 21st through 30th rows
|
|
|
+$count = 10;
|
|
|
+$offset = 20;
|
|
|
+
|
|
|
+$select = $table->select()->where(array('bug_status = ?' => 'NEW'))
|
|
|
+ ->order($order)
|
|
|
+ ->limit($count, $offset);
|
|
|
+
|
|
|
+$rows = $table->fetchAll($select);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ All of the arguments above are optional. If you omit the ORDER clause, the result
|
|
|
+ set includes rows from the table in an unpredictable order. If no LIMIT clause is
|
|
|
+ set, you retrieve every row in the table that matches the WHERE clause.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.advanced.usage">
|
|
|
+
|
|
|
+ <title>Advanced usage</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ For more specific and optimized requests, you may wish to limit the number of
|
|
|
+ columns returned in a row/rowset. This can be achieved by passing a FROM clause to
|
|
|
+ the select object. The first argument in the FROM clause is identical to that of a
|
|
|
+ Zend_Db_Select object with the addition of being able to pass an instance of
|
|
|
+ Zend_Db_Table_Abstract and have it automatically determine the table name.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.qry.rows.set.retrieving.a.example">
|
|
|
+
|
|
|
+ <title>Retrieving specific columns</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$select = $table->select();
|
|
|
+$select->from($table, array('bug_id', 'bug_description'))
|
|
|
+ ->where('bug_status = ?', 'NEW');
|
|
|
+
|
|
|
+$rows = $table->fetchAll($select);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+
|
|
|
+ <important>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The rowset contains rows that are still 'valid' - they simply contain a
|
|
|
+ subset of the columns of a table. If a save() method is called on a partial
|
|
|
+ row then only the fields available will be modified.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </important>
|
|
|
+
|
|
|
+ You can also specify expressions within a FROM clause and have these returned as a
|
|
|
+ readOnly row/rowset. In this example we will return a rows from the bugs table that
|
|
|
+ show an aggregate of the number of new bugs reported by individuals. Note the GROUP
|
|
|
+ clause. The 'count' column will be made available to the row for evaluation and can
|
|
|
+ be accessed as if it were part of the schema.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.qry.rows.set.retrieving.b.example">
|
|
|
+
|
|
|
+ <title>Retrieving expressions as columns</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$select = $table->select();
|
|
|
+$select->from($table,
|
|
|
+ array('COUNT(reported_by) as `count`', 'reported_by'))
|
|
|
+ ->where('bug_status = ?', 'NEW')
|
|
|
+ ->group('reported_by');
|
|
|
+
|
|
|
+$rows = $table->fetchAll($select);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ You can also use a lookup as part of your query to further refine your fetch
|
|
|
+ operations. In this example the accounts table is queried as part of a search for
|
|
|
+ all new bugs reported by 'Bob'.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.qry.rows.set.refine.example">
|
|
|
+
|
|
|
+ <title>Using a lookup table to refine the results of fetchAll()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$select = $table->select();
|
|
|
+$select->where('bug_status = ?', 'NEW')
|
|
|
+ ->join('accounts', 'accounts.account_name = bugs.reported_by')
|
|
|
+ ->where('accounts.account_name = ?', 'Bob');
|
|
|
+
|
|
|
+$rows = $table->fetchAll($select);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The <classname>Zend_Db_Table_Select</classname> is primarily used to constrain and
|
|
|
+ validate so that it may enforce the criteria for a legal SELECT query. However
|
|
|
+ there may be certain cases where you require the flexibility of the
|
|
|
+ Zend_Db_Table_Row component and do not require a writable or deletable row. For
|
|
|
+ this specific user case, it is possible to retrieve a row/rowset by passing a false
|
|
|
+ value to setIntegrityCheck. The resulting row/rowset will be returned as a 'locked'
|
|
|
+ row (meaning the save(), delete() and any field-setting methods will throw an
|
|
|
+ exception).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.qry.rows.set.integrity.example">
|
|
|
+
|
|
|
+ <title>Removing the integrity check on Zend_Db_Table_Select to allow JOINed rows</title>
|
|
|
+
|
|
|
+ <programlisting><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$select = $table->select()->setIntegrityCheck(false);
|
|
|
+$select->where('bug_status = ?', 'NEW')
|
|
|
+ ->join('accounts',
|
|
|
+ 'accounts.account_name = bugs.reported_by',
|
|
|
+ 'account_name')
|
|
|
+ ->where('accounts.account_name = ?', 'Bob');
|
|
|
+
|
|
|
+$rows = $table->fetchAll($select);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.fetch-row">
|
|
|
+
|
|
|
+ <title>Querying for a Single Row</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can query for a single row using criteria similar to that of the
|
|
|
+ <code>fetchAll()</code> method.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.fetch-row.example1">
|
|
|
+
|
|
|
+ <title>Example of finding a single row by an expression</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$select = $table->select()->where('bug_status = ?', 'NEW')
|
|
|
+ ->order('bug_id');
|
|
|
+
|
|
|
+$row = $table->fetchRow($select);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This method returns an object of type Zend_Db_Table_Row_Abstract. If the search
|
|
|
+ criteria you specified match no rows in the database table, then
|
|
|
+ <code>fetchRow()</code> returns PHP's <code>null</code> value.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.info">
|
|
|
+
|
|
|
+ <title>Retrieving Table Metadata Information</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The Zend_Db_Table_Abstract class provides some information about its metadata. The
|
|
|
+ <code>info()</code> method returns an array structure with information about the table,
|
|
|
+ its columns and primary key, and other metadata.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.info.example">
|
|
|
+
|
|
|
+ <title>Example of getting the table name</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$info = $table->info();
|
|
|
+
|
|
|
+echo "The table name is " . $info['name'] . "\n";
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The keys of the array returned by the <code>info()</code> method are described below:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">name</emphasis> => the name of the table.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">cols</emphasis> => an array, naming the column(s) of
|
|
|
+ the table.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">primary</emphasis> => an array, naming the column(s) in
|
|
|
+ the primary key.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">metadata</emphasis> => an associative array, mapping
|
|
|
+ column names to information about the columns. This is the information returned
|
|
|
+ by the <code>describeTable()</code> method.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">rowClass</emphasis> => the name of the concrete class
|
|
|
+ used for Row objects returned by methods of this table instance. This defaults
|
|
|
+ to Zend_Db_Table_Row.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">rowsetClass</emphasis> => the name of the concrete
|
|
|
+ class used for Rowset objects returned by methods of this table instance. This
|
|
|
+ defaults to Zend_Db_Table_Rowset.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">referenceMap</emphasis> => an associative array, with
|
|
|
+ information about references from this table to any parent tables. See
|
|
|
+ <xref linkend="zend.db.table.relationships.defining"/>.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">dependentTables</emphasis> => an array of class names
|
|
|
+ of tables that reference this table. See
|
|
|
+ <xref linkend="zend.db.table.relationships.defining"/>.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">schema</emphasis> => the name of the schema (or
|
|
|
+ database or tablespace) for this table.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.metadata.caching">
|
|
|
+
|
|
|
+ <title>Caching Table Metadata</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ By default, <code>Zend_Db_Table_Abstract</code> queries the
|
|
|
+ underlying database for <link linkend="zend.db.table.info">table
|
|
|
+ metadata</link> whenever that data is needed to perform table
|
|
|
+ operations. The table object fetches the table metadata from the
|
|
|
+ database using the adapter's <code>describeTable()</code> method.
|
|
|
+ Operations requiring this introspection include:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>insert()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>find()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>info()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In some circumstances, particularly when many table objects are instantiated against
|
|
|
+ the same database table, querying the database for the table metadata for each instance
|
|
|
+ may be undesirable from a performance standpoint. In such cases, users may benefit by
|
|
|
+ caching the table metadata retrieved from the database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ There are two primary ways in which a user may take advantage of table metadata
|
|
|
+ caching:
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">Call
|
|
|
+ Zend_Db_Table_Abstract::setDefaultMetadataCache()</emphasis> - This allows
|
|
|
+ a developer to once set the default cache object to be used for all table
|
|
|
+ classes.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">Configure
|
|
|
+ Zend_Db_Table_Abstract::__construct()</emphasis> - This allows a developer
|
|
|
+ to set the cache object to be used for a particular table class instance.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ In both cases, the cache specification must be either <code>null</code> (i.e., no cache
|
|
|
+ used) or an instance of
|
|
|
+ <link linkend="zend.cache.frontends.core"><code>Zend_Cache_Core</code></link>. The
|
|
|
+ methods may be used in conjunction when it is desirable to have both a default metadata
|
|
|
+ cache and the ability to change the cache for individual table objects.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.metadata.caching-default">
|
|
|
+
|
|
|
+ <title>Using a Default Metadata Cache for all Table Objects</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The following code demonstrates how to set a default metadata cache to be used for
|
|
|
+ all table objects:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[<
|
|
|
+// First, set up the Cache
|
|
|
+$frontendOptions = array(
|
|
|
+ 'automatic_serialization' => true
|
|
|
+ );
|
|
|
+
|
|
|
+$backendOptions = array(
|
|
|
+ 'cache_dir' => 'cacheDir'
|
|
|
+ );
|
|
|
+
|
|
|
+$cache = Zend_Cache::factory('Core',
|
|
|
+ 'File',
|
|
|
+ $frontendOptions,
|
|
|
+ $backendOptions);
|
|
|
+
|
|
|
+
|
|
|
+// Next, set the cache to be used with all table objects
|
|
|
+Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
|
|
|
+
|
|
|
+
|
|
|
+// A table class is also needed
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ // ...
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// Each instance of Bugs now uses the default metadata cache
|
|
|
+$bugs = new Bugs();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <example id="zend.db.table.metadata.caching-instance">
|
|
|
+
|
|
|
+ <title>Using a Metadata Cache for a Specific Table Object</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The following code demonstrates how to set a metadata cache for a specific table
|
|
|
+ object instance:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// First, set up the Cache
|
|
|
+$frontendOptions = array(
|
|
|
+ 'automatic_serialization' => true
|
|
|
+ );
|
|
|
+
|
|
|
+$backendOptions = array(
|
|
|
+ 'cache_dir' => 'cacheDir'
|
|
|
+ );
|
|
|
+
|
|
|
+$cache = Zend_Cache::factory('Core',
|
|
|
+ 'File',
|
|
|
+ $frontendOptions,
|
|
|
+ $backendOptions);
|
|
|
+
|
|
|
+// A table class is also needed
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ // ...
|
|
|
+}
|
|
|
+
|
|
|
+// Configure an instance upon instantiation
|
|
|
+$bugs = new Bugs(array('metadataCache' => $cache));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <title>Automatic Serialization with the Cache Frontend</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Since the information returned from the adapter's describeTable() method is an
|
|
|
+ array, ensure that the <code>automatic_serialization</code> option is set to
|
|
|
+ <code>true</code> for the <code>Zend_Cache_Core</code> frontend.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Though the above examples use <code>Zend_Cache_Backend_File</code>, developers may use
|
|
|
+ whatever cache backend is appropriate for the situation. Please see
|
|
|
+ <link linkend="zend.cache">Zend_Cache</link> for more information.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.metadata.caching.hardcoding">
|
|
|
+ <title>Hardcoding Table Metadata</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ To take metadata caching a step further, you can also choose to
|
|
|
+ hardcode metadata. In this particular case, however, any changes
|
|
|
+ to the table schema will require a change in your code. As such,
|
|
|
+ it is only recommended for those who are optimizing for
|
|
|
+ production usage.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The metadata structure is as follows:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+protected $_metadata = array(
|
|
|
+ '<column_name>' => array(
|
|
|
+ 'SCHEMA_NAME' => <string>,
|
|
|
+ 'TABLE_NAME' => <string>,
|
|
|
+ 'COLUMN_NAME' => <string>,
|
|
|
+ 'COLUMN_POSITION' => <int>,
|
|
|
+ 'DATA_TYPE' => <string>,
|
|
|
+ 'DEFAULT' => NULL|<value>,
|
|
|
+ 'NULLABLE' => <bool>,
|
|
|
+ 'LENGTH' => <string - length>,
|
|
|
+ 'SCALE' => NULL|<value>,
|
|
|
+ 'PRECISION' => NULL|<value>,
|
|
|
+ 'UNSIGNED' => NULL|<bool>,
|
|
|
+ 'PRIMARY' => <bool>,
|
|
|
+ 'PRIMARY_POSITION' => <int>,
|
|
|
+ 'IDENTITY' => <bool>,
|
|
|
+ ),
|
|
|
+ // additional columns...
|
|
|
+);
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ An easy way to get the appropriate values is to use the metadata
|
|
|
+ cache, and then to deserialize values stored in the cache.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can disable this optimization by turning of the
|
|
|
+ <code>metadataCacheInClass</code> flag:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// At instantiation:
|
|
|
+$bugs = new Bugs(array('metadataCacheInClass' => false));
|
|
|
+
|
|
|
+// Or later:
|
|
|
+$bugs->setMetadataCacheInClass(false);
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The flag is enabled by default, which ensures that the
|
|
|
+ <code>$_metadata</code> array is only populated once per
|
|
|
+ instance.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.extending">
|
|
|
+
|
|
|
+ <title>Customizing and Extending a Table Class</title>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.extending.row-rowset">
|
|
|
+
|
|
|
+ <title>Using Custom Row or Rowset Classes</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ By default, methods of the Table class return a Rowset in instances of the concrete
|
|
|
+ class Zend_Db_Table_Rowset, and Rowsets contain a collection of instances of the
|
|
|
+ concrete class Zend_Db_Table_Row. You can specify an alternative class to use for
|
|
|
+ either of these, but they must be classes that extend Zend_Db_Table_Rowset_Abstract
|
|
|
+ and Zend_Db_Table_Row_Abstract, respectively.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can specify Row and Rowset classes using the Table constructor's options array,
|
|
|
+ in keys <code>'rowClass'</code> and <code>'rowsetClass'</code> respectively.
|
|
|
+ Specify the names of the classes using strings.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.extending.row-rowset.example">
|
|
|
+
|
|
|
+ <title>Example of specifying the Row and Rowset classes</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_Row extends Zend_Db_Table_Row_Abstract
|
|
|
+{
|
|
|
+ ...
|
|
|
+}
|
|
|
+
|
|
|
+class My_Rowset extends Zend_Db_Table_Rowset_Abstract
|
|
|
+{
|
|
|
+ ...
|
|
|
+}
|
|
|
+
|
|
|
+$table = new Bugs(
|
|
|
+ array(
|
|
|
+ 'rowClass' => 'My_Row',
|
|
|
+ 'rowsetClass' => 'My_Rowset'
|
|
|
+ )
|
|
|
+);
|
|
|
+
|
|
|
+$where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
|
|
|
+
|
|
|
+// Returns an object of type My_Rowset,
|
|
|
+// containing an array of objects of type My_Row.
|
|
|
+$rows = $table->fetchAll($where);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can change the classes by specifying them with the <code>setRowClass()</code>
|
|
|
+ and <code>setRowsetClass()</code> methods. This applies to rows and rowsets created
|
|
|
+ subsequently; it does not change the class of any row or rowset objects you have
|
|
|
+ created previously.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.extending.row-rowset.example2">
|
|
|
+
|
|
|
+ <title>Example of changing the Row and Rowset classes</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$table = new Bugs();
|
|
|
+
|
|
|
+$where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
|
|
|
+
|
|
|
+// Returns an object of type Zend_Db_Table_Rowset
|
|
|
+// containing an array of objects of type Zend_Db_Table_Row.
|
|
|
+$rowsStandard = $table->fetchAll($where);
|
|
|
+
|
|
|
+$table->setRowClass('My_Row');
|
|
|
+$table->setRowsetClass('My_Rowset');
|
|
|
+
|
|
|
+// Returns an object of type My_Rowset,
|
|
|
+// containing an array of objects of type My_Row.
|
|
|
+$rowsCustom = $table->fetchAll($where);
|
|
|
+
|
|
|
+// The $rowsStandard object still exists, and it is unchanged.
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ For more information on the Row and Rowset classes, see
|
|
|
+ <xref linkend="zend.db.table.row"/> and <xref linkend="zend.db.table.rowset"/>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.extending.insert-update">
|
|
|
+
|
|
|
+ <title>Defining Custom Logic for Insert, Update, and Delete</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can override the <code>insert()</code> and <code>update()</code> methods in
|
|
|
+ your Table class. This gives you the opportunity to implement custom code that is
|
|
|
+ executed before performing the database operation. Be sure to call the parent class
|
|
|
+ method when you are done.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.extending.insert-update.example">
|
|
|
+
|
|
|
+ <title>Custom logic to manage timestamps</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bugs';
|
|
|
+
|
|
|
+ public function insert(array $data)
|
|
|
+ {
|
|
|
+ // add a timestamp
|
|
|
+ if (empty($data['created_on'])) {
|
|
|
+ $data['created_on'] = time();
|
|
|
+ }
|
|
|
+ return parent::insert($data);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function update(array $data, $where)
|
|
|
+ {
|
|
|
+ // add a timestamp
|
|
|
+ if (empty($data['updated_on'])) {
|
|
|
+ $data['updated_on'] = time();
|
|
|
+ }
|
|
|
+ return parent::update($data, $where);
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can also override the <code>delete()</code> method.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.extending.finders">
|
|
|
+
|
|
|
+ <title>Define Custom Search Methods in Zend_Db_Table</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can implement custom query methods in your Table class, if you have frequent
|
|
|
+ need to do queries against this table with specific criteria. Most queries can be
|
|
|
+ written using <code>fetchAll()</code>, but this requires that you duplicate code to
|
|
|
+ form the query conditions if you need to run the query in several places in your
|
|
|
+ application. Therefore it can be convenient to implement a method in the Table
|
|
|
+ class to perform frequently-used queries against this table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.extending.finders.example">
|
|
|
+
|
|
|
+ <title>Custom method to find bugs by status</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bugs';
|
|
|
+
|
|
|
+ public function findByStatus($status)
|
|
|
+ {
|
|
|
+ $where = $this->getAdapter()->quoteInto('bug_status = ?', $status);
|
|
|
+ return $this->fetchAll($where, 'bug_id');
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.extending.inflection">
|
|
|
+
|
|
|
+ <title>Define Inflection in Zend_Db_Table</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Some people prefer that the table class name match a table name in the RDBMS by
|
|
|
+ using a string transformation called <emphasis>inflection</emphasis>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ For example, if your table class name is "<code>BugsProducts</code>", it would
|
|
|
+ match the physical table in the database called "<code>bugs_products</code>," if
|
|
|
+ you omit the explicit declaration of the <code>$_name</code> class property. In
|
|
|
+ this inflection mapping, the class name spelled in "CamelCase" format would be
|
|
|
+ transformed to lower case, and words are separated with an underscore.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can specify the database table name independently from the class name by
|
|
|
+ declaring the table name with the <code>$_name</code> class property in each of
|
|
|
+ your table classes.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Db_Table_Abstract performs no inflection to map the class name to the table
|
|
|
+ name. If you omit the declaration of <code>$_name</code> in your table class, the
|
|
|
+ class maps to a database table that matches the spelling of the class name exactly.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ It is inappropriate to transform identifiers from the database, because this can
|
|
|
+ lead to ambiguity or make some identifiers inaccessible. Using the SQL identifiers
|
|
|
+ exactly as they appear in the database makes Zend_Db_Table_Abstract both simpler
|
|
|
+ and more flexible.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you prefer to use inflection, then you must implement the transformation
|
|
|
+ yourself, by overriding the <code>_setupTableName()</code> method in your Table
|
|
|
+ classes. One way to do this is to define an abstract class that extends
|
|
|
+ Zend_Db_Table_Abstract, and then the rest of your tables extend your new abstract
|
|
|
+ class.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.extending.inflection.example">
|
|
|
+
|
|
|
+ <title>Example of an abstract table class that implements inflection</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+abstract class MyAbstractTable extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected function _setupTableName()
|
|
|
+ {
|
|
|
+ if (!$this->_name) {
|
|
|
+ $this->_name = myCustomInflector(get_class($this));
|
|
|
+ }
|
|
|
+ parent::_setupTableName();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class BugsProducts extends MyAbstractTable
|
|
|
+{
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You are responsible for writing the functions to perform inflection transformation.
|
|
|
+ Zend Framework does not provide such a function.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.db.table.row" xml:base="module_specs/Zend_Db_Table_Row.xml">
|
|
|
+
|
|
|
+ <title>Zend_Db_Table_Row</title>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.row.introduction">
|
|
|
+
|
|
|
+ <title>Introduction</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Db_Table_Row is a class that contains an individual row of a Zend_Db_Table object.
|
|
|
+ When you run a query against a Table class, the result is returned in a set of
|
|
|
+ Zend_Db_Table_Row objects. You can also use this object to create new rows and add them
|
|
|
+ to the database table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Db_Table_Row is an implementation of the <ulink url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data Gateway</ulink>
|
|
|
+ pattern.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.row.read">
|
|
|
+
|
|
|
+ <title>Fetching a Row</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Db_Table_Abstract provides methods <code>find()</code> and
|
|
|
+ <code>fetchAll()</code>, which each return an object of type Zend_Db_Table_Rowset, and
|
|
|
+ the method <code>fetchRow()</code>, which returns an object of type Zend_Db_Table_Row.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.read.example">
|
|
|
+
|
|
|
+ <title>Example of fetching a row</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A Zend_Db_Table_Rowset object contains a collection of Zend_Db_Table_Row objects. See
|
|
|
+ <xref linkend="zend.db.table.rowset"/>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.read.example-rowset">
|
|
|
+
|
|
|
+ <title>Example of reading a row in a rowset</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$rowset = $bugs->fetchAll($bugs->select()->where('bug_status = ?', 1));
|
|
|
+$row = $rowset->current();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.read.get">
|
|
|
+
|
|
|
+ <title>Reading column values from a row</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Db_Table_Row_Abstract provides accessor methods so you can reference columns
|
|
|
+ in the row as object properties.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.read.get.example">
|
|
|
+
|
|
|
+ <title>Example of reading a column in a row</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
|
|
|
+
|
|
|
+// Echo the value of the bug_description column
|
|
|
+echo $row->bug_description;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Earlier versions of Zend_Db_Table_Row mapped these column accessors to the
|
|
|
+ database column names using a string transformation called
|
|
|
+ <emphasis>inflection</emphasis>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Currently, Zend_Db_Table_Row does not implement inflection. Accessed property
|
|
|
+ names need to match the spelling of the column names as they appear in your
|
|
|
+ database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.read.to-array">
|
|
|
+
|
|
|
+ <title>Retrieving Row Data as an Array</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can access the row's data as an array using the <code>toArray()</code> method
|
|
|
+ of the Row object. This returns an associative array of the column names to the
|
|
|
+ column values.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.read.to-array.example">
|
|
|
+
|
|
|
+ <title>Example of using the toArray() method</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
|
|
|
+
|
|
|
+// Get the column/value associative array from the Row object
|
|
|
+$rowArray = $row->toArray();
|
|
|
+
|
|
|
+// Now use it as a normal array
|
|
|
+foreach ($rowArray as $column => $value) {
|
|
|
+ echo "Column: $column\n";
|
|
|
+ echo "Value: $value\n";
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The array returned from <code>toArray()</code> is not updateable. You can modify
|
|
|
+ values in the array as you can with any array, but you cannot save changes to this
|
|
|
+ array to the database directly.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.read.relationships">
|
|
|
+
|
|
|
+ <title>Fetching data from related tables</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The Zend_Db_Table_Row_Abstract class provides methods for fetching rows and rowsets
|
|
|
+ from related tables. See <xref linkend="zend.db.table.relationships"/> for more
|
|
|
+ information on table relationships.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.row.write">
|
|
|
+
|
|
|
+ <title>Writing rows to the database</title>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.write.set">
|
|
|
+
|
|
|
+ <title>Changing column values in a row</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can set individual column values using column accessors, similar to how the
|
|
|
+ columns are read as object properties in the example above.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Using a column accessor to set a value changes the column value of the row object
|
|
|
+ in your application, but it does not commit the change to the database yet. You can
|
|
|
+ do that with the <code>save()</code> method.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.write.set.example">
|
|
|
+
|
|
|
+ <title>Example of changing a column in a row</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
|
|
|
+
|
|
|
+// Change the value of one or more columns
|
|
|
+$row->bug_status = 'FIXED';
|
|
|
+
|
|
|
+// UPDATE the row in the database with new values
|
|
|
+$row->save();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.write.insert">
|
|
|
+
|
|
|
+ <title>Inserting a new row</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can create a new row for a given table with the <code>createRow()</code> method
|
|
|
+ of the table class. You can access fields of this row with the object-oriented
|
|
|
+ interface, but the row is not stored in the database until you call the
|
|
|
+ <code>save()</code> method.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.write.insert.example">
|
|
|
+
|
|
|
+ <title>Example of creating a new row for a table</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$newRow = $bugs->createRow();
|
|
|
+
|
|
|
+// Set column values as appropriate for your application
|
|
|
+$newRow->bug_description = '...description...';
|
|
|
+$newRow->bug_status = 'NEW';
|
|
|
+
|
|
|
+// INSERT the new row to the database
|
|
|
+$newRow->save();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The optional argument to the createRow() method is an associative array, with which
|
|
|
+ you can populate fields of the new row.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.write.insert.example2">
|
|
|
+
|
|
|
+ <title>Example of populating a new row for a table</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$data = array(
|
|
|
+ 'bug_description' => '...description...',
|
|
|
+ 'bug_status' => 'NEW'
|
|
|
+);
|
|
|
+
|
|
|
+$bugs = new Bugs();
|
|
|
+$newRow = $bugs->createRow($data);
|
|
|
+
|
|
|
+// INSERT the new row to the database
|
|
|
+$newRow->save();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The <code>createRow()</code> method was called <code>fetchNew()</code> in
|
|
|
+ earlier releases of Zend_Db_Table. You are encouraged to use the new method
|
|
|
+ name, even though the old name continues to work for the sake of backward
|
|
|
+ compatibility.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.write.set-from-array">
|
|
|
+
|
|
|
+ <title>Changing values in multiple columns</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Db_Table_Row_Abstract provides the <code>setFromArray()</code> method to
|
|
|
+ enable you to set several columns in a single row at once, specified in an
|
|
|
+ associative array that maps the column names to values. You may find this method
|
|
|
+ convenient for setting values both for new rows and for rows you need to update.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.write.set-from-array.example">
|
|
|
+
|
|
|
+ <title>Example of using setFromArray() to set values in a new Row</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$newRow = $bugs->createRow();
|
|
|
+
|
|
|
+// Data are arranged in an associative array
|
|
|
+$data = array(
|
|
|
+ 'bug_description' => '...description...',
|
|
|
+ 'bug_status' => 'NEW'
|
|
|
+);
|
|
|
+
|
|
|
+// Set all the column values at once
|
|
|
+$newRow->setFromArray($data);
|
|
|
+
|
|
|
+// INSERT the new row to the database
|
|
|
+$newRow->save();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.write.delete">
|
|
|
+
|
|
|
+ <title>Deleting a row</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can call the <code>delete()</code> method on a Row object. This deletes rows in
|
|
|
+ the database matching the primary key in the Row object.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.write.delete.example">
|
|
|
+
|
|
|
+ <title>Example of deleting a row</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$row = $bugs->fetchRow('bug_id = 1');
|
|
|
+
|
|
|
+// DELETE this row
|
|
|
+$row->delete();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You do not have to call <code>save()</code> to apply the delete; it is executed
|
|
|
+ against the database immediately.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.row.serialize">
|
|
|
+
|
|
|
+ <title>Serializing and unserializing rows</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ It is often convenient to save the contents of a database row to be used later.
|
|
|
+ <emphasis>Serialization</emphasis> is the name for the operation that converts an
|
|
|
+ object into a form that is easy to save in offline storage (for example, a file).
|
|
|
+ Objects of type Zend_Db_Table_Row_Abstract are serializable.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.serialize.serializing">
|
|
|
+
|
|
|
+ <title>Serializing a Row</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Simply use PHP's <code>serialize()</code> function to create a string containing a
|
|
|
+ byte-stream representation of the Row object argument.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.serialize.serializing.example">
|
|
|
+
|
|
|
+ <title>Example of serializing a row</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$row = $bugs->fetchRow('bug_id = 1');
|
|
|
+
|
|
|
+// Convert object to serialized form
|
|
|
+$serializedRow = serialize($row);
|
|
|
+
|
|
|
+// Now you can write $serializedRow to a file, etc.
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.serialize.unserializing">
|
|
|
+
|
|
|
+ <title>Unserializing Row Data</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Use PHP's <code>unserialize()</code> function to restore a string containing a
|
|
|
+ byte-stream representation of an object. The function returns the original object.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Note that the Row object returned is in a <emphasis>disconnected</emphasis> state.
|
|
|
+ You can read the Row object and its properties, but you cannot change values in the
|
|
|
+ Row or execute other methods that require a database connection (for example,
|
|
|
+ queries against related tables).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.serialize.unserializing.example">
|
|
|
+
|
|
|
+ <title>Example of unserializing a serialized row</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$rowClone = unserialize($serializedRow);
|
|
|
+
|
|
|
+// Now you can use object properties, but read-only
|
|
|
+echo $rowClone->bug_description;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <title>Why do Rows unserialize in a disconnected state?</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A serialized object is a string that is readable to anyone who possesses it. It
|
|
|
+ could be a security risk to store parameters such as database account and
|
|
|
+ password in plain, unencrypted text in the serialized string. You would not
|
|
|
+ want to store such data to a text file that is not protected, or send it in an
|
|
|
+ email or other medium that is easily read by potential attackers. The reader of
|
|
|
+ the serialized object should not be able to use it to gain access to your
|
|
|
+ database without knowing valid credentials.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.serialize.set-table">
|
|
|
+
|
|
|
+ <title>Reactivating a Row as Live Data</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can reactivate a disconnected Row, using the <code>setTable()</code> method.
|
|
|
+ The argument to this method is a valid object of type Zend_Db_Table_Abstract, which
|
|
|
+ you create. Creating a Table object requires a live connection to the database, so
|
|
|
+ by reassociating the Table with the Row, the Row gains access to the database.
|
|
|
+ Subsequently, you can change values in the Row object and save the changes to the
|
|
|
+ database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.serialize.set-table.example">
|
|
|
+
|
|
|
+ <title>Example of reactivating a row</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$rowClone = unserialize($serializedRow);
|
|
|
+
|
|
|
+$bugs = new Bugs();
|
|
|
+
|
|
|
+// Reconnect the row to a table, and
|
|
|
+// thus to a live database connection
|
|
|
+$rowClone->setTable($bugs);
|
|
|
+
|
|
|
+// Now you can make changes to the row and save them
|
|
|
+$rowClone->bug_status = 'FIXED';
|
|
|
+$rowClone->save();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.row.extending">
|
|
|
+
|
|
|
+ <title>Extending the Row class</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Db_Table_Row is the default concrete class that extends
|
|
|
+ Zend_Db_Table_Row_Abstract. You can define your own concrete class for instances of Row
|
|
|
+ by extending Zend_Db_Table_Row_Abstract. To use your new Row class to store results of
|
|
|
+ Table queries, specify the custom Row class by name either in the
|
|
|
+ <code>$_rowClass</code> protected member of a Table class, or in the array argument of
|
|
|
+ the constructor of a Table object.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.extending.example">
|
|
|
+
|
|
|
+ <title>Specifying a custom Row class</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class MyRow extends Zend_Db_Table_Row_Abstract
|
|
|
+{
|
|
|
+ // ...customizations
|
|
|
+}
|
|
|
+
|
|
|
+// Specify a custom Row to be used by default
|
|
|
+// in all instances of a Table class.
|
|
|
+class Products extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'products';
|
|
|
+ protected $_rowClass = 'MyRow';
|
|
|
+}
|
|
|
+
|
|
|
+// Or specify a custom Row to be used in one
|
|
|
+// instance of a Table class.
|
|
|
+$bugs = new Bugs(array('rowClass' => 'MyRow'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.extending.overriding">
|
|
|
+
|
|
|
+ <title>Row initialization</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If application-specific logic needs to be initialized when a row is constructed,
|
|
|
+ you can select to move your tasks to the <code>init()</code> method, which is
|
|
|
+ called after all row metadata has been processed. This is recommended over the
|
|
|
+ <code>__construct</code> method if you do not need to alter the metadata in any
|
|
|
+ programmatic way.
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.init.usage.example">
|
|
|
+
|
|
|
+ <title>Example usage of init() method</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class MyApplicationRow extends Zend_Db_Table_Row_Abstract
|
|
|
+{
|
|
|
+ protected $_role;
|
|
|
+
|
|
|
+ public function init()
|
|
|
+ {
|
|
|
+ $this->_role = new MyRoleClass();
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.extending.insert-update">
|
|
|
+
|
|
|
+ <title>Defining Custom Logic for Insert, Update, and Delete in Zend_Db_Table_Row</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The Row class calls protected methods <code>_insert()</code>,
|
|
|
+ <code>_update()</code>, and <code>_delete()</code> before performing the
|
|
|
+ corresponding operations <code>INSERT</code>, <code>UPDATE</code>, and
|
|
|
+ <code>DELETE</code>. You can add logic to these methods in your custom Row
|
|
|
+ subclass.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you need to do custom logic in a specific table, and the custom logic must occur
|
|
|
+ for every operation on that table, it may make more sense to implement your custom
|
|
|
+ code in the <code>insert()</code>, <code>update()</code> and <code>delete()</code>
|
|
|
+ methods of your Table class. However, sometimes it may be necessary to do custom
|
|
|
+ logic in the Row class.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Below are some example cases where it might make sense to implement custom logic in
|
|
|
+ a Row class instead of in the Table class:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.extending.overriding-example1">
|
|
|
+
|
|
|
+ <title>Example of custom logic in a Row class</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The custom logic may not apply in all cases of operations on the respective
|
|
|
+ Table. You can provide custom logic on demand by implementing it in a Row class
|
|
|
+ and creating an instance of the Table class with that custom Row class
|
|
|
+ specified. Otherwise, the Table uses the default Row class.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You need data operations on this table to record the operation to a
|
|
|
+ Zend_Log object, but only if the application configuration has enabled this
|
|
|
+ behavior.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class MyLoggingRow extends Zend_Db_Table_Row_Abstract
|
|
|
+{
|
|
|
+ protected function _insert()
|
|
|
+ {
|
|
|
+ $log = Zend_Registry::get('database_log');
|
|
|
+ $log->info(Zend_Debug::dump($this->_data,
|
|
|
+ "INSERT: $this->_tableClass",
|
|
|
+ false)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// $loggingEnabled is an example property that depends
|
|
|
+// on your application configuration
|
|
|
+if ($loggingEnabled) {
|
|
|
+ $bugs = new Bugs(array('rowClass' => 'MyLoggingRow'));
|
|
|
+} else {
|
|
|
+ $bugs = new Bugs();
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.extending.overriding-example2">
|
|
|
+
|
|
|
+ <title>Example of a Row class that logs insert data for multiple tables</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The custom logic may be common to multiple tables. Instead of implementing the
|
|
|
+ same custom logic in every one of your Table classes, you can implement the
|
|
|
+ code for such actions in the definition of a Row class, and use this Row in
|
|
|
+ each of your Table classes.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In this example, the logging code is identical in all table classes.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class MyLoggingRow extends Zend_Db_Table_Row_Abstract
|
|
|
+{
|
|
|
+ protected function _insert()
|
|
|
+ {
|
|
|
+ $log = Zend_Registry::get('database_log');
|
|
|
+ $log->info(Zend_Debug::dump($this->_data,
|
|
|
+ "INSERT: $this->_tableClass",
|
|
|
+ false)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bugs';
|
|
|
+ protected $_rowClass = 'MyLoggingRow';
|
|
|
+}
|
|
|
+
|
|
|
+class Products extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'products';
|
|
|
+ protected $_rowClass = 'MyLoggingRow';
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.row.extending.inflection">
|
|
|
+
|
|
|
+ <title>Define Inflection in Zend_Db_Table_Row</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Some people prefer that the table class name match a table name in the RDBMS by
|
|
|
+ using a string transformation called <emphasis>inflection</emphasis>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Db classes do not implement inflection by default. See
|
|
|
+ <xref linkend="zend.db.table.extending.inflection"/> for an explanation of this
|
|
|
+ policy.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you prefer to use inflection, then you must implement the transformation yourself,
|
|
|
+ by overriding the <code>_transformColumn()</code> method in a custom Row class, and
|
|
|
+ using that custom Row class when you perform queries against your Table class.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.row.extending.inflection.example">
|
|
|
+
|
|
|
+ <title>Example of defining an inflection transformation</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This allows you to use an inflected version of the column name in the
|
|
|
+ accessors. The Row class uses the <code>_transformColumn()</code> method to
|
|
|
+ change the name you use to the native column name in the database table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class MyInflectedRow extends Zend_Db_Table_Row_Abstract
|
|
|
+{
|
|
|
+ protected function _transformColumn($columnName)
|
|
|
+ {
|
|
|
+ $nativeColumnName = myCustomInflector($columnName);
|
|
|
+ return $nativeColumnName;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bugs';
|
|
|
+ protected $_rowClass = 'MyInflectedRow';
|
|
|
+}
|
|
|
+
|
|
|
+$bugs = new Bugs();
|
|
|
+$row = $bugs->fetchNew();
|
|
|
+
|
|
|
+// Use camelcase column names, and rely on the
|
|
|
+// transformation function to change it into the
|
|
|
+// native representation.
|
|
|
+$row->bugDescription = 'New description';
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You are responsible for writing the functions to perform inflection transformation.
|
|
|
+ Zend Framework does not provide such a function.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.db.table.rowset" xml:base="module_specs/Zend_Db_Table_Rowset.xml">
|
|
|
+
|
|
|
+ <title>Zend_Db_Table_Rowset</title>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.rowset.introduction">
|
|
|
+
|
|
|
+ <title>Introduction</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ When you run a query against a Table class using the <code>find()</code> or <code>fetchAll()</code>
|
|
|
+ methods, the result is returned in an object of type <code>Zend_Db_Table_Rowset_Abstract</code>. A Rowset
|
|
|
+ contains a collection of objects descending from <code>Zend_Db_Table_Row_Abstract</code>. You can iterate
|
|
|
+ through the Rowset and access individual Row objects, reading or modifying data in the Rows.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.rowset.fetch">
|
|
|
+
|
|
|
+ <title>Fetching a Rowset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Db_Table_Abstract</code> provides methods <code>find()</code> and <code>fetchAll()</code>, each
|
|
|
+ of which returns an object of type <code>Zend_Db_Table_Rowset_Abstract</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.rowset.fetch.example">
|
|
|
+
|
|
|
+ <title>Example of fetching a rowset</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$rowset = $bugs->fetchAll("bug_status = 'NEW'");
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.rowset.rows">
|
|
|
+
|
|
|
+ <title>Retrieving Rows from a Rowset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The Rowset itself is usually less interesting than the Rows that it contains. This section illustrates how
|
|
|
+ to get the Rows that comprise the Rowset.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A legitimate query returns zero rows when no rows in the database match the query conditions. Therefore, a
|
|
|
+ Rowset object might contain zero Row objects. Since <code>Zend_Db_Table_Rowset_Abstract</code> implements
|
|
|
+ the <code>Countable</code> interface, you can use <code>count()</code> to determine the number of Rows in
|
|
|
+ the Rowset.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.rowset.rows.counting.example">
|
|
|
+
|
|
|
+ <title>Counting the Rows in a Rowset</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$rowset = $bugs->fetchAll("bug_status = 'FIXED'");
|
|
|
+
|
|
|
+$rowCount = count($rowset);
|
|
|
+
|
|
|
+if ($rowCount > 0) {
|
|
|
+ echo "found $rowCount rows";
|
|
|
+} else {
|
|
|
+ echo 'no rows matched the query';
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <example id="zend.db.table.rowset.rows.current.example">
|
|
|
+
|
|
|
+ <title>Reading a Single Row from a Rowset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The simplest way to access a Row from a Rowset is to use the <code>current()</code> method. This is
|
|
|
+ particularly appropriate when the Rowset contains exactly one Row.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$rowset = $bugs->fetchAll("bug_id = 1");
|
|
|
+$row = $rowset->current();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If the Rowset contains zero rows, <code>current()</code> returns
|
|
|
+ PHP's <code>null</code> value.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.rowset.rows.iterate.example">
|
|
|
+
|
|
|
+ <title>Iterating through a Rowset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Objects descending from <code>Zend_Db_Table_Rowset_Abstract</code> implement the <code>SeekableIterator</code>
|
|
|
+ interface, which means you can loop through them using the <code>foreach</code> construct. Each value
|
|
|
+ you retrieve this way is a <code>Zend_Db_Table_Row_Abstract</code> object that corresponds to one
|
|
|
+ record from the table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+
|
|
|
+// fetch all records from the table
|
|
|
+$rowset = $bugs->fetchAll();
|
|
|
+
|
|
|
+foreach ($rowset as $row) {
|
|
|
+
|
|
|
+ // output 'Zend_Db_Table_Row' or similar
|
|
|
+ echo get_class($row) . "\n";
|
|
|
+
|
|
|
+ // read a column in the row
|
|
|
+ $status = $row->bug_status;
|
|
|
+
|
|
|
+ // modify a column in the current row
|
|
|
+ $row->assigned_to = 'mmouse';
|
|
|
+
|
|
|
+ // write the change to the database
|
|
|
+ $row->save();
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <example id="zend.db.table.rowset.rows.seek.example">
|
|
|
+
|
|
|
+ <title>Seeking to a known position into a Rowset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>SeekableIterator</code> allows you to seek to a position that you would like the iterator to jump to.
|
|
|
+ Simply use the <code>seek()</code> method for that. Pass it an integer representing the number of the Row
|
|
|
+ you would like your Rowset to point to next, don't forget that it starts with index 0. If the index is wrong,
|
|
|
+ ie doesn't exist, an exception will be thrown. You should use <code>count()</code> to check the number of
|
|
|
+ results before seeking to a position.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+
|
|
|
+// fetch all records from the table
|
|
|
+$rowset = $bugs->fetchAll();
|
|
|
+
|
|
|
+// takes the iterator to the 9th element (zero is one element) :
|
|
|
+$rowset->seek(8);
|
|
|
+
|
|
|
+// retrive it
|
|
|
+$row9 = $rowset->current();
|
|
|
+
|
|
|
+// and use it
|
|
|
+$row9->assigned_to = 'mmouse';
|
|
|
+$row9->save();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>getRow()</code> allows you to get a specific row in the Rowset, knowing its position; don't forget
|
|
|
+ however that positions start with index zero. The first parameter for <code>getRow()</code> is an integer
|
|
|
+ for the position asked. The second optional parameter is a boolean; it tells the Rowset iterator if it must
|
|
|
+ seek to that position in the same time, or not (default is false). This method returns a Zend_Db_Table_Row
|
|
|
+ object by default. If the position requested does not exist, an exception will be thrown. Here is an example :
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+
|
|
|
+// fetch all records from the table
|
|
|
+$rowset = $bugs->fetchAll();
|
|
|
+
|
|
|
+// retrieve the 9th element immediately:
|
|
|
+$row9->getRow(8);
|
|
|
+
|
|
|
+// and use it:
|
|
|
+$row9->assigned_to = 'mmouse';
|
|
|
+$row9->save();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ <para>
|
|
|
+ After you have access to an individual Row object, you can manipulate the Row using methods described in
|
|
|
+ <xref linkend="zend.db.table.row"/>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.rowset.to-array">
|
|
|
+
|
|
|
+ <title>Retrieving a Rowset as an Array</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can access all the data in the Rowset as an array using the <code>toArray()</code> method of the Rowset
|
|
|
+ object. This returns an array containing one entry per Row. Each entry is an associative array having keys
|
|
|
+ that correspond to column names and elements that correspond to the respective column values.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.rowset.to-array.example">
|
|
|
+
|
|
|
+ <title>Using toArray()</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$rowset = $bugs->fetchAll();
|
|
|
+
|
|
|
+$rowsetArray = $rowset->toArray();
|
|
|
+
|
|
|
+$rowCount = 1;
|
|
|
+foreach ($rowsetArray as $rowArray) {
|
|
|
+ echo "row #$rowCount:\n";
|
|
|
+ foreach ($rowArray as $column => $value) {
|
|
|
+ echo "\t$column => $value\n";
|
|
|
+ }
|
|
|
+ ++$rowCount;
|
|
|
+ echo "\n";
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The array returned from <code>toArray()</code> is not updateable. That is, you can modify values in the
|
|
|
+ array as you can with any array, but changes to the array data are not propagated to the database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.rowset.serialize">
|
|
|
+
|
|
|
+ <title>Serializing and Unserializing a Rowset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Objects of type <code>Zend_Db_Table_Rowset_Abstract</code> are serializable. In a similar fashion to
|
|
|
+ serializing an individual Row object, you can serialize a Rowset and unserialize it later.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.rowset.serialize.example.serialize">
|
|
|
+
|
|
|
+ <title>Serializing a Rowset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Simply use PHP's <code>serialize()</code> function to create a string containing a byte-stream
|
|
|
+ representation of the Rowset object argument.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugs = new Bugs();
|
|
|
+$rowset = $bugs->fetchAll();
|
|
|
+
|
|
|
+// Convert object to serialized form
|
|
|
+$serializedRowset = serialize($rowset);
|
|
|
+
|
|
|
+// Now you can write $serializedRowset to a file, etc.
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <example id="zend.db.table.rowset.serialize.example.unserialize">
|
|
|
+
|
|
|
+ <title>Unserializing a Serialized Rowset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Use PHP's <code>unserialize()</code> function to restore a string containing a byte-stream
|
|
|
+ representation of an object. The function returns the original object.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Note that the Rowset object returned is in a <emphasis>disconnected</emphasis> state. You can iterate
|
|
|
+ through the Rowset and read the Row objects and their properties, but you cannot change values in the
|
|
|
+ Rows or execute other methods that require a database connection (for example, queries against related
|
|
|
+ tables).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$rowsetDisconnected = unserialize($serializedRowset);
|
|
|
+
|
|
|
+// Now you can use object methods and properties, but read-only
|
|
|
+$row = $rowsetDisconnected->current();
|
|
|
+echo $row->bug_description;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Why do Rowsets unserialize in a disconnected state?</title>
|
|
|
+ <para>
|
|
|
+ A serialized object is a string that is readable to anyone who possesses it. It could be a security
|
|
|
+ risk to store parameters such as database account and password in plain, unencrypted text in the
|
|
|
+ serialized string. You would not want to store such data to a text file that is not protected, or send
|
|
|
+ it in an email or other medium that is easily read by potential attackers. The reader of the serialized
|
|
|
+ object should not be able to use it to gain access to your database without knowing valid credentials.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can reactivate a disconnected Rowset using the <code>setTable()</code> method. The argument to this
|
|
|
+ method is a valid object of type <code>Zend_Db_Table_Abstract</code>, which you create. Creating a Table
|
|
|
+ object requires a live connection to the database, so by reassociating the Table with the Rowset, the
|
|
|
+ Rowset gains access to the database. Subsequently, you can change values in the Row objects contained in
|
|
|
+ the Rowset and save the changes to the database.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.rowset.serialize.example.set-table">
|
|
|
+
|
|
|
+ <title>Reactivating a Rowset as Live Data</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$rowset = unserialize($serializedRowset);
|
|
|
+
|
|
|
+$bugs = new Bugs();
|
|
|
+
|
|
|
+// Reconnect the rowset to a table, and
|
|
|
+// thus to a live database connection
|
|
|
+$rowset->setTable($bugs);
|
|
|
+
|
|
|
+$row = $rowset->current();
|
|
|
+
|
|
|
+// Now you can make changes to the row and save them
|
|
|
+$row->bug_status = 'FIXED';
|
|
|
+$row->save();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Reactivating a Rowset with <code>setTable()</code> also reactivates all the Row objects contained in that
|
|
|
+ Rowset.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.rowset.extending">
|
|
|
+
|
|
|
+ <title>Extending the Rowset class</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can use an alternative concrete class for instances of Rowsets
|
|
|
+ by extending Zend_Db_Table_Rowset_Abstract. Specify the custom
|
|
|
+ Rowset class by name either in the <code>$_rowsetClass</code>
|
|
|
+ protected member of a Table class, or in the array argument of the
|
|
|
+ constructor of a Table object.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.rowset.extending.example">
|
|
|
+ <title>Specifying a custom Rowset class</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class MyRowset extends Zend_Db_Table_Rowset_Abstract
|
|
|
+{
|
|
|
+ // ...customizations
|
|
|
+}
|
|
|
+
|
|
|
+// Specify a custom Rowset to be used by default
|
|
|
+// in all instances of a Table class.
|
|
|
+class Products extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'products';
|
|
|
+ protected $_rowsetClass = 'MyRowset';
|
|
|
+}
|
|
|
+
|
|
|
+// Or specify a custom Rowset to be used in one
|
|
|
+// instance of a Table class.
|
|
|
+$bugs = new Bugs(array('rowsetClass' => 'MyRowset'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Typically, the standard Zend_Db_Rowset concrete class is
|
|
|
+ sufficient for most usage. However, you might find it useful
|
|
|
+ to add new logic to a Rowset, specific to a given Table.
|
|
|
+ For example, a new method could calculate an aggregate
|
|
|
+ over all the Rows in the Rowset.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.rowset.extending.example-aggregate">
|
|
|
+ <title>Example of Rowset class with a new method</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class MyBugsRowset extends Zend_Db_Table_Rowset_Abstract
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * Find the Row in the current Rowset with the
|
|
|
+ * greatest value in its 'updated_at' column.
|
|
|
+ */
|
|
|
+ public function getLatestUpdatedRow()
|
|
|
+ {
|
|
|
+ $max_updated_at = 0;
|
|
|
+ $latestRow = null;
|
|
|
+ foreach ($this as $row) {
|
|
|
+ if ($row->updated_at > $max_updated_at) {
|
|
|
+ $latestRow = $row;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return $latestRow;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bugs';
|
|
|
+ protected $_rowsetClass = 'MyBugsRowset';
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.db.table.relationships" xml:base="module_specs/Zend_Db_Table-Relationships.xml">
|
|
|
+
|
|
|
+ <title>Zend_Db_Table Relationships</title>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.relationships.introduction">
|
|
|
+
|
|
|
+ <title>Introduction</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Tables have relationships to each other in a relational database. An entity in one
|
|
|
+ table can be linked to one or more entities in another table by using referential
|
|
|
+ integrity constraints defined in the database schema.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The Zend_Db_Table_Row class has methods for querying related rows in other tables.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.relationships.defining">
|
|
|
+
|
|
|
+ <title>Defining Relationships</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Define classes for each of your tables, extending the abstract class
|
|
|
+ Zend_Db_Table_Abstract, as described in <xref linkend="zend.db.table.defining"/>. Also
|
|
|
+ see <xref linkend="zend.db.adapter.example-database"/> for a description of the
|
|
|
+ example database for which the following example code is designed.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Below are the PHP class definitions for these tables:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Accounts extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'accounts';
|
|
|
+ protected $_dependentTables = array('Bugs');
|
|
|
+}
|
|
|
+
|
|
|
+class Products extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'products';
|
|
|
+ protected $_dependentTables = array('BugsProducts');
|
|
|
+}
|
|
|
+
|
|
|
+class Bugs extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bugs';
|
|
|
+
|
|
|
+ protected $_dependentTables = array('BugsProducts');
|
|
|
+
|
|
|
+ protected $_referenceMap = array(
|
|
|
+ 'Reporter' => array(
|
|
|
+ 'columns' => 'reported_by',
|
|
|
+ 'refTableClass' => 'Accounts',
|
|
|
+ 'refColumns' => 'account_name'
|
|
|
+ ),
|
|
|
+ 'Engineer' => array(
|
|
|
+ 'columns' => 'assigned_to',
|
|
|
+ 'refTableClass' => 'Accounts',
|
|
|
+ 'refColumns' => 'account_name'
|
|
|
+ ),
|
|
|
+ 'Verifier' => array(
|
|
|
+ 'columns' => array('verified_by'),
|
|
|
+ 'refTableClass' => 'Accounts',
|
|
|
+ 'refColumns' => array('account_name')
|
|
|
+ )
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+class BugsProducts extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ protected $_name = 'bugs_products';
|
|
|
+
|
|
|
+ protected $_referenceMap = array(
|
|
|
+ 'Bug' => array(
|
|
|
+ 'columns' => array('bug_id'),
|
|
|
+ 'refTableClass' => 'Bugs',
|
|
|
+ 'refColumns' => array('bug_id')
|
|
|
+ ),
|
|
|
+ 'Product' => array(
|
|
|
+ 'columns' => array('product_id'),
|
|
|
+ 'refTableClass' => 'Products',
|
|
|
+ 'refColumns' => array('product_id')
|
|
|
+ )
|
|
|
+ );
|
|
|
+
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you use Zend_Db_Table to emulate cascading UPDATE and DELETE operations, declare the
|
|
|
+ <code>$_dependentTables</code> array in the class for the parent table. List the class
|
|
|
+ name for each dependent table. Use the class name, not the physical name of the SQL
|
|
|
+ table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Skip declaration of <code>$_dependentTables</code> if you use referential integrity
|
|
|
+ constraints in the RDBMS server to implement cascading operations. See
|
|
|
+ <xref linkend="zend.db.table.relationships.cascading"/> for more information.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Declare the <code>$_referenceMap</code> array in the class for each dependent table.
|
|
|
+ This is an associative array of reference "rules". A reference rule identifies which
|
|
|
+ table is the parent table in the relationship, and also lists which columns in the
|
|
|
+ dependent table reference which columns in the parent table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The rule key is a string used as an index to the <code>$_referenceMap</code> array.
|
|
|
+ This rule key is used to identify each reference relationship. Choose a descriptive
|
|
|
+ name for this rule key. It's best to use a string that can be part of a PHP method
|
|
|
+ name, as you will see later.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In the example PHP code above, the rule keys in the Bugs table class are:
|
|
|
+ <code>'Reporter'</code>, <code>'Engineer'</code>, <code>'Verifier'</code>, and
|
|
|
+ <code>'Product'</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The value of each rule entry in the <code>$_referenceMap</code> array is also an
|
|
|
+ associative array. The elements of this rule entry are described below:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">columns</emphasis> => A string or an array of strings
|
|
|
+ naming the foreign key column name(s) in the dependent table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ It's common for this to be a single column, but some tables have multi-column
|
|
|
+ keys.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">refTableClass</emphasis> => The class name of the
|
|
|
+ parent table. Use the class name, not the physical name of the SQL table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ It's common for a dependent table to have only one reference to its parent
|
|
|
+ table, but some tables have multiple references to the same parent table. In
|
|
|
+ the example database, there is one reference from the <code>bugs</code> table
|
|
|
+ to the <code>products</code> table, but three references from the
|
|
|
+ <code>bugs</code> table to the <code>accounts</code> table. Put each reference
|
|
|
+ in a separate entry in the <code>$_referenceMap</code> array.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">refColumns</emphasis> => A string or an array of
|
|
|
+ strings naming the primary key column name(s) in the parent table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ It's common for this to be a single column, but some tables have multi-column
|
|
|
+ keys. If the reference uses a multi-column key, the order of columns in the
|
|
|
+ <code>'columns'</code> entry must match the order of columns in the
|
|
|
+ <code>'refColumns'</code> entry.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ It is optional to specify this element. If you don't specify the
|
|
|
+ <code>refColumns</code>, the column(s) reported as the primary key columns of
|
|
|
+ the parent table are used by default.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">onDelete</emphasis> => The rule for an action to
|
|
|
+ execute if a row is deleted in the parent table. See
|
|
|
+ <xref linkend="zend.db.table.relationships.cascading"/> for more information.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">onUpdate</emphasis> => The rule for an action to
|
|
|
+ execute if values in primary key columns are updated in the parent table. See
|
|
|
+ <xref linkend="zend.db.table.relationships.cascading"/> for more information.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.relationships.fetching.dependent">
|
|
|
+
|
|
|
+ <title>Fetching a Dependent Rowset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you have a Row object as the result of a query on a parent table, you can fetch rows
|
|
|
+ from dependent tables that reference the current row. Use the method:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$row->findDependentRowset($table, [$rule]);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This method returns a Zend_Db_Table_Rowset_Abstract object, containing a set of rows
|
|
|
+ from the dependent table <code>$table</code> that refer to the row identified by the
|
|
|
+ <code>$row</code> object.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The first argument <code>$table</code> can be a string that specifies the dependent
|
|
|
+ table by its class name. You can also specify the dependent table by using an object of
|
|
|
+ that table class.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.relationships.fetching.dependent.example">
|
|
|
+
|
|
|
+ <title>Fetching a Dependent Rowset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This example shows getting a Row object from the table <code>Accounts</code>, and
|
|
|
+ finding the <code>Bugs</code> reported by that account.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$accountsTable = new Accounts();
|
|
|
+$accountsRowset = $accountsTable->find(1234);
|
|
|
+$user1234 = $accountsRowset->current();
|
|
|
+
|
|
|
+$bugsReportedByUser = $user1234->findDependentRowset('Bugs');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The second argument <code>$rule</code> is optional. It is a string that names the rule
|
|
|
+ key in the <code>$_referenceMap</code> array of the dependent table class. If you don't
|
|
|
+ specify a rule, the first rule in the array that references the parent table is used.
|
|
|
+ If you need to use a rule other than the first, you need to specify the key.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In the example code above, the rule key is not specified, so the rule used by default
|
|
|
+ is the first one that matches the parent table. This is the rule
|
|
|
+ <code>'Reporter'</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.relationships.fetching.dependent.example-by">
|
|
|
+
|
|
|
+ <title>Fetching a Dependent Rowset By a Specific Rule</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This example shows getting a Row object from the table <code>Accounts</code>, and
|
|
|
+ finding the <code>Bugs</code> assigned to be fixed by the user of that account. The
|
|
|
+ rule key string that corresponds to this reference relationship in this example is
|
|
|
+ <code>'Engineer'</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$accountsTable = new Accounts();
|
|
|
+$accountsRowset = $accountsTable->find(1234);
|
|
|
+$user1234 = $accountsRowset->current();
|
|
|
+
|
|
|
+$bugsAssignedToUser = $user1234->findDependentRowset('Bugs', 'Engineer');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can also add criteria, ordering and limits to your relationships using the parent
|
|
|
+ row's select object.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.relationships.fetching.dependent.example-by-select">
|
|
|
+
|
|
|
+ <title>Fetching a Dependent Rowset using a Zend_Db_Table_Select</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This example shows getting a Row object from the table <code>Accounts</code>,
|
|
|
+ and finding the <code>Bugs</code> assigned to be fixed by the user of that
|
|
|
+ account, limited only to 3 rows and ordered by name.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$accountsTable = new Accounts();
|
|
|
+$accountsRowset = $accountsTable->find(1234);
|
|
|
+$user1234 = $accountsRowset->current();
|
|
|
+$select = $accountsTable->select()->order('name ASC')
|
|
|
+ ->limit(3);
|
|
|
+
|
|
|
+$bugsAssignedToUser = $user1234->findDependentRowset('Bugs',
|
|
|
+ 'Engineer',
|
|
|
+ $select);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ Alternatively, you can query rows from a dependent table using a special mechanism
|
|
|
+ called a "magic method". Zend_Db_Table_Row_Abstract invokes the method:
|
|
|
+ <code>findDependentRowset('<TableClass>', '<Rule>')</code> if you invoke a method on
|
|
|
+ the Row object matching either of the following patterns:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>$row->find<TableClass>()</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>$row->find<TableClass>By<Rule>()</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In the patterns above, <code><TableClass></code> and <code><Rule></code> are strings
|
|
|
+ that correspond to the class name of the dependent table, and the dependent table's
|
|
|
+ rule key that references the parent table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Some application frameworks, such as Ruby on Rails, use a mechanism called
|
|
|
+ "inflection" to allow the spelling of identifiers to change depending on usage. For
|
|
|
+ simplicity, Zend_Db_Table_Row does not provide any inflection mechanism. The table
|
|
|
+ identity and the rule key named in the method call must match the spelling of the
|
|
|
+ class and rule key exactly.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <example id="zend.db.table.relationships.fetching.dependent.example-magic">
|
|
|
+
|
|
|
+ <title>Fetching Dependent Rowsets using the Magic Method</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This example shows finding dependent Rowsets equivalent to those in the previous
|
|
|
+ examples. In this case, the application uses the magic method invocation instead of
|
|
|
+ specifying the table and rule as strings.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$accountsTable = new Accounts();
|
|
|
+$accountsRowset = $accountsTable->find(1234);
|
|
|
+$user1234 = $accountsRowset->current();
|
|
|
+
|
|
|
+// Use the default reference rule
|
|
|
+$bugsReportedBy = $user1234->findBugs();
|
|
|
+
|
|
|
+// Specify the reference rule
|
|
|
+$bugsAssignedTo = $user1234->findBugsByEngineer();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.relationships.fetching.parent">
|
|
|
+
|
|
|
+ <title>Fetching a Parent Row</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you have a Row object as the result of a query on a dependent table, you can fetch
|
|
|
+ the row in the parent to which the dependent row refers. Use the method:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$row->findParentRow($table, [$rule]);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ There always should be exactly one row in the parent table referenced by a dependent
|
|
|
+ row, therefore this method returns a Row object, not a Rowset object.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The first argument <code>$table</code> can be a string that specifies the parent table
|
|
|
+ by its class name. You can also specify the parent table by using an object of that
|
|
|
+ table class.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.relationships.fetching.parent.example">
|
|
|
+
|
|
|
+ <title>Fetching the Parent Row</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This example shows getting a Row object from the table <code>Bugs</code> (for
|
|
|
+ example one of those bugs with status 'NEW'), and finding the row in the
|
|
|
+ <code>Accounts</code> table for the user who reported the bug.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugsTable = new Bugs();
|
|
|
+$bugsRowset = $bugsTable->fetchAll(array('bug_status = ?' => 'NEW'));
|
|
|
+$bug1 = $bugsRowset->current();
|
|
|
+
|
|
|
+$reporter = $bug1->findParentRow('Accounts');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The second argument <code>$rule</code> is optional. It is a string that names the rule
|
|
|
+ key in the <code>$_referenceMap</code> array of the dependent table class. If you don't
|
|
|
+ specify a rule, the first rule in the array that references the parent table is used.
|
|
|
+ If you need to use a rule other than the first, you need to specify the key.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In the example above, the rule key is not specified, so the rule used by default is the
|
|
|
+ first one that matches the parent table. This is the rule <code>'Reporter'</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.relationships.fetching.parent.example-by">
|
|
|
+
|
|
|
+ <title>Fetching a Parent Row By a Specific Rule</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This example shows getting a Row object from the table <code>Bugs</code>, and
|
|
|
+ finding the account for the engineer assigned to fix that bug. The rule key string
|
|
|
+ that corresponds to this reference relationship in this example is
|
|
|
+ <code>'Engineer'</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugsTable = new Bugs();
|
|
|
+$bugsRowset = $bugsTable->fetchAll(array('bug_status = ?', 'NEW'));
|
|
|
+$bug1 = $bugsRowset->current();
|
|
|
+
|
|
|
+$engineer = $bug1->findParentRow('Accounts', 'Engineer');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Alternatively, you can query rows from a parent table using a "magic method".
|
|
|
+ Zend_Db_Table_Row_Abstract invokes the method:
|
|
|
+ <code>findParentRow('<TableClass>', '<Rule>')</code> if you invoke a method
|
|
|
+ on the Row object matching either of the following patterns:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>$row->findParent<TableClass>([Zend_Db_Table_Select $select])</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>$row->findParent<TableClass>By<Rule>([Zend_Db_Table_Select
|
|
|
+ $select])</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In the patterns above, <code><TableClass></code> and <code><Rule></code>
|
|
|
+ are strings that correspond to the class name of the parent table, and the dependent
|
|
|
+ table's rule key that references the parent table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The table identity and the rule key named in the method call must match the
|
|
|
+ spelling of the class and rule key exactly.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <example id="zend.db.table.relationships.fetching.parent.example-magic">
|
|
|
+
|
|
|
+ <title>Fetching the Parent Row using the Magic Method</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This example shows finding parent Rows equivalent to those in the previous
|
|
|
+ examples. In this case, the application uses the magic method invocation instead of
|
|
|
+ specifying the table and rule as strings.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugsTable = new Bugs();
|
|
|
+$bugsRowset = $bugsTable->fetchAll(array('bug_status = ?', 'NEW'));
|
|
|
+$bug1 = $bugsRowset->current();
|
|
|
+
|
|
|
+// Use the default reference rule
|
|
|
+$reporter = $bug1->findParentAccounts();
|
|
|
+
|
|
|
+// Specify the reference rule
|
|
|
+$engineer = $bug1->findParentAccountsByEngineer();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.relationships.fetching.many-to-many">
|
|
|
+
|
|
|
+ <title>Fetching a Rowset via a Many-to-many Relationship</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If you have a Row object as the result of a query on one table in a many-to-many
|
|
|
+ relationship (for purposes of the example, call this the "origin" table), you can
|
|
|
+ fetch corresponding rows in the other table (call this the "destination" table) via an
|
|
|
+ intersection table. Use the method:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$row->findManyToManyRowset($table,
|
|
|
+ $intersectionTable,
|
|
|
+ [$rule1,
|
|
|
+ [$rule2,
|
|
|
+ [Zend_Db_Table_Select $select]
|
|
|
+ ]
|
|
|
+ ]);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This method returns a Zend_Db_Table_Rowset_Abstract containing rows from the table
|
|
|
+ <code>$table</code>, satisfying the many-to-many relationship. The current Row object
|
|
|
+ <code>$row</code> from the origin table is used to find rows in the intersection table,
|
|
|
+ and that is joined to the destination table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The first argument <code>$table</code> can be a string that specifies the destination
|
|
|
+ table in the many-to-many relationship by its class name. You can also specify the
|
|
|
+ destination table by using an object of that table class.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The second argument <code>$intersectionTable</code> can be a string that specifies the
|
|
|
+ intersection table between the two tables in the the many-to-many relationship by its
|
|
|
+ class name. You can also specify the intersection table by using an object of that
|
|
|
+ table class.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.relationships.fetching.many-to-many.example">
|
|
|
+
|
|
|
+ <title>Fetching a Rowset with the Many-to-many Method</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This example shows getting a Row object from from the origin table
|
|
|
+ <code>Bugs</code>, and finding rows from the destination table
|
|
|
+ <code>Products</code>, representing products related to that bug.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugsTable = new Bugs();
|
|
|
+$bugsRowset = $bugsTable->find(1234);
|
|
|
+$bug1234 = $bugsRowset->current();
|
|
|
+
|
|
|
+$productsRowset = $bug1234->findManyToManyRowset('Products',
|
|
|
+ 'BugsProducts');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The third and fourth arguments <code>$rule1</code> and <code>$rule2</code> are
|
|
|
+ optional. These are strings that name the rule keys in the <code>$_referenceMap</code>
|
|
|
+ array of the intersection table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The <code>$rule1</code> key names the rule for the relationship from the intersection
|
|
|
+ table to the origin table. In this example, this is the relationship from
|
|
|
+ <code>BugsProducts</code> to <code>Bugs</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The <code>$rule2</code> key names the rule for the relationship from the intersection
|
|
|
+ table to the destination table. In this example, this is the relationship from
|
|
|
+ <code>Bugs</code> to <code>Products</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Similarly to the methods for finding parent and dependent rows, if you don't specify a
|
|
|
+ rule, the method uses the first rule in the <code>$_referenceMap</code> array that
|
|
|
+ matches the tables in the relationship. If you need to use a rule other than the first,
|
|
|
+ you need to specify the key.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In the example code above, the rule key is not specified, so the rules used by default
|
|
|
+ are the first ones that match. In this case, <code>$rule1</code> is
|
|
|
+ <code>'Reporter'</code> and <code>$rule2</code> is <code>'Product'</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.relationships.fetching.many-to-many.example-by">
|
|
|
+
|
|
|
+ <title>Fetching a Rowset with the Many-to-many Method By a Specific Rule</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This example shows geting a Row object from from the origin table
|
|
|
+ <code>Bugs</code>, and finding rows from the destination table
|
|
|
+ <code>Products</code>, representing products related to that bug.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugsTable = new Bugs();
|
|
|
+$bugsRowset = $bugsTable->find(1234);
|
|
|
+$bug1234 = $bugsRowset->current();
|
|
|
+
|
|
|
+$productsRowset = $bug1234->findManyToManyRowset('Products',
|
|
|
+ 'BugsProducts',
|
|
|
+ 'Bug');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Alternatively, you can query rows from the destination table in a many-to-many
|
|
|
+ relationship using a "magic method." Zend_Db_Table_Row_Abstract invokes the method:
|
|
|
+ <code>findManyToManyRowset('<TableClass>', '<IntersectionTableClass>',
|
|
|
+ '<Rule1>', '<Rule2>')</code> if you invoke a method matching any of the
|
|
|
+ following patterns:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>$row->find<TableClass>Via<IntersectionTableClass>
|
|
|
+ ([Zend_Db_Table_Select $select])</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>$row->find<TableClass>Via<IntersectionTableClass>By<Rule1>
|
|
|
+ ([Zend_Db_Table_Select $select])</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>$row->find<TableClass>Via<IntersectionTableClass>By<Rule1>And<Rule2>
|
|
|
+ ([Zend_Db_Table_Select $select])</code>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In the patterns above, <code><TableClass></code> and
|
|
|
+ <code><IntersectionTableClass></code> are strings that correspond to the class
|
|
|
+ names of the destination table and the intersection table, respectively.
|
|
|
+ <code><Rule1></code> and <code><Rule2></code> are strings that correspond
|
|
|
+ to the rule keys in the intersection table that reference the origin table and the
|
|
|
+ destination table, respectively.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The table identities and the rule keys named in the method call must match the
|
|
|
+ spelling of the class and rule key exactly.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <example id="zend.db.table.relationships.fetching.many-to-many.example-magic">
|
|
|
+
|
|
|
+ <title>Fetching Rowsets using the Magic Many-to-many Method</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This example shows finding rows in the destination table of a many-to-many
|
|
|
+ relationship representing products related to a given bug.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$bugsTable = new Bugs();
|
|
|
+$bugsRowset = $bugsTable->find(1234);
|
|
|
+$bug1234 = $bugsRowset->current();
|
|
|
+
|
|
|
+// Use the default reference rule
|
|
|
+$products = $bug1234->findProductsViaBugsProducts();
|
|
|
+
|
|
|
+// Specify the reference rule
|
|
|
+$products = $bug1234->findProductsViaBugsProductsByBug();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.db.table.relationships.cascading">
|
|
|
+
|
|
|
+ <title>Cascading Write Operations</title>
|
|
|
+
|
|
|
+ <note>
|
|
|
+
|
|
|
+ <title>Declare DRI in the database:</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Declaring cascading operations in Zend_Db_Table is intended
|
|
|
+ <emphasis role="strong">only</emphasis> for RDBMS brands that do not support
|
|
|
+ declarative referential integrity (DRI).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ For example, if you use MySQL's MyISAM storage engine, or SQLite, these solutions
|
|
|
+ do not support DRI. You may find it helpful to declare the cascading operations
|
|
|
+ with Zend_Db_Table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If your RDBMS implements DRI and the <code>ON DELETE</code> and
|
|
|
+ <code>ON UPDATE</code> clauses, you should declare these clauses in your database
|
|
|
+ schema, instead of using the cascading feature in Zend_Db_Table. Declaring
|
|
|
+ cascading DRI rules in the RDBMS is better for database performance, consistency,
|
|
|
+ and integrity.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Most importantly, do not declare cascading operations both in the RDBMS and in your
|
|
|
+ Zend_Db_Table class.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can declare cascading operations to execute against a dependent table when you
|
|
|
+ apply an <code>UPDATE</code> or a <code>DELETE</code> to a row in a parent table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.relationships.cascading.example-delete">
|
|
|
+
|
|
|
+ <title>Example of a Cascading Delete</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This example shows deleting a row in the <code>Products</code> table, which is
|
|
|
+ configured to automatically delete dependent rows in the <code>Bugs</code> table.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$productsTable = new Products();
|
|
|
+$productsRowset = $productsTable->find(1234);
|
|
|
+$product1234 = $productsRowset->current();
|
|
|
+
|
|
|
+$product1234->delete();
|
|
|
+// Automatically cascades to Bugs table
|
|
|
+// and deletes dependent rows.
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Similarly, if you use <code>UPDATE</code> to change the value of a primary key in a
|
|
|
+ parent table, you may want the value in foreign keys of dependent tables to be updated
|
|
|
+ automatically to match the new value, so that such references are kept up to date.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ It's usually not necessary to update the value of a primary key that was generated by a
|
|
|
+ sequence or other mechanism. But if you use a <emphasis>natural key</emphasis> that may
|
|
|
+ change value occasionally, it is more likely that you need to apply cascading updates
|
|
|
+ to dependent tables.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ To declare a cascading relationship in the Zend_Db_Table, edit the rules in the
|
|
|
+ <code>$_referenceMap</code>. Set the associative array keys <code>'onDelete'</code> and
|
|
|
+ <code>'onUpdate'</code> to the string 'cascade' (or the constant
|
|
|
+ <code>self::CASCADE</code>). Before a row is deleted from the parent table, or its
|
|
|
+ primary key values updated, any rows in the dependent table that refer to the parent's
|
|
|
+ row are deleted or updated first.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.db.table.relationships.cascading.example-declaration">
|
|
|
+
|
|
|
+ <title>Example Declaration of Cascading Operations</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In the example below, rows in the <code>Bugs</code> table are automatically deleted
|
|
|
+ if the row in the <code>Products</code> table to which they refer is deleted. The
|
|
|
+ <code>'onDelete'</code> element of the reference map entry is set to
|
|
|
+ <code>self::CASCADE</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ No cascading update is done in the example below if the primary key value in the
|
|
|
+ parent class is changed. The <code>'onUpdate'</code> element of the reference map
|
|
|
+ entry is <code>self::RESTRICT</code>. You can get the same result using the value
|
|
|
+ <code>self::NO_ACTION</code>, or by omitting the <code>'onUpdate'</code> entry.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class BugsProducts extends Zend_Db_Table_Abstract
|
|
|
+{
|
|
|
+ ...
|
|
|
+ protected $_referenceMap = array(
|
|
|
+ 'Product' => array(
|
|
|
+ 'columns' => array('product_id'),
|
|
|
+ 'refTableClass' => 'Products',
|
|
|
+ 'refColumns' => array('product_id'),
|
|
|
+ 'onDelete' => self::CASCADE,
|
|
|
+ 'onUpdate' => self::RESTRICT
|
|
|
+ ),
|
|
|
+ ...
|
|
|
+ );
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <sect3 id="zend.db.table.relationships.cascading.notes">
|
|
|
+
|
|
|
+ <title>Notes Regarding Cascading Operations</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">Cascading operations invoked by Zend_Db_Table are not
|
|
|
+ atomic.</emphasis>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This means that if your database implements and enforces referential integrity
|
|
|
+ constraints, a cascading <code>UPDATE</code> executed by a Zend_Db_Table class
|
|
|
+ conflicts with the constraint, and results in a referential integrity violation.
|
|
|
+ You can use cascading <code>UPDATE</code> in Zend_Db_Table
|
|
|
+ <emphasis>only</emphasis> if your database does not enforce that referential
|
|
|
+ integrity constraint.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cascading <code>DELETE</code> suffers less from the problem of referential
|
|
|
+ integrity violations. You can delete dependent rows as a non-atomic action before
|
|
|
+ deleting the parent row that they reference.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ However, for both <code>UPDATE</code> and <code>DELETE</code>, changing the
|
|
|
+ database in a non-atomic way also creates the risk that another database user can
|
|
|
+ see the data in an inconsistent state. For example, if you delete a row and all its
|
|
|
+ dependent rows, there is a small chance that another database client program can
|
|
|
+ query the database after you have deleted the dependent rows, but before you delete
|
|
|
+ the parent row. That client program may see the parent row with no dependent rows,
|
|
|
+ and assume this is the intended state of the data. There is no way for that client
|
|
|
+ to know that its query read the database in the middle of a change.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The issue of non-atomic change can be mitigated by using transactions to isolate
|
|
|
+ your change. But some RDBMS brands don't support transactions, or allow clients to
|
|
|
+ read "dirty" changes that have not been committed yet.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">Cascading operations in Zend_Db_Table are invoked only by
|
|
|
+ Zend_Db_Table.</emphasis>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cascading deletes and updates defined in your Zend_Db_Table classes are applied if
|
|
|
+ you execute the <code>save()</code> or <code>delete()</code> methods on the Row
|
|
|
+ class. However, if you update or delete data using another interface, such as a
|
|
|
+ query tool or another application, the cascading operations are not applied. Even
|
|
|
+ when using <code>update()</code> and <code>delete()</code> methods in the
|
|
|
+ Zend_Db_Adapter class, cascading operations defined in your Zend_Db_Table classes
|
|
|
+ are not executed.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">No Cascading <code>INSERT</code>.</emphasis>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ There is no support for a cascading <code>INSERT</code>. You must insert a row to a
|
|
|
+ parent table in one operation, and insert row(s) to a dependent table in a separate
|
|
|
+ operation.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.debug">
|
|
|
+ <title>Zend_Debug</title>
|
|
|
+ <!-- versión 11089 --><sect1 id="zend.debug.dumping" xml:base="module_specs/Zend_Debug.xml">
|
|
|
+
|
|
|
+ <title>Mostrar información de variables(Dumping Variables)</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método estático <code>Zend_Debug::dump()</code> imprime o devuelve
|
|
|
+ información sobre una expresión. Esta sencilla técnica de depuración es
|
|
|
+ común, porque es fácil de utilizar en caliente y no requiere
|
|
|
+ inicialización, herramientas especiales, o la depuración del entorno.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.debug.dumping.example">
|
|
|
+ <title>Ejemplo del método dump()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+
|
|
|
+Zend_Debug::dump($var, $label=null, $echo=true);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El argumento <code>$var</code> especifica la expresión o variable sobre
|
|
|
+ la cual el método <code>Zend_Debug::dump()</code> generará información.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El argumento boleano <code>$echo</code> especifica si la salida de
|
|
|
+ <code>Zend_Debug::dump()</code> es o no mostrada. Si es
|
|
|
+ <code>verdadera</code>, la salida es mostrada. A pesar del valor del
|
|
|
+ argumento <code>$echo</code>, el retorno de este método contiene la
|
|
|
+ salida.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede ser útil comprender que el método <code>Zend_Debug::dump()</code>
|
|
|
+ envuelve la función de PHP
|
|
|
+ <ulink url="http://php.net/var_dump"><code>var_dump()</code></ulink>.
|
|
|
+ Si el flujo de salida es detectado como una presentación de la web, la
|
|
|
+ salida de <code>var_dump()</code> es escapada usando
|
|
|
+ <ulink url="http://php.net/htmlspecialchars"><code>htmlspecialchars()</code></ulink>
|
|
|
+ y envuelta con el tag (X)HTML <code>pre</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <tip>
|
|
|
+ <title>Depurando con Zend_Log</title>
|
|
|
+ <para>
|
|
|
+ Usar <code>Zend_Debug::dump()</code> es lo mejor para la depuración
|
|
|
+ en caliente durante el desarrollo de software. Puede añadir el código para
|
|
|
+ volcar una variable y después quitar el código fácilmente.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ También considere el componente <link linkend="zend.log.overview">
|
|
|
+ Zend_Log</link> escribiendo el código de depuración más
|
|
|
+ permanente. Por ejemplo, puede utilizar el nivel de log de
|
|
|
+ <code>DEPURACIÓN</code> y el Stream log writer, para mostrar la
|
|
|
+ cadena de salida de <code>Zend_Debug::dump()</code>.
|
|
|
+ </para>
|
|
|
+ </tip>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+ vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.dojo">
|
|
|
+ <title>Zend_Dojo</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Dojo.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Dojo-Data.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Dojo-View.xml" parse="xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Dojo-Form.xml" parse="xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.dom">
|
|
|
+ <title>Zend_Dom</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Dom.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Dom-Query.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.exception">
|
|
|
+ <title>Zend_Exception</title>
|
|
|
+ <sect1 id="zend.exception.using" xml:base="module_specs/Zend_Exception.xml">
|
|
|
+
|
|
|
+ <title>Usando Excepciones</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todas las excepciones lanzadas por las clases de Zend Framework
|
|
|
+ deberian arrojar una excepción que deriva de la clase base
|
|
|
+ Zend_Exception.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.exception.using.example">
|
|
|
+ <title>Ejemplo de catching de una excepción</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+try {
|
|
|
+ Zend_Loader::loadClass('clasenoexistente');
|
|
|
+} catch (Zend_Exception $e) {
|
|
|
+ echo "Recibida excepción: " . get_class($e) . "\n";
|
|
|
+ echo "Mensaje: " . $e->getMessage() . "\n";
|
|
|
+ // código para recuperar el fallo.
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Consulte la documentación de cada uno de los componente de Zend
|
|
|
+ Framework para obtener información más específica sobre los
|
|
|
+ métodos que lanzan excepciones, las circunstancias de las
|
|
|
+ excepciones, y qué clases derivan de Zend_Exception.
|
|
|
+ </para>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+ vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.feed">
|
|
|
+ <title>Zend_Feed</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Feed-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Feed-Importing.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Feed-FindFeeds.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Feed-ConsumingRss.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Feed-ConsumingAtom.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Feed-ConsumingAtomSingle.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Feed-ModifyingFeed.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Feed-CustomFeed.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.file">
|
|
|
+ <title>Zend_File</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_File_Transfer-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_File_Transfer-Validators.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_File_Transfer-Filters.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_File_Transfer-Migration.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.filter">
|
|
|
+ <title>Zend_Filter</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Filter.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Filter-Set.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Filter-FilterChains.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Filter-WritingFilters.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Filter_Input.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Filter-Inflector.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.form">
|
|
|
+ <title>Zend_Form</title>
|
|
|
+ <sect1 id="zend.form.introduction" xml:base="module_specs/Zend_Form-Introduction.xml">
|
|
|
+ <title>Zend_Form</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Form simplifica la creación y manejo de formularios en sus
|
|
|
+ aplicaciones web. Cumple los siguientes objetivos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>Validación y filtrado de la información suministrada</para></listitem>
|
|
|
+ <listitem><para>Ordenado de elementos</para></listitem>
|
|
|
+ <listitem><para>Elementos y su presentación, incluyendo su escape</para></listitem>
|
|
|
+ <listitem><para>Agrupación de elementos y formularios</para></listitem>
|
|
|
+ <listitem><para>Configuración de componentes a nivel de formulario</para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Se aprovecha en gran medida de otros componentes de Zend Framework para lograr sus objetivos,
|
|
|
+ incluyendo <code>Zend_Config</code>, <code>Zend_Validate</code>, <code>Zend_Filter</code>,
|
|
|
+ <code>Zend_Loader_PluginLoader</code> y, opcionalmente, <code>Zend_View</code>.
|
|
|
+ </para>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.form.quickstart" xml:base="module_specs/Zend_Form-QuickStart.xml">
|
|
|
+ <title>Inicio rápido a Zend_Form</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esta guía rápida pretende cubrir los fundamentos para
|
|
|
+ crear, validar y presentar formularios usando <code>Zend_Form</code>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.quickstart.create">
|
|
|
+ <title>Creando un objeto formulario</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Crear un objeto de formulario es muy simple: solo instancíe
|
|
|
+ <code>Zend_Form</code>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form = new Zend_Form;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para casos de uso avanzados, es posible desee crear una subclase de
|
|
|
+ <code>Zend_Form</code>, pero para formularios simples, puede
|
|
|
+ programar la creación de un formulario usando un objeto
|
|
|
+ <code>Zend_Form</code>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si desea especificar el action y method del formulario (siempre
|
|
|
+ buenas ideas), puede hacer uso de los accesos
|
|
|
+ <code>setAction()</code> y <code>setMethod()</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->setAction('/resource/process')
|
|
|
+ ->setMethod('post');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El código de arriba establece el action del formulario a la URL
|
|
|
+ parcial "/resource/process" y como method HTTP POST. Esto se
|
|
|
+ mostrará en la presentación final.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Usted puede establecer atributos HTML adicionales para la etiqueta
|
|
|
+ <code><form></code> mediante el uso de los métodos
|
|
|
+ setAttrib() o setAttribs(). Por ejemplo, si desea especificar el id
|
|
|
+ establezca el atributo "id":
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->setAttrib('id', 'login');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.quickstart.elements">
|
|
|
+ <title>Añadir elementos al formulario</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un formulario no es nada sin sus elementos. <code>Zend_Form</code>
|
|
|
+ contiene de manera predeterminada algunos elementos que generan
|
|
|
+ XHTML vía auxiliares <code>Zend_View</code>. Son los
|
|
|
+ siguientes:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ button
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ checkbox (o varios checkboxes a la vez con multiCheckbox)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ hidden
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ image
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ password
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ radio
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ reset
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ select (tanto regulares como de multi-selección)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ submit
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ text
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ textarea
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Tiene dos opciones para añadir elementos a un formulario; puede
|
|
|
+ instanciar elementos concretos y pasarlos como objetos, o
|
|
|
+ simplemente puede pasar el tipo de elemento y <code>Zend_Form</code>
|
|
|
+ instaciará por usted un objeto del tipo correspondiente.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Algunos ejemplos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Instanciando un elemento y pasandolo al objeto form:
|
|
|
+$form->addElement(new Zend_Form_Element_Text('username'));
|
|
|
+
|
|
|
+// Pasando el tipo de elemento del formulario al objeto form:
|
|
|
+$form->addElement('text', 'username');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ De manera predeterminada, éstos no tienen validadores o filtros.
|
|
|
+ Esto significa que tendrá que configurar sus elementos con un
|
|
|
+ mínimo de validadores, y potencialmente filtros. Puede hacer esto
|
|
|
+ (a) antes de pasar el elemento al formulario, (b) vía opciones de
|
|
|
+ configuración pasadas cuando crea un elemento a través de
|
|
|
+ <code>Zend_Form</code>, o (c) recuperar el elemento del objeto form
|
|
|
+ y configurándolo posteriormente.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Veamos primero la creación de validadores para la instancia de
|
|
|
+ un elemento concreto. Puede pasar objetos
|
|
|
+ <code>Zend_Validate_*</code> o el nombre de un validador para utilizar:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$username = new Zend_Form_Element_Text('username');
|
|
|
+
|
|
|
+// Pasando un objeto Zend_Validate_*:
|
|
|
+$username->addValidator(new Zend_Validate_Alnum());
|
|
|
+
|
|
|
+// Pasando el nombre de un validador:
|
|
|
+$username->addValidator('alnum');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cuando se utiliza esta segunda opción, si el constructor del
|
|
|
+ validador acepta argumentos, se pueden pasar en un array
|
|
|
+ como tercer parámetro:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Pasando un patrón
|
|
|
+$username->addValidator('regex', false, array('/^[a-z]/i'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ (El segundo parámetro se utiliza para indicar si el fallo
|
|
|
+ debería prevenir la ejecución de validadores posteriores o no; por
|
|
|
+ defecto, el valor es false.)
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede también desear especificar un elemento como requerido. Esto
|
|
|
+ puede hacerse utilizando un método de acceso o pasando una opción al
|
|
|
+ crear el elemento. En el primer caso:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Hace este elemento requerido:
|
|
|
+$username->setRequired(true);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cuando un elemento es requerido, un validador 'NotEmpty' (NoVacio)
|
|
|
+ es añadido a la parte superior de la cadena de validaciones,
|
|
|
+ asegurando que el elemento tenga algún valor cuando sea requerido.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los filtros son registrados básicamente de la misma manera que los
|
|
|
+ validadores. Para efectos ilustrativos, vamos a agregar un filtro
|
|
|
+ para poner en minúsculas el valor final:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$username->addFilter('StringtoLower');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Entonces, la configuración final de nuestro elemento queda así:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$username->addValidator('alnum')
|
|
|
+ ->addValidator('regex', false, array('/^[a-z]/'))
|
|
|
+ ->setRequired(true)
|
|
|
+ ->addFilter('StringToLower');
|
|
|
+
|
|
|
+// o, de manera más compacta:
|
|
|
+$username->addValidators(array('alnum',
|
|
|
+ array('regex', false, '/^[a-z]/i')
|
|
|
+ ))
|
|
|
+ ->setRequired(true)
|
|
|
+ ->addFilters(array('StringToLower'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Tan simple como esto, realizarlo para cada uno de los elementos
|
|
|
+ del formulario puede resultar un poco tedioso. Intentemos la opción
|
|
|
+ (b) arriba mencionada. Cuando creamos un nuevo elemento utilizando
|
|
|
+ <code>Zend_Form::addElement()</code> como fábrica, opcionalmente
|
|
|
+ podemos pasar las opciones de configuración. Éstas pueden incluir
|
|
|
+ validadores y los filtros que se van a utilizar. Por lo tanto, para hacer todo
|
|
|
+ lo anterior implícitamente, intente lo siguiente:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->addElement('text', 'username', array(
|
|
|
+ 'validators' => array(
|
|
|
+ 'alnum',
|
|
|
+ array('regex', false, '/^[a-z]/i')
|
|
|
+ ),
|
|
|
+ 'required' => true,
|
|
|
+ 'filters' => array('StringToLower'),
|
|
|
+));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <note><para>
|
|
|
+ Si encuentra que está asignando elementos con las mismas opciones en
|
|
|
+ varios lugares, podría considerar crear su propia subclase de
|
|
|
+ <code>Zend_Form_Element</code> y utilizar ésta; a largo plazo le
|
|
|
+ permitirá escribir menos.
|
|
|
+ </para></note>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.quickstart.render">
|
|
|
+ <title>Generar un formulario</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Generar un formulario es simple. La mayoría de los elementos
|
|
|
+ utilizan un auxiliar de <code>Zend_View</code> para generarse a sí
|
|
|
+ mismos, por lo tanto necesitan un objeto vista con el fin de
|
|
|
+ generarse. Además, tiene dos opciones: usar el método render()
|
|
|
+ del formulario, o simplemente mostrarlo con echo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Llamando a render() explicitamente, y pasando un objeto vista opcional:
|
|
|
+echo $form->render($view);
|
|
|
+
|
|
|
+// Suponiendo un objeto vista ha sido previamente establecido vía setView():
|
|
|
+echo $form;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ De manera predeterminada, <code>Zend_Form</code> y
|
|
|
+ <code>Zend_Form_Element</code> intentarán utilizar el objeto vista
|
|
|
+ inicializado en el <code>ViewRenderer</code>, lo que significa que
|
|
|
+ no tendrá que establecer la vista manualmente cuando use el MVC de
|
|
|
+ Zend Framework. Generar un formulario en un script vista es tan
|
|
|
+ simple como:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+<?php echo $this->form ?>
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Detrás del telón, <code>Zend_Form</code> utiliza "decoradores"
|
|
|
+ (decorators) para generar la salida. Estos decoradores pueden
|
|
|
+ reemplazar, añadir o anteponer contenido, y tienen plena
|
|
|
+ introspección al elemento que les es pasado. Como resultado, puede
|
|
|
+ combinar múltiples decoradores para lograr efectos personalizados.
|
|
|
+ Predeterminadamente, <code>Zend_Form_Element</code> actualmente
|
|
|
+ combina cuatro decoradores para obtener su salida; la configuración
|
|
|
+ sería como sigue:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element->addDecorators(array(
|
|
|
+ 'ViewHelper',
|
|
|
+ 'Errors',
|
|
|
+ array('HtmlTag', array('tag' => 'dd')),
|
|
|
+ array('Label', array('tag' => 'dt')),
|
|
|
+));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ (Donde <HELPERNAME> es el nombre de un view helper que
|
|
|
+ utilizar, y varía según el elemento)
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Lo anterior crea una salida como la siguiente:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="html"><![CDATA[
|
|
|
+<dt><label for="username" class="required">Username</dt>
|
|
|
+<dd>
|
|
|
+ <input type="text" name="username" value="123-abc" />
|
|
|
+ <ul class="errors">
|
|
|
+ <li>'123-abc' has not only alphabetic and digit characters</li>
|
|
|
+ <li>'123-abc' does not match against pattern '/^[a-z]/i'</li>
|
|
|
+ </ul>
|
|
|
+</dd>
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ (Aunque no con el mismo formato.)
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede cambiar los decoradores usados para un elemento si desea tener
|
|
|
+ diferente salida; véase la sección sobre decoradores para mayor
|
|
|
+ información.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El propio formulario simplemente itera sobre los elementos y
|
|
|
+ los cubre en un <form> HTML. El action y method que
|
|
|
+ proporcionó cuando definió el formulario se pasan a la etiqueta
|
|
|
+ <code><form></code>, como cualquier atributo que establezca
|
|
|
+ vía <code>setAttribs()</code> y familia.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Elementos son desplegados en el orden en el que fueron registrados,
|
|
|
+ o, si el elemento contienen un atributo de orden, ese orden será
|
|
|
+ utilizado. Usted puede fijar el orden de un elemento usando:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element->setOrder(10);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ O, cuando crea un elemento, pasándolo como una opción:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->addElement('text', 'username', array('order' => 10));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.quickstart.validate">
|
|
|
+ <title>Comprobar si un formulario es válido</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Después que un formulario es enviado, necesitará comprobar y ver si
|
|
|
+ pasa las validaciones. Cada elemento es valuado contra los datos
|
|
|
+ provistos; si una clave no está presente y el campo fue marcado como
|
|
|
+ requerido, la validación se ejecuta contra un valor nulo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ ¿De dónde provienen los datos?. Puede usar <code>$_POST</code> o
|
|
|
+ <code>$_GET</code>, o cualquier otra fuente de datos que tenga a
|
|
|
+ mano (solicitud de un servicio web, por ejemplo):
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+if ($form->isValid($_POST)) {
|
|
|
+ // ¡Correcto!
|
|
|
+} else {
|
|
|
+ // ¡Fallo!
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Con solicitudes AJAX, a veces puede ignorar la validación de un solo
|
|
|
+ elemento, o grupo de elementos.
|
|
|
+ <code>isValidPartial()</code> validará parcialmente el formulario.
|
|
|
+ A diferencia de <code>isValid()</code>, que como sea, si alguna
|
|
|
+ clave no esta presente, no ejecutará las validaciones para ese
|
|
|
+ elemento en particular.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+if ($form->isValidPartial($_POST)) {
|
|
|
+ // de los elementos presentes, todos pasaron las validaciones
|
|
|
+} else {
|
|
|
+ // uno u más elementos probados no pasaron las validaciones
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un método adicional, <code>processAjax()</code>, puede también ser
|
|
|
+ usado para validar formularios parciales. A diferencia de
|
|
|
+ <code>isValidPartial()</code>, regresa una cadena en formato JSON
|
|
|
+ conteniendo mensajes de error en caso de fallo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Asumiendo que sus validaciones han pasado, ahora puede obtener los
|
|
|
+ valores filtrados:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$values = $form->getValues();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si necesita los valores sin filtrar en algún punto, utilice:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$unfiltered = $form->getUnfilteredValues();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.quickstart.errorstatus">
|
|
|
+ <title>Obteniendo el estado de error</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Entonces, ¿su formulario no es válido? En la mayoría de los casos,
|
|
|
+ simplemente puede generar el formulario nuevamente y los errores se
|
|
|
+ mostrarán cuando se usen los decoradores predeterminados:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+if (!$form->isValid($_POST)) {
|
|
|
+ echo $form;
|
|
|
+
|
|
|
+ // o asigne al objeto vista y genere una vista...
|
|
|
+ $this->view->form = $form;
|
|
|
+ return $this->render('form');
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si quiere inspeccionar los errores, tiene dos métodos.
|
|
|
+ <code>getErrors()</code> regresa una matriz asociativa de nombres /
|
|
|
+ códigos de elementos (donde códigos es una matriz de códigos de
|
|
|
+ error). <code>getMessages()</code> regresa una matriz asociativa
|
|
|
+ de nombres / mensajes de elementos (donde mensajes es una matriz
|
|
|
+ asociativa de pares código de error / mensaje de error). Si un
|
|
|
+ elemento no tiene ningún error, no será incluido en la matriz.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.quickstart.puttingtogether">
|
|
|
+ <title>Poniendo todo junto</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Construyamos un simple formulario de login. Necesitaremos
|
|
|
+ elementos que representen:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>usuario</para></listitem>
|
|
|
+ <listitem><para>contraseña</para></listitem>
|
|
|
+ <listitem><para>Botón de ingreso</para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para nuestros propósitos, vamos a suponer que un usuario válido
|
|
|
+ cumplirá con tener solo caracteres alfanuméricos, comenzar con una
|
|
|
+ letra, tener una longitud mínima de 6 caracteres y una longitud
|
|
|
+ máxima de 20 caracteres; se normalizarán en minúsculas. Las
|
|
|
+ contraseñas deben tener un mínimo de 6 caracteres. Cuando se procese
|
|
|
+ vamos simplemente a mostrar el valor, por lo que puede permanecer
|
|
|
+ inválido.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Usaremos el poder de la opciones de configuración de
|
|
|
+ <code>Zend_Form</code> para crear el formulario:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form = new Zend_Form();
|
|
|
+$form->setAction('/user/login')
|
|
|
+ ->setMethod('post');
|
|
|
+
|
|
|
+// Crea un y configura el elemento username
|
|
|
+$username = $form->createElement('text', 'username');
|
|
|
+$username->addValidator('alnum')
|
|
|
+ ->addValidator('regex', false, array('/^[a-z]+/'))
|
|
|
+ ->addValidator('stringLength', false, array(6, 20))
|
|
|
+ ->setRequired(true)
|
|
|
+ ->addFilter('StringToLower');
|
|
|
+
|
|
|
+// Crea y configura el elemento password:
|
|
|
+$password = $form->createElement('password', 'password');
|
|
|
+$password->addValidator('StringLength', false, array(6))
|
|
|
+ ->setRequired(true);
|
|
|
+
|
|
|
+// Añade los elementos al formulario:
|
|
|
+$form->addElement($username)
|
|
|
+ ->addElement($password)
|
|
|
+ // uso de addElement() como fábrica para crear el botón 'Login':
|
|
|
+ ->addElement('submit', 'login', array('label' => 'Login'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A continuación, vamos a crear un controlador para manejar esto:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class UserController extends Zend_Controller_Action
|
|
|
+{
|
|
|
+ public function getForm()
|
|
|
+ {
|
|
|
+ // crea el formulario como se indicó arriba
|
|
|
+ return $form;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function indexAction()
|
|
|
+ {
|
|
|
+ // genera user/form.phtml
|
|
|
+ $this->view->form = $this->getForm();
|
|
|
+ $this->render('form');
|
|
|
+ }
|
|
|
+
|
|
|
+ public function loginAction()
|
|
|
+ {
|
|
|
+ if (!$this->getRequest()->isPost()) {
|
|
|
+ return $this->_forward('index');
|
|
|
+ }
|
|
|
+ $form = $this->getForm();
|
|
|
+ if (!$form->isValid($_POST)) {
|
|
|
+ // Falla la validación; Se vuelve a mostrar el formulario
|
|
|
+ $this->view->form = $form;
|
|
|
+ return $this->render('form');
|
|
|
+ }
|
|
|
+
|
|
|
+ $values = $form->getValues();
|
|
|
+ // ahora intenta y autentica...
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Y un script para la vista que muestra el formulario:
|
|
|
+ </para>
|
|
|
+
|
|
|
+<programlisting role="php"><![CDATA[
|
|
|
+<h2>Please login:</h2>
|
|
|
+<?= $this->form ?>
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como notará en el código del controlador, hay más trabajo por hacer:
|
|
|
+ mientras la información enviada sea válida, necesitará todavía
|
|
|
+ realizar la autenticación usando <code>Zend_Auth</code>, por
|
|
|
+ ejemplo.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.quickstart.config">
|
|
|
+ <title>Usando un objeto Zend_Config</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todas las clases <code>Zend_Form</code> son configurables mediante
|
|
|
+ <code>Zend_Config</code>; puede incluso pasar un objeto al
|
|
|
+ constructor o pasarlo a través de <code>setConfig()</code>. Veamos
|
|
|
+ cómo podemos crear el formulario anterior usando un archivo INI.
|
|
|
+ Primero, vamos a seguir las recomendaciones, y colocaremos nuestras
|
|
|
+ configuraciones dentro de secciones reflejando su objetivo y
|
|
|
+ y enfocándonos en la sección 'development'. A continuación,
|
|
|
+ pondremos en una sección de configuración para el controlador dado
|
|
|
+ ('user'), y una clave para el formulario ('login'):
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="ini"><![CDATA[
|
|
|
+[development]
|
|
|
+; metainformación general del formulario
|
|
|
+user.login.action = "/user/login"
|
|
|
+user.login.method = "post"
|
|
|
+
|
|
|
+; elemento username
|
|
|
+user.login.elements.username.type = "text"
|
|
|
+user.login.elements.username.options.validators.alnum.validator = "alnum"
|
|
|
+user.login.elements.username.options.validators.regex.validator = "regex"
|
|
|
+user.login.elements.username.options.validators.regex.options.pattern = "/^[a-z]/i"
|
|
|
+user.login.elements.username.options.validators.strlen.validator = "StringLength"
|
|
|
+user.login.elements.username.options.validators.strlen.options.min = "6"
|
|
|
+user.login.elements.username.options.validators.strlen.options.max = "20"
|
|
|
+user.login.elements.username.options.required = true
|
|
|
+user.login.elements.username.options.filters.lower.filter = "StringToLower"
|
|
|
+
|
|
|
+; elemento password
|
|
|
+user.login.elements.password.type = "password"
|
|
|
+user.login.elements.password.options.validators.strlen.validator = "StringLength"
|
|
|
+user.login.elements.password.options.validators.strlen.options.min = "6"
|
|
|
+user.login.elements.password.options.required = true
|
|
|
+
|
|
|
+; elemento submit
|
|
|
+user.login.elements.submit.type = "submit"
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Entonces puede pasarlo al constructor del formulario:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$config = new Zend_Config_Ini($configFile, 'development');
|
|
|
+$form = new Zend_Form($config->user->login);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ y el formulario entero será definido.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.quickstart.conclusion">
|
|
|
+ <title>Conclusión</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esperamos que después de este pequeño tutorial sea capaz de descubrir
|
|
|
+ el poder y flexibilidad de <code>Zend_Form</code>. Continúe leyendo
|
|
|
+ para profundizar más en el tema.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.form.elements" xml:base="module_specs/Zend_Form-Elements.xml">
|
|
|
+ <title>Creando elementos de formulario usando Zend_Form_Element</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un formulario esta compuesto de elementos, que normalmente corresponden
|
|
|
+ al elemento HTML input. <code>Zend_Form_Element</code> encapsula
|
|
|
+ elementos de formulario individualmente, con las siguientes áreas de
|
|
|
+ responsabilidad:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ validación (¿los datos enviados son válidos?)
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>captura de códigos y mensajes de error</para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ filtrado (¿cómo es escapado y normalizado el elemento para su
|
|
|
+ validación y/o salida?
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ generación (¿cómo es mostrado el elemento?)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ metadatos y atributos (¿qué información amplía la definición del
|
|
|
+ elemento?)
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La clase base, <code>Zend_Form_Element</code>, funciona por defecto para
|
|
|
+ varios casos, pero es mejor extender la clase para elementos con fines
|
|
|
+ especiales de uso común. Adicionalmente, Zend Framework contiene un
|
|
|
+ número de elementos XHTML estándar; puede leer de ellos <link linkend="zend.form.standarElements">en el capítulo Elementos
|
|
|
+ Estándares</link>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.elements.loaders">
|
|
|
+ <title>Cargadores de Plugin</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element</code> hace uso de <link linkend="zend.loader.pluginloader">Zend_Loader_PluginLoader</link>
|
|
|
+ para permitir a los desarrolladores especificar ubicaciones de
|
|
|
+ validadores, filtros y decoradores alternos. Cada uno tiene su
|
|
|
+ propio cargador de plugin asociado a él y métodos de acceso
|
|
|
+ generales usados para su recuperación y modificación.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los siguientes tipos de cargadores son usados con los varios métodos
|
|
|
+ del cargador de plugin: 'validate', 'filter', y 'decorator'. Los
|
|
|
+ nombres son sensibles a mayúsculas y minúsculas.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los métodos usados para interactuar con los cargadores de plugin son
|
|
|
+ los siguientes:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>setPluginLoader($loader, $type)</code>:
|
|
|
+ <code>$loader</code> es el propio objeto cargador, mientras
|
|
|
+ <code>$type</code> es uno de los tipos arriba mencionados. Esto
|
|
|
+ establece el cargador de plugin para el tipo dado en el objeto
|
|
|
+ cargador recién especificado.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getPluginLoader($type)</code>: obtiene el cargador de
|
|
|
+ plugin asociado con <code>$type</code>.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addPrefixPath($prefix, $path, $type = null)</code>: agrega
|
|
|
+ una asociación prefijo/ruta para el cargador especificado por
|
|
|
+ <code>$type</code>. Si <code>$type</code> es null, se intentará
|
|
|
+ agregar la ruta a todos los cargadores, añadiendo el prefijo a
|
|
|
+ cada "_Validate", "_Filter" y "_Decorator"; y agregandole
|
|
|
+ "Validate/", "Filter/" y "Decorator/" a la ruta. Si tiene todas
|
|
|
+ sus clases extras para elementos de formulario dentro de
|
|
|
+ una jerarquía común, este método es conveniente para establecer
|
|
|
+ el prefijo para todas ellas.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addPrefixPaths(array $spec)</code>: le permite añadir
|
|
|
+ varias rutas de una sola vez a uno o más cargadores de plugin.
|
|
|
+ Se espera cada elemento de la matriz sea un array con claves
|
|
|
+ 'path', 'prefix', y 'type'.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Validadores, filtros y decoradores personalizados son una manera
|
|
|
+ simple de compartir funcionalidad entre formularios y encapsular
|
|
|
+ funcionalidad personalizada.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.form.elements.loaders.customLabel">
|
|
|
+ <title>Etiqueta personalizada</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un uso común de los plugins es proveer reemplazos para las
|
|
|
+ clases estándares. Por ejemplo, si desea proveer una implementación diferente
|
|
|
+ del decorador 'Label' -- por ejemplo, para
|
|
|
+ añadir siempre dos puntos -- puede crear su propio decorador
|
|
|
+ 'Label' con su propio prefijo de clase, y entonces añadirlo a su
|
|
|
+ prefijo de ruta.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Comencemos con un decorador de etiqueta personalizado. Le
|
|
|
+ daremos el prefijo "My_Decorator", y la clase estará en el
|
|
|
+ archivo "My/Decorator/Label.php".
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_Decorator_Label extends Zend_Form_Decorator_Abstract
|
|
|
+{
|
|
|
+ protected $_placement = 'PREPEND';
|
|
|
+
|
|
|
+ public function render($content)
|
|
|
+ {
|
|
|
+ if (null === ($element = $this->getElement())) {
|
|
|
+ return $content;
|
|
|
+ }
|
|
|
+ if (!method_exists($element, 'getLabel')) {
|
|
|
+ return $content;
|
|
|
+ }
|
|
|
+
|
|
|
+ $label = $element->getLabel() . ':';
|
|
|
+
|
|
|
+ if (null === ($view = $element->getView())) {
|
|
|
+ return $this->renderLabel($content, $label);
|
|
|
+ }
|
|
|
+
|
|
|
+ $label = $view->formLabel($element->getName(), $label);
|
|
|
+
|
|
|
+ return $this->renderLabel($content, $label);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function renderLabel($content, $label)
|
|
|
+ {
|
|
|
+ $placement = $this->getPlacement();
|
|
|
+ $separator = $this->getSeparator();
|
|
|
+
|
|
|
+ switch ($placement) {
|
|
|
+ case 'APPEND':
|
|
|
+ return $content . $separator . $label;
|
|
|
+ case 'PREPEND':
|
|
|
+ default:
|
|
|
+ return $label . $separator . $content;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Ahora diremos al elemento que use esta ruta cuando busque por
|
|
|
+ decoradores:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Alternativamente, podemos hacerlo en el formulario para asegurar
|
|
|
+ que todos los decoradores usen esta ruta:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->addElementPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Con esta ruta añadida, cuando agregue un decorador, la ruta
|
|
|
+ 'My/Decorator' será consultada primero en búsqueda de la
|
|
|
+ existencia del decorador en este lugar. Como resultado,
|
|
|
+ 'My_Decorator_Label' ahora será utilizado cuando el decorador
|
|
|
+ 'Label' sea requerido.
|
|
|
+ </para>
|
|
|
+ </example>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.elements.filters">
|
|
|
+ <title>Filters</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A menudo es útil y/o necesario realizar alguna normalización en la
|
|
|
+ entrada antes de la validación – por ejemplo, puede querer eliminar
|
|
|
+ todo el HTML, pero realizar las validaciones sobre lo restante para
|
|
|
+ asegurarse que el envío es válido. O puede eliminar los espacios en
|
|
|
+ blanco al inicio o fin de la entrada para asegurarse de que un validador
|
|
|
+ StringLenth (longitud de la cadena) no regrese un positivo falso. Estas
|
|
|
+ operaciones pueden realizarse usando <code>Zend_Filter</code>, y
|
|
|
+ <code>Zend_Form_Element</code> que soportan cadenas de filtros,
|
|
|
+ permitiéndole especificar múltiples filtros secuenciales a utilizar.
|
|
|
+ El filtrado sucede tanto en la validación como cuando recupera el
|
|
|
+ valor del elemento vía <code>getValue()</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$filtered = $element->getValue();
|
|
|
+
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los filtros pueden ser agregados a la pila de dos maneras:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ pasándolo en una instancia de filtro específica
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ proveyendo un nombre de filtro – el correspondiente nombre
|
|
|
+ corto o completo de la clase
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Veamos algunos ejemplos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Instancia específica del filtro
|
|
|
+$element->addFilter(new Zend_Filter_Alnum());
|
|
|
+
|
|
|
+// El correspondiente nombre completo de la clase:
|
|
|
+$element->addFilter('Zend_Filter_Alnum');
|
|
|
+
|
|
|
+// Nombre corto del filtro:
|
|
|
+$element->addFilter('Alnum');
|
|
|
+$element->addFilter('alnum');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los nombres cortos son típicamente el nombre del filtro sin el
|
|
|
+ prefijo. En el caso predeterminado, esto se refiere a sin el prefijo
|
|
|
+ 'Zend_Filter_'. Además, la primera letra no necesita estar en
|
|
|
+ mayúscula.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Usando clases de filtros personalizados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si tiene su propio conjunto de clases de filtro, puede
|
|
|
+ informarle de ellas a <code>Zend_Form_Element</code> usando
|
|
|
+ <code>addPrefixPath()</code>. Por ejemplo, si tiene filtros
|
|
|
+ con el prefijo 'My_Filter', puede indicárselo a
|
|
|
+ <code>Zend_Form_Element</code> de la siguiente manera:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element->addPrefixPath('My_Filter', 'My/Filter/', 'filter');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ (Recuerde que el tercer argumento indica el cargador de plugin
|
|
|
+ sobre el cual ha de ejecutarse la acción.)
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si en algún momento necesita un valor no filtrado, use el método
|
|
|
+ <code>getUnfilteredValue()</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$unfiltered = $element->getUnfilteredValue();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para mayor información sobre filtros, vea la <link linkend="zend.filter.introduction">documentación de
|
|
|
+ Zend_Filter</link>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Métodos asociados con filtros incluyen:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>addFilter($nameOfFilter, array $options = null)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addFilters(array $filters)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setFilters(array $filters)</code> (sobreescribe todos los
|
|
|
+ filtros)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getFilter($name)</code> (recupera un objeto filtro por su
|
|
|
+ nombre)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getFilters()</code> (recupera todos los filtros)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>removeFilter($name)</code> (elimina un filtro por su
|
|
|
+ nombre)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>clearFilters()</code> (elimina todos los filtros)
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.elements.validators">
|
|
|
+ <title>Validadores</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si sigue el mantra de seguridad "filtrar la entrada, escapar la
|
|
|
+ salida" querrá validar ("filtrar la entrada") los datos de los
|
|
|
+ formularios. En <code>Zend_Form</code> cada elemento contiene su
|
|
|
+ propia cadena de validadores, consistente en validadores
|
|
|
+ <code>Zend_Validate_*</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los validadores pueden ser agregados de dos maneras:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ pasándolo en una instancia de validador específica
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ proveyendo un nombre de validador – el correspondiente nombre
|
|
|
+ corto o completo de clase
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Veamos algunos ejemplos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Instancia específica del validador:
|
|
|
+$element->addValidator(new Zend_Validate_Alnum());
|
|
|
+
|
|
|
+// El correspondiente nombre completo de la clase:
|
|
|
+$element->addValidator('Zend_Validate_Alnum');
|
|
|
+
|
|
|
+// Nombre corto del validador:
|
|
|
+$element->addValidator('Alnum');
|
|
|
+$element->addValidator('alnum');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los nombres cortos son típicamente el nombre del validador sin el
|
|
|
+ prefijo. En el caso predeterminado, esto se refiere a sin el prefijo
|
|
|
+ 'Zend_Validate_'. Además, la primera letra no necesita estar en
|
|
|
+ mayúscula.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Usando clases de validación personalizadas</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si tiene su propio conjunto de clases de validación, puede
|
|
|
+ informarle de ellas a <code>Zend_Form_Element</code> usando
|
|
|
+ <code>addPrefixPath()</code>. Por ejemplo, si tiene validadores
|
|
|
+ con el prefijo 'My_Validator', puede indicárselo a
|
|
|
+ <code>Zend_Form_Element</code> de la siguiente manera:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element->addPrefixPath('My_Validator', 'My/Validator/', 'validate');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ (Recuerde que el tercer argumento indica el cargador de plugin
|
|
|
+ sobre el cual ha de ejecutarse la acción.)
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si el fallo de un validador debe evitar validaciones posteriores,
|
|
|
+ pase el boleano <code>true</code> como segundo parámetro:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element->addValidator('alnum', true);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si está usando la cadena nombre para añadir el validador, y la clase
|
|
|
+ del validador acepta argumentos para su constructor, puede pasarlos
|
|
|
+ a el tercer parámetro de <code>addValidator()</code> como un
|
|
|
+ array:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element->addValidator('StringLength', false, array(6, 20));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los argumentos pasados de esta manera deben estar en el orden en el
|
|
|
+ cual son definidos en el constructor. El ejemplo de arriba
|
|
|
+ instanciará la clase <code>Zend_Validate_StringLenth</code> con los
|
|
|
+ parámetros <code>$min</code> y <code>$max</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$validator = new Zend_Validate_StringLength(6, 20);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Estipulando mensajes de error de validación personalizados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Algunos desarrolladores querrán estipular mensajes de error
|
|
|
+ personalizados para un validador. El argumento
|
|
|
+ <code>$options</code> de
|
|
|
+ <code>Zend_Form_Element::addValidator()</code> le permite
|
|
|
+ hacerlo proporcionando la clave 'messages' y estableciendolos en
|
|
|
+ un array de pares clave/valor para especificar las plantillas
|
|
|
+ de mensaje. Necesitará conocer los códigos de error de los
|
|
|
+ diferentes tipos de error de un validador en particular.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Una opción mejor es usar <code>Zend_Translate_Adapter</code>
|
|
|
+ con su formulario. Los códigos de error son automáticamente
|
|
|
+ pasados al adaptador por el decorador Errors por defecto; puede
|
|
|
+ especificar su propias cadenas de mensaje de error mediante la
|
|
|
+ creación de traducciones para los varios códigos de error de
|
|
|
+ sus validadores.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede también establecer varios validadores a la vez, usando
|
|
|
+ <code>addValidators()</code>. Su uso básico es pasar una matriz de
|
|
|
+ arrays, donde cada array contenga de 1 a 3 valores,
|
|
|
+ correspondientes al constructor de <code>addValidator()</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element->addValidators(array(
|
|
|
+ array('NotEmpty', true),
|
|
|
+ array('alnum'),
|
|
|
+ array('stringLength', false, array(6, 20)),
|
|
|
+));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si quiere ser más detallado o explícito, puede utilizar las claves
|
|
|
+ 'validator', 'breakChainOnFailure', y 'options' en el array:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element->addValidators(array(
|
|
|
+ array(
|
|
|
+ 'validator' => 'NotEmpty',
|
|
|
+ 'breakChainOnFailure' => true),
|
|
|
+ array('validator' => 'alnum'),
|
|
|
+ array(
|
|
|
+ 'validator' => 'stringLength',
|
|
|
+ 'options' => array(6, 20)),
|
|
|
+));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Este uso es bueno para ilustrar cómo puede configurar validadores
|
|
|
+ en un archivo de configuración:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="ini"><![CDATA[
|
|
|
+element.validators.notempty.validator = "NotEmpty"
|
|
|
+element.validators.notempty.breakChainOnFailure = true
|
|
|
+element.validators.alnum.validator = "Alnum"
|
|
|
+element.validators.strlen.validator = "StringLength"
|
|
|
+element.validators.strlen.options.min = 6
|
|
|
+element.validators.strlen.options.max = 20
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Note que cada elemento tiene una clave, la necesite o no; esta es
|
|
|
+ una limitación del uso de archivos de configuración -- pero también
|
|
|
+ ayuda a hacer más explicito el para qué son usados los argumentos.
|
|
|
+ Sólo recuerde que cualesquiera opciones del validador deben ser
|
|
|
+ especificadas en orden.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para validar un elemento, pase el valor a
|
|
|
+ <code>isValid()</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+if ($element->isValid($value)) {
|
|
|
+ // válido
|
|
|
+} else {
|
|
|
+ // no válido
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Validación operando en valores filtrados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element::isValid()</code> siempre filtra los
|
|
|
+ valores antes de la validación a través de la cadena de filtros.
|
|
|
+ Vea <link linkend="zend.form.elements.filters">la sección de
|
|
|
+ filtros</link> para más información.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Contexto de validación</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element::isValid()</code> soporta un argumento
|
|
|
+ adicional, <code>$context</code>.
|
|
|
+ <code>Zend_Form::isValid()</code> pasa todo el conjunto de datos
|
|
|
+ procesados a <code>$context</code> cuando valida un formulario,
|
|
|
+ y <code>Zend_Form_Element::isValid()</code>, a su vez, lo pasa a
|
|
|
+ cada validador. Esto significa que puede escribir validadores
|
|
|
+ que son conscientes de los datos pasados a otros elementos del
|
|
|
+ formulario. Como ejemplo, considere un formulario de registro
|
|
|
+ estándar que tiene campos para la contraseña y la confirmación
|
|
|
+ de la contraseña; una validación sería que los dos campos
|
|
|
+ coincidan. Este validador puede tener un aspecto como el
|
|
|
+ siguiente:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_Validate_PasswordConfirmation extends Zend_Validate_Abstract
|
|
|
+{
|
|
|
+ const NOT_MATCH = 'notMatch';
|
|
|
+
|
|
|
+ protected $_messageTemplates = array(
|
|
|
+ self::NOT_MATCH => 'Password confirmation does not match'
|
|
|
+ );
|
|
|
+
|
|
|
+ public function isValid($value, $context = null)
|
|
|
+ {
|
|
|
+ $value = (string) $value;
|
|
|
+ $this->_setValue($value);
|
|
|
+
|
|
|
+ if (is_array($context)) {
|
|
|
+ if (isset($context['password_confirm'])
|
|
|
+ && ($value == $context['password_confirm']))
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ } elseif (is_string($context) && ($value == $context)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->_error(self::NOT_MATCH);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los validadores son procesados en orden. Cada validador es
|
|
|
+ procesado, a menos que un validador creado con un valor true para
|
|
|
+ <code>breakChainOnFailure</code> falle su validación. Asegúrese de
|
|
|
+ especificar sus validadores en un orden razonable.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Después de una validación fallida, puede recuperar los códigos y
|
|
|
+ mensajes de error de la cadena del validador:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$errors = $element->getErrors();
|
|
|
+$messages = $element->getMessages();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ (Nota: los mensajes de error retornados son un array asociativo de
|
|
|
+ pares código / mensaje de error.)
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En adición a los validadores, puede especificar que un elemento es
|
|
|
+ necesario, usando <code>setRequired(true)</code>. Por defecto, esta
|
|
|
+ bandera es false, lo que significa que pasará su cadena de
|
|
|
+ validadores si ningún valor es pasado a <code>isValid()</code>.
|
|
|
+ Puede modificar este comportamiento en un número de maneras:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Por defecto, cuando un elemento es requerido, una bandera,
|
|
|
+ 'allowEmpty', también es true. Esto quiere decir que si un
|
|
|
+ valor empty es evaluado pasándolo a <code>isValid()</code>,
|
|
|
+ los validadores serán saltados. Puede intercalar esta
|
|
|
+ bandera usando el método de acceso
|
|
|
+ <code>setAllowEmpty($flag)</code>; cuando la bandera es
|
|
|
+ false, si un valor es pasado, los validadores seguirán
|
|
|
+ ejecutándose.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Por defecto, si un elemento es requerido, pero no contiene
|
|
|
+ un validador 'NotEmpty', <code>isValid()</code> añadirá uno
|
|
|
+ en la cima de la pila, con la bandera
|
|
|
+ <code>breakChainOnFailure</code> establecido. Esto hace que
|
|
|
+ la bandera requerida tenga un significado semántico: si
|
|
|
+ ningún valor es pasado, inmediatamente invalidamos el envío
|
|
|
+ y se le notifica al usuario, e impedimos que otros
|
|
|
+ validadores se ejecuten en lo que ya sabemos son datos
|
|
|
+ inválidos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si no quiere este comportamiento, puede desactivarlo pasando
|
|
|
+ un valor false a
|
|
|
+ <code>setAutoInsertNotEmptyValidator($flag)</code>; esto
|
|
|
+ prevendrá a <code>isValid()</code> de colocar un validador
|
|
|
+ 'NotEmpty' en la cadena de validaciones.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para mayor información sobre validadores, vea la <link linkend="zend.validate.introduction">documentación de
|
|
|
+ Zend_Validate</link>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Usando Zend_Form_Elements como validador de propósito general</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element</code> implementa
|
|
|
+ <code>Zend_Validate_Interface</code>, significando un elemento
|
|
|
+ puede también usarse como un validador en otro, cadenas de
|
|
|
+ validación no relacionadas al formulario.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Métodos asociados con validación incluyen:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>setRequired($flag)</code> y
|
|
|
+ <code>isRequired()</code> permiten establecer y recuperar el
|
|
|
+ estado de la bandera 'required'. Cuando se le asigna un
|
|
|
+ booleano <code>true</code>, esta bandera requiere que el
|
|
|
+ elemento esté presente en la información procesada por
|
|
|
+ <code>Zend_Form</code>.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setAllowEmpty($flag)</code> y
|
|
|
+ <code>getAllowEmpty()</code> permiten modificar el
|
|
|
+ comportamiento de elementos opcionales (p.e., elementos
|
|
|
+ donde la bandera required es false). Cuando la bandera
|
|
|
+ 'allow empty' es true, valores vacíos no pasarán la cadena
|
|
|
+ de validadores.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setAutoInsertNotEmptyValidator($flag)</code> permite
|
|
|
+ especificar si realmente un validador 'NotEmpty' será
|
|
|
+ añadido el inicio de la cadena de validaciones cuando un
|
|
|
+ elemento es requerido. Por defecto, esta bandera es true.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addValidator($nameOrValidator, $breakChainOnFailure = false, array $options = null)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addValidators(array $validators)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setValidators(array $validators)</code> (sobreescribe todos los validadores)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getValidator($name)</code> (recupera un objeto validador por nombre)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getValidators()</code> (recupera todos los validadores)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>removeValidator($name)</code> (elimina un validador por nombre)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>clearValidators()</code> (elimina todos los validadores)
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <sect3 id="zend.form.elements.validators.errors">
|
|
|
+ <title>Errores de mensaje personalizados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Alguna veces, querrá especificar uno o más mensajes de error para
|
|
|
+ usarlos en lugar de los mensajes de error generados por los
|
|
|
+ validadores adjuntos a los elementos. Adicionalmente, algunas
|
|
|
+ veces usted mismo querrá marcar al elemento como inválido. A
|
|
|
+ partir de 1.6.0, esta funcionalidad es posible vía los
|
|
|
+ siguientes métodos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>addErrorMessage($message)</code>: añade un mensaje de
|
|
|
+ error para mostrarlos en forma de errores de validación. Puede
|
|
|
+ llamarlo más de una vez, y los nuevos mensajes nuevos son
|
|
|
+ añadidos a la pila.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addErrorMessages(array $messages)</code>: añade
|
|
|
+ múltiples mensajes de error para mostrarlos en forma de errores de
|
|
|
+ validación.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setErrorMessages(array $messages)</code>: añade
|
|
|
+ múltiples mensajes de error para mostrarlos en forma de errores de
|
|
|
+ validación, sobreescribiendo todos los mensajes de error
|
|
|
+ previamente establecidos.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getErrorMessages()</code>: recupera la lista de
|
|
|
+ mensajes de error personalizados que fueron definidos.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>clearErrorMessages()</code>: remueve todos los
|
|
|
+ mensajes de error personalizados que hayan sido definidos.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>markAsError()</code>: marca al elemento como que falló
|
|
|
+ la validación.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>hasErrors()</code>: determina si el elemento ha
|
|
|
+ fallado la validación o ha sido marcado como inválido.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addError($message)</code>: añade un mensaje a la pila
|
|
|
+ de mensaje de error personalizados y marca al elemento como
|
|
|
+ inválido.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addErrors(array $messages)</code>: añade varios
|
|
|
+ mensajes a la pila de mensajes de error personalizados y
|
|
|
+ marca al elemento como inválido.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setErrors(array $messages)</code>: sobreescribe el
|
|
|
+ mensaje de error personalizado en la pila con los mensajes
|
|
|
+ previstos y marca al elemento como inválido.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todos los errores establecidos de este modo pueden ser
|
|
|
+ traducidos. Adicionalmente, puede insertar el marcador "%value%"
|
|
|
+ para representar el valor del elemento; este valor actual del
|
|
|
+ elemento será sustituido cuando el mensaje de error sea
|
|
|
+ recuperado.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.elements.decorators">
|
|
|
+ <title>Decoradores</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Una dolencia particular para muchos desarrolladores web es la creación
|
|
|
+ del XHTML para formularios por ellos mismos. Para cada elemento, el
|
|
|
+ desarrollador necesita crear la marcación para el elemento mismo,
|
|
|
+ comúnmente una etiqueta (label), y, si son amables con sus usuarios,
|
|
|
+ la marcación para mostrar mensajes de errores de validación. Cuanto
|
|
|
+ más elementos en una página, menos trivial se convierte esta tarea.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element</code> intenta resolver este problema mediante
|
|
|
+ el uso de "decoradores". Los decoradores son clases simples que tienen
|
|
|
+ métodos de acceso al elemento y métodos para generar el contenido. Para
|
|
|
+ obtener mayor información sobre cómo trabajan los decoradores, consulte
|
|
|
+ por favor la sección sobre
|
|
|
+ <link linkend="zend.form.decorators">Zend_Form_Decorator</link>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los decoradores usados por defecto por
|
|
|
+ <code>Zend_Form_Element</code> son:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>ViewHelper</emphasis>: especifica un view helper que
|
|
|
+ usar para general el elemento. El atributo 'helper' del elemento
|
|
|
+ puede usarse para especificar qué auxiliar vista usar. Por
|
|
|
+ defecto, <code>Zend_Form_Element</code> especifica el auxiliar
|
|
|
+ vista 'formText', pero cada subclase especifica diferentes
|
|
|
+ auxiliares.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>Errors</emphasis>: añade mensajes de error al elemento
|
|
|
+ usando <code>Zend_View_Helper_FormErrors</code>. Si no está
|
|
|
+ presente, no se añade nada.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>Description</emphasis>: añade la descripción del
|
|
|
+ elemento. Si no está presente, no se añade nada. Por defecto, la
|
|
|
+ descripción es generada dentro de una etiqueta <p> con un
|
|
|
+ class 'description'.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>HtmlTag</emphasis>: envuelve el elemento y los errores
|
|
|
+ en una etiqueta HTML <dd>.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>Label</emphasis>: añade al comienzo una etiqueta al
|
|
|
+ elemento usando <code>Zend_View_Helper_FormLabel</code>, y
|
|
|
+ envolviéndola en una etiqueta <dt>. Si ninguna etiqueta es
|
|
|
+ provista, solo la etiqueta de la definición es generada.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Decoradores por defecto no necesitan ser cargados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, los decoradores por defecto son cargados durante la
|
|
|
+ inicialización del objeto. Puede deshabilitar esto pasando la
|
|
|
+ opción 'disableLoadDefaultDecorators' al constructor:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element = new Zend_Form_Element('foo',
|
|
|
+ array('disableLoadDefaultDecorators' =>
|
|
|
+ true)
|
|
|
+ );
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esta opción puede ser combinada junto con cualquier otra opción que
|
|
|
+ pase, ya sea como un array de opciones o en un objeto
|
|
|
+ <code>Zend_Config</code>.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Ya que el orden en el cual los decoradores son registrados importa
|
|
|
+ -- el primer decorador registrado es ejecutado primero -- necesitará
|
|
|
+ estar seguro de registrar sus decoradores en el orden apropiado, o
|
|
|
+ asegurarse de que estableció las opciones de colocación en el modo apropiado. Por
|
|
|
+ dar un ejemplo, aquí esta el código que registran los decoradores
|
|
|
+ por defecto:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$this->addDecorators(array(
|
|
|
+ array('ViewHelper'),
|
|
|
+ array('Errors'),
|
|
|
+ array('Description', array('tag' => 'p', 'class' => 'description')),
|
|
|
+ array('HtmlTag', array('tag' => 'dd')),
|
|
|
+ array('Label', array('tag' => 'dt')),
|
|
|
+));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El contenido inicial es creado por el decorador 'ViewHelper', que
|
|
|
+ crea el propio elemento. En seguida, el decorador 'Errors' consulta
|
|
|
+ los mensajes de error del elemento, y, si hay alguno presente, los
|
|
|
+ pasa al auxiliar vista 'FormErrors' para mostrarlos. Si una
|
|
|
+ descripción está presente, el decorador 'Description' añadirá
|
|
|
+ un párrafo con class 'description' conteniendo el texto descriptivo
|
|
|
+ para el contenido agregado. El siguiente decorador, 'HtmlTag',
|
|
|
+ envuelve al elemento, los errores, y la descripción en una etiqueta
|
|
|
+ HTML <dd>. Finalmente, el último decorador, 'label', recupera
|
|
|
+ la etiqueta del elemento y la pasa al auxiliar vista 'FormLabel',
|
|
|
+ envolviéndolo en una etiqueta <dt>; por default el valor es
|
|
|
+ añadido al inicio del contenido. El resultado de la salida
|
|
|
+ básicamente se ve así:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="html"><![CDATA[
|
|
|
+<dt><label for="foo" class="optional">Foo</label></dt>
|
|
|
+<dd>
|
|
|
+ <input type="text" name="foo" id="foo" value="123" />
|
|
|
+ <ul class="errors">
|
|
|
+ <li>"123" is not an alphanumeric value</li>
|
|
|
+ </ul>
|
|
|
+ <p class="description">
|
|
|
+ This is some descriptive text regarding the element.
|
|
|
+ </p>
|
|
|
+</dd>
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para más información sobre decoradores, lea la <link linkend="zend.form.decorators"> sección de Zend_Form_Decorator</link>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Usando múltiples decoradores al mismo tiempo</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Internamente, <code>Zend_Form_Element</code> utiliza una clase
|
|
|
+ decorador como mecanismo de búsqueda para la recuperación de
|
|
|
+ decoradores. Como resultado, no puede registrar múltiples
|
|
|
+ decoradores del mismo tipo; decoradores subsecuentes
|
|
|
+ simplemente sobreescribirán aquellos que ya existían.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para evitar esto, puede usar <emphasis>alias</emphasis>. En
|
|
|
+ lugar de pasar un decorador o nombre de decorador como primer
|
|
|
+ argumento a <code>addDecorator()</code>, pase una matriz con un
|
|
|
+ solo elemento, con el alias apuntando al nombre o objeto
|
|
|
+ decorador:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Alias a 'FooBar':
|
|
|
+$element->addDecorator(array('FooBar' => 'HtmlTag'),
|
|
|
+ array('tag' => 'div'));
|
|
|
+
|
|
|
+// Y recuperandolo posteriormente:
|
|
|
+$decorator = $element->getDecorator('FooBar');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En los métodos <code>addDecorators()</code> y
|
|
|
+ <code>setDecorators()</code>, necesitará pasar la opción
|
|
|
+ 'decorator' en la matriz representando el decorador:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Y dos decoradores 'HtmlTag', 'FooBar' como alias:
|
|
|
+$element->addDecorators(
|
|
|
+ array('HtmlTag', array('tag' => 'div')),
|
|
|
+ array(
|
|
|
+ 'decorator' => array('FooBar' => 'HtmlTag'),
|
|
|
+ 'options' => array('tag' => 'dd')
|
|
|
+ ),
|
|
|
+);
|
|
|
+
|
|
|
+// Y recuperándolos posteriormente:
|
|
|
+$htmlTag = $element->getDecorator('HtmlTag');
|
|
|
+$fooBar = $element->getDecorator('FooBar');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Métodos asociados con decoradores incluyen:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>addDecorator($nameOrDecorator, array $options = null)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addDecorators(array $decorators)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setDecorators(array $decorators)</code> (sobreescribe
|
|
|
+ todos los decoradores)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getDecorator($name)</code> (recupera un objeto decorador
|
|
|
+ por su nombre)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getDecorators()</code> (recupera todos los decoradores)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>removeDecorator($name)</code> (elimina un decorador por su
|
|
|
+ nombre)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>clearDecorators()</code> (elimina todos los decoradores)
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element</code> también utiliza la sobrecarga para
|
|
|
+ permitir generar decoradores específicos. <code>__call()</code>
|
|
|
+ interceptará métodos que comiencen con el texto 'render' y utilizará
|
|
|
+ el resto del nombre del método para buscar un decorador; si se
|
|
|
+ encuentra, entonces será generado <emphasis>sólo ese</emphasis>
|
|
|
+ decorador. Cualquier argumento pasado al llamado del método será
|
|
|
+ usado como contenido para pasar al método <code>render()</code> del
|
|
|
+ decorador. Como ejemplo:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Genera solo el decorador ViewHelper:
|
|
|
+echo $element->renderViewHelper();
|
|
|
+
|
|
|
+// Genera solo el decorador HtmlTag, pasándole contenido:
|
|
|
+echo $element->renderHtmlTag("This is the html tag content");
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si el decorador no existe, una excepción es lanzada.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.elements.metadata">
|
|
|
+ <title>Metadatos y atributos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element</code> manipula una variedad de atributos y
|
|
|
+ medatados del elemento. Atributos básicos incluyen:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>name</emphasis>: el nombre del elemento. Emplea los
|
|
|
+ métodos de acceso <code>setName()</code> y <code>getName()</code>.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>label</emphasis>: la etiqueta del elemento. Emplea los
|
|
|
+ métodos de acceso <code>setLabel()</code> y <code>getLabel()</code>.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>order</emphasis>: el índice en el cual los elementos
|
|
|
+ deben ir mostrándose en el formulario. Emplea los métodos de
|
|
|
+ acceso <code>setOrder()</code> y <code>getOrder()</code>.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>value</emphasis>: El valor del elemento actual. Emplea
|
|
|
+ los métodos de acceso <code>setValue()</code> y
|
|
|
+ <code>getValue()</code>.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>description</emphasis>: una descripción del elemento;
|
|
|
+ a menudo utilizada para proveer un tooltip o ayuda contextual
|
|
|
+ con javascript describiendo el propósito del elemento. Emplea
|
|
|
+ los métodos de acceso <code>setDescription()</code> y
|
|
|
+ <code>getDescription()</code>.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>required</emphasis>: bandera que indica si un elemento
|
|
|
+ es requerido o no cuando se efectúa la validación del
|
|
|
+ formulario. Emplea los métodos de acceso
|
|
|
+ <code>setRequired()</code> y <code>getRequired()</code>. Esta
|
|
|
+ bandera es false por defecto.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>allowEmpty</emphasis>: bandera indicando si un
|
|
|
+ elemento no-requerido (opcional) debe intentar validar o no
|
|
|
+ valores vacíos. Cuando es true, y la bandera required es false,
|
|
|
+ valores vacíos no pasarán la cadena de validación, y se supone
|
|
|
+ verdadero. Emplea los métodos de acceso
|
|
|
+ <code>setAllowEmpty()</code> y <code>getAllowEmpty()</code>.
|
|
|
+ Esta bandera es true por defecto.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>autoInsertNotEmptyValidator</emphasis>: bandera
|
|
|
+ indicando insertar o no un validador 'NotEmpty' cuando un
|
|
|
+ elemento es requerido. Por defecto, esta bandera es true.
|
|
|
+ Establezca la bandera con
|
|
|
+ <code>setAutoInsertNotEmptyValidator($flag)</code> y determine
|
|
|
+ el valor con <code>autoInsertNotEmptyValidator()</code>.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los elementos del formulario pueden requerir metainformación
|
|
|
+ adicional. Para elementos XHTML del formuladio, por ejemplo, puede
|
|
|
+ querer especificar atributos como el class o id. Para facilitar esto
|
|
|
+ hay un conjunto de métodos de acceso:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>setAttrib($name, $value)</emphasis>: añade un atributo
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>setAttribs(array $attribs)</emphasis>: como
|
|
|
+ addAttribs(), pero sobreescribiendo
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>getAttrib($name)</emphasis>: recupera el valor de solo
|
|
|
+ un atributo
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>getAttribs()</emphasis>: recupera todos los atributos
|
|
|
+ como pares clave/valor
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La mayoría de las veces, como sea, puede simplemente acceder a ellos
|
|
|
+ como propiedades de objeto, ya que <code>Zend_Form_Element</code>
|
|
|
+ utiliza la sobrecarga para facilitar el acceso a ellos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Equivalente a $element->setAttrib('class', 'text'):
|
|
|
+$element->class = 'text;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, todos los atributos son pasados al auxiliar vista usado
|
|
|
+ por el elemento durante la generación, y generados como atributos de
|
|
|
+ la etiqueta del elemento.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.elements.standard">
|
|
|
+ <title>Elementos Estándar</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form</code> contiene un buen número de elementos
|
|
|
+ estándar; por favor lea el capítulo <link linkend="zend.form.standarElements">Elementos Estándar</link> para
|
|
|
+ todos los detalles.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.elements.methods">
|
|
|
+ <title>Métodos de Zend_Form_Element</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element</code> tiene muchos, muchos métodos. Lo que
|
|
|
+ sigue es un sumario de sus funciones, agrupados por tipo:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>Configuración:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setOptions(array $options)</code></para></listitem>
|
|
|
+ <listitem><para><code>setConfig(Zend_Config $config)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>I18n:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setTranslator(Zend_Translate_Adapter $translator = null)</code></para></listitem>
|
|
|
+ <listitem><para><code>getTranslator()</code></para></listitem>
|
|
|
+ <listitem><para><code>setDisableTranslator($flag)</code></para></listitem>
|
|
|
+ <listitem><para><code>translatorIsDisabled()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Propiedades:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setName($name)</code></para></listitem>
|
|
|
+ <listitem><para><code>getName()</code></para></listitem>
|
|
|
+ <listitem><para><code>setValue($value)</code></para></listitem>
|
|
|
+ <listitem><para><code>getValue()</code></para></listitem>
|
|
|
+ <listitem><para><code>getUnfilteredValue()</code></para></listitem>
|
|
|
+ <listitem><para><code>setLabel($label)</code></para></listitem>
|
|
|
+ <listitem><para><code>getLabel()</code></para></listitem>
|
|
|
+ <listitem><para><code>setDescription($description)</code></para></listitem>
|
|
|
+ <listitem><para><code>getDescription()</code></para></listitem>
|
|
|
+ <listitem><para><code>setOrder($order)</code></para></listitem>
|
|
|
+ <listitem><para><code>getOrder()</code></para></listitem>
|
|
|
+ <listitem><para><code>setRequired($flag)</code></para></listitem>
|
|
|
+ <listitem><para><code>getRequired()</code></para></listitem>
|
|
|
+ <listitem><para><code>setAllowEmpty($flag)</code></para></listitem>
|
|
|
+ <listitem><para><code>getAllowEmpty()</code></para></listitem>
|
|
|
+ <listitem><para><code>setAutoInsertNotEmptyValidator($flag)</code></para></listitem>
|
|
|
+ <listitem><para><code>autoInsertNotEmptyValidator()</code></para></listitem>
|
|
|
+ <listitem><para><code>setIgnore($flag)</code></para></listitem>
|
|
|
+ <listitem><para><code>getIgnore()</code></para></listitem>
|
|
|
+ <listitem><para><code>getType()</code></para></listitem>
|
|
|
+ <listitem><para><code>setAttrib($name, $value)</code></para></listitem>
|
|
|
+ <listitem><para><code>setAttribs(array $attribs)</code></para></listitem>
|
|
|
+ <listitem><para><code>getAttrib($name)</code></para></listitem>
|
|
|
+ <listitem><para><code>getAttribs()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Cargadores y rutas de plugin:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type)</code></para></listitem>
|
|
|
+ <listitem><para><code>getPluginLoader($type)</code></para></listitem>
|
|
|
+ <listitem><para><code>addPrefixPath($prefix, $path, $type = null)</code></para></listitem>
|
|
|
+ <listitem><para><code>addPrefixPaths(array $spec)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Validación:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>addValidator($validator, $breakChainOnFailure = false, $options = array())</code></para></listitem>
|
|
|
+ <listitem><para><code>addValidators(array $validators)</code></para></listitem>
|
|
|
+ <listitem><para><code>setValidators(array $validators)</code></para></listitem>
|
|
|
+ <listitem><para><code>getValidator($name)</code></para></listitem>
|
|
|
+ <listitem><para><code>getValidators()</code></para></listitem>
|
|
|
+ <listitem><para><code>removeValidator($name)</code></para></listitem>
|
|
|
+ <listitem><para><code>clearValidators()</code></para></listitem>
|
|
|
+ <listitem><para><code>isValid($value, $context = null)</code></para></listitem>
|
|
|
+ <listitem><para><code>getErrors()</code></para></listitem>
|
|
|
+ <listitem><para><code>getMessages()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Filtros:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>addFilter($filter, $options = array())</code></para></listitem>
|
|
|
+ <listitem><para><code>addFilters(array $filters)</code></para></listitem>
|
|
|
+ <listitem><para><code>setFilters(array $filters)</code></para></listitem>
|
|
|
+ <listitem><para><code>getFilter($name)</code></para></listitem>
|
|
|
+ <listitem><para><code>getFilters()</code></para></listitem>
|
|
|
+ <listitem><para><code>removeFilter($name)</code></para></listitem>
|
|
|
+ <listitem><para><code>clearFilters()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Generación:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setView(Zend_View_Interface $view = null)</code></para></listitem>
|
|
|
+ <listitem><para><code>getView()</code></para></listitem>
|
|
|
+ <listitem><para><code>addDecorator($decorator, $options = null)</code></para></listitem>
|
|
|
+ <listitem><para><code>addDecorators(array $decorators)</code></para></listitem>
|
|
|
+ <listitem><para><code>setDecorators(array $decorators)</code></para></listitem>
|
|
|
+ <listitem><para><code>getDecorator($name)</code></para></listitem>
|
|
|
+ <listitem><para><code>getDecorators()</code></para></listitem>
|
|
|
+ <listitem><para><code>removeDecorator($name)</code></para></listitem>
|
|
|
+ <listitem><para><code>clearDecorators()</code></para></listitem>
|
|
|
+ <listitem><para><code>render(Zend_View_Interface $view = null)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.elements.config">
|
|
|
+ <title>Configuración</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El constructor de <code>Zend_Form_Element</code> acepta tanto una
|
|
|
+ matriz de opciones como un objeto <code>Zend_Config</code>
|
|
|
+ conteniendo opciones, y esto puede configurarse usando
|
|
|
+ <code>setOptions()</code> o <code>setConfig()</code>. Hablando de
|
|
|
+ manera general, las claves son nombradas de la siguiente manera:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ Si 'set' + clave se refiere a un método de
|
|
|
+ <code>Zend_Form_Element</code>, entonces el valor provisto será
|
|
|
+ pasado a el método.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ De otra manera, el valor será usado para establecer un atributo.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Excepciones a la regla incluyen las siguientes:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>prefixPath</code> será pasado a
|
|
|
+ <code>addPrefixPaths()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ Los siguientes setters no pueden establecerse de esta manera:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>setAttrib</code> (aunque
|
|
|
+ <code>setAttribs</code> <emphasis>funcionará</emphasis>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setConfig</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setOptions</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setPluginLoader</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setTranslator</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setView</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como ejemplo, aquí esta un archivo de configuración pasado para
|
|
|
+ cada tipo de dato configurable:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="ini"><![CDATA[
|
|
|
+[element]
|
|
|
+name = "foo"
|
|
|
+value = "foobar"
|
|
|
+label = "Foo:"
|
|
|
+order = 10
|
|
|
+required = true
|
|
|
+allowEmpty = false
|
|
|
+autoInsertNotEmptyValidator = true
|
|
|
+description = "Foo elements are for examples"
|
|
|
+ignore = false
|
|
|
+attribs.id = "foo"
|
|
|
+attribs.class = "element"
|
|
|
+; sets 'onclick' attribute
|
|
|
+onclick = "autoComplete(this, '/form/autocomplete/element')"
|
|
|
+prefixPaths.decorator.prefix = "My_Decorator"
|
|
|
+prefixPaths.decorator.path = "My/Decorator/"
|
|
|
+disableTranslator = 0
|
|
|
+validators.required.validator = "NotEmpty"
|
|
|
+validators.required.breakChainOnFailure = true
|
|
|
+validators.alpha.validator = "alpha"
|
|
|
+validators.regex.validator = "regex"
|
|
|
+validators.regex.options.pattern = "/^[A-F].*/$"
|
|
|
+filters.ucase.filter = "StringToUpper"
|
|
|
+decorators.element.decorator = "ViewHelper"
|
|
|
+decorators.element.options.helper = "FormText"
|
|
|
+decorators.label.decorator = "Label"
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.elements.custom">
|
|
|
+ <title>Elementos personalizados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Usted puede crear sus propios elementos personalizados simplemente
|
|
|
+ extendiendo la clase <code>Zend_Form_Element</code>. Las razones
|
|
|
+ comunes para hacer esto incluyen:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ Elementos que comparten validadores y/o filtros comunes
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Elementos que tienen decoradores con funcionalidad personalizada
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Hay dos métodos típicamente usados para extender un elemento:
|
|
|
+ <code>init()</code>, el cual puede usarse para añadir una lógica de
|
|
|
+ inicialización personalizada a su elemento, y
|
|
|
+ <code>loadDefaultDecorators()</code>, el cual puede usarse para
|
|
|
+ establecer una lista de decoradores usados por su elemento de manera
|
|
|
+ predeterminada.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como un ejemplo, digamos que todos los elementos de tipo texto en un
|
|
|
+ formulario que está creando, necesitan ser filtrados con
|
|
|
+ <code>StringTrim</code>, validados con una expresión regular, y que
|
|
|
+ quiere usar un decorador personalizado que ha creado para
|
|
|
+ mostrarlos, 'My_Decorator_TextItem'; adicionalmente, tiene un número
|
|
|
+ de atributos estándars, incluyendo 'size', 'maxLength', y 'class'
|
|
|
+ que quisiera especificar. Puede definir un elemento tal como sigue:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_Element_Text extends Zend_Form_Element
|
|
|
+{
|
|
|
+ public function init()
|
|
|
+ {
|
|
|
+ $this->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator')
|
|
|
+ ->addFilters('StringTrim')
|
|
|
+ ->addValidator('Regex', false, array('/^[a-z0-9]{6,}$/i'))
|
|
|
+ ->addDecorator('TextItem')
|
|
|
+ ->setAttrib('size', 30)
|
|
|
+ ->setAttrib('maxLength', 45)
|
|
|
+ ->setAttrib('class', 'text');
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Entonces puede informar a su objeto formulario acerca del prefijo de
|
|
|
+ ruta para elementos de ese tipo, y comenzar creando elementos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->addPrefixPath('My_Element', 'My/Element/', 'element')
|
|
|
+ ->addElement('foo', 'text');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El elemento 'foo' será ahora del tipo <code>My_Element_Text</code>,
|
|
|
+ y mostrará el comportamiento que ha especificado.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Otro método que puede querer sobreescribir cuando extienda
|
|
|
+ <code>Zend_Form_Element</code> es el método
|
|
|
+ <code>loadDefaultDecorators()</code>. Este método carga
|
|
|
+ condicionalmente un grupo de decoradores predefinidos para su
|
|
|
+ elemento; puede querer sustituir su propio decorador en su clase
|
|
|
+ extendida:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_Element_Text extends Zend_Form_Element
|
|
|
+{
|
|
|
+ public function loadDefaultDecorators()
|
|
|
+ {
|
|
|
+ $this->addDecorator('ViewHelper')
|
|
|
+ ->addDecorator('DisplayError')
|
|
|
+ ->addDecorator('Label')
|
|
|
+ ->addDecorator('HtmlTag',
|
|
|
+ array('tag' => 'div', 'class' => 'element'));
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Hay muchas maneras de personalizar elementos; asegúrese de leer la
|
|
|
+ documentación de la API de <code>Zend_Form_Element</code> para
|
|
|
+ conocer todos los métodos disponibles.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 tw=80 ai et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.form.forms" xml:base="module_specs/Zend_Form-Forms.xml">
|
|
|
+ <title>Creando formularios usando Zend_Form</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La clase <code>Zend_Form</code> es usada para agregar elementos de
|
|
|
+ formulario, desplegar grupos y subformularios. Éstos pueden ejecutar las
|
|
|
+ siguientes acciones en estos elementos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ Validación, incluyendo la recuperación de código y mensajes de error
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Agregación de valor, incluyendo el llenado de elementos y recuperación
|
|
|
+ de valores tanto filtrados como no filtrados para todos los elementos
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Iteración sobre todos los elementos, en el orden en el cual han sido
|
|
|
+ introducidos o basados en el orden recuperado de cada elemento
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Generando el formulario entero, ya sea por un simple decorador que
|
|
|
+ ejecuta un muestreo personalizado o por iteración sobre cada
|
|
|
+ elemento del formulario
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Mientras los formularios creados con <code>Zend_Form</code> pueden ser
|
|
|
+ complejos, probablemente su mejor uso es para formularios simples; es
|
|
|
+ mejor utilizarlo para desarrollar aplicaciones rápidas y de prototipado.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En lo más básico, simplemente instancie el objeto formulario:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Objeto form genérico:
|
|
|
+$form = new Zend_Form();
|
|
|
+
|
|
|
+// Objeto form personalizado:
|
|
|
+$form = new My_Form()
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Opcionalmente puede pasarlo en la configuración, la cual será usada para
|
|
|
+ establecer el estado del objeto, potencialmente así como también crear
|
|
|
+ nuevos elementos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Pasando opciones en la configuración:
|
|
|
+$form = new Zend_Form($config);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form</code> es iterable, e iterará sobre elementos, grupos que
|
|
|
+ mostrar y subformularios, usando el orden en el cual han sido registrados
|
|
|
+ y en cualquier índice de orden que cada uno pueda tener. Esto es útil
|
|
|
+ en casos donde desee generar los elementos manualmente en el orden apropiado.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La magia de <code>Zend_Form</code> radica en la habilidad para servir como
|
|
|
+ fábrica para elementos y grupos, así como también la habilidad de generarse
|
|
|
+ a sí mismo a través de decoradores.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.forms.plugins">
|
|
|
+ <title>Cargadores de Plugin</title>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form</code> hace uso de
|
|
|
+ <code>Zend_Loader_PluginLoader</code> para permitir a los
|
|
|
+ desarroladores especificar la ubicación de elementos y decoradores
|
|
|
+ alternativos. Cada uno tiene su propio plugin loader asociado, y
|
|
|
+ métodos de acceso genéricos son usados para recuperar y modificar
|
|
|
+ cada uno.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los siguientes tipos de cargadores son usados con los variados métodos
|
|
|
+ del plugin loader: 'element' y 'decorator'. Los nombres de los tipos
|
|
|
+ no distinguen mayúsculas de minúsculas.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los métodos usados para interactuar con plugin loaders son los siguientes:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>setPluginLoader($loader, $type)</code>: $loader es el propio
|
|
|
+ objeto plugin loader, mientras $type es uno de los tipos
|
|
|
+ especificados arriba. Esto establece el plugin loader para el
|
|
|
+ tipo dado al objeto loader recién especificado.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getPluginLoader($type)</code>: recupera el plugin loader
|
|
|
+ asociado con $type.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addPrefixPath($prefix, $path, $type = null)</code>: agrega
|
|
|
+ una asociación prefijo/ruta al loader especificado por $type. Si
|
|
|
+ $type es nulo, intentará añadir una ruta a todos los loaders,
|
|
|
+ añadiendo el prefijo "_Element" y "_Decorator"; y añadiendo la
|
|
|
+ ruta con "Element/" y "Decorator/". Si tiene todas sus clases
|
|
|
+ form element extras bajo una jerarquía común, éste es un método
|
|
|
+ coveniente para establecer el prefijo de base para ellas.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addPrefixPaths(array $spec)</code>: le permite añadir varias
|
|
|
+ rutas en uno o mas plugin loaders. Se espera que cada elemento
|
|
|
+ del array sea un array con las claves 'path', 'prefix' y 'type'.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Adicionalmente, puede especificar prefijos de rutas para todos los
|
|
|
+ elementos y mostrar grupos creados a través de una instancia de
|
|
|
+ <code>Zend_Form</code> usando los siguientes métodos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>addElementPrefixPath($prefix, $path, $type = null)</code>:
|
|
|
+ Igual que <code>addPrefixPath()</code>, debe especificar un
|
|
|
+ prefijo y ruta de clase. <code>$type</code>, cuando se especifica,
|
|
|
+ tiene que ser uno de los tipos plugin loader especificados por
|
|
|
+ <code>Zend_Form_Element</code>; vea la <link linkend="zend.form.elements.loaders">sección elemento plugins
|
|
|
+ </link> para más información de valores válidos para
|
|
|
+ <code>$type</code>. Si <code>$type</code> no es especificado, el
|
|
|
+ método asumirá que es un prefijo general para todos los tipos.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addDisplayGroupPrefixPath($prefix, $path)</code>:
|
|
|
+ Igual que <code>addPrefixPath()</code>, debe especificar un
|
|
|
+ prefijo y ruta de clase; sin embargo, dado que los grupos de visualización (display groups)
|
|
|
+ sólo soportan decoradores como plugins, <code>$type</code> no es
|
|
|
+ necesario.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Elementos y decoradores personalizados son una manera fácil de compartir
|
|
|
+ funcionalidad entre formularios y encapsular funcionalidad personalizada.
|
|
|
+ Vea el <link linkend="zend.form.elements.loaders.customLabel">ejemplo de Etiqueta
|
|
|
+ Personalizada</link> en la documentación de elementos para un
|
|
|
+ ejemplo de cómo elementos personalizados pueden ser usados como
|
|
|
+ reemplazos para clases estándar.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.forms.elements">
|
|
|
+ <title>Elementos</title>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form</code> proporciona varios métodos de acceso para añadir
|
|
|
+ y eliminar elementos de el formulario. Éstos pueden tomar instancias
|
|
|
+ de objetos de elemento o servir como fábricas para instanciar el
|
|
|
+ objeto elemento a sí mismo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método más básico para añadir un elemento es
|
|
|
+ <code>addElement()</code>. Este método puede tomar también un objeto
|
|
|
+ de tipo <code>Zend_Form_Element</code> (o de una clase extendiendo
|
|
|
+ <code>Zend_Form_Element</code>), o argumentos para construir un nuevo
|
|
|
+ elemento -- incluyendo el elemento tipo, nombre y algunas opciones de
|
|
|
+ configuración.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como algunos ejemplos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Usando un elemento instanciado:
|
|
|
+$element = new Zend_Form_Element_Text('foo');
|
|
|
+$form->addElement($element);
|
|
|
+
|
|
|
+// Usando una fábrica
|
|
|
+//
|
|
|
+// Crea un elemento de tipo Zend_Form_Element_Text con el
|
|
|
+// nombre de 'foo':
|
|
|
+$form->addElement('text', 'foo');
|
|
|
+
|
|
|
+// Pasa una opción etiqueta al elemento:
|
|
|
+$form->addElement('text', 'foo', array('label' => 'Foo:'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>addElement() Implementa una Interfaz Fluida</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>addElement()</code> implementa una interfaz fluida; es
|
|
|
+ decir, retorna el objeto <code>Zend_Form</code> y no un
|
|
|
+ elemento. Esto se ha hecho para permitirle encadenar
|
|
|
+ multiples métodos addElement() u otros métodos formulario que
|
|
|
+ implementen una interfaz fluida (todos los establecedores en Zend_Form
|
|
|
+ implementan el patrón).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si desea retornar el elemento, use
|
|
|
+ <code>createElement()</code>, el cual es esbozado abajo. Tenga en cuenta
|
|
|
+ de cualquier manera que <code>createElement()</code> no adjunta el
|
|
|
+ elemento al formulario.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Internamente, <code>addElement()</code> en realidad emplea
|
|
|
+ <code>createElement()</code> para crear el elemento antes de
|
|
|
+ adjuntarlo al formulario.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Una vez que el elemento ha sido añadido al formulario, puede recuperarlo por
|
|
|
+ el nombre. Puede también finalizar usando el método <code>getElement()</code>
|
|
|
+ o usando sobrecarga para acceder al elemento como una propiedad de
|
|
|
+ objeto:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// getElement():
|
|
|
+$foo = $form->getElement('foo');
|
|
|
+
|
|
|
+// Como propiedad del objeto:
|
|
|
+$foo = $form->foo;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Ocasionalmente, se quiere crear un elemento sin adjuntarlo
|
|
|
+ al formulario (para instanciar, si se desea hacer uso de las
|
|
|
+ rutas de plugin introducidas con el formulario, pero después se desea adjuntar el
|
|
|
+ objeto al subformulario). El método <code>createElement()</code>
|
|
|
+ permite hacer eso:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// $username llega a ser un objeto Zend_Form_Element_Text:
|
|
|
+$username = $form->createElement('text', 'username');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <sect3 id="zend.form.forms.elements.values">
|
|
|
+ <title>Llenar y recuperar valores</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Después de validar el formulario, originalmente se necesitará recuperar los
|
|
|
+ valores para poder ejecutar otras operaciones, tal como actualizar una
|
|
|
+ base de datos o notificar un servicio web. Se pueden recuperar todos los valores
|
|
|
+ para todos los elementos usando <code>getValues()</code>;
|
|
|
+ <code>getValue($name)</code> le permite recuperar un solo
|
|
|
+ valor del elemento por su nombre:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Obtener todos los valores:
|
|
|
+$values = $form->getValues();
|
|
|
+
|
|
|
+// Obtener sólo los valores del elemento 'foo':
|
|
|
+$value = $form->getValue('foo');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A veces se quiere llenar el formulario con valores especificos
|
|
|
+ antes de generarlos. Éstos pueden ser llevados a cabo ya sea con los
|
|
|
+ métodos <code>setDefaults()</code> o <code>populate()</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->setDefaults($data);
|
|
|
+$form->populate($data);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por otro lado, si se quisera limpiar el formulario antes de llenarlo
|
|
|
+ o validarlo; se puede realizar usando el
|
|
|
+ método <code>reset()</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->reset();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.form.forms.elements.global">
|
|
|
+ <title>Operaciones Globales</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Ocasionalemnte se necesitarán ciertas operaciones que afecten a todos
|
|
|
+ los elementos. Escenarios comunes incluyen la necesidad de determinar rutas de acceso
|
|
|
+ al prefijo complemento para todos los elementos, determinando decoradores para todos los elementos y
|
|
|
+ determinando filtros para todos los elementos. Como ejemplos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.form.forms.elements.global.allpaths">
|
|
|
+ <title>Determinando rutas de acceso de prefijos para todos los elementos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Se puede determinar rutas de acceso para prefijos para todos los elementos por tipo,
|
|
|
+ o usando un prefijo global. Como ejemplos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Determinar la ruta de acceso de prefijos global
|
|
|
+// Crear rutas de acceso para los prefijos My_Foo_Filter, My_Foo_Validate,
|
|
|
+// y My_Foo_Decorator
|
|
|
+$form->addElementPrefixPath('My_Foo', 'My/Foo/');
|
|
|
+
|
|
|
+// Sólo rutas de acceso de filtros:
|
|
|
+$form->addElementPrefixPath('My_Foo_Filter',
|
|
|
+ 'My/Foo/Filter',
|
|
|
+ 'filter');
|
|
|
+
|
|
|
+// Sólo rutas de acceso de validadores:
|
|
|
+$form->addElementPrefixPath('My_Foo_Validate',
|
|
|
+ 'My/Foo/Validate',
|
|
|
+ 'validate');
|
|
|
+
|
|
|
+// Sólo rutas de acceso de decoradores:
|
|
|
+$form->addElementPrefixPath('My_Foo_Decorator',
|
|
|
+ 'My/Foo/Decorator',
|
|
|
+ 'decorator');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <example id="zend.form.forms.elements.global.decorators">
|
|
|
+ <title>Determinando Decoradores para todos los elementos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Se pueden determinar decoradores para todos los elementos.
|
|
|
+ <code>setElementDecorators()</code> acepta una matriz de
|
|
|
+ decoradores, solo como <code>setDecorators()</code>, y
|
|
|
+ reescribirá cualquier decorador previamente determinado en cada elemento. En
|
|
|
+ este ejemplo, determinamos los decoradores para simplificar una ViewHelper
|
|
|
+ y una Label:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->setElementDecorators(array(
|
|
|
+ 'ViewHelper',
|
|
|
+ 'Label'
|
|
|
+));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <example id="zend.form.forms.elements.global.decoratorsFilter">
|
|
|
+ <title>Determinando decoradores para algunos elementos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Pueden determinarse también decoradores para un subconjunto de elementos,
|
|
|
+ ya sea por inclusión o exclusión. El segundo argumento
|
|
|
+ <code>setElementDecorators()</code> puede ser un array de
|
|
|
+ nombres de elemento; por defecto, especificar un array de ese tipo
|
|
|
+ determinará los decoradores especificados en esos elementos solamente. Puede
|
|
|
+ tambien pasar un tercer elemento, una bandera indicando si
|
|
|
+ esta lista de elementos es para propósitos de inclusión o exclusión;
|
|
|
+ si es falso, decorará todos los elementos
|
|
|
+ <emphasis>excepto</emphasis> los pasados en la lista,
|
|
|
+ Como uso estándar del método, cualquier decorador pasado
|
|
|
+ reescribirá cualquier decorador previamente determinado en cada
|
|
|
+ elemento.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En el siguiente fragmento, indicamos que queremos los decoradores
|
|
|
+ ViewHelper y Label para los elementos
|
|
|
+ 'foo' y 'bar':
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->setElementDecorators(
|
|
|
+ array(
|
|
|
+ 'ViewHelper',
|
|
|
+ 'Label'
|
|
|
+ ),
|
|
|
+ array(
|
|
|
+ 'foo',
|
|
|
+ 'bar'
|
|
|
+ )
|
|
|
+);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por otro lado, con este fragmento, indicaremos
|
|
|
+ que queremos usar solamente los decoradores
|
|
|
+ ViewHelper y Label para cada elemento <emphasis>excepto</emphasis>
|
|
|
+ los elementos 'foo' y 'bar':
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->setElementDecorators(
|
|
|
+ array(
|
|
|
+ 'ViewHelper',
|
|
|
+ 'Label'
|
|
|
+ ),
|
|
|
+ array(
|
|
|
+ 'foo',
|
|
|
+ 'bar'
|
|
|
+ ),
|
|
|
+ false
|
|
|
+);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Algunos Decoradores son Inapropiados para algunos Elementos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Mientras <code>setElementDecorators()</code> puede parecer
|
|
|
+ una buena solución, existen algunos casos donde puede
|
|
|
+ terminar con resultados inesperados, Por ejemplo,
|
|
|
+ los muchos elementos botones (Submit, Button, Reset),
|
|
|
+ actualmente usan la etiqueta como el valor del botón
|
|
|
+ y sólo usan los decoradores ViewHelper y DtDdWrapper --
|
|
|
+ previniendo una etiqueta adicional, errores, y sugerencias de
|
|
|
+ ser generadas; el ejemplo de arriba podría duplicar algún
|
|
|
+ contenido (la etiqueta).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Se puede usar el array de inclusión/exclusión para superar
|
|
|
+ este problema como se ha notado en el ejemplo anterior.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Entonces, use este método sabiamente y dése cuenta de que puede
|
|
|
+ necesitar excluir o cambiar manualmente algunos elementos decoradores
|
|
|
+ para prevenir una salida no deseada.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <example id="zend.form.forms.elements.global.filters">
|
|
|
+ <title>Determinando Filtros para todos los Elementos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En muchos casos, puede quererse aplicar el mismo filtro a todos
|
|
|
+ los elementos; un caso común es <code>trim()</code> a todos los valores:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->setElementFilters(array('StringTrim'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.form.forms.elements.methods">
|
|
|
+ <title>Métodos para Interactuar con los Elementos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los siguientes métodos pueden ser usados para interactuar con los elementos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>createElement($element, $name = null, $options = null)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addElement($element, $name = null, $options = null)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addElements(array $elements)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setElements(array $elements)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getElement($name)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getElements()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>removeElement($name)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>clearElements()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setDefaults(array $defaults)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setDefault($name, $value)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getValue($name)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getValues()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getUnfilteredValue($name)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getUnfilteredValues()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setElementFilters(array $filters)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setElementDecorators(array $decorators)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addElementPrefixPath($prefix, $path, $type = null)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addElementPrefixPaths(array $spec)</code>
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.forms.displaygroups">
|
|
|
+ <title>Grupos de visualización (display groups)</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los grupos de visualización (display groups) son una manera de crear grupos virtuales de elementos para
|
|
|
+ propósitos de visualización. Todos los elementos quedan accesibles por nombre en el
|
|
|
+ formulario, pero cuando interactúan o se ejecutan sobre el formulario, cualquiera de los elementos en
|
|
|
+ un grupos de visualización son generados juntos. El caso más común de uso es
|
|
|
+ agrupando los elementos en fieldsets. (TODO)
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La clase base para los grupos de visualización es
|
|
|
+ <code>Zend_Form_DisplayGroup</code>. Mientras puede ser instanciado
|
|
|
+ directamente, es mejor usar el método <code>addDisplayGroup()</code>
|
|
|
+ de la clase<code>Zend_Form</code>. Este método toma un
|
|
|
+ array de elementos como primer argumento y el nombre para el grupo de
|
|
|
+ visualización como segundo argumento. Opcionalmente, se puede pasar en una array
|
|
|
+ de opciones o en un objeto <code>Zend_Config</code> como tercer argumento.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Asumiendo que los elementos 'username' y 'password' has sido determinados
|
|
|
+ en el formulario, el siguiente código podría agrupar estos elementos en un
|
|
|
+ grupo de visualización 'login':
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->addDisplayGroup(array('username', 'password'), 'login');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede acceder a los grupos de visualización usando el
|
|
|
+ método <code>getDisplayGroup()</code>, o mediante la sobrecarga usando el
|
|
|
+ nombre del grupo de visualización:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Usando getDisplayGroup():
|
|
|
+$login = $form->getDisplayGroup('login');
|
|
|
+
|
|
|
+// Usando sobrecarga:
|
|
|
+$login = $form->login;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Decoradores por defecto que no necesitan ser cargados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, los grupos de visualización son cargados durante la
|
|
|
+ inicialización del objeto. Se puede deshabilitar pasando la
|
|
|
+ opción 'disableLoadDefaultDecorators' cuando se crea un grupo de visualización:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->addDisplayGroup(
|
|
|
+ array('foo', 'bar'),
|
|
|
+ 'foobar',
|
|
|
+ array('disableLoadDefaultDecorators' => true)
|
|
|
+);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esta opción puede ser una mezcla con otras opciones pasadas,
|
|
|
+ ambas como opciones de array o en el objeto <code>Zend_Config</code>
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <sect3 id="zend.form.forms.displaygroups.global">
|
|
|
+ <title>Operaciones Globales</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Al igual que los elementos, existen algunas operaciones que
|
|
|
+ pueden afectar a todos los grupos de visualización; éstas incluyen determinar decoradores
|
|
|
+ y fijar la ruta de acceso donde buscar los decoradores.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.form.forms.displaygroups.global.paths">
|
|
|
+ <title>Fijando el Prefijo de Ruta del Decorador para todos los Grupos de Visualización</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, los grupos de visualización heredan cualquier
|
|
|
+ ruta de decorador que use el formulario; sin embargo, si deberían buscar
|
|
|
+ en una ruta alternativa, puede usar el método
|
|
|
+ <code>addDisplayGroupPrefixPath()</code> method.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->addDisplayGroupPrefixPath('My_Foo_Decorator', 'My/Foo/Decorator');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <example id="zend.form.forms.displaygroups.global.decorators">
|
|
|
+ <title>Fijando Decoradores para Todos los Grupos de Visualización</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Pueden determinarse decoradores para todos los grupos de visualización,
|
|
|
+ <code>setDisplayGroupDecorators()</code> admite un array de
|
|
|
+ decoradores, al igual que <code>setDecorators()</code>, y sobreescribirá
|
|
|
+ cualquier conjunto de decoradores previo en cada grupo de visualización.
|
|
|
+ En este ejemplo, fijamos los decoradores a un fieldset (el decorador FormElements
|
|
|
+ es necesario para asegurar que los elementos son iterador):
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->setDisplayGroupDecorators(array(
|
|
|
+ 'FormElements',
|
|
|
+ 'Fieldset'
|
|
|
+));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.form.forms.displaygroups.customClasses">
|
|
|
+ <title>Usando Clases de Grupos de Visualización Personalizadas</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, <code>Zend_Form</code> utiliza la clase
|
|
|
+ <code>Zend_Form_DisplayGroup</code> para grupos de visualización.
|
|
|
+ Puede ocurrir que necesite extender esta clase con el fin
|
|
|
+ de obtener una funcionalid personalizada. <code>addDisplayGroup()</code>
|
|
|
+ no permite pasar una instancia determinada, pero permite especificar
|
|
|
+ la clase que usar como una de sus opciones, usando la clave
|
|
|
+ 'displayGroupClass':
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Use the 'My_DisplayGroup' class
|
|
|
+$form->addDisplayGroup(
|
|
|
+ array('username', 'password'),
|
|
|
+ 'user',
|
|
|
+ array('displayGroupClass' => 'My_DisplayGroup')
|
|
|
+);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si la clase no ha sido todavía cargada, <code>Zend_Form</code>
|
|
|
+ intentará cargarla a través de <code>Zend_Loader</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ También puede especificar una clase de grupo de visualización por defecto
|
|
|
+ para usar con el formulario, de forma que todos los grupos de visualización
|
|
|
+ creados con el objeto formulario usen esa clase:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Use the 'My_DisplayGroup' class for all display groups:
|
|
|
+$form->setDefaultDisplayGroupClass('My_DisplayGroup');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esta funcionalidad puede especificarse en configuraciones como
|
|
|
+ 'defaultDisplayGroupClass', y será cargada con antelación para
|
|
|
+ asegurar que todos los grupos de visualización usen esa clase.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.form.forms.displaygroups.interactionmethods">
|
|
|
+ <title>Métodos para Interactuar con Grupos de Visualización</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los siguientes métodos pueden ser usados para interactuar con el grupo de visualización:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>addDisplayGroup(array $elements, $name, $options = null)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addDisplayGroups(array $groups)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setDisplayGroups(array $groups)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getDisplayGroup($name)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getDisplayGroups()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>removeDisplayGroup($name)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>clearDisplayGroups()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setDisplayGroupDecorators(array $decorators)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addDisplayGroupPrefixPath($prefix, $path)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setDefaultDisplayGroupClass($class)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getDefaultDisplayGroupClass($class)</code>
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.form.forms.displaygroups.methods">
|
|
|
+ <title>Métodos Zend_Form_DisplayGroup</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_DisplayGroup</code> tiene los siguientes métodos,
|
|
|
+ agrupados por tipo:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>Configuración:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setOptions(array $options)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setConfig(Zend_Config $config)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Metadatos:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setAttrib($key, $value)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addAttribs(array $attribs)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setAttribs(array $attribs)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getAttrib($key)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getAttribs()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>removeAttrib($key)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>clearAttribs()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setName($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getName()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setDescription($value)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getDescription()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setLegend($legend)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getLegend()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setOrder($order)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getOrder()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Elementos:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>createElement($type, $name, array $options = array())</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addElement($typeOrElement, $name, array $options = array())</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addElements(array $elements)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setElements(array $elements)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getElement($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getElements()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>removeElement($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>clearElements()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Cargadores Complemento:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setPluginLoader(Zend_Loader_PluginLoader $loader)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getPluginLoader()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addPrefixPath($prefix, $path)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addPrefixPaths(array $spec)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Decoratores:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>addDecorator($decorator, $options = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addDecorators(array $decorators)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setDecorators(array $decorators)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getDecorator($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getDecorators()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>removeDecorator($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>clearDecorators()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Generadores:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setView(Zend_View_Interface $view = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getView()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>render(Zend_View_Interface $view = null)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>I18n:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setTranslator(Zend_Translate_Adapter $translator = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getTranslator()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setDisableTranslator($flag)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>translatorIsDisabled()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.forms.subforms">
|
|
|
+ <title>Subformularios</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los Sub formularios sirven para diferentes propósitos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ Crear grupos de elementos lógicos. Dado que los sub formularios son
|
|
|
+ simplemente formularios, se pueden validar subformularios como entidades individuales.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Crear formularios multi-páginas. Dado que los sub formularios son simplemente formularios,
|
|
|
+ se puede deplegar un sub formulario por separado por página, incrementando formularios
|
|
|
+ multi-páginas donde cada formulario tiene su propia validación lógica. Solo una vez
|
|
|
+ que todos los sub formularios se validen, el formulario se consideraría completo.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Agrupaciones de visualización. Como grupos de visualización, los sub formularios, cuando son generados
|
|
|
+ como parte de un formulario más grande, pueden ser usados para agrupar elementos. Sea consciente,
|
|
|
+ de todas maneras, que el objeto formulario principal no tendrá
|
|
|
+ conocimiento de los elementos en un sub formulario.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un sub formulario puede ser un objeto <code>Zend_Form</code> o mas
|
|
|
+ originalmente, un objeto <code>Zend_Form_SubForm</code>. éste último
|
|
|
+ contiene decoradores apropiados para la inclusión en un formulario extenso (i.e.,
|
|
|
+ no se generan adicionales formulario etiquetas HTML, pero si grupos de
|
|
|
+ elementos). Para adjuntar un sub formulario, simplemente añádalo al formulario y déle
|
|
|
+ un nombre:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->addSubForm($subForm, 'subform');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Se puede recuperar un sub formulario usando ya sea
|
|
|
+ <code>getSubForm($name)</code> o sobrecarga usando el nombre
|
|
|
+ del sub formulario:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Usando getSubForm():
|
|
|
+$subForm = $form->getSubForm('subform');
|
|
|
+
|
|
|
+// Usando sobrecarga:
|
|
|
+$subForm = $form->subform;
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los Subformularios son incluidos en la interacción del formulario, sin embargo los elementos
|
|
|
+ que lo contienen no lo son
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.form.forms.subforms.global">
|
|
|
+ <title>Operaciones Globales</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como los elementos y los grupos de visualización, existen algunas operaciones que
|
|
|
+ pueden afectar a todos los sub formularios. A diferencia de los grupos de visualización y los
|
|
|
+ elementos, sin embargo, los sub formularios heredan más funcionalidad del
|
|
|
+ objeto formulario principal, y la única operación real que puede
|
|
|
+ realizarse globalmente es determinar decoradores para sub formularios. Para
|
|
|
+ este propósito, existe el método <code>setSubFormDecorators()</code>.
|
|
|
+ En el siguiente ejemplo, determinaremos el decorador para todos los
|
|
|
+ subformularios que sera un simple campo (el decorador FormElements es
|
|
|
+ necesario para asegurar que los elementos son iterados):
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->setSubFormDecorators(array(
|
|
|
+ 'FormElements',
|
|
|
+ 'Fieldset'
|
|
|
+));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.form.forms.subforms.methods">
|
|
|
+ <title>Métodos para interactuar con Sub Formularios</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los siguientes métodos pueden ser usados para interactuar con sub formularios:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>addSubForm(Zend_Form $form, $name, $order = null)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addSubForms(array $subForms)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setSubForms(array $subForms)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getSubForm($name)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getSubForms()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>removeSubForm($name)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>clearSubForms()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setSubFormDecorators(array $decorators)</code>
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.forms.metadata">
|
|
|
+ <title>Metadatos y Atributos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Mientras la utilidad de un formulario primariamente deriva de los elementos
|
|
|
+ que contiene, también pueden contener otros metadatos, como un nombre (usado
|
|
|
+ a menudo como ID único en el marcado HTML ); la accion y el método del formulario;
|
|
|
+ el número de elementos, grupos y sub formularios que lo contienen; y
|
|
|
+ arbitrariamente metadatos (usualmente usados para determinar atributos HTML para la
|
|
|
+ etiqueta del propio formulario).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Se puede determinar y recuperar el nombre del formulario usando el accesor nombre:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Determinar el nombre:
|
|
|
+$form->setName('registration');
|
|
|
+
|
|
|
+// Recuperar el nombre:
|
|
|
+$name = $form->getName();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para determinar la acción (url en el cual se envia el formulario) y método (método
|
|
|
+ por el cual debería enviar, ej. 'POST' or 'GET'), use los accesores acción
|
|
|
+ y método:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Determinar la acción y método:
|
|
|
+$form->setAction('/user/login')
|
|
|
+ ->setMethod('post');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Se puede también especificar el tipo de codificación del fomulario usando el
|
|
|
+ enctype accessors. Zend_Form define dos constantes,
|
|
|
+ <code>Zend_Form::ENCTYPE_URLENCODED</code> y
|
|
|
+ <code>Zend_Form::ENCTYPE_MULTIPART</code>, correspondiente a los
|
|
|
+ valores 'application/x-www-form-urlencoded' y
|
|
|
+ 'multipart/form-data', respectivamente; sin embargo, puede configurarlo
|
|
|
+ con cualquier tipo de codificación.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Determinar la acción, método y enctype:
|
|
|
+$form->setAction('/user/login')
|
|
|
+ ->setMethod('post')
|
|
|
+ ->setEnctype(Zend_Form::ENCTYPE_MULTIPART);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ El método, acción y enctype son solo usados internamente para generar,
|
|
|
+ y no para algún tipo de validación.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form</code> implementa la interfaz <code>Countable</code>
|
|
|
+ permitiéndole pasarlo como un argumento para contar:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$numItems = count($form);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Determinar metadatos arbitrariamente se realiza a través de los accesores 'atribs'.
|
|
|
+ Dado que la sobrecarga en <code>Zend_Form</code> es usada para acceder
|
|
|
+ elementos, grupos de visualización y subformularios, este es el único método para
|
|
|
+ acceder a los metadatos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Determinando atributos:
|
|
|
+$form->setAttrib('class', 'zend-form')
|
|
|
+ ->addAttribs(array(
|
|
|
+ 'id' => 'registration',
|
|
|
+ 'onSubmit' => 'validate(this)',
|
|
|
+ ));
|
|
|
+
|
|
|
+// Recuperando atributos:
|
|
|
+$class = $form->getAttrib('class');
|
|
|
+$attribs = $form->getAttribs();
|
|
|
+
|
|
|
+// Removiendo atributos:
|
|
|
+$form->removeAttrib('onSubmit');
|
|
|
+
|
|
|
+// Limpiando todos los atributos:
|
|
|
+$form->clearAttribs();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.forms.decorators">
|
|
|
+ <title>Decoradores</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Crear el marcado para un formulario es a menudo una tarea que consume mucho tiempo,
|
|
|
+ particularmente si se planea reusar el mismo marcado para mostrar acciones
|
|
|
+ tales como validación de errores, enviar valores, etc.
|
|
|
+ La respuesta de <code>Zend_Form</code> a este problema es los
|
|
|
+ <emphasis>decoradores</emphasis>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los decoradores para objetos <code>Zend_Form</code> pueden ser usados para generar
|
|
|
+ un formulario. El decorador FormElements iterará a través de todos los elementos en
|
|
|
+ un formulario -- elementos, grupos de visualización y subformularios -- y los generará,
|
|
|
+ devolviendo el resultado. Adicionalmente, los decoradores pueden ser usados
|
|
|
+ para envolver el contenido o anteponerlo o postponerlo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los decoradores por defecto de <code>Zend_Form</code> son FormElements,
|
|
|
+ HtmlTag (envuelve una lista de definición) y Form; el código equivalente
|
|
|
+ para crearlos es como sigue:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->setDecorators(array(
|
|
|
+ 'FormElements',
|
|
|
+ array('HtmlTag', array('tag' => 'dl')),
|
|
|
+ 'Form'
|
|
|
+));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Que crea la salida como sigue:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="html"><![CDATA[
|
|
|
+<form action="/form/action" method="post">
|
|
|
+<dl>
|
|
|
+...
|
|
|
+</dl>
|
|
|
+</form>
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Algunos de los atributos se determinan en el objeto formulario que será usado como
|
|
|
+ atributos HTML de la etiqueta <code><form></code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Decoradores por defecto que no necesitan ser cargados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, el decorador por defecto son cargados durante la
|
|
|
+ inicialización del objeto. Puede deshabilitarlo pasando la
|
|
|
+ opción 'disableLoadDefaultDecorators' al constructor:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form = new Zend_Form(array('disableLoadDefaultDecorators' => true));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esta opción puede ser combinada con alguna otra opción que usted pueda pasar,
|
|
|
+ tanto como opciones de array o en un objeto <code>Zend_Config</code>
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Usando multiples decoradores del mismo tipo</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Internamente, <code>Zend_Form</code> usa una clase decorador
|
|
|
+ como un mecanismo buscador cuando se recuperan decoradores. Como
|
|
|
+ resultado, no se pueden registrar multiples decoradores del mismo
|
|
|
+ tipo; subsecuentemente los decoradores simplemente sobrescribirán esos
|
|
|
+ decoradores que existían antes.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para conseguir esto, se pueden usar alias. En vez de pasar un
|
|
|
+ decorador o un nombre de decorador como primer argumento a
|
|
|
+ <code>addDecorator()</code>, pase un array con un solo
|
|
|
+ elemento, con el alias apuntando al objeto decorador o
|
|
|
+ nombre:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Alias para 'FooBar':
|
|
|
+$form->addDecorator(array('FooBar' => 'HtmlTag'), array('tag' => 'div'));
|
|
|
+
|
|
|
+// y recuperarlo después:
|
|
|
+$form = $element->getDecorator('FooBar');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En los métodos <code>addDecorators()</code> y
|
|
|
+ <code>setDecorators()</code>, se necesitará pasar
|
|
|
+ la opción 'decorator' en el array representando el decorador:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Añadir dos decoradores 'HtmlTag', poniendo un alias a 'FooBar':
|
|
|
+$form->addDecorators(
|
|
|
+ array('HtmlTag', array('tag' => 'div')),
|
|
|
+ array(
|
|
|
+ 'decorator' => array('FooBar' => 'HtmlTag'),
|
|
|
+ 'options' => array('tag' => 'dd')
|
|
|
+ ),
|
|
|
+);
|
|
|
+
|
|
|
+// y recuperándolo después:
|
|
|
+$htmlTag = $form->getDecorator('HtmlTag');
|
|
|
+$fooBar = $form->getDecorator('FooBar');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede crear su propio decorador para generar el formulario. Un
|
|
|
+ caso de uso común es si sabe el HTML exacto que desea usar; su
|
|
|
+ decorador puede crear el mismo HTML y simplemente retornarlo,
|
|
|
+ potencialmente usando los decoradores de individuales elementos o
|
|
|
+ grupos de visualización.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los siguientes métodos puden ser usados para interactuar con decoradores:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>addDecorator($decorator, $options = null)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addDecorators(array $decorators)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setDecorators(array $decorators)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getDecorator($name)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getDecorators()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>removeDecorator($name)</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>clearDecorators()</code>
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form</code> también usa sobrecarga que permite generar
|
|
|
+ decoradores específicos. <code>__call()</code> interceptará métodos
|
|
|
+ que lleve con el texto 'render' y use el resto del nombre del método
|
|
|
+ para buscar un decorador; si se encuentran, serán generados por un
|
|
|
+ <emphasis>solo</emphasis> decorador. Cualquier argumento pasado a la
|
|
|
+ llamada del método será usado como contenido que pasar al método
|
|
|
+ <code>render()</code> del decorador. Como ejemplo:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Generar solo los decoradores FormElements:
|
|
|
+echo $form->renderFormElements();
|
|
|
+
|
|
|
+// Generar solo el campo decorador, pasando el contenido:
|
|
|
+echo $form->renderFieldset("<p>This is fieldset content</p>");
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si el decorador no existe, una excepción se creará.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.forms.validation">
|
|
|
+ <title>Validación</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un caso de uso primario para formularios es validar datos enviados.
|
|
|
+ <code>Zend_Form</code> le permite validar un formulario entero de una vez,
|
|
|
+ o una parte de él, asi como también automatizar las respuestas de validación para
|
|
|
+ XmlHttpRequests (AJAX). Si los datos enviados no son válidos, contiene
|
|
|
+ métodos para recuperar los distintos códigos errores y los mensajes de
|
|
|
+ elementos y subformularios de validaciones fallidas.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para validar un formulario entero, use el método <code>isValid()</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+if (!$form->isValid($_POST)) {
|
|
|
+ // validación fallida
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>isValid()</code> validará cada elemento requerido, y algún
|
|
|
+ elemento no requerido contenido en la data sometida.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Algunas veces se necesitará validar sólo un subset del dato; para
|
|
|
+ esto use <code>isValidPartial($data)</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+if (!$form->isValidPartial($data)) {
|
|
|
+ // validación fallida
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>isValidPartial()</code> sólo intenta validar aquellos elementos
|
|
|
+ en la información para los cuales existen similares elementos; si un elemento es
|
|
|
+ no representado en la información, es pasado por alto.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cuando se validan elementos o grupos de elementos para un requeirimiento AJAX,
|
|
|
+ típicamente se validará un subset del formulario, y quiere la respuesta
|
|
|
+ en JSON. <code>processAjax()</code> precisamente realiza eso:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$json = $form->processAjax($data);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Entonces, puede simplemente enviar la respuesta JSON al cliente. Si el
|
|
|
+ formulario es válido, ésta será una respuesta booleana. Si no, será
|
|
|
+ un objeto javascript conteniendo pares de clave/mensaje, donde cada
|
|
|
+ 'message' es un array de validación de mensajes de error.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para los formularios que fallan la validación, se pueden recuperar ambos códigos
|
|
|
+ de error y mensajes de error, usando <code>getErrors()</code> y
|
|
|
+ <code>getMessages()</code>, respectivamente:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$codes = $form->getErrors();
|
|
|
+$messages = $form->getMessage();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ Dado que los mensajes devueltos por <code>getMessages()</code> son un
|
|
|
+ array de pares de errores código/mensaje, <code>getErrors()</code> no
|
|
|
+ es necesario.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede recuperar códigos y mensajes de error para elementos individuales
|
|
|
+ simplemente pasando el nombre del elemento a cada uno:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$codes = $form->getErrors('username');
|
|
|
+$messages = $form->getMessages('username');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ Nota: Cuando validamos elementos, <code>Zend_Form</code> envía un
|
|
|
+ segundo argumento a cada método <code>isValid()</code> del elemento:
|
|
|
+ el array de los datos que se están validando. Esto puede ser usado por
|
|
|
+ validadores individuales para permitirles utilizar otros valores
|
|
|
+ enviados al determinar la validez de los datos. Un ejemplo
|
|
|
+ sería un formulario de registro que requiere tanto una contraseña
|
|
|
+ como una confirmación de la contraseña; el elemento contraseña puede usar la
|
|
|
+ confirmación de la contraseña como parte de su validación.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <sect3 id="zend.form.forms.validation.errors">
|
|
|
+ <title>Mensajes de error personalizados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A veces, puede querer especificar uno o más mensajes
|
|
|
+ de error en vez de los mensajes de error generados por los
|
|
|
+ validadores adjuntos a los elementos. Adicionalmente, a veces
|
|
|
+ puede querer marcar el formulario inválido usted mismo. Como 1.6.0,
|
|
|
+ esta funcionalidad es posible siguiendo los métodos.
|
|
|
+
|
|
|
+ At times, you may want to specify one or more specific error
|
|
|
+ messages to use instead of the error messages generated by the
|
|
|
+ validators attached to your elements. Additionally, at times you
|
|
|
+ may want to mark the form invalid yourself. As of 1.6.0, this
|
|
|
+ functionality is possible via the following methods.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>addErrorMessage($message)</code>: añade un mensaje de error
|
|
|
+ para desplegar en el formulario los errores de validación. Se debe llamar más
|
|
|
+ de una vez, y los nuevos mensajes son adicionados a la pila.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addErrorMessages(array $messages)</code>: añade múltiples
|
|
|
+ mensajes de error para desplegar en el formulario los errores de validación
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setErrorMessages(array $messages)</code>: añade multiples
|
|
|
+ mensajes de error para desplegar en el formulario los errores de validación,
|
|
|
+ sobrescribiendo todos los mensajes de error previamente determinados.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getErrorMessages()</code>: recupera la lista de
|
|
|
+ mensajes de error personalizados que han sido definidos.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>clearErrorMessages()</code>: remueve todos los mensajes
|
|
|
+ de error personalizados que han sido definidos.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>markAsError()</code>: marca el formulario como que la
|
|
|
+ validación ha fallado.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addError($message)</code>: añade un mensaje a la pila de
|
|
|
+ mensajes de error personalizados y señala al formulario como inválido.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>addErrors(array $messages)</code>: añade muchos
|
|
|
+ mensajes a la pila de mensajes de error personalizados y señala al
|
|
|
+ formulario como inválido.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>setErrors(array $messages)</code>: sobrescribe la
|
|
|
+ pila de mensajes de error personalizada con los mensajes proporcionados
|
|
|
+ y señala el formulario como inválido.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todos los errores determinados de esta manera pueden ser traducidos.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.forms.methods">
|
|
|
+ <title>Métodos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La siguiente lista es la lista completa de métodos disponibles para
|
|
|
+ <code>Zend_Form</code>, agrupados por tipo:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>Configuración y opciones:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setOptions(array $options)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setConfig(Zend_Config $config)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Cargadores de plugins y rutas:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getPluginLoader($type = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addPrefixPath($prefix, $path, $type = null) </code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addPrefixPaths(array $spec)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addElementPrefixPath($prefix, $path, $type = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addElementPrefixPaths(array $spec)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addDisplayGroupPrefixPath($prefix, $path)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Metadato:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setAttrib($key, $value)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addAttribs(array $attribs)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setAttribs(array $attribs)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getAttrib($key)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getAttribs()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>removeAttrib($key)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>clearAttribs()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setAction($action)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getAction()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setMethod($method)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getMethod()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setName($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getName()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Elementos:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>addElement($element, $name = null, $options = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addElements(array $elements)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setElements(array $elements)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getElement($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getElements()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>removeElement($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>clearElements()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setDefaults(array $defaults)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setDefault($name, $value)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getValue($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getValues()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getUnfilteredValue($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getUnfilteredValues()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setElementFilters(array $filters)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setElementDecorators(array $decorators)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Subformularios:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>addSubForm(Zend_Form $form, $name, $order = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addSubForms(array $subForms)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setSubForms(array $subForms)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getSubForm($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getSubForms()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>removeSubForm($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>clearSubForms()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setSubFormDecorators(array $decorators)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Grupos de Visualización</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>addDisplayGroup(array $elements, $name, $options = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addDisplayGroups(array $groups)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setDisplayGroups(array $groups)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getDisplayGroup($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getDisplayGroups()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>removeDisplayGroup($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>clearDisplayGroups()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setDisplayGroupDecorators(array $decorators)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Validación</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>populate(array $values)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>isValid(array $data)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>isValidPartial(array $data)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>processAjax(array $data)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>persistData()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getErrors($name = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getMessages($name = null)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>Generadores:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setView(Zend_View_Interface $view = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getView()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addDecorator($decorator, $options = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addDecorators(array $decorators)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setDecorators(array $decorators)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getDecorator($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getDecorators()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>removeDecorator($name)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>clearDecorators()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>render(Zend_View_Interface $view = null)</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>I18n:</para>
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setTranslator(Zend_Translate_Adapter $translator = null)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>getTranslator()</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setDisableTranslator($flag)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>translatorIsDisabled()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.forms.config">
|
|
|
+ <title>Configuración</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form</code> es totalmente configurable mediante
|
|
|
+ <code>setOptions()</code> y <code>setConfig()</code> (o
|
|
|
+ pasando opciones o un objeto <code>Zend_Config</code> al
|
|
|
+ constructor). Usando estos métodos, se pueden especificar elementos formulario,
|
|
|
+ grupos de visualización, decoradores, y metadatos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como regla general, si 'set' + la clave de opción (option key) hacen referencia a
|
|
|
+ métodos <code>Zend_Form</code>, entonces el valor proporcionado será
|
|
|
+ pasado al método. Si el accessor no existe, se asume que la clave
|
|
|
+ referencia a un atributo, y será pasado a
|
|
|
+ <code>setAttrib()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Excepciones a las reglas incluyen lo siguiente:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>prefixPaths</code> será pasado a
|
|
|
+ <code>addPrefixPaths()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>elementPrefixPaths</code> será pasado a
|
|
|
+ <code>addElementPrefixPaths()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>displayGroupPrefixPaths</code> será pasado a
|
|
|
+ <code>addDisplayGroupPrefixPaths()</code>
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>los siguientes establecedores no pueden ser determinado de ésta manera:</para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>setAttrib (aunque setAttribs *funcionará*)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setConfig</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setDefault</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setOptions</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setPluginLoader</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setSubForms</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setTranslator</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setView</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como un ejemplo, aquí esta un archivo de configuración que pasa la configuración
|
|
|
+ por cada tipo de datos configurables:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="ini"><![CDATA[
|
|
|
+[element]
|
|
|
+name = "registration"
|
|
|
+action = "/user/register"
|
|
|
+method = "post"
|
|
|
+attribs.class = "zend_form"
|
|
|
+attribs.onclick = "validate(this)"
|
|
|
+
|
|
|
+disableTranslator = 0
|
|
|
+
|
|
|
+prefixPath.element.prefix = "My_Element"
|
|
|
+prefixPath.element.path = "My/Element/"
|
|
|
+elementPrefixPath.validate.prefix = "My_Validate"
|
|
|
+elementPrefixPath.validate.path = "My/Validate/"
|
|
|
+displayGroupPrefixPath.prefix = "My_Group"
|
|
|
+displayGroupPrefixPath.path = "My/Group/"
|
|
|
+
|
|
|
+elements.username.type = "text"
|
|
|
+elements.username.options.label = "Username"
|
|
|
+elements.username.options.validators.alpha.validator = "Alpha"
|
|
|
+elements.username.options.filters.lcase = "StringToLower"
|
|
|
+; more elements, of course...
|
|
|
+
|
|
|
+elementFilters.trim = "StringTrim"
|
|
|
+;elementDecorators.trim = "StringTrim"
|
|
|
+
|
|
|
+displayGroups.login.elements.username = "username"
|
|
|
+displayGroups.login.elements.password = "password"
|
|
|
+displayGroupDecorators.elements.decorator = "FormElements"
|
|
|
+displayGroupDecorators.fieldset.decorator = "Fieldset"
|
|
|
+
|
|
|
+decorators.elements.decorator = "FormElements"
|
|
|
+decorators.fieldset.decorator = "FieldSet"
|
|
|
+decorators.fieldset.decorator.options.class = "zend_form"
|
|
|
+decorators.form.decorator = "Form"
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El código de arriba fácilmente puede ser abstraído a un XML o un archivo de configuración basado en arrays PHP.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.forms.custom">
|
|
|
+ <title>Formularios personalizados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Una alternativa a usar los formularios basados en configuraciones es realizar una subclase de
|
|
|
+ <code>Zend_Form</code>. Esto tiene muchos beneficios:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ Se puede centrar la prueba de su formulario facilmente para asegurar las validaciones y
|
|
|
+ generar la ejecución esperada.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Control preciso sobre los individuales elementos.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Reutilización del objeto formulario, y mejor portabilidad (no se necesita
|
|
|
+ seguir los archivos de configuración).
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Implementar funcionalidad personalizada.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El caso mas típico de uso sería el método
|
|
|
+ <code>init()</code> para determinar elementos de formulario específicos y
|
|
|
+ de configuración:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_Form_Login extends Zend_Form
|
|
|
+{
|
|
|
+ public function init()
|
|
|
+ {
|
|
|
+ $username = new Zend_Form_Element_Text('username');
|
|
|
+ $username->class = 'formtext';
|
|
|
+ $username->setLabel('Username:')
|
|
|
+ ->setDecorators(array(
|
|
|
+ array('ViewHelper',
|
|
|
+ array('helper' => 'formText')),
|
|
|
+ array('Label',
|
|
|
+ array('class' => 'label'))
|
|
|
+ ));
|
|
|
+
|
|
|
+ $password = new Zend_Form_Element_Password('password');
|
|
|
+ $password->class = 'formtext';
|
|
|
+ $password->setLabel('Username:')
|
|
|
+ ->setDecorators(array(
|
|
|
+ array('ViewHelper',
|
|
|
+ array('helper' => 'formPassword')),
|
|
|
+ array('Label',
|
|
|
+ array('class' => 'label'))
|
|
|
+ ));
|
|
|
+
|
|
|
+ $submit = new Zend_Form_Element_Submit('login');
|
|
|
+ $submit->class = 'formsubmit';
|
|
|
+ $submit->setValue('Login')
|
|
|
+ ->setDecorators(array(
|
|
|
+ array('ViewHelper',
|
|
|
+ array('helper' => 'formSubmit'))
|
|
|
+ ));
|
|
|
+
|
|
|
+ $this->addElements(array(
|
|
|
+ $username,
|
|
|
+ $password,
|
|
|
+ $submit
|
|
|
+ ));
|
|
|
+
|
|
|
+ $this->setDecorators(array(
|
|
|
+ 'FormElements',
|
|
|
+ 'Fieldset',
|
|
|
+ 'Form'
|
|
|
+ ));
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Este formulario puede ser instanciado simplemente así:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form = new My_Form_Login();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ y toda la funcionalidad está instalada y lista; no se necesitan archivos
|
|
|
+ de configuración. (Note que este ejemplo esta simplificado, no contiene
|
|
|
+ validadores o filtros para los elementos.)
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Otra razón común para la extension es definir un conjunto de
|
|
|
+ decoradores por defecto. Puede hacerlo sobreescribiendo el
|
|
|
+ método <code>loadDefaultDecorators()</code>:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_Form_Login extends Zend_Form
|
|
|
+{
|
|
|
+ public function loadDefaultDecorators()
|
|
|
+ {
|
|
|
+ $this->setDecorators(array(
|
|
|
+ 'FormElements',
|
|
|
+ 'Fieldset',
|
|
|
+ 'Form'
|
|
|
+ ));
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.form.decorators" xml:base="module_specs/Zend_Form-Decorators.xml">
|
|
|
+ <title>Creando un personalizado marcado de formulario usando Zend_Form_Decorator</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Representar un objeto form es completamente opcional -- no está obligado a usar
|
|
|
+ los métodos <code>Zend_Form</code> render() en absoluto. Sin embargo, si lo hace,
|
|
|
+ los decoradores se usan para representar distintos objetos form.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un número arbitrario de decoradores pueden estar junto a cada elemento
|
|
|
+ (elements, display groups, sub forms o el objeto form por si mismo);
|
|
|
+ Sin embargo, solo un decorador de un tipo dado puede estar al lado de cada
|
|
|
+ elemento. Los decoradores son llamados en el orden en que han sido introducidos. Dependiendo
|
|
|
+ del decorador, puede reemplazar el contenido que se ha pasado, postponerlo o
|
|
|
+ anteponerlo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El estado del objeto es determinado a través de las opciones de configuración pasadas al constructor
|
|
|
+ o el método decorador <code>setOptions()</code>. Cuando se crean
|
|
|
+ decoradores mediante funciones <code>addDecorator()</code> o métodos relacionados,
|
|
|
+ las opciones pueden ser pasadas como argumentos al método. Esto puese ser usado para
|
|
|
+ una ubicación especifica, un separador se usa entre el contenido pasado y el
|
|
|
+ nuevo contenido generado y cualquier opción que el decorador soporte.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Antes de que el <code>render()</code> de cada decorador sea llamado, el
|
|
|
+ item actual es determinado en el decorador usando <code>setElement()</code>,
|
|
|
+ dando al decorador conocimiento del item representado. Esto permite
|
|
|
+ crear decoradores que sólo representan porciones especificas del item
|
|
|
+ -- tal como etiquetas, el valor, mensajes de error, etc. Encadenando
|
|
|
+ muchos decoradores que representan especificos segmentos, puede construir
|
|
|
+ marcados complejos representando al item entero.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.decorators.operation">
|
|
|
+ <title>Operación</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para configurar un decorador, pase un array de opciones o un
|
|
|
+ objeto <code>Zend_Config</code> a este constructor, a un array
|
|
|
+ <code>setOptions()</code>, o a un objeto <code>Zend_Config</code>
|
|
|
+ <code>setConfig()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Opciones estándar incluyen:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>placement</code>: La ubicación puede ser cualquiera de los dos 'append' o
|
|
|
+ 'prepend' (caso insensitivo) e indica cualquier contenido
|
|
|
+ pasado a <code>render()</code> será postpuesto o
|
|
|
+ antepuesto respectivamente. En el caso de que el decorador
|
|
|
+ reemplace el contenido, esta configuración es ignorada. La configuración
|
|
|
+ por defecto es adjuntada.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>separator</code>: El separator es usado entre el
|
|
|
+ contenido pasado a <code>render()</code> y el nuevo contenido
|
|
|
+ generado por el decorador, o entre items generados por el
|
|
|
+ decorador (ejemplo FormElements usa el separador entre cada
|
|
|
+ item generado). En el caso que un decorador reemplace el
|
|
|
+ contenido, esta configuración puede ser ignorada. El valor por defecto
|
|
|
+ es <code>PHP_EOL</code>.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La interface del decorador especifica los métodos para interactuar con las
|
|
|
+ opciones. Esto incluye:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>setOption($key, $value)</code>: determina una sola opción.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getOption($key)</code>: recuperar un solo valor de opción.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>getOptions()</code>: recuperar todas las opciones.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>removeOption($key)</code>: eliminar una sola opción.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>clearOptions()</code>: eliminar todas las opciones.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Decoradores son diseñados para interactuar con varios
|
|
|
+ tipos de clases <code>Zend_Form</code>: <code>Zend_Form</code>,
|
|
|
+ <code>Zend_Form_Element</code>, <code>Zend_Form_DisplayGroup</code>,
|
|
|
+ y todas las clases derivan de ellas. El método
|
|
|
+ <code>setElement()</code> permite determinar el objeto del
|
|
|
+ decorador que esta actualmente trabajando con, y <code>getElement()</code>
|
|
|
+ es usado para recuperarlo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cada método decorador <code>render()</code> acepta una cadena
|
|
|
+ <code>$content</code>. Cuando el primer decorador es llamado, esta
|
|
|
+ cadena esta tipicamente vacía, mientras las subsecuentes llamadas serán
|
|
|
+ puestas. Basados en el tipo de decorador y en las opciones pasadas,
|
|
|
+ el decorador ya sea reemplazará la cadena, antenpodrá la cadena
|
|
|
+ o adjuntará la cadena; una separador opcional será usado en las
|
|
|
+ dos últimas situaciones.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.decorators.standard">
|
|
|
+ <title>Decoradores estándar</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form</code> entrega muchos decoradores estándar; ver
|
|
|
+ <link linkend="zend.form.standardDecorators">el capítulo Decoradores
|
|
|
+ estándar</link> para detalles.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.decorators.custom">
|
|
|
+ <title>Decoradores personalizados</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si encuentra que sus necesidades son complejas o necesita una enorme
|
|
|
+ personalización, debería considerar crear un decorador personalizado.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los decoradores necesitan implementar sólo
|
|
|
+ <code>Zend_Decorator_Interface</code>. La interface especifica lo
|
|
|
+ siguiente:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+interface Zend_Decorator_Interface
|
|
|
+{
|
|
|
+ public function __construct($options = null);
|
|
|
+ public function setElement($element);
|
|
|
+ public function getElement();
|
|
|
+ public function setOptions(array $options);
|
|
|
+ public function setConfig(Zend_Config $config);
|
|
|
+ public function setOption($key, $value);
|
|
|
+ public function getOption($key);
|
|
|
+ public function getOptions();
|
|
|
+ public function removeOption($key);
|
|
|
+ public function clearOptions();
|
|
|
+ public function render($content);
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para hacerlo mas simple, simplemente puede extender
|
|
|
+ <code>Zend_Decorator_Abstract</code>, el cual implementa todos los métodos
|
|
|
+ excepto <code>render()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como ejemplo, digamos que quiere reducir el número de
|
|
|
+ decoradores que utiliza, y construir un decorador compuesto que se
|
|
|
+ encargó de renderizar la etiqueta generadora, el elemento, cualquier
|
|
|
+ mensaje de error, y descripción en un <code>div</code> HTML.
|
|
|
+ Puede construir como un decorador compuesto como sigue:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_Decorator_Composite extends Zend_Form_Decorator_Abstract
|
|
|
+{
|
|
|
+ public function buildLabel()
|
|
|
+ {
|
|
|
+ $element = $this->getElement();
|
|
|
+ $label = $element->getLabel();
|
|
|
+ if ($translator = $element->getTranslator()) {
|
|
|
+ $label = $translator->translate($label);
|
|
|
+ }
|
|
|
+ if ($element->isRequired()) {
|
|
|
+ $label .= '*';
|
|
|
+ }
|
|
|
+ $label .= ':';
|
|
|
+ return $element->getView()
|
|
|
+ ->formLabel($element->getName(), $label);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function buildInput()
|
|
|
+ {
|
|
|
+ $element = $this->getElement();
|
|
|
+ $helper = $element->helper;
|
|
|
+ return $element->getView()->$helper(
|
|
|
+ $element->getName(),
|
|
|
+ $element->getValue(),
|
|
|
+ $element->getAttribs(),
|
|
|
+ $element->options
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ public function buildErrors()
|
|
|
+ {
|
|
|
+ $element = $this->getElement();
|
|
|
+ $messages = $element->getMessages();
|
|
|
+ if (empty($messages)) {
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+ return '<div class="errors">' .
|
|
|
+ $element->getView()->formErrors($messages) . '</div>';
|
|
|
+ }
|
|
|
+
|
|
|
+ public function buildDescription()
|
|
|
+ {
|
|
|
+ $element = $this->getElement();
|
|
|
+ $desc = $element->getDescription();
|
|
|
+ if (empty($desc)) {
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+ return '<div class="description">' . $desc . '</div>';
|
|
|
+ }
|
|
|
+
|
|
|
+ public function render($content)
|
|
|
+ {
|
|
|
+ $element = $this->getElement();
|
|
|
+ if (!$element instanceof Zend_Form_Element) {
|
|
|
+ return $content;
|
|
|
+ }
|
|
|
+ if (null === $element->getView()) {
|
|
|
+ return $content;
|
|
|
+ }
|
|
|
+
|
|
|
+ $separator = $this->getSeparator();
|
|
|
+ $placement = $this->getPlacement();
|
|
|
+ $label = $this->buildLabel();
|
|
|
+ $input = $this->buildInput();
|
|
|
+ $errors = $this->buildErrors();
|
|
|
+ $desc = $this->buildDescription();
|
|
|
+
|
|
|
+ $output = '<div class="form element">'
|
|
|
+ . $label
|
|
|
+ . $input
|
|
|
+ . $errors
|
|
|
+ . $desc
|
|
|
+ . '</div>'
|
|
|
+
|
|
|
+ switch ($placement) {
|
|
|
+ case (self::PREPEND):
|
|
|
+ return $output . $separator . $content;
|
|
|
+ case (self::APPEND):
|
|
|
+ default:
|
|
|
+ return $content . $separator . $output;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede entonces ubicarlo en el directorio del decorador:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// para un elemento:
|
|
|
+$element->addPrefixPath('My_Decorator',
|
|
|
+ 'My/Decorator/',
|
|
|
+ 'decorator');
|
|
|
+
|
|
|
+// para todos los elementos:
|
|
|
+$form->addElementPrefixPath('My_Decorator',
|
|
|
+ 'My/Decorator/',
|
|
|
+ 'decorator');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede especificar este decorador como compuesto (composite) y adjuntarlo a
|
|
|
+ un elemento:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Sobreescribe los decoradores existentes con este otro:
|
|
|
+$element->setDecorators(array('Composite'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Mientras este ejemplo mostró cómo crear un decorador que genera
|
|
|
+ salidas complejas de muchas propiedades de elementos, puede también crear
|
|
|
+ decoradores que manejen un solo aspecto de un elemento; los decoradores
|
|
|
+ 'Decorator' y 'Label' son excelentes ejemplos para
|
|
|
+ esta práctica. Hacerlo le permite mezclar y combinar decoradores para llegar
|
|
|
+ a complejas salidas -- y también anular aspectos de decoración para
|
|
|
+ personalizar sus necesidades.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por ejemplo, si quiere simplemente desplegar que un error ha ocurrido
|
|
|
+ cuando validábamos un elemento, pero no desplegar individualmente
|
|
|
+ cada uno de los mensajes de error, usted podría crear su propio
|
|
|
+ decorador 'Errores':
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_Decorator_Errors
|
|
|
+{
|
|
|
+ public function render($content = '')
|
|
|
+ {
|
|
|
+ $output = '<div class="errors">El valor que proporcionó no es válido;
|
|
|
+ please try again</div>';
|
|
|
+
|
|
|
+ $placement = $this->getPlacement();
|
|
|
+ $separator = $this->getSeparator();
|
|
|
+
|
|
|
+ switch ($placement) {
|
|
|
+ case 'PREPEND':
|
|
|
+ return $output . $separator . $content;
|
|
|
+ case 'APPEND':
|
|
|
+ default:
|
|
|
+ return $content . $separator . $output;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En este ejemplo particular, debido al segmento del decorador final,
|
|
|
+ 'Errors', se combina como <code>Zend_Form_Decorator_Errors</code>,
|
|
|
+ será generado <emphasis>en lugar de</emphasis> el decorador
|
|
|
+ -- significa que no necesitará cambiar ningún decorador para modificar la
|
|
|
+ salida. Nombrando sus decoradores después de los decoradores existentes
|
|
|
+ estándar, usted puede modificar decoradores sin necesitad de modificar sus
|
|
|
+ elementos decoradores.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.decorators.individual">
|
|
|
+ <title>Generando decoradores individuales</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Desde que los decoradores pueden capturar distintos metadatos del elemento o formulario
|
|
|
+ que ellos decoran, es a menudo útil generar un decorador individual.
|
|
|
+ Afortunadamente, esta caracteristica es posible inicializando el método
|
|
|
+ en cada tipo de clase form (forms, sub form, display group,
|
|
|
+ element).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para hacer eso, simplemente <code>render[DecoratorName]()</code>, cuando
|
|
|
+ "[DecoratorName]" es el "nombre corto" de su decorador; opcionalmente,
|
|
|
+ puede pasar en el contenido lo que usted quiera. Por ejemplo:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// genera el elemento decorador label:
|
|
|
+echo $element->renderLabel();
|
|
|
+
|
|
|
+// genera sólo el campo display group, con algún contenido:
|
|
|
+echo $group->renderFieldset('fieldset content');
|
|
|
+
|
|
|
+// genera sólo el formulario HTML, con algún contenido:
|
|
|
+echo $form->renderHtmlTag('wrap this content');
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si el decorador no existe, una excepción es inicializada.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esto puede ser útil particularmente cuando se genera un formulario con el
|
|
|
+ decorador ViewScript; cada elemento puede usar sus decoradores adjuntos
|
|
|
+ para generar contenido, pero con un control minucioso.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.form.standardElements" xml:base="module_specs/Zend_Form-StandardElements.xml">
|
|
|
+ <title>Elementos Enviados en el Formulario Estandard de Zend Framework</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend Framework viene con clases de elementos concretos cubriendo la
|
|
|
+ mayoría de los elementos de los formularios HTML. La mayoría simplemente
|
|
|
+ especifica una vista de ayuda para usar cuando se decora el elemento,
|
|
|
+ pero varios ofrecen funcionalidad adicional. La siguiente es una lista
|
|
|
+ de todas las clases, así como también una descripción de la
|
|
|
+ funcionalidad que ofrecen.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.button">
|
|
|
+ <title>Zend_Form_Element_Button</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Usada para crear elementos HTML de tipo button,
|
|
|
+ <code>Zend_Form_Element_Button</code> extiende <link linkend="zend.form.standardElements.submit">Zend_Form_Element_Submit</link>,
|
|
|
+ derivandi sy funcionalidad personalizada. It specifies the 'formButton'
|
|
|
+ view helper for decoration.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Like the submit element, it uses the element's label as the element
|
|
|
+ value for display purposes; in other words, to set the text of the
|
|
|
+ button, set the value of the element. The label will be translated
|
|
|
+ if a translation adapter is present.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Because the label is used as part of the element, the button element
|
|
|
+ uses only the <link linkend="zend.form.standardDecorators.viewHelper">ViewHelper</link>
|
|
|
+ and <link linkend="zend.form.standardDecorators.dtDdWrapper">DtDdWrapper</link>
|
|
|
+ decorators.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Después de llenar o validar un formulario, se puede verificar si el
|
|
|
+ botón dado fue clickeado usando el método <code>isChecked()</code>.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.captcha">
|
|
|
+ <title>Zend_Form_Element_Captcha</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los CAPTCHAs son usados para prevenir el envio automático de
|
|
|
+ formularios por los robots y otros procesos automatizados.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The Captcha form element allows you to specify which
|
|
|
+ <link linkend="zend.captcha.adapters">Zend_Captcha adapter</link> you
|
|
|
+ wish to utilize as a form captcha. It then sets this adapter as a
|
|
|
+ validator to the object, and uses a Captcha decorator for rendering
|
|
|
+ (which proxies to the captcha adapter).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Adapters may be any adapters in <code>Zend_Captcha</code>, as well
|
|
|
+ as any custom adapters you may have defined elsewhere. To allow
|
|
|
+ this, you may pass an additional plugin loader type key, 'CAPTCHA'
|
|
|
+ or 'captcha', when specifying a plugin loader prefix path:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element->addPrefixPath('My_Captcha', 'My/Captcha/', 'captcha');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los Captcha entonces pueden ser cargados usando el método
|
|
|
+ <code>setCaptcha()</code>, el cual puede tomar una instancia
|
|
|
+ cualquiera de captcha instance, o el nombre corto del adaptador
|
|
|
+ captcha:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// instancia concreta:
|
|
|
+$element->setCaptcha(new Zend_Captcha_Figlet());
|
|
|
+
|
|
|
+// Usando nombre corto:
|
|
|
+$element->setCaptcha('Dumb');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si desea cargar sus elementos configuración, especifique la clave
|
|
|
+ 'captcha' con un array conteniendo la clave 'captcha', o
|
|
|
+ ambas claves 'captcha' y 'captchaOptions':
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Usindo la clave captcha simple:
|
|
|
+$element = new Zend_Form_Element_Captcha('foo', array(
|
|
|
+ 'label' => "Please verify you're a human",
|
|
|
+ 'captcha' => array(
|
|
|
+ 'captcha' => 'Figlet',
|
|
|
+ 'wordLen' => 6,
|
|
|
+ 'timeout' => 300,
|
|
|
+ ),
|
|
|
+));
|
|
|
+
|
|
|
+// Usindo captcha y captchaOptions:
|
|
|
+$element = new Zend_Form_Element_Captcha('foo', array(
|
|
|
+ 'label' => "Please verify you're a human"
|
|
|
+ 'captcha' => 'Figlet',
|
|
|
+ 'captchaOptions' => array(
|
|
|
+ 'captcha' => 'Figlet',
|
|
|
+ 'wordLen' => 6,
|
|
|
+ 'timeout' => 300,
|
|
|
+ ),
|
|
|
+));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El decorador usado es determinado consultando el adaptador captcha.
|
|
|
+ Por defecto, es usado el
|
|
|
+ <link linkend="zend.form.standardDecorators.captcha">Captcha
|
|
|
+ decorator</link>, pero un adaptadpr puede especificar uno
|
|
|
+ diferente vía su método<code>getDecorator()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como ha notado, el adaptador captcha actúa él mismo como un validador
|
|
|
+ para el elemento. Adicionalmente, el validador NotEmpty validator
|
|
|
+ no es usado y el elemento es marcado como requerido. Enla mayoría de
|
|
|
+ los casos, usted no necesitará hacer nada más para tener un captcha
|
|
|
+ presente en su formulario.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.checkbox">
|
|
|
+ <title>Zend_Form_Element_Checkbox</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las casillas de verigicación (checkboxes) HTML le permiten devolver
|
|
|
+ un valor específico, pero básicamente operata como los booleanos:
|
|
|
+ cuando está marcada, el valor es enviado; cuando no está marcada, no se envía nada. Internamente, Zend_Form_Element_Checkbox forza este
|
|
|
+ estado.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, si la casilla (checkbox) está marcada su valor es '1',
|
|
|
+ y si no está marcada su valor es '0'.
|
|
|
+ You can specify the values to use using the
|
|
|
+ <code>setCheckedValue()</code> and <code>setUncheckedValue()</code>
|
|
|
+ accessors, respectively. Internally, any time you set the value, if
|
|
|
+ the provided value matches the checked value, then it is set, but
|
|
|
+ any other value causes the unchecked value to be set.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Additionally, setting the value sets the <code>checked</code>
|
|
|
+ property of the checkbox. You can query this using
|
|
|
+ <code>isChecked()</code> or simply accessing the property. Using the
|
|
|
+ <code>setChecked($flag)</code> method will both set the state of the
|
|
|
+ flag as well as set the appropriate checked or unchecked value in the
|
|
|
+ element. Please use this method when setting the checked state of a
|
|
|
+ checkbox element to ensure the value is set properly.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element_Checkbox</code> uses the 'formCheckbox' view
|
|
|
+ helper. The checked value is always used to populate it.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.file">
|
|
|
+ <title>Zend_Form_Element_File</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The File form element provides a mechanism for supplying file upload
|
|
|
+ fields to your form. It utilizes <link linkend="zend.file.transfer.introduction">Zend_File_Transfer</link>
|
|
|
+ internally to provide this functionality, and the
|
|
|
+ <code>FormFile</code> view helper as also the <code>File</code>
|
|
|
+ decorator to display the form element.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ By default, it uses the <code>Http</code> transfer adapter, which
|
|
|
+ introspects the <code>$_FILES</code> array and allows you to attach
|
|
|
+ validators and filters. Validators and filters attached to the form
|
|
|
+ element will be attached to the transfer adapter.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.form.standardElements.file.usage">
|
|
|
+ <title>File form element usage</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The above explanation of using the File form element may seem
|
|
|
+ arcane, but actual usage is relatively trivial:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element = new Zend_Form_Element_File('foo');
|
|
|
+$element->setLabel('Upload an image:')
|
|
|
+ ->setDestination('/var/www/upload');
|
|
|
+// ensure only 1 file
|
|
|
+$element->addValidator('Count', false, 1);
|
|
|
+// limit to 100K
|
|
|
+$element->addValidator('Size', false, 102400);
|
|
|
+// only JPEG, PNG, and GIFs
|
|
|
+$element->addValidator('Extension', false, 'jpg,png,gif');
|
|
|
+$form->addElement($element, 'foo');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ También debe asegurarse de que se ha provisto un tipo de
|
|
|
+ codificación corecto al formulario; se debe utilizar
|
|
|
+ 'multipart/form-data'. Se puede hacer esto estableciendo el
|
|
|
+ atributo 'enctype' en el formulario:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->setAttrib('enctype', 'multipart/form-data');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cuando el atributo ha sido validado exitosamente, usted debe
|
|
|
+ recibir el archivo para alamacenarlo en el destino final
|
|
|
+ usando receive(). Adicionalmente puede determinar la
|
|
|
+ ubicación final usando getFileName():
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+if (!$form->isValid) {
|
|
|
+ print "Ohoh... validation error";
|
|
|
+}
|
|
|
+
|
|
|
+if (!$form->foo->receive()) {
|
|
|
+ print "Error receiving the file";
|
|
|
+}
|
|
|
+
|
|
|
+$location = $form->foo->getFileName();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Ubicaciones Predeterminadas para la Carga de Archivos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, los archivos son cargados al directorio temp del
|
|
|
+ sistema.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Valores de archivo</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Dentro de HTTP un elemento file no tiene valor. Por tanto y a
|
|
|
+ causa de razones de seguridad usted solo obtendrá el nombre del
|
|
|
+ archivo cargado llamando a getValue() y no el destino completo.
|
|
|
+ si usted necesita la información completa llame getFileName() y
|
|
|
+ le retormará el destino y nombre de archivo completo.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element_File</code> soporta también archivos
|
|
|
+ múltiples. Para llamar el método <code>setMultiFile($count)</code>
|
|
|
+ usted puede establecer la cantidad de elementos file que usted desea
|
|
|
+ crear. Esto le previene de establecer la misma configuración varias
|
|
|
+ veces.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.form.standardElements.file.multiusage">
|
|
|
+ <title>Configuración de múltiples archivos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Crear un elemento multi archivo es lo mismo que querer configurar
|
|
|
+ un elemento único. Sólo tiene que llamar a
|
|
|
+ <code>setMultiFile()</code> adicionalmente después de la creación:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element = new Zend_Form_Element_File('foo');
|
|
|
+$element->setLabel('Upload an image:')
|
|
|
+ ->setDestination('/var/www/upload');
|
|
|
+// asegura mínimo 1, maximo 3 archivos
|
|
|
+$element->addValidator('Count', false, array('min' => 1, 'max' => 3));
|
|
|
+// limita a 100K
|
|
|
+$element->addValidator('Size', false, 102400);
|
|
|
+// solo JPEG, PNG, y GIFs
|
|
|
+$element->addValidator('Extension', false, 'jpg,png,gif');
|
|
|
+// define 3 elementos file idénticos
|
|
|
+$element->setMultiFile(3);
|
|
|
+$form->addElement($element, 'foo');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En su vista usted ahora obtendrá 3 elementos para carga de
|
|
|
+ archivos idénticos los cuales comparten la misma configuración.
|
|
|
+ para obtener el conjunto de el número de archivos múltiples
|
|
|
+ simplemente llame <code>getMultiFile()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Elementos File en Subformularioss</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cuando usted use elementos file in subformularios debería
|
|
|
+ establecer nombres únicos.
|
|
|
+ Así, cuando usted nombre su elemento file en el subformulario1,
|
|
|
+ debe darle un nombre diferente el el subformulario2.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Tan pronto como haya dos elementos file nombrados de forma
|
|
|
+ idéntica, el segundo elemento no se mostrará o enviará.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para limitar el tamaño del archivo, el cual es cargado por el
|
|
|
+ cliente, debe establecer el tamaño máximo de archivo que el
|
|
|
+ formulario acepta . Esto limitará eñ tamaño del archivo en el lado
|
|
|
+ del cliente configurando la opción <code>MAX_FILE_SIZE</code>
|
|
|
+ en el formulario. Tan pronto como establesca este valor usando
|
|
|
+ el método <code>setMaxFileSize($size)</code>, estó será generado
|
|
|
+ con el elemento file.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element = new Zend_Form_Element_File('foo');
|
|
|
+$element->setLabel('Upload an image:')
|
|
|
+ ->setDestination('/var/www/upload')
|
|
|
+ ->addValidator('Size', false, 102400) // límite en 100K
|
|
|
+ ->setMaxFileSize(102400); // limita el tamaño del archivo en el lado del cliente
|
|
|
+$form->addElement($element, 'foo');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>MaxFileSize con elementos file múltiples</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cuando usted usa elementos file múltiples en los formularios tiene
|
|
|
+ que establecer el <code>MAX_FILE_SIZE</code> una sola vez.
|
|
|
+ Establecerlo otra vez sobreescribirá el valor previamente
|
|
|
+ establecido.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Note, que usted puede establecer <code>MAX_FILE_SIZE</code>
|
|
|
+ una sola ves, incluso si usas múltiples formularios.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.hidden">
|
|
|
+ <title>Zend_Form_Element_Hidden</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los elementos Hidden simplemente injectan datos que deben ser
|
|
|
+ enviados, pero que el usuario no debe manipular.
|
|
|
+ <code>Zend_Form_Element_Hidden</code> logra esto através del uso de
|
|
|
+ el helper de vista 'formHidden'.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.hash">
|
|
|
+ <title>Zend_Form_Element_Hash</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Este elemento provee protección de ataques desde CSRF sobre
|
|
|
+ formularios, asegurando que el dato es enviado por la sesión del
|
|
|
+ usuario que generó el formulario y no por un script pillero.
|
|
|
+ La protección se logra mediante la adición de un elemento hash a
|
|
|
+ un formulario y verificandolo cuando el formulario es enviado.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El nombre del elemnto hash debe ser único. Se recomienda usar la
|
|
|
+ opción <literal>salt</literal> para el elemento, dos hashes con
|
|
|
+ el mismo nombre y diferentes salts no chocan:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->addElement('hash', 'no_csrf_foo', array('salt' => 'unique'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede establecer el salt más tarde usando el método
|
|
|
+ <code>setSalt($salt)</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Internamente, el elemento alamacena un identificador único usando
|
|
|
+ <code>Zend_Session_Namespace</code>, y lo comprueba en el momento
|
|
|
+ que se envía (comprueba que el TTL has no espiró). El validador
|
|
|
+ 'Identical' entonces es usado para asegurarse que el hash enviado
|
|
|
+ marcha con el hash alamacenado.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El helper de vista 'formHidden' es usado par generar el elemento
|
|
|
+ en el formulario.
|
|
|
+ form.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.Image">
|
|
|
+ <title>Zend_Form_Element_Image</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las imáagenes pueden ser usadas como elmentos de formulario, y le
|
|
|
+ permite especificar elementos gráficos como botones de formulario.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los elementos Image necesitan una imagen fuente.
|
|
|
+ <code>Zend_Form_Element_Image</code> le permite especificar esto
|
|
|
+ usando el método de acceso <code>setImage()</code>
|
|
|
+ (o clave de configuración 'image'). Opcionalmente, también puede
|
|
|
+ especificar un valor para utilizar al momento de enviar la imagen
|
|
|
+ utilizando el método de acceso <code>setImageValue()</code>
|
|
|
+ (o clave de configuración 'imageValue'). Cuando el valor establecido
|
|
|
+ para el elemento son similares al <code>imageValue</code>, entonces
|
|
|
+ el método de acceso <code>isChecked()</code> devolverá true.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El elemento Image usa el
|
|
|
+ <link linkend="zend.form.standardDecorators.image">Decorador de
|
|
|
+ Imagen </link> para generar (así como el estandard Errors,
|
|
|
+ HtmlTag, y decorador Label). Opcionalmente, puede especificar una
|
|
|
+ etiqueta para el decorador <code>Image</code> que luego
|
|
|
+ envuelva al elemento imagen.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.multiCheckbox">
|
|
|
+ <title>Zend_Form_Element_MultiCheckbox</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A menudo tiene un conjunto de checkboxes, y desea agrupar los
|
|
|
+ resultados. Esto es como un
|
|
|
+ <link linkend="zend.form.standardElements.multiselect">Multiselect</link>,
|
|
|
+ pero en lugar de estar en una lista desplegable, necesita mostrarlos en pares checkbox/value (casilla de verificación/valor).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element_MultiCheckbox</code> hace esto sencillo. Like
|
|
|
+ all other elements extending the base Multi element, you can specify
|
|
|
+ a list of options, and easily validate against that same list. The
|
|
|
+ 'formMultiCheckbox' view helper ensures that these are returned as
|
|
|
+ an array in the form submission.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ By default, this element registers an <code>InArray</code> validator
|
|
|
+ which validates against the array keys of registered options. You
|
|
|
+ can disable this behavior by either calling
|
|
|
+ <code>setRegisterInArrayValidator(false)</code>, or by passing a
|
|
|
+ false value to the <code>registerInArrayValidator</code>
|
|
|
+ configuration key.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You may manipulate the various checkbox options using the following
|
|
|
+ methods:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>addMultiOption($option, $value)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addMultiOptions(array $options)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setMultiOptions(array $options)</code>
|
|
|
+ (overwrites existing options)</para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>getMultiOption($option)</para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>getMultiOptions()</para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>removeMultiOption($option)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>clearMultiOptions()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ To mark checked items, you need to pass an array of values to
|
|
|
+ <code>setValue()</code>. The following will check the values "bar"
|
|
|
+ and "bat":
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$element = new Zend_Form_Element_MultiCheckbox('foo', array(
|
|
|
+ 'multiOptions' => array(
|
|
|
+ 'foo' => 'Foo Option',
|
|
|
+ 'bar' => 'Bar Option',
|
|
|
+ 'baz' => 'Baz Option',
|
|
|
+ 'bat' => 'Bat Option',
|
|
|
+ );
|
|
|
+));
|
|
|
+
|
|
|
+$element->setValue(array('bar', 'bat'));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Note that even when setting a single value, you must pass an array.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.multiselect">
|
|
|
+ <title>Zend_Form_Element_Multiselect</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ XHTML <code>select</code> elements allow a 'multiple' attribute,
|
|
|
+ indicating multiple options may be selected for submission, instead
|
|
|
+ of the usual one. <code>Zend_Form_Element_Multiselect</code> extends
|
|
|
+ <link linkend="zend.form.standardElements.select">Zend_Form_Element_Select</link>,
|
|
|
+ and sets the <code>multiple</code> attribute to 'multiple'. Like
|
|
|
+ other classes that inherit from the base
|
|
|
+ <code>Zend_Form_Element_Multi</code> class, you can manipulate the
|
|
|
+ options for the select using:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>addMultiOption($option, $value)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addMultiOptions(array $options)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setMultiOptions(array $options)</code>
|
|
|
+ (overwrites existing options)</para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>getMultiOption($option)</para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>getMultiOptions()</para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>removeMultiOption($option)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>clearMultiOptions()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If a translation adapter is registered with the form and/or element,
|
|
|
+ option values will be translated for display purposes.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ By default, this element registers an <code>InArray</code> validator
|
|
|
+ which validates against the array keys of registered options. You
|
|
|
+ can disable this behavior by either calling
|
|
|
+ <code>setRegisterInArrayValidator(false)</code>, or by passing a
|
|
|
+ false value to the <code>registerInArrayValidator</code>
|
|
|
+ configuration key.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.password">
|
|
|
+ <title>Zend_Form_Element_Password</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Password elements are basically normal text elements -- except that
|
|
|
+ you typically do not want the submitted password displayed in error
|
|
|
+ messages or the element itself when the form is re-displayed.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element_Password</code> achieves this by calling
|
|
|
+ <code>setObscureValue(true)</code> on each validator (ensuring that
|
|
|
+ the password is obscured in validation error messages), and using
|
|
|
+ the 'formPassword' view helper (which does not display the value
|
|
|
+ passed to it).
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.radio">
|
|
|
+ <title>Zend_Form_Element_Radio</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Radio elements allow you to specify several options, of which you
|
|
|
+ need a single value returned. <code>Zend_Form_Element_Radio</code>
|
|
|
+ extends the base <code>Zend_Form_Element_Multi</code> class,
|
|
|
+ allowing you to specify a number of options, and then uses the
|
|
|
+ <code>formRadio</code> view helper to display these.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ By default, this element registers an <code>InArray</code> validator
|
|
|
+ which validates against the array keys of registered options. You
|
|
|
+ can disable this behavior by either calling
|
|
|
+ <code>setRegisterInArrayValidator(false)</code>, or by passing a
|
|
|
+ false value to the <code>registerInArrayValidator</code>
|
|
|
+ configuration key.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Like all elements extending the Multi element base class, the
|
|
|
+ following methods may be used to manipulate the radio options
|
|
|
+ displayed:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>addMultiOption($option, $value)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addMultiOptions(array $options)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setMultiOptions(array $options)</code>
|
|
|
+ (overwrites existing options)</para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>getMultiOption($option)</para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>getMultiOptions()</para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>removeMultiOption($option)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>clearMultiOptions()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.reset">
|
|
|
+ <title>Zend_Form_Element_Reset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Reset buttons are typically used to clear a form, and are not part
|
|
|
+ of submitted data. However, as they serve a purpose in the display,
|
|
|
+ they are included in the standard elements.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element_Reset</code> extends <link linkend="zend.form.standardElements.submit">Zend_Form_Element_Submit</link>.
|
|
|
+ As such, the label is used for the button display, and will be
|
|
|
+ translated if a translation adapter is present. It utilizes only the
|
|
|
+ 'ViewHelper' and 'DtDdWrapper' decorators, as there should never be
|
|
|
+ error messages for such elements, nor will a label be necessary.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.select">
|
|
|
+ <title>Zend_Form_Element_Select</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Select boxes are a common way of limiting to specific choices for a
|
|
|
+ given form datum. <code>Zend_Form_Element_Select</code> allows you
|
|
|
+ to generate these quickly and easily.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ By default, this element registers an <code>InArray</code> validator
|
|
|
+ which validates against the array keys of registered options. You
|
|
|
+ can disable this behavior by either calling
|
|
|
+ <code>setRegisterInArrayValidator(false)</code>, or by passing a
|
|
|
+ false value to the <code>registerInArrayValidator</code>
|
|
|
+ configuration key.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ As it extends the base Multi element, the following methods may be
|
|
|
+ used to manipulate the select options:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para><code>addMultiOption($option, $value)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>addMultiOptions(array $options)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>setMultiOptions(array $options)</code>
|
|
|
+ (overwrites existing options)</para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>getMultiOption($option)</para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>getMultiOptions()</para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>removeMultiOption($option)</code></para></listitem>
|
|
|
+
|
|
|
+ <listitem><para><code>clearMultiOptions()</code></para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element_Select</code> uses the 'formSelect' view
|
|
|
+ helper for decoration.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.submit">
|
|
|
+ <title>Zend_Form_Element_Submit</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Submit buttons are used to submit a form. You may use multiple
|
|
|
+ submit buttons; you can use the button used to submit the form to
|
|
|
+ decide what action to take with the data submitted.
|
|
|
+ <code>Zend_Form_Element_Submit</code> makes this decisioning easy,
|
|
|
+ by adding a <code>isChecked()</code> method; as only one button
|
|
|
+ element will be submitted by the form, after populating or
|
|
|
+ validating the form, you can call this method on each submit button
|
|
|
+ to determine which one was used.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form_Element_Submit</code> uses the label as the "value"
|
|
|
+ of the submit button, translating it if a translation adapter is
|
|
|
+ present. <code>isChecked()</code> checks the submitted value against
|
|
|
+ the label in order to determine if the button was used.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The <link linkend="zend.form.standardDecorators.viewHelper">ViewHelper</link>
|
|
|
+ and <link linkend="zend.form.standardDecorators.dtDdWrapper">DtDdWrapper</link>
|
|
|
+ decorators to render the element. No label decorator is used, as the
|
|
|
+ button label is used when rendering the element; also, typically,
|
|
|
+ you will not associate errors with a submit element.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.text">
|
|
|
+ <title>Zend_Form_Element_Text</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ By far the most prevalent type of form element is the text element,
|
|
|
+ allowing for limited text entry; it's an ideal element for most data
|
|
|
+ entry. <code>Zend_Form_Element_Text</code> simply uses the
|
|
|
+ 'formText' view helper to display the element.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardElements.textarea">
|
|
|
+ <title>Zend_Form_Element_Textarea</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Textareas are used when large quantities of text are expected, and
|
|
|
+ place no limits on the amount of text submitted (other than maximum
|
|
|
+ size limits as dictated by your server or PHP).
|
|
|
+ <code>Zend_Form_Element_Textarea</code> uses the 'textArea' view
|
|
|
+ helper to display such elements, placing the value as the content of
|
|
|
+ the element.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 tw=80 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.form.standardDecorators" xml:base="module_specs/Zend_Form-StandardDecorators.xml">
|
|
|
+ <title>Decoradores de Formulario (Form Decorartors) estándar contenidos en Zend Framework</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form</code> se distribuye con distintos decoradores estándar. Para más
|
|
|
+ información sobre el uso de decoradores en general, vea <link linkend="zend.form.decorators">la sección sobre decoradores</link>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.callback">
|
|
|
+ <title>Zend_Form_Decorator_Callback</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El decorador Callback (llamada de retorno) permite ejecutar una llamada de retorno para
|
|
|
+ mostrar el contenido. Las llamadas de retorno deben especificarse a través
|
|
|
+ de la opción 'callback' pasada en la configuración del decorador, y pueden
|
|
|
+ ser de cualquier valor de llamada de retorno PHP. Los Callbacks deben
|
|
|
+ aceptar tres argumentos: <code>$content</code> (el contenido original
|
|
|
+ enviado al decorador), <code>$element</code> (el objeto que se está decorando),
|
|
|
+ y un array de <code>$options</code>. Un callback de ejemplo sería:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class Util
|
|
|
+{
|
|
|
+ public static function label($content, $element, array $options)
|
|
|
+ {
|
|
|
+ return '<span class="label">' . $element->getLabel() . "</span>";
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Esta llamada de retorno se especificaría como <code>array('Util',
|
|
|
+ 'label')</code>, y generaría un (mal) código HTML para
|
|
|
+ la etiqueta. El decorador Callback reemplazará, antepondrá o postpondrá
|
|
|
+ el contenido original con el que devuelva.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El decorador Callback permite especificar un valor null para la opción
|
|
|
+ placement (colocación), que reemplazará el contenido original
|
|
|
+ con el valor devuelto de la llamada de retorno; 'prepend' (anteponer) y 'append' (postponer)
|
|
|
+ siguen siendo válidas.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.captcha">
|
|
|
+ <title>Zend_Form_Decorator_Captcha</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El decorador Captcha se usa junto con el <link linkend="zend.form.standardElements.captcha">elemento de formulario Captcha</link>. Utiliza el método
|
|
|
+ <code>render()</code> del adaptador del captcha para generar la salida.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Una variante del decorador Captcha, 'Captcha_Word', es usada frecuentemente,
|
|
|
+ y crea dos elementos, un id y una entrada (input). El id indica
|
|
|
+ el identificador de sesión que hay que comparar, y la entrada es para
|
|
|
+ la verificación de usuario del captcha. Éstos elementos son validados
|
|
|
+ como un sólo elemento.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.description">
|
|
|
+ <title>Zend_Form_Decorator_Description</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El decorador Description puede ser usado para mostrar un conjunto de descripciones
|
|
|
+ de un elemento <code>Zend_Form</code>, <code>Zend_Form_Element</code>, o
|
|
|
+ <code>Zend_Form_DisplayGroup</code>; toma la descripción usando el método
|
|
|
+ <code>getDescription()</code> del objeto.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, si no se encuentra la descripción, no se genera ninguna salida.
|
|
|
+ Si la descripción está presente, entonces se envolverá en una etiqueta
|
|
|
+ <code>p</code> HTML por defecto, aunque tiene la posibilidad de especificar
|
|
|
+ una etiqueta pasando una opción <code>tag</code> al crear el decorador, o
|
|
|
+ llamando a <code>setTag()</code>. También puede especificar una clase
|
|
|
+ para el tag usando la opción <code>class</code> o llamando a
|
|
|
+ <code>setClass()</code>; por defecto, se usa la clase 'hint'.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La descripción es escapada utilizando los mecanismos de escapado por defecto
|
|
|
+ del objeto de vista. Puede desactivar esto pasando un valor
|
|
|
+ <code>false</code> a la opción 'escape' del decorador o el método
|
|
|
+ <code>setEscape()</code>.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.dtDdWrapper">
|
|
|
+ <title>Zend_Form_Decorator_DtDdWrapper</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los decoradores por defecto utilizan listas de definición
|
|
|
+ (<code><dl></code>) para generar elementos de formulario (form).
|
|
|
+ Dato que los elementos de formulario pueden aparecer en cualquier orden,
|
|
|
+ grupos de visualización y subformularios pueden ser encapsulados dentro de
|
|
|
+ otros elementos de formulario. Para mantener estos tipos de elemento particulares
|
|
|
+ dentro de la lista de definición, DtDdWrapper crea una nuevo término de definición
|
|
|
+ vacío (definition term)(<code><dt></code>) y encapsula su contenido
|
|
|
+ en un nuevo dato de definición (<code><dd></code>).
|
|
|
+ La salida queda como sigue:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="html"><![CDATA[
|
|
|
+<dt></dt>
|
|
|
+<dd><fieldset id="subform">
|
|
|
+ <legend>Información de Usuario</legend>
|
|
|
+ ...
|
|
|
+</fieldset></dd>
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Este decorador reemplaza el contenido que se le provee
|
|
|
+ envolviéndolo dentro del elemento <code><dd></code>.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.errors">
|
|
|
+ <title>Zend_Form_Decorator_Errors</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los errores de elemento obtienen su propio decorador con el decorador
|
|
|
+ de errores. Este decorador sustituye al view helper FormErrors,
|
|
|
+ que genera mensajes de error en una lista no ordenada
|
|
|
+ (<code><ul></code>) como elementos de lista (li). El elemento
|
|
|
+ <code><ul></code> recibe una clase de "errores".
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El decorador de Errores puede anteponerse o postponerse al contenido
|
|
|
+ que se le provee.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.fieldset">
|
|
|
+ <title>Zend_Form_Decorator_Fieldset</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, los grupos de visualización y subformularios generan sus contenidos dentro
|
|
|
+ de fieldsets, EL decorador Fieldset busca la opción
|
|
|
+ 'legend' o bien el método <code>getLegend()</code> en el elemento
|
|
|
+ registrado, y lo usa como campo "legend" si no es vacío. Cualquier
|
|
|
+ contenido pasado es envuelto en el fieldset HTML, reemplazando
|
|
|
+ al contenido original. Cualquier atributo pasado al elemento decorado
|
|
|
+ será generado como atributo del fieldset HTML.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.file">
|
|
|
+ <title>Zend_Form_Decorator_File</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los elementos de tipo "File" (upload de ficheros) tienen una notación especial
|
|
|
+ cuando se usan múltiples elementos file o subformularios. El decorador
|
|
|
+ File es usado por <code>Zend_Form_Element_File</code> y permite fijar
|
|
|
+ múltiples elementos file con una única llamada al método. Se usa automáticamente
|
|
|
+ y fija el nombre de cada elemento.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.form">
|
|
|
+ <title>Zend_Form_Decorator_Form</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los objetos <code>Zend_Form</code> normalmente necesitan generar una etiqueta
|
|
|
+ HTML "form". El decorador Form utiliza la ayuda del view helper Form. Encapsula
|
|
|
+ cualquier contenido provista en un elemento HTML form, usando la acción y el
|
|
|
+ método del objeto Zend Form, y cualquier atributo como atributo HTML.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.formElements">
|
|
|
+ <title>Zend_Form_Decorator_FormElements</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los formularios(forms), grupos de visualización y subformularios
|
|
|
+ son colecciones de elementos. Para poder generar estos elementos,
|
|
|
+ utilizan el decorador FormElements, el cual itera sobre todos los elementos,
|
|
|
+ llamando a <code>render()</code> en cada uno de ellos y uniéndolos
|
|
|
+ con el separador indicado. Puede anteponer o postponer al contenido que
|
|
|
+ se le envía.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.formErrors">
|
|
|
+ <title>Zend_Form_Decorator_FormErrors</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Algunos desarrolladores y diseñadores prefieren agrupar todos los
|
|
|
+ mensajes de error en la parte superior del formulario. El decorador
|
|
|
+ FormErrors le permite hacer esto.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, la lista de errores generada tiene el siguiente marcado:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="html"><![CDATA[
|
|
|
+<ul class="form-errors">
|
|
|
+ <li><b>[etiqueta de elemento o nombre]</b><ul>
|
|
|
+ <li>[mensaje de error]</li>
|
|
|
+ <li>[mensaje de error]</li>
|
|
|
+ </ul>
|
|
|
+ </li>
|
|
|
+ <li><ul>
|
|
|
+ <li><b>[etiqueta o nombre de elemento subformulario</b><ul>
|
|
|
+ <li>[mensaje de error]</li>
|
|
|
+ <li>[mensaje de error]</li>
|
|
|
+ </ul>
|
|
|
+ </li>
|
|
|
+ </ul></li>
|
|
|
+</ul>
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede pasar como parámetro varias opciones para configurar la salida generada:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>ignoreSubForms</code>: se desactiva o no la recursividad
|
|
|
+ en los subformularios. Por defecto: false (i.e., permitir recursividad).
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>markupElementLabelEnd</code>: Marcado para postponer las etiquetas de elementos. Por defecto: '</b>'
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>markupElementLabelStart</code>: Marcado para anteponer las etiquetas de elementos. Por defecto'<b>'
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>markupListEnd</code>: Marcado para postponer listas de mensajes de error. Por defecto: '</ul>'.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>markupListItemEnd</code>: Marcado para postponer mensajes de error individuales. Por defecto: '</li>'
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>markupListItemStart</code>: Marcado para anteponer mensajes de error individuales. Por defecto: '<li>'
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>markupListStart</code>: Marcado para anteponer listas de mensajes de error. Por defecto: '<ul class="form-errors">'
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El decorador FormErrors puede anteponerse o postponerse al contenido
|
|
|
+ que se le provee.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.htmlTag">
|
|
|
+ <title>Zend_Form_Decorator_HtmlTag</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El decorador HtmlTag le permite utilizar etiquetas HTML para
|
|
|
+ decorador el contenido; la etiqueta utiliza es pasada en la opción 'tag'
|
|
|
+ , y cualquier otra opción es usada como atributo HTML de esa etiqueta.
|
|
|
+ Por defecto, el contenido generado reemplaza al contenido envolviéndolo en
|
|
|
+ la etiqueta dada. De cualquier forma, se permite especificar una
|
|
|
+ localización de tipo 'append' (postponer) o 'prepend' (anteponer).
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.image">
|
|
|
+ <title>Zend_Form_Decorator_Image</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El decorador Image le permite crear un input HTML de tipo image
|
|
|
+ (<code><input type="image" ... /></code>), y opcionalmente
|
|
|
+ mostrarlo dentro de otro tag HTML.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, el decorador usa la propiedad src del elemento,
|
|
|
+ que puede fijarse con el método <code>setImage()</code>, como la ruta
|
|
|
+ de la imagen ('src'). Adicionalmente, la etiqueta del elemento será usada
|
|
|
+ como la etiqueta 'alt', y <code>imageValue</code> (manipulado con los
|
|
|
+ métodos <code>setImageValue()</code> y
|
|
|
+ <code>getImageValue()</code>) será usada como el campo 'value'.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para especificar una etiqueta HTML que utilizar con el elemento, pase la opción
|
|
|
+ 'tag' al decorador, o llame explícitamente a
|
|
|
+ <code>setTag()</code>.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.label">
|
|
|
+ <title>Zend_Form_Decorator_Label</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Comúnmente, los elementos de formulario tienen etiquetas (labels) y se
|
|
|
+ usa el decorador Label para generar esas etiquetas.
|
|
|
+ Utiliza la ayuda del view helper FormLabel,
|
|
|
+ y toma la etiqueta del elemento mediante el método
|
|
|
+ <code>getLabel()</code> de ese elemento. Si no se encuentra
|
|
|
+ la etiqueta, no se genera. Por defecto, las etiquetas se
|
|
|
+ traducen cuando existe un adaptador de traducciones y existe una
|
|
|
+ traducción para la etiqueta.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Opcionalmente, se puede especificar la opción 'tag'; si se suministra, encapsula
|
|
|
+ la etiqueta en la etiqueta HTML en cuestión. Si la opción está presenta
|
|
|
+ pero no hay etiqueta, la etiqueta será generada sin contenido.
|
|
|
+ Puede especificar la clase que usar con la etiqueta mediante la opción
|
|
|
+ 'class' o llamando a <code>setClass()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Adicionalmente, se pueden especificar prefijos o sufijos que usar
|
|
|
+ al mostrar en pantalla los elementos, basados en si la etiqueta es para
|
|
|
+ un elemento opcional o requerido. Por ejemplo, podríamos querer
|
|
|
+ añadir ':' a la etiqueta o un '*', indicando que el elemento es requerido.
|
|
|
+ Se puede realizar con las siguientes opciones y métodos:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>optionalPrefix</code>: fija el texto antepuesto a la etiqueta
|
|
|
+ cuando el elemento es opcional. Utilice los accesores
|
|
|
+ <code>setOptionalPrefix()</code> y
|
|
|
+ <code>getOptionalPrefix()</code> para manipularlo.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>optionalSuffix</code>: fija el texto pospuesto a la etiqueta
|
|
|
+ cuando el elemento es opcional. Utilice los accesores
|
|
|
+ <code>setOptionalSuffix()</code> y
|
|
|
+ <code>getOptionalSuffix()</code> para manipularlo.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>requiredPrefix</code>: fija el texto antepuesto a la etiqueta
|
|
|
+ cuando el elemento es requerido. Utilice los accesores
|
|
|
+ <code>setRequiredPrefix()</code> y
|
|
|
+ <code>getRequiredPrefix()</code> para manipularlo.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>requiredSuffix</code>: fija el texto antepuesto a la etiqueta
|
|
|
+ cuando el elemento es requerido. Utilice los accesores
|
|
|
+ <code>setRequiredSuffix()</code> y
|
|
|
+ <code>getRequiredSuffix()</code> para manipularlo.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, el decorador Label antecede al contenido provisto;
|
|
|
+ especifique la opción 'placement' (colocación) como 'append' para
|
|
|
+ colocarlo después del contenido.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.prepareElements">
|
|
|
+ <title>Zend_Form_Decorator_PrepareElements</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Formularios, grupos de visualización, y subformularios son colecciones
|
|
|
+ de elementos. Al usar el decorador <link linkend="zend.form.standardDecorators.viewScript">ViewScript</link>
|
|
|
+ con un formulario o subformulario, resulta útil el poder fijar
|
|
|
+ recursívamente el objeto de vista, el traductor (translator)y todos los
|
|
|
+ nombres relacionados (determinados por la notiación de tabla del subformulario).
|
|
|
+ Esta tarea puede realizarse gracias al decorador
|
|
|
+ 'PrepareElements'. Normalmente, se indicará como el primer
|
|
|
+ decorador en al lista.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$form->setDecorators(array(
|
|
|
+ 'PrepareElements',
|
|
|
+ array('ViewScript', array('viewScript' => 'form.phtml')),
|
|
|
+));
|
|
|
+]]></programlisting>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.viewHelper">
|
|
|
+ <title>Zend_Form_Decorator_ViewHelper</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La mayoría de los elementos utiliza helpers <code>Zend_View</code>
|
|
|
+ para generar el contenido, y esto se realiza con el decorador ViewHelper.
|
|
|
+ Con él, se puede especificar una etiqueta 'helper' para fijar
|
|
|
+ explicitamente el view helper que utilizar; si no se suministra ninguno,
|
|
|
+ utiliza el último segmento del nombre de clase del elemento para determinar
|
|
|
+ el helper, anteponiéndole la cadena 'form': e.g., 'Zend_Form_Element_Text'
|
|
|
+ buscaría un view helper del tipo 'formText'.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cualquier atributo del elemento suministrado es pasado al view helper
|
|
|
+ como atributo del elemento.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto, este decorador postpone el contenido; utilice la opción 'placement'
|
|
|
+ para especificar una localización distinta.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.standardDecorators.viewScript">
|
|
|
+ <title>Zend_Form_Decorator_ViewScript</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A veces es necesario usar un view script para crear elementos;
|
|
|
+ De esta forma, se puede tener un control preciso sobre los elementos;
|
|
|
+ entregar el view script a un diseñador, o simplemente crear
|
|
|
+ una forma fácil de sobreescribir basado en el módulo que se esté usando.
|
|
|
+ El decorador ViewScript soluciona este problema.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El decorador ViewScript requiere una opción 'viewScript', o bien suministrada
|
|
|
+ al decorador, o bien como atributo del elemento. Entonces genera ese script de vista como un
|
|
|
+ script parcial, lo que significa que cada llamada a él tiene su propio espacio de variables;
|
|
|
+ Ninguna variable de la vista será rellenada, aparte del elemento en sí. Distintas variables son
|
|
|
+ entonces rellenadas:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>element</code>: el elemento decorado
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>content</code>: el contenido pasado al decorador
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>decorator</code>: el propio objeto decorador
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Del mismo modo, todas las opciones pasadas al decorador a través de
|
|
|
+ <code>setOptions()</code> que no son usadas internamente (tales
|
|
|
+ como placement, separator, etc.) son pasadas como
|
|
|
+ variables de vista.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Como ejemplo, se pueden tener el siguiente elemento:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Fija un decorador ViewScript a un único elemento ,
|
|
|
+// especificando como opción el script de vista (obligatorio) y algunas opciones extra
|
|
|
+$element->setDecorators(array(array('ViewScript', array(
|
|
|
+ 'viewScript' => '_element.phtml',
|
|
|
+ 'class' => 'form element'
|
|
|
+))));
|
|
|
+
|
|
|
+// o especificando el viewScript como un atributo del elemento:
|
|
|
+$element->viewScript = '_element.phtml';
|
|
|
+$element->setDecorators(array(array('ViewScript',
|
|
|
+ array('class' => 'form element'))));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un view script puede tener el siguiente aspecto:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+<div class="<?= $this->class ?>">
|
|
|
+ <?= $this->formLabel($this->element->getName(),
|
|
|
+ $this->element->getLabel()) ?>
|
|
|
+ <?= $this->{$this->element->helper}(
|
|
|
+ $this->element->getName(),
|
|
|
+ $this->element->getValue(),
|
|
|
+ $this->element->getAttribs()
|
|
|
+ ) ?>
|
|
|
+ <?= $this->formErrors($this->element->getMessages()) ?>
|
|
|
+ <div class="hint"><?= $this->element->getDescription() ?></div>
|
|
|
+</div>
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>Reemplazar contenido con un script de vista (view script)</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Resulta interesante que el script de vista reemplace el
|
|
|
+ contenido provisto por el decorador -- por ejemplo, si desea encapsularlo.
|
|
|
+ Puede hacer esto especificando un valor booleano false en la
|
|
|
+ opción 'placement' del decorador:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// En la creación del decorador:
|
|
|
+$element->addDecorator('ViewScript', array('placement' => false));
|
|
|
+
|
|
|
+// Aplicado a una instancia de un decorador ya existente:
|
|
|
+$decorator->setOption('placement', false);
|
|
|
+
|
|
|
+// Aplicado a un decorador ya asociado a un elemento:
|
|
|
+$element->getDecorator('ViewScript')->setOption('placement', false);
|
|
|
+
|
|
|
+// Dentro de un view script usado por un decorador:
|
|
|
+$this->decorator->setOption('placement', false);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Se recomienda usar el decorador ViewScript cuando necesite un control
|
|
|
+ muy preciso sobre cómo generados sus elementos.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 tw=80 et:
|
|
|
+-->
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Form-I18n.xml"/>
|
|
|
+ <sect1 id="zend.form.advanced" xml:base="module_specs/Zend_Form-Advanced.xml">
|
|
|
+ <title>Uso avanzado de Zend_Form</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form</code> tiene una riqueza de funcionalidad, has a wealth of functionality, muchas de ellas diregidas
|
|
|
+ a expertos desarroladores. Este capítulo tiene por objeto al documento algunas de estas
|
|
|
+ funcionalidades con ejemplos y casos de uso.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.advanced.arrayNotation">
|
|
|
+ <title>Notación de array</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Muchos desarroladores experimentados les gusta agrupar elementos de formulario
|
|
|
+ usando notación de array en los nombres de elementos. Por ejemplo, si se tiene
|
|
|
+ dos direcciones que se desea capturar, un envio y una dirección de facturación,
|
|
|
+ se puede tener elementos identicos; agrupandolos en un array se puede
|
|
|
+ asegurar que son capturados por separado. Toma el siguiente fomrulario
|
|
|
+ por ejemplo:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="html"><![CDATA[
|
|
|
+<form>
|
|
|
+ <fieldset>
|
|
|
+ <legend>Shipping Address</legend>
|
|
|
+ <dl>
|
|
|
+ <dt><label for="recipient">Ship to:</label></dt>
|
|
|
+ <dd><input name="recipient" type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="address">Address:</label></dt>
|
|
|
+ <dd><input name="address" type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="municipality">City:</label></dt>
|
|
|
+ <dd><input name="municipality" type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="province">State:</label></dt>
|
|
|
+ <dd><input name="province" type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="postal">Postal Code:</label></dt>
|
|
|
+ <dd><input name="postal" type="text" value="" /></dd>
|
|
|
+ </dl>
|
|
|
+ </fieldset>
|
|
|
+
|
|
|
+ <fieldset>
|
|
|
+ <legend>Billing Address</legend>
|
|
|
+ <dl>
|
|
|
+ <dt><label for="payer">Bill To:</label></dt>
|
|
|
+ <dd><input name="payer" type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="address">Address:</label></dt>
|
|
|
+ <dd><input name="address" type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="municipality">City:</label></dt>
|
|
|
+ <dd><input name="municipality" type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="province">State:</label></dt>
|
|
|
+ <dd><input name="province" type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="postal">Postal Code:</label></dt>
|
|
|
+ <dd><input name="postal" type="text" value="" /></dd>
|
|
|
+ </dl>
|
|
|
+ </fieldset>
|
|
|
+
|
|
|
+ <dl>
|
|
|
+ <dt><label for="terms">I agree to the Terms of Service</label></dt>
|
|
|
+ <dd><input name="terms" type="checkbox" value="" /></dd>
|
|
|
+
|
|
|
+ <dt></dt>
|
|
|
+ <dd><input name="save" type="submit" value="Save" /></dd>
|
|
|
+ </dl>
|
|
|
+</form>
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En este ejemplo, la facturación y la dirección de envío contienen algunos
|
|
|
+ campos identicos, eso significa uno puede sobre escribir al otro. Nosotros podemos
|
|
|
+ resolver esta solución usando una notación de array:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="html"><![CDATA[
|
|
|
+<form>
|
|
|
+ <fieldset>
|
|
|
+ <legend>Shipping Address</legend>
|
|
|
+ <dl>
|
|
|
+ <dt><label for="shipping-recipient">Ship to:</label></dt>
|
|
|
+ <dd><input name="shipping[recipient]" id="shipping-recipient"
|
|
|
+ type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="shipping-address">Address:</label></dt>
|
|
|
+ <dd><input name="shipping[address]" id="shipping-address"
|
|
|
+ type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="shipping-municipality">City:</label></dt>
|
|
|
+ <dd><input name="shipping[municipality]" id="shipping-municipality"
|
|
|
+ type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="shipping-province">State:</label></dt>
|
|
|
+ <dd><input name="shipping[province]" id="shipping-province"
|
|
|
+ type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="shipping-postal">Postal Code:</label></dt>
|
|
|
+ <dd><input name="shipping[postal]" id="shipping-postal"
|
|
|
+ type="text" value="" /></dd>
|
|
|
+ </dl>
|
|
|
+ </fieldset>
|
|
|
+
|
|
|
+ <fieldset>
|
|
|
+ <legend>Billing Address</legend>
|
|
|
+ <dl>
|
|
|
+ <dt><label for="billing-payer">Bill To:</label></dt>
|
|
|
+ <dd><input name="billing[payer]" id="billing-payer"
|
|
|
+ type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="billing-address">Address:</label></dt>
|
|
|
+ <dd><input name="billing[address]" id="billing-address"
|
|
|
+ type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="billing-municipality">City:</label></dt>
|
|
|
+ <dd><input name="billing[municipality]" id="billing-municipality"
|
|
|
+ type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="billing-province">State:</label></dt>
|
|
|
+ <dd><input name="billing[province]" id="billing-province"
|
|
|
+ type="text" value="" /></dd>
|
|
|
+
|
|
|
+ <dt><label for="billing-postal">Postal Code:</label></dt>
|
|
|
+ <dd><input name="billing[postal]" id="billing-postal"
|
|
|
+ type="text" value="" /></dd>
|
|
|
+ </dl>
|
|
|
+ </fieldset>
|
|
|
+
|
|
|
+ <dl>
|
|
|
+ <dt><label for="terms">I agree to the Terms of Service</label></dt>
|
|
|
+ <dd><input name="terms" type="checkbox" value="" /></dd>
|
|
|
+
|
|
|
+ <dt></dt>
|
|
|
+ <dd><input name="save" type="submit" value="Save" /></dd>
|
|
|
+ </dl>
|
|
|
+</form>
|
|
|
+]]>
|
|
|
+</programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In the above sample, we now get separate addresses. In the submitted
|
|
|
+ form, we'll now have three elements, the 'save' element for the
|
|
|
+ submit, and then two arrays, 'shipping' and 'billing', each with
|
|
|
+ keys for their various elements.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form</code> attempts to automate this process with its
|
|
|
+ <link linkend="zend.form.forms.subforms">sub forms</link>. By
|
|
|
+ default, sub forms render using the array notation as shown in the
|
|
|
+ previous HTML form listing, complete with ids. The array name is
|
|
|
+ based on the sub form name, with the keys based on the elements
|
|
|
+ contained in the sub form. Sub forms may be nested arbitrarily deep,
|
|
|
+ and this will create nested arrays to reflect the structure.
|
|
|
+ Additionally, the various validation routines in
|
|
|
+ <code>Zend_Form</code> honor the array structure, ensuring that your
|
|
|
+ form validates correctly, no matter how arbitrarily deep you nest
|
|
|
+ your sub forms. You need do nothing to benefit from this; this
|
|
|
+ behaviour is enabled by default.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Additionally, there are facilities that allow you to turn on array
|
|
|
+ notation conditionally, as well as specify the specific array to
|
|
|
+ which an element or collection belongs:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <code>Zend_Form::setIsArray($flag)</code>: By setting the
|
|
|
+ flag true, you can indicate that an entire form should be
|
|
|
+ treated as an array. By default, the form's name will be
|
|
|
+ used as the name of the array, unless
|
|
|
+ <code>setElementsBelongTo()</code> has been called. If the
|
|
|
+ form has no specified name, or if
|
|
|
+ <code>setElementsBelongTo()</code> has not been set, this
|
|
|
+ flag will be ignored (as there is no array name to which
|
|
|
+ the elements may belong).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You may determine if a form is being treated as an array
|
|
|
+ using the <code>isArray()</code> accessor.
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>Zend_Form::setElementsBelongTo($array)</code>:
|
|
|
+ Using this method, you can specify the name of an array to
|
|
|
+ which all elements of the form belong. You can determine the
|
|
|
+ name using the <code>getElementsBelongTo()</code> accessor.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Additionally, on the element level, you can specify individual
|
|
|
+ elements may belong to particular arrays using
|
|
|
+ <code>Zend_Form_Element::setBelongsTo()</code> method.
|
|
|
+ To discover what this value is -- whether set explicitly or
|
|
|
+ implicitly via the form -- you may use the
|
|
|
+ <code>getBelongsTo()</code> accessor.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.form.advanced.multiPage">
|
|
|
+ <title>Multi-Page Forms</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Currently, Multi-Page forms are not officially supported in
|
|
|
+ <code>Zend_Form</code>; however, most support for implementing them
|
|
|
+ is available and can be utilized with a little extra tooling.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The key to creating a multi-page form is to utilize sub forms, but
|
|
|
+ to display only one such sub form per page. This allows you to
|
|
|
+ submit a single sub form at a time and validate it, but not process
|
|
|
+ the form until all sub forms are complete.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.form.advanced.multiPage.registration">
|
|
|
+ <title>Registration Form Example</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Let's use a registration form as an example. For our purposes,
|
|
|
+ we want to capture the desired username and password on the
|
|
|
+ first page, then the user's metadata -- given name, family name,
|
|
|
+ and location -- and finally allow them to decide what mailing
|
|
|
+ lists, if any, they wish to subscribe to.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ First, let's create our own form, and define several sub forms
|
|
|
+ within it:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_Form_Registration extends Zend_Form
|
|
|
+{
|
|
|
+ public function init()
|
|
|
+ {
|
|
|
+ // Create user sub form: username and password
|
|
|
+ $user = new Zend_Form_SubForm();
|
|
|
+ $user->addElements(array(
|
|
|
+ new Zend_Form_Element_Text('username', array(
|
|
|
+ 'required' => true,
|
|
|
+ 'label' => 'Username:',
|
|
|
+ 'filters' => array('StringTrim', 'StringToLower'),
|
|
|
+ 'validators' => array(
|
|
|
+ 'Alnum',
|
|
|
+ array('Regex',
|
|
|
+ false,
|
|
|
+ array('/^[a-z][a-z0-9]{2,}$/'))
|
|
|
+ )
|
|
|
+ )),
|
|
|
+
|
|
|
+ new Zend_Form_Element_Password('password', array(
|
|
|
+ 'required' => true,
|
|
|
+ 'label' => 'Password:',
|
|
|
+ 'filters' => array('StringTrim'),
|
|
|
+ 'validators' => array(
|
|
|
+ 'NotEmpty',
|
|
|
+ array('StringLength', false, array(6))
|
|
|
+ )
|
|
|
+ )),
|
|
|
+ ));
|
|
|
+
|
|
|
+ // Create demographics sub form: given name, family name, and
|
|
|
+ // location
|
|
|
+ $demog = new Zend_Form_SubForm();
|
|
|
+ $demog->addElements(array(
|
|
|
+ new Zend_Form_Element_Text('givenName', array(
|
|
|
+ 'required' => true,
|
|
|
+ 'label' => 'Given (First) Name:',
|
|
|
+ 'filters' => array('StringTrim'),
|
|
|
+ 'validators' => array(
|
|
|
+ array('Regex',
|
|
|
+ false,
|
|
|
+ array('/^[a-z][a-z0-9., \'-]{2,}$/i'))
|
|
|
+ )
|
|
|
+ )),
|
|
|
+
|
|
|
+ new Zend_Form_Element_Text('familyName', array(
|
|
|
+ 'required' => true,
|
|
|
+ 'label' => 'Family (Last) Name:',
|
|
|
+ 'filters' => array('StringTrim'),
|
|
|
+ 'validators' => array(
|
|
|
+ array('Regex',
|
|
|
+ false,
|
|
|
+ array('/^[a-z][a-z0-9., \'-]{2,}$/i'))
|
|
|
+ )
|
|
|
+ )),
|
|
|
+
|
|
|
+ new Zend_Form_Element_Text('location', array(
|
|
|
+ 'required' => true,
|
|
|
+ 'label' => 'Your Location:',
|
|
|
+ 'filters' => array('StringTrim'),
|
|
|
+ 'validators' => array(
|
|
|
+ array('StringLength', false, array(2))
|
|
|
+ )
|
|
|
+ )),
|
|
|
+ ));
|
|
|
+
|
|
|
+ // Create mailing lists sub form
|
|
|
+ $listOptions = array(
|
|
|
+ 'none' => 'No lists, please',
|
|
|
+ 'fw-general' => 'Zend Framework General List',
|
|
|
+ 'fw-mvc' => 'Zend Framework MVC List',
|
|
|
+ 'fw-auth' => 'Zend Framwork Authentication and ACL List',
|
|
|
+ 'fw-services' => 'Zend Framework Web Services List',
|
|
|
+ );
|
|
|
+ $lists = new Zend_Form_SubForm();
|
|
|
+ $lists->addElements(array(
|
|
|
+ new Zend_Form_Element_MultiCheckbox('subscriptions', array(
|
|
|
+ 'label' =>
|
|
|
+ 'Which lists would you like to subscribe to?',
|
|
|
+ 'multiOptions' => $listOptions,
|
|
|
+ 'required' => true,
|
|
|
+ 'filters' => array('StringTrim'),
|
|
|
+ 'validators' => array(
|
|
|
+ array('InArray',
|
|
|
+ false,
|
|
|
+ array(array_keys($listOptions)))
|
|
|
+ )
|
|
|
+ )),
|
|
|
+ ));
|
|
|
+
|
|
|
+ // Attach sub forms to main form
|
|
|
+ $this->addSubForms(array(
|
|
|
+ 'user' => $user,
|
|
|
+ 'demog' => $demog,
|
|
|
+ 'lists' => $lists
|
|
|
+ ));
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Note that there are no submit buttons, and that we have done
|
|
|
+ nothing with the sub form decorators -- which means that by
|
|
|
+ default they will be displayed as fieldsets. We will need to be
|
|
|
+ able to override these as we display each individual sub form,
|
|
|
+ and add in submit buttons so we can actually process them --
|
|
|
+ which will also require action and method properties. Let's add
|
|
|
+ some scaffolding to our class to provide that information:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_Form_Registration extends Zend_Form
|
|
|
+{
|
|
|
+ // ...
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Prepare a sub form for display
|
|
|
+ *
|
|
|
+ * @param string|Zend_Form_SubForm $spec
|
|
|
+ * @return Zend_Form_SubForm
|
|
|
+ */
|
|
|
+ public function prepareSubForm($spec)
|
|
|
+ {
|
|
|
+ if (is_string($spec)) {
|
|
|
+ $subForm = $this->{$spec};
|
|
|
+ } elseif ($spec instanceof Zend_Form_SubForm) {
|
|
|
+ $subForm = $spec;
|
|
|
+ } else {
|
|
|
+ throw new Exception('Invalid argument passed to ' .
|
|
|
+ __FUNCTION__ . '()');
|
|
|
+ }
|
|
|
+ $this->setSubFormDecorators($subForm)
|
|
|
+ ->addSubmitButton($subForm)
|
|
|
+ ->addSubFormActions($subForm);
|
|
|
+ return $subForm;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Add form decorators to an individual sub form
|
|
|
+ *
|
|
|
+ * @param Zend_Form_SubForm $subForm
|
|
|
+ * @return My_Form_Registration
|
|
|
+ */
|
|
|
+ public function setSubFormDecorators(Zend_Form_SubForm $subForm)
|
|
|
+ {
|
|
|
+ $subForm->setDecorators(array(
|
|
|
+ 'FormElements',
|
|
|
+ array('HtmlTag', array('tag' => 'dl',
|
|
|
+ 'class' => 'zend_form')),
|
|
|
+ 'Form',
|
|
|
+ ));
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Add a submit button to an individual sub form
|
|
|
+ *
|
|
|
+ * @param Zend_Form_SubForm $subForm
|
|
|
+ * @return My_Form_Registration
|
|
|
+ */
|
|
|
+ public function addSubmitButton(Zend_Form_SubForm $subForm)
|
|
|
+ {
|
|
|
+ $subForm->addElement(new Zend_Form_Element_Submit(
|
|
|
+ 'save',
|
|
|
+ array(
|
|
|
+ 'label' => 'Save and continue',
|
|
|
+ 'required' => false,
|
|
|
+ 'ignore' => true,
|
|
|
+ )
|
|
|
+ ));
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Add action and method to sub form
|
|
|
+ *
|
|
|
+ * @param Zend_Form_SubForm $subForm
|
|
|
+ * @return My_Form_Registration
|
|
|
+ */
|
|
|
+ public function addSubFormActions(Zend_Form_SubForm $subForm)
|
|
|
+ {
|
|
|
+ $subForm->setAction('/registration/process')
|
|
|
+ ->setMethod('post');
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Next, we need to add some scaffolding in our action controller,
|
|
|
+ and have several considerations. First, we need to make sure we
|
|
|
+ persist form data between requests, so that we can determine
|
|
|
+ when to quit. Second, we need some logic to determine what form
|
|
|
+ segments have already been submitted, and what sub form to
|
|
|
+ display based on that information. We'll use
|
|
|
+ <code>Zend_Session_Namespace</code> to persist data, which will
|
|
|
+ also help us answer the question of which form to submit.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Let's create our controller, and add a method for retrieving a
|
|
|
+ form instance:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class RegistrationController extends Zend_Controller_Action
|
|
|
+{
|
|
|
+ protected $_form;
|
|
|
+
|
|
|
+ public function getForm()
|
|
|
+ {
|
|
|
+ if (null === $this->_form) {
|
|
|
+ $this->_form = new My_Form_Registration();
|
|
|
+ }
|
|
|
+ return $this->_form;
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Now, let's add some functionality for determining which form to
|
|
|
+ display. Basically, until the entire form is considered valid,
|
|
|
+ we need to continue displaying form segments. Additionally, we
|
|
|
+ likely want to make sure they're in a particular order: user,
|
|
|
+ demog, and then lists. We can determine what data has been
|
|
|
+ submitted by checking our session namespace for particular keys
|
|
|
+ representing each subform.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class RegistrationController extends Zend_Controller_Action
|
|
|
+{
|
|
|
+ // ...
|
|
|
+
|
|
|
+ protected $_namespace = 'RegistrationController';
|
|
|
+ protected $_session;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get the session namespace we're using
|
|
|
+ *
|
|
|
+ * @return Zend_Session_Namespace
|
|
|
+ */
|
|
|
+ public function getSessionNamespace()
|
|
|
+ {
|
|
|
+ if (null === $this->_session) {
|
|
|
+ $this->_session =
|
|
|
+ new Zend_Session_Namespace($this->_namespace);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $this->_session;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get a list of forms already stored in the session
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public function getStoredForms()
|
|
|
+ {
|
|
|
+ $stored = array();
|
|
|
+ foreach ($this->getSessionNamespace() as $key => $value) {
|
|
|
+ $stored[] = $key;
|
|
|
+ }
|
|
|
+
|
|
|
+ return $stored;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get list of all subforms available
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public function getPotentialForms()
|
|
|
+ {
|
|
|
+ return array_keys($this->getForm()->getSubForms());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * What sub form was submitted?
|
|
|
+ *
|
|
|
+ * @return false|Zend_Form_SubForm
|
|
|
+ */
|
|
|
+ public function getCurrentSubForm()
|
|
|
+ {
|
|
|
+ $request = $this->getRequest();
|
|
|
+ if (!$request->isPost()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach ($this->getPotentialForms() as $name) {
|
|
|
+ if ($data = $request->getPost($name, false)) {
|
|
|
+ if (is_array($data)) {
|
|
|
+ return $this->getForm()->getSubForm($name);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get the next sub form to display
|
|
|
+ *
|
|
|
+ * @return Zend_Form_SubForm|false
|
|
|
+ */
|
|
|
+ public function getNextSubForm()
|
|
|
+ {
|
|
|
+ $storedForms = $this->getStoredForms();
|
|
|
+ $potentialForms = $this->getPotentialForms();
|
|
|
+
|
|
|
+ foreach ($potentialForms as $name) {
|
|
|
+ if (!in_array($name, $storedForms)) {
|
|
|
+ return $this->getForm()->getSubForm($name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The above methods allow us to use notations such as "<code>$subForm =
|
|
|
+ $this->getCurrentSubForm();</code>" to retrieve the current
|
|
|
+ sub form for validation, or "<code>$next =
|
|
|
+ $this->getNextSubForm();</code>" to get the next one to
|
|
|
+ display.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Now, let's figure out how to process and display the various sub
|
|
|
+ forms. We can use <code>getCurrentSubForm()</code> to determine
|
|
|
+ if any sub forms have been submitted (false return values
|
|
|
+ indicate none have been displayed or submitted), and
|
|
|
+ <code>getNextSubForm()</code> to retrieve a form to display. We
|
|
|
+ can then use the form's <code>prepareSubForm()</code> method to
|
|
|
+ ensure the form is ready for display.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ When we have a form submission, we can validate the sub form,
|
|
|
+ and then check to see if the entire form is now valid. To do
|
|
|
+ these tasks, we'll need additional methods that ensure that
|
|
|
+ submitted data is added to the session, and that when validating
|
|
|
+ the form entire, we validate against all segments from the
|
|
|
+ session:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class RegistrationController extends Zend_Controller_Action
|
|
|
+{
|
|
|
+ // ...
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Is the sub form valid?
|
|
|
+ *
|
|
|
+ * @param Zend_Form_SubForm $subForm
|
|
|
+ * @param array $data
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ public function subFormIsValid(Zend_Form_SubForm $subForm,
|
|
|
+ array $data)
|
|
|
+ {
|
|
|
+ $name = $subForm->getName();
|
|
|
+ if ($subForm->isValid($data)) {
|
|
|
+ $this->getSessionNamespace()->$name = $subForm->getValues();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Is the full form valid?
|
|
|
+ *
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ public function formIsValid()
|
|
|
+ {
|
|
|
+ $data = array();
|
|
|
+ foreach ($this->getSessionNamespace() as $key => $info) {
|
|
|
+ $data[$key] = $info;
|
|
|
+ }
|
|
|
+
|
|
|
+ return $this->getForm()->isValid($data);
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Now that we have the legwork out of the way, let's build the
|
|
|
+ actions for this controller. We'll need a landing page for the
|
|
|
+ form, and then a 'process' action for processing the form.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class RegistrationController extends Zend_Controller_Action
|
|
|
+{
|
|
|
+ // ...
|
|
|
+
|
|
|
+ public function indexAction()
|
|
|
+ {
|
|
|
+ // Either re-display the current page, or grab the "next"
|
|
|
+ // (first) sub form
|
|
|
+ if (!$form = $this->getCurrentSubForm()) {
|
|
|
+ $form = $this->getNextSubForm();
|
|
|
+ }
|
|
|
+ $this->view->form = $this->getForm()->prepareSubForm($form);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function processAction()
|
|
|
+ {
|
|
|
+ if (!$form = $this->getCurrentSubForm()) {
|
|
|
+ return $this->_forward('index');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!$this->subFormIsValid($form,
|
|
|
+ $this->getRequest()->getPost())) {
|
|
|
+ $this->view->form = $this->getForm()->prepareSubForm($form);
|
|
|
+ return $this->render('index');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!$this->formIsValid()) {
|
|
|
+ $form = $this->getNextSubForm();
|
|
|
+ $this->view->form = $this->getForm()->prepareSubForm($form);
|
|
|
+ return $this->render('index');
|
|
|
+ }
|
|
|
+
|
|
|
+ // Valid form!
|
|
|
+ // Render information in a verification page
|
|
|
+ $this->view->info = $this->getSessionNamespace();
|
|
|
+ $this->render('verification');
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ As you'll notice, the actual code for processing the form is
|
|
|
+ relatively simple. We check to see if we have a current sub form
|
|
|
+ submission, and if not, we go back to the landing page. If we do
|
|
|
+ have a sub form, we attempt to validate it, redisplaying it if
|
|
|
+ it fails. If the sub form is valid, we then check to see if the
|
|
|
+ form is valid, which would indicate we're done; if not, we
|
|
|
+ display the next form segment. Finally, we display a
|
|
|
+ verification page with the contents of the session.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The view scripts are very simple:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+<? // registration/index.phtml ?>
|
|
|
+<h2>Registration</h2>
|
|
|
+<?= $this->form ?>
|
|
|
+
|
|
|
+<? // registration/verification.phtml ?>
|
|
|
+<h2>Thank you for registering!</h2>
|
|
|
+<p>
|
|
|
+ Here is the information you provided:
|
|
|
+</p>
|
|
|
+
|
|
|
+<?
|
|
|
+// Have to do this construct due to how items are stored in session
|
|
|
+// namespaces
|
|
|
+foreach ($this->info as $info):
|
|
|
+ foreach ($info as $form => $data): ?>
|
|
|
+<h4><?= ucfirst($form) ?>:</h4>
|
|
|
+<dl>
|
|
|
+ <? foreach ($data as $key => $value): ?>
|
|
|
+ <dt><?= ucfirst($key) ?></dt>
|
|
|
+ <? if (is_array($value)):
|
|
|
+ foreach ($value as $label => $val): ?>
|
|
|
+ <dd><?= $val ?></dd>
|
|
|
+ <? endforeach;
|
|
|
+ else: ?>
|
|
|
+ <dd><?= $this->escape($value) ?></dd>
|
|
|
+ <? endif;
|
|
|
+ endforeach; ?>
|
|
|
+</dl>
|
|
|
+<? endforeach;
|
|
|
+endforeach ?>
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Upcoming releases of Zend Framework will include components to
|
|
|
+ make multi page forms simpler by abstracting the session and
|
|
|
+ ordering logic. In the meantime, the above example should serve
|
|
|
+ as a reasonable guideline on how to accomplish this task for
|
|
|
+ your site.
|
|
|
+ </para>
|
|
|
+ </example>
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.gdata">
|
|
|
+ <title>Zend_Gdata</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Gdata-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Gdata_AuthSub.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Gdata_Books.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Gdata_ClientLogin.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Gdata_Calendar.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Gdata_Docs.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Gdata_Spreadsheets.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Gdata_Gapps.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Gdata_Gbase.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Gdata_Photos.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Gdata_YouTube.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Gdata_Exception.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.http">
|
|
|
+ <title>Zend_Http</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Http_Client.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Http_Client-Advanced.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Http_Client-Adapters.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Http_Cookie-Handling.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Http_Response.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.infocard">
|
|
|
+ <title>Zend_InfoCard</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_InfoCard-Basics.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.json">
|
|
|
+ <title>Zend_Json</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Json-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Json-Basics.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Json-Objects.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Json-xml2json.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Json-Server.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.layout">
|
|
|
+ <title>Zend_Layout</title>
|
|
|
+ <sect1 id="zend.layout.introduction" xml:base="module_specs/Zend_Layout-Introduction.xml">
|
|
|
+ <title>Introducción</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Layout</code> implementa un patrón clásico "Vista en dos
|
|
|
+ etapas" (Two Step View) permitiendo a los desarrolladores colocar el
|
|
|
+ contenido de la aplicación dentro de otra vista, usualmente
|
|
|
+ representando la plantilla del sitio. Tales plantillas son a menudo
|
|
|
+ denominadas <emphasis>layouts</emphasis> por otros proyectos, y Zend
|
|
|
+ Framework ha adoptado este término por consistencia.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los objetivos principales de <code>Zend_Layout</code> son los
|
|
|
+ siguientes:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ Automatizar la selección y renderizado de layouts cuando se usan
|
|
|
+ con los componentes MVC de Zend Framework.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Proveer ámbitos separados para variables relacionadas al diseño
|
|
|
+ y contenido.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Permitir configuraciones, incluyendo el nombre del layout,
|
|
|
+ resolución (inflexión) del script layout, y ruta del script
|
|
|
+ layout.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Permitir deshabilitar layouts, cambiar el script de diseño y
|
|
|
+ otras condiciones; permitir estas acciones dentro de los
|
|
|
+ controladores y scripts de vista.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Seguir normas de resolución similares (inflexión) como el <link linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>,
|
|
|
+ pero permitiendo también el uso de normas distintas
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ Permitir el uso de los componentes MVC de Zend Framework.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Layout-QuickStart.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Layout-Options.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Layout-Advanced.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.ldap">
|
|
|
+ <title>Zend_Ldap</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Ldap.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.loader">
|
|
|
+ <title>Zend_Loader</title>
|
|
|
+ <!-- versión 12819 --><sect1 id="zend.loader.load" xml:base="module_specs/Zend_Loader.xml">
|
|
|
+
|
|
|
+ <title>Cargando archivos y clases dinámicamente</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La clase Zend_Loader incluye métodos para ayudar a cargar archivos
|
|
|
+ dinámicamente.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <tip>
|
|
|
+ <title>Zend_Loader vs. require_once()</title>
|
|
|
+ <para>
|
|
|
+ Los métodos de <code>Zend_Loader</code> tienen más utilidad si el
|
|
|
+ nombre de archivo que necesita cargar es variable. Por ejemplo,
|
|
|
+ si éste se basa en un parametro de entrada del usuario o argumento
|
|
|
+ de un método. Si carga un archivo o clase cuyo nombre es constante, no
|
|
|
+ hay ningún beneficio al usar <code>Zend_Loader</code> sobre el uso
|
|
|
+ de funciones tradicionales de PHP como
|
|
|
+ <ulink url="http://php.net/require_once"><code>require_once()</code></ulink>.
|
|
|
+ </para>
|
|
|
+ </tip>
|
|
|
+
|
|
|
+ <sect2 id="zend.loader.load.file">
|
|
|
+
|
|
|
+ <title>Cargando Archivos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método estático <code>Zend_Loader::loadFile()</code> carga un archivo
|
|
|
+ PHP. El archivo cargado puede contener cualquier código PHP.
|
|
|
+ El método se comporta como un envoltorio para la función PHP
|
|
|
+ <ulink url="http://php.net/include"><code>include()</code></ulink>.
|
|
|
+ Este método devuelve un booleano false en caso de fallo, por ejemplo,
|
|
|
+ si el archivo especificado no existe.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.loader.load.file.example">
|
|
|
+ <title>Ejemplo del Método loadFile()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+Zend_Loader::loadFile($filename, $dirs=null, $once=false);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El argumento <code>$filename</code> especifica el archivo que se va a cargar,
|
|
|
+ el cual no debe contener ninguna información de rutas.
|
|
|
+ Una verificación de seguridad es efectuada sobre <code>$filename</code>.
|
|
|
+ El archivo <code>$filename</code> sólo puede contener caracteres alfanuméricos,
|
|
|
+ guiones ("-"), barras bajas ("_"), o puntos (".").
|
|
|
+ No hay ninguna restricción en el argumento <code>$dirs</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El parámetro <code>$dirs</code> especifica en qué carpetas buscar el archivo.
|
|
|
+ Si el valor es <code>NULL</code>, sólo se buscará en el <code>include_path</code>
|
|
|
+ ; si el valor es un string o un array, se buscará en la carpeta o carpetas especificadas
|
|
|
+ , seguidas del <code>include_path</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El argumento <code>$once</code> es un booleano. Si es <code>TRUE</code>,
|
|
|
+ <code>Zend_Loader::loadFile()</code> esa la función PHP
|
|
|
+ <ulink url="http://php.net/include"><code>include_once()</code></ulink>
|
|
|
+ para cargar el archivo, de lo contrario se utiliza la función PHP
|
|
|
+ <ulink url="http://php.net/include_once"><code>include()</code></ulink>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.loader.load.class">
|
|
|
+
|
|
|
+ <title>Cargando Clases</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método estático <code>Zend_Loader::loadClass($class, $dirs)</code>
|
|
|
+ carga un archivo PHP y comprueba la existencia de la clase.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.loader.load.class.example">
|
|
|
+ <title>Ejemplo del método loadClass()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+Zend_Loader::loadClass('Container_Tree',
|
|
|
+ array(
|
|
|
+ '/home/production/mylib',
|
|
|
+ '/home/production/myapp'
|
|
|
+ )
|
|
|
+);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La cadena que especifica la clase es convertida a una ruta relativa sustituyendo las barras
|
|
|
+ bajas (_) por el separador de carpeta de su Sistema Operativo, y añadiendo
|
|
|
+ '.php'. En el ejemplo de arriba, 'Container_Tree' se convierte en 'Container/Tree.php' en Windows.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si <code>$dirs</code> es una cadena o un array,
|
|
|
+ <code>Zend_Loader::loadClass()</code> busca las carpetas en el
|
|
|
+ orden suministrado. El primer archivo encontrado es cargado. Si el archivo
|
|
|
+ no existe en el <code>$dirs</code> especificado, entonces se busca en el
|
|
|
+ <code>include_path</code> del entorno PHP.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si el archivo no es encontrado o la clase no existe después de la carga,
|
|
|
+ <code>Zend_Loader::loadClass()</code> lanza una <code>Zend_Exception</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Loader::loadFile()</code> se usa para cargar, así que
|
|
|
+ el nombre de la clase puede contener únicamente caracteres alfanuméricos,
|
|
|
+ guiones ('-'), barras bajas ('_'), y puntos ('.').
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.loader.load.isreadable">
|
|
|
+
|
|
|
+ <title>Comprobando si un Archivo Puede Ser Leído</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método estático <code>Zend_Loader::isReadable($pathname)</code>
|
|
|
+ devuelve <code>TRUE</code> si el archivo en la ruta $pathname existe
|
|
|
+ y tiene permisos de lectura, <code>FALSE</code> en caso contrario.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.loader.load.isreadable.example">
|
|
|
+ <title>Ejemplo del método isReadable()</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+if (Zend_Loader::isReadable($filename)) {
|
|
|
+ // hace algo con $filename
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El argumento <code>$filename</code> especifica el nombre de archivo que
|
|
|
+ comprobar. Puede contener información de la ruta.
|
|
|
+ Este método envuelve la función PHP
|
|
|
+ <ulink url="http://php.net/is_readable"><code>is_readable()</code></ulink>.
|
|
|
+ La función PHP no busca en <code>include_path</code>,
|
|
|
+ mientras que <code>Zend_Loader::isReadable()</code> sí.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.loader.load.autoload">
|
|
|
+
|
|
|
+ <title>Usando el Autoloader</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La clase <code>Zend_Loader</code> contiene un método que se puede registrar
|
|
|
+ con PHP SPL autoloader. <code>Zend_Loader::autoload()</code> es el método
|
|
|
+ callback. Por comodidad, <code>Zend_Loader</code> permite a la función
|
|
|
+ <code>registerAutoload()</code> registrar su método
|
|
|
+ <code>autoload()</code>. Si la extensión <code>spl_autoload</code>
|
|
|
+ no está presente en el entorno PHP, entonces el método
|
|
|
+ <code>registerAutoload()</code> lanza una <code>Zend_Exception</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.loader.load.autoload.example">
|
|
|
+ <title>Ejemplo de registro del método callback del autoloader</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+Zend_Loader::registerAutoload();
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Después de registrar el callback de autoload de Zend Framework, se pueden
|
|
|
+ referenciar clases de Zend Framework sin tener que cargarlas
|
|
|
+ explícitamente. El método <code>autoload()</code> usa automáticamente
|
|
|
+ <code>Zend_Loader::loadClass()</code> cuando referencie una clase.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si ha extendido la clase <code>Zend_Loader</code>, se puede pasar un
|
|
|
+ argumento opcional a <code>registerAutoload()</code>, para especificar
|
|
|
+ la clase a partir de la cual registrar un método <code>autoload()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.loader.load.autoload.example-extended">
|
|
|
+ <title>Ejemplo de registro del método de callback autoload desde una clase
|
|
|
+ extendida</title>
|
|
|
+ <para>
|
|
|
+ Debido a la semántica de referencia de funciones estáticas en PHP,
|
|
|
+ se debe implementar código tanto para la clase <code>loadClass()</code>
|
|
|
+ como <code>autoload()</code>, y <code>autoload()</code>
|
|
|
+ debe llamar a <code>self::loadClass()</code>. Si su método
|
|
|
+ <code>autoload()</code> delega en su padre la llamada a
|
|
|
+ <code>self::loadClass()</code>, entonces llamará
|
|
|
+ al método con ese nombre en la clase padre, no la subclase.
|
|
|
+ </para>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_Loader extends Zend_Loader
|
|
|
+{
|
|
|
+ public static function loadClass($class, $dirs = null)
|
|
|
+ {
|
|
|
+ parent::loadClass($class, $dirs);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static function autoload($class)
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ self::loadClass($class);
|
|
|
+ return $class;
|
|
|
+ } catch (Exception $e) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Zend_Loader::registerAutoload('My_Loader');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Se puede eliminar un callback de autoload.
|
|
|
+ <code>registerAutoload()</code> tiene un segundo parámetro opcional,
|
|
|
+ que es <code>true</code> por defecto. Si este parámetro es
|
|
|
+ <code>false</code>, el callback de autoload será borrado de la pila
|
|
|
+ de autoload SPL.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Loader-PluginLoader.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.locale">
|
|
|
+ <title>Zend_Locale</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Locale-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Locale-Functions.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Locale-Parsing.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Locale-DatesTimes.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Locale-AppendixLanguages.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Locale-Migration.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.log">
|
|
|
+ <title>Zend_Log</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Log-Overview.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Log-Writers.xml" parse="xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Log-Formatters.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Log-Filters.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.mail">
|
|
|
+ <title>Zend_Mail</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-Sending.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-MultipleEmails.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-DifferentTransports.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-HtmlMails.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-Attachments.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-AddingRecipients.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-Boundary.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-AdditionalHeaders.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-CharacterSets.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-Encoding.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-SmtpAuthentication.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail-SmtpSecure.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mail_Read.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.measure">
|
|
|
+ <title>Zend_Measure</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Measure-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Measure-Creation.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Measure-Output.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Measure-Edit.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Measure-Types.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.memory">
|
|
|
+ <title>Zend_Memory</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Memory-Overview.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Memory-MemoryManager.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Memory-MemoryObjects.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.mime">
|
|
|
+ <title>Zend_Mime</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mime.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mime_Message.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Mime_Part.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.openid">
|
|
|
+ <title>Zend_OpenId</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_OpenId-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_OpenId-Consumer.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_OpenId-Provider.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.paginator">
|
|
|
+ <title>Zend_Paginator</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Paginator-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Paginator-Usage.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Paginator-Configuration.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Paginator-Advanced.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.pdf">
|
|
|
+ <title>Zend_Pdf</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Pdf-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Pdf-Create.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Pdf-Save.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Pdf-Pages.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Pdf-Drawing.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Pdf-Properties.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Pdf-Usage.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.progressbar">
|
|
|
+ <title>Zend_ProgressBar</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_ProgressBar.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.registry">
|
|
|
+ <title>Zend_Registry</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Registry.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.rest">
|
|
|
+ <title>Zend_Rest</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Rest.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Rest_Client.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Rest_Server.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.search.lucene">
|
|
|
+ <title>Zend_Search_Lucene</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Search_Lucene-Overview.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Search_Lucene-IndexCreation.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Search_Lucene-Searching.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Search_Lucene-QueryLanguage.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Search_Lucene-Queries.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Search_Lucene-Charset.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Search_Lucene-Extending.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Search_Lucene-JavaLucene.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Search_Lucene-Advanced.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Search_Lucene-BestPractice.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.server">
|
|
|
+ <title>Zend_Server</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Server.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Server_Reflection.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.service">
|
|
|
+ <title>Zend_Service</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_Akismet.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_Amazon.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_Audioscrobbler.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_Delicious.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_Flickr.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_Nirvanix.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service-ReCaptcha.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_Simpy.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_SlideShare.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_StrikeIron-Overview.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_StrikeIron-BundledServices.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_StrikeIron-AdvancedUses.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_Technorati.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_Twitter.xml" parse="xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Service_Yahoo.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.session">
|
|
|
+ <title>Zend_Session</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Session-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Session-BasicUsage.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Session-AdvancedUsage.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Session-GlobalSessionManagement.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Session-SaveHandler-DbTable.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.soap">
|
|
|
+ <title>Zend_Soap</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Soap_Server.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Soap_Client.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Soap_Wsdl.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Soap_AutoDiscovery.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.test">
|
|
|
+ <title>Zend_Test</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Test.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Test-PHPUnit.xml" parse="xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.text">
|
|
|
+ <title>Zend_Text</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Text_Figlet.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Text_Table.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.timesync">
|
|
|
+ <title>Zend_TimeSync</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_TimeSync.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_TimeSync-Working.xml"/>
|
|
|
+ </chapter>
|
|
|
+
|
|
|
+ <chapter id="zend.translate">
|
|
|
+ <title>Zend_Translate</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Translate-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Translate-Adapters.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Translate-Using.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Translate-Migration.xml"/>
|
|
|
+ </chapter>
|
|
|
+ <chapter id="zend.uri">
|
|
|
+ <title>Zend_Uri</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Uri.xml"/>
|
|
|
+ </chapter>
|
|
|
+ <chapter id="zend.validate">
|
|
|
+ <title>Zend_Validate</title>
|
|
|
+ <sect1 id="zend.validate.introduction" xml:base="module_specs/Zend_Validate.xml">
|
|
|
+
|
|
|
+ <title>Introducción</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cuando se necesita validar algún tipo de dato, el componente Zend_Validate ofrece un conjunto de validadores,
|
|
|
+ como así también un sencillo mecanismo de encadenado de validaciones por el cual
|
|
|
+ múltiples validadores pueden aplicarse a un dato en un orden definido por el usuario.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.introduction.definition">
|
|
|
+
|
|
|
+ <title>¿Qué es un validador?</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un validador examina su entrada con respecto a algunos requerimientos
|
|
|
+ y produce un resultado booleano si la entrada valida satisfactoriamente
|
|
|
+ con los requisitos. Si la entrada no cumple los requisitos,
|
|
|
+ un validador también podrá proporcionar información adicional
|
|
|
+ sobre que requisito(s) no son satisfechos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por ejemplo, una aplicación web podría requerir que un usuario ingrese
|
|
|
+ su nombre, de entre seis y doce caracteres de longitud y
|
|
|
+ que sólo puede contener caracteres alfanuméricos.
|
|
|
+ Se puede usar un validador para asegurar que los usuarios cumplan
|
|
|
+ estos requisitos.
|
|
|
+ Si el nombre de usuario elegido no cumple con uno o ambos de los requisitos,
|
|
|
+ sería útil saber cuál de estos requisitos no se cumple.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.introduction.using">
|
|
|
+
|
|
|
+ <title>Uso básico de validadores</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Habiendo definido la validación de esta manera, Zend Framework nos proporciona el fundamento
|
|
|
+ para <code>Zend_Validate_Interface</code> que define dos métodos,
|
|
|
+ <code>isValid()</code> y <code>getMessages()</code>.
|
|
|
+ El método <code>isValid()</code> realiza la validación del valor,
|
|
|
+ devolviendo <code>true</code> si y sólo si el valor pasa contra el criterio de
|
|
|
+ validación.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si <code>isValid()</code> devuelve <code>false</code>, la función
|
|
|
+ <code>getMessages()</code> devuelve un array de mensajes explicando
|
|
|
+ el motivo(s) del fracaso de la validación. Las claves del array son
|
|
|
+ strings cortos que identifican las razones por las cuales fracasó
|
|
|
+ la validación, y los valores del array son los correspondientes mensajes
|
|
|
+ para ser leídos por un ser humano.
|
|
|
+ Las claves y los valores son dependientes de la clase; cada clase de validación
|
|
|
+ define su propio conjunto de mensajes de validación fallidas y las
|
|
|
+ claves únicas que las identifican.
|
|
|
+ Cada clase tiene también una definición <code>const</code>
|
|
|
+ que hace corresponder a cada identificador con una causa del fallo
|
|
|
+ de validación.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ El método <code>getMessages()</code> devuelve información del fracaso
|
|
|
+ de la validación sólo para la llamada más reciente a <code>isValid()</code>.
|
|
|
+ Cada llamada a <code>isValid()</code> borra los mensajes y errores
|
|
|
+ causados por una llamada anterior <code>isValid()</code>, porque es
|
|
|
+ probable que cada llamada a <code>isValid()</code> se refiera al valor de una entrada diferente.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El siguiente ejemplo ilustra la validación de una dirección de e-mail:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$validator = new Zend_Validate_EmailAddress();
|
|
|
+
|
|
|
+if ($validator->isValid($email)) {
|
|
|
+ // email parece ser válido
|
|
|
+} else {
|
|
|
+ // email es inválido; muestre la razones
|
|
|
+ foreach ($validator->getMessages() as $messageId => $message) {
|
|
|
+ echo "Falla de validación '$messageId': $message\n";
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.introduction.messages">
|
|
|
+
|
|
|
+ <title>Personalizar los mensajes</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para validar las clases se proporciona un método <code>setMessage()</code>
|
|
|
+ con el que se puede especificar el formato de un mensaje devuelto por
|
|
|
+ <code>getMessages()</code> en caso de fallo de validación.
|
|
|
+ El primer argumento de este método es un string que contiene el mensaje
|
|
|
+ de error. Usted puede incluir tokens en este array que serán sustituidos
|
|
|
+ con datos relevantes al validador. El token <code>%value%</code> es aceptado
|
|
|
+ por todos los validadores, que es sustituido por el valor que pasó a
|
|
|
+ <code>isValid()</code>. Cada clase de validación, puede dar apoyo a otros
|
|
|
+ tokens en base a cada caso. Por ejemplo, <code>%max%</code> es un token
|
|
|
+ apoyado por <code>Zend_Validate_LessThan</code>.
|
|
|
+ El método <code>getMessageVariables()</code> devuelve un array de tokens
|
|
|
+ variables aceptados por el validador.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El segundo argumento opcional es un string que identifica la plantilla
|
|
|
+ de mensajes que se establecerá en caso del fracaso de la validación,
|
|
|
+ lo que es útil cuando una clase de validación define más de una causa para
|
|
|
+ el fallo.
|
|
|
+ Si omite el segundo argumento, <code>setMessage()</code> asume que el
|
|
|
+ mensaje que especifique debe ser utilizado por la plantilla del
|
|
|
+ primer mensaje que declaró en la clase de validación.
|
|
|
+ Muchas clases de validación sólo definen una plantilla de mensaje de
|
|
|
+ error, así que no hay necesidad de especificar el cambio de plantilla
|
|
|
+ de mensaje.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$validator = new Zend_Validate_StringLength(8);
|
|
|
+
|
|
|
+$validator->setMessage(
|
|
|
+ 'El string \'%value%\' es muy corto; debe tener al menos %min% ' .
|
|
|
+ 'caracteres',
|
|
|
+ Zend_Validate_StringLength::TOO_SHORT);
|
|
|
+
|
|
|
+if (!$validator->isValid('word')) {
|
|
|
+ $messages = $validator->getMessages();
|
|
|
+ echo current($messages);
|
|
|
+
|
|
|
+ // "El string 'word' es muy corto; debe tener al menos 8 caracteres"
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede establecer varios mensajes usando el método <code>setMessages()</code>.
|
|
|
+ Su argumento es un array que contiene pares de clave/mensaje.
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$validator = new Zend_Validate_StringLength(8, 12);
|
|
|
+
|
|
|
+$validator->setMessages( array(
|
|
|
+ Zend_Validate_StringLength::TOO_SHORT =>
|
|
|
+ 'El string \'%value%\' es muy corto',
|
|
|
+ Zend_Validate_StringLength::TOO_LONG =>
|
|
|
+ 'El string \'%value%\' es muy largo'
|
|
|
+));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Incluso, si su aplicación requiere una mayor flexibilidad para informar
|
|
|
+ los fallos de validación, puede acceder a las propiedades por el
|
|
|
+ mismo nombre, tal como los tokens de mensajes apoyados por una determinada
|
|
|
+ clase de validación.
|
|
|
+ La propiedad <code>value</code> siempre está disponible en un validador;
|
|
|
+ es el valor que especificó en el argumento de <code>isValid()</code>.
|
|
|
+ En cada clase de validación se puede dar apoyo a otras propiedades
|
|
|
+ basándose en el esquema de caso por caso.
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$validator = new Zend_Validate_StringLength(8, 12);
|
|
|
+
|
|
|
+if (!validator->isValid('word')) {
|
|
|
+ echo 'Palabra fallada: '
|
|
|
+ . $validator->value
|
|
|
+ . '; su longitud no está entre '
|
|
|
+ . $validator->min
|
|
|
+ . ' y '
|
|
|
+ . $validator->max
|
|
|
+ . "\n";
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.introduction.static">
|
|
|
+
|
|
|
+ <title>Utilizando el método estático <code>is()</code> </title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si es inconveniente cargar una clase de validación y crear una
|
|
|
+ instancia del validador, puede usar el método estático
|
|
|
+ <code>Zend_Validate::is()</code> como un estilo alternativo de invocación.
|
|
|
+ El primer argumento de este método es el valor de una entrada de datos
|
|
|
+ que usted pasaría al método <code>isValid()</code>.
|
|
|
+ El segundo argumento es un string, que corresponde al nombre base
|
|
|
+ de la clase de validación, relativo al nombre de espacio <code>Zend_Validate</code>.
|
|
|
+ El método <code>is()</code> carga automáticamente la clase, crea una
|
|
|
+ instancia y aplica el método <code>isValid()</code> a la entrada de datos.
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+if (Zend_Validate::is($email, 'EmailAddress')) {
|
|
|
+ // Si, el email parece ser válido
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si el validador lo necesita, también puede pasar un array de constructores de argumentos.
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+if (Zend_Validate::is($value, 'Between', array(1, 12))) {
|
|
|
+ // Si, $value está entre 1 y 12
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método <code>is()</code> devuelve un valor booleano, lo mismo que
|
|
|
+ el método <code>isValid()</code>. Cuando se utiliza el método estático
|
|
|
+ <code>is()</code>, no están disponibles los mensajes de fracaso de
|
|
|
+ validación.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El uso estático puede ser conveniente para invocar un validador ad-hoc
|
|
|
+ (hecho especialmente), pero si tiene la necesidad de ejecutar el validador para múltiples
|
|
|
+ entradas, es más eficiente usar métodos no estáticos, creando una
|
|
|
+ instancia del objeto validador y llamando a su método <code>isValid()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ También la clase <code>Zend_Filter_Input</code> le permite crear
|
|
|
+ ejemplos y ejecutar múltiples filtros y clases de validadores por
|
|
|
+ demanda, para procesar juegos de datos de entrada. Ver
|
|
|
+ <xref linkend="zend.filter.input"/>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 xmlns:xi="http://www.w3.org/2001/XInclude" id="zend.validate.set" xml:base="module_specs/Zend_Validate-Set.xml">
|
|
|
+
|
|
|
+ <title>Clases de Validación Estándar</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend Framework viene con un conjunto estándar de clases de validación
|
|
|
+ listas para usar.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.alnum">
|
|
|
+ <title>Alnum</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> contiene
|
|
|
+ caracteres alfanuméricos únicamente.
|
|
|
+ Este validador incluye una opción para considerar también al espacio
|
|
|
+ en blanco como caracter válido.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.alpha">
|
|
|
+ <title>Alpha</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> sólo
|
|
|
+ contiene caracteres alfabéticos.
|
|
|
+ Este validador incluye una opción para considerar también al espacio
|
|
|
+ en blanco como caracter válido.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.barcode">
|
|
|
+ <title>Barcode</title>
|
|
|
+ <para>
|
|
|
+ Este validador es instanciado con un tipo de código de barras contra
|
|
|
+ el valor del código de barras que quiere validar.
|
|
|
+ En la actualidad acepta los tipos de código de barras "<code>UPC-A</code>"
|
|
|
+ (Universal Product Code) y "<code>EAN-13</code>" (European Article Number),
|
|
|
+ además el método <code>isValid()</code> devuelve verdadero si y solo si
|
|
|
+ la entrada valida satisfactoriamente contra el algoritmo de validación
|
|
|
+ del código de barras.
|
|
|
+ Antes de enviar los datos de entrada al validador, debe asegurarse
|
|
|
+ de eliminar todos los caracteres distintos a los dígitos cero a nueve (0-9).
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.between">
|
|
|
+ <title>Between</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> está entre
|
|
|
+ los valores límites mínimo y máximo.
|
|
|
+ La comparación es inclusiva por defecto (<code>$valor</code> puede ser
|
|
|
+ igual a una valor límite), aunque esto puede ser anulado a fin de
|
|
|
+ hacer una comparación estricta, donde <code>$valor</code> debe ser
|
|
|
+ estrictamente mayor al mínimo y estrictamente menor al máximo.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.ccnum">
|
|
|
+ <title>Ccnum</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> sigue el
|
|
|
+ algoritmo Luhn (mod-10 checksum) para tarjetas de crédito.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.date">
|
|
|
+ <title>Date</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> es una
|
|
|
+ fecha válida en el formato <code>YYYY-MM-DD</code> (AAAA-MM-DD).
|
|
|
+ Si se usa la opción <code>locale</code> entonces la fecha
|
|
|
+ será validada de acuerdo a lo establecido para ese lugar.
|
|
|
+ El formato <code>format</code> es una opción que establece este
|
|
|
+ formato a ser utilizado para la validación.
|
|
|
+ Para los detalles acerca de los parámetros opcionales ver en:
|
|
|
+ <link linkend="zend.date.others.comparison.table">Zend_Date::isDate()</link>.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.digits">
|
|
|
+ <title>Digits</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> contiene
|
|
|
+ solamente dígitos.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+<!--
|
|
|
+ <xi:include href="Zend_Validate-EmailAddress.xml" />
|
|
|
+-->
|
|
|
+ <sect2 id="zend.validate.set.float">
|
|
|
+ <title>Float</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> es un
|
|
|
+ valor de punto flotante.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.greater_than">
|
|
|
+ <title>GreaterThan</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> es mayor
|
|
|
+ al límite mínimo.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.hex">
|
|
|
+ <title>Hex</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> contiene
|
|
|
+ caracteres hexadecimales (0-9 y A-F).
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.hostname">
|
|
|
+
|
|
|
+ <title>Hostname (Nombre de Host)</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Validate_Hostname</code> le permite validar un nombre de host
|
|
|
+ contra una serie de especificaciones conocidas.
|
|
|
+ Es posible comprobar por tres diferentes tipos de nombres:
|
|
|
+ el DNS Hostname (domain.com por ejemplo), dirección IP (es decir 1.2.3.4),
|
|
|
+ y nombres de host locales (localhost, por ejemplo).
|
|
|
+ Por defecto sólo se comprobarán nombres de host DNS.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">Uso básico</emphasis>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El siguiente es un ejemplo de uso basico:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$validator = new Zend_Validate_Hostname();
|
|
|
+if ($validator->isValid($hostname)) {
|
|
|
+ // hostname parece ser válido
|
|
|
+} else {
|
|
|
+ // hostname es inválido; muestre las razones
|
|
|
+ foreach ($validator->getMessages() as $message) {
|
|
|
+ echo "$message\n";
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ Comprobará el nombre de host <code>$hostname</code> y si fracasa
|
|
|
+ alimentará a <code>$validator->getMessages()</code> con mensajes de error.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">Validar diferentes tipos de nombres de host</emphasis>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ También se puede encontrar coincidencias de direcciones IP,
|
|
|
+ nombres de host locales, o una combinación de todos los tipos permitidos.
|
|
|
+ Esto puede hacerse pasando un parámetro a <code>Zend_Validate_Hostname</code>
|
|
|
+ cuando lo instancia.
|
|
|
+ El parámetro debe ser un entero que determina qué tipos de nombres de
|
|
|
+ host están permitidos.
|
|
|
+ Se recomienda el uso de las constantes de <code>Zend_Validate_Hostname</code>
|
|
|
+ para hacerlo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las constantes de <code>Zend_Validate_Hostname</code> son:
|
|
|
+ <code>ALLOW_DNS</code> para permitir sólo nombres de host DNS,
|
|
|
+ <code>ALLOW_IP</code> para permitir direcciones IP,
|
|
|
+ <code>ALLOW_LOCAL</code> para permitir nombres de host de la red local, y
|
|
|
+ <code>ALLOW_ALL</code> para permitir todos estos tres tipos.
|
|
|
+ Para comprobar que direcciones IP puede utilizar, vea el siguiente ejemplo:
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$validator = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_IP);
|
|
|
+if ($validator->isValid($hostname)) {
|
|
|
+ // hostname parece ser válido
|
|
|
+} else {
|
|
|
+ // hostname es inválido; muestre las razones
|
|
|
+ foreach ($validator->getMessages() as $message) {
|
|
|
+ echo "$message\n";
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Usando <code>ALLOW_ALL</code> para aceptar todos los tipos de nombres de
|
|
|
+ host, también puede combinar estos tipos para realizar combinaciones.
|
|
|
+ Por ejemplo, para aceptar nombres de host DNS y locales, instancie el
|
|
|
+ objeto <code>Zend_Validate_Hostname</code> como:
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$validator = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_DNS |
|
|
|
+ Zend_Validate_Hostname::ALLOW_IP);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">Validación de Nombres de Dominio Internacionales</emphasis>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Algunos (ccTLD), es decir países "Country Code Top Level Domains" , como 'de' (Alemania),
|
|
|
+ aceptan caracteres internacionales como nombres de dominio.
|
|
|
+ Estos son conocidos como Nombres de Dominio Internacionales
|
|
|
+ (IDN, por sus siglas en inglés).
|
|
|
+ Se puede buscar una coincidencia de estos dominios con Zend_Validate_Hostname,
|
|
|
+ a través de caracteres extendidos que se utilizan en el proceso de validación.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En la actualidad la lista de las ccTLDs incluyen a:
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>at (Austria)</para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>ch (Suiza)</para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>li (Liechtenstein)</para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>de (Alemania)</para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>fi (Finlandia)</para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>hu (Hungría)</para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>no (Noruega)</para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>se (Suecia)</para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cotejar dominios IDN es tan simple como usar el validador estándar
|
|
|
+ Hostname, ya que este viene habilitado por defecto.
|
|
|
+ Si desea desactivar la validación IDN, se puede hacer ya sea pasando un
|
|
|
+ parámetro al constructor Zend_Validate_Hostname o a través del método
|
|
|
+ <code>$validator->setValidateIdn()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Puede deshabilitar la validación IDN, pasando un segundo parámetro al
|
|
|
+ constructor Zend_Validate_Hostname de la siguiente manera.
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$validator =
|
|
|
+ new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_DNS, false);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ Alternativamente puede pasar TRUE o FALSE a <code>$validator->setValidateIdn()</code>
|
|
|
+ para activar o desactivar la validación IDN.
|
|
|
+ Si está tratando de cotejar un nombre de host IDN que actualmente no
|
|
|
+ está soportado, es probable que falle la validación si tiene caracteres
|
|
|
+ internacionales en el nombre de host.
|
|
|
+ Cuando un archivo ccTLD no existe en Zend/Validate/Hostname, especificando
|
|
|
+ los caracteres adicionales se puede realizar una validación normal.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Tenga en cuenta que una validación IDN solo se realizará si tiene habilidada
|
|
|
+ la validación para nombres de host DNS.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <emphasis role="strong">Validar dominios de nivel superior</emphasis>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por defecto un nombre de host se cotejará con una lista de TLDs conocidos.
|
|
|
+ Si esta funcionalidad no es necesaria, puede ser desactivada en la misma
|
|
|
+ forma que deshabilita el soporte IDN.
|
|
|
+ Puede deshabilitar la validación TLD pasando un tercer parámetro al
|
|
|
+ constructor Zend_Validate_Hostname.
|
|
|
+ En el siguiente ejemplo estamos dando respaldo a la validación IDN a través
|
|
|
+ del segundo parámetro.
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$validator =
|
|
|
+ new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_DNS,
|
|
|
+ true,
|
|
|
+ false);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ Alternativamente puede pasar TRUE o FALSE a <code>$validator->setValidateTld()</code>
|
|
|
+ para activar o desactivar la validación TLD.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Tenga en cuenta que una validación de TLDs solo se realizará si tiene habilidada
|
|
|
+ la validación para nombres de host DNS.
|
|
|
+ </para>
|
|
|
+
|
|
|
+</sect2><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.in_array">
|
|
|
+ <title>InArray</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> se encuentra
|
|
|
+ en un array, y si la opción es estricta entonces también verificará
|
|
|
+ el tipo de dato de <code>$valor</code>.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.int">
|
|
|
+ <title>Int</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> es un valor entero válido.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.ip">
|
|
|
+ <title>Ip</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> es una dirección IP válida.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.less_than">
|
|
|
+ <title>LessThan</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> es menor
|
|
|
+ al límite máximo.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.not_empty">
|
|
|
+ <title>NotEmpty</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> no es vacío.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.regex">
|
|
|
+ <title>Regex</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si <code>$valor</code> coincide
|
|
|
+ con el patrón de una expresión regular.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.validate.set.string_length">
|
|
|
+ <title>StringLength</title>
|
|
|
+ <para>
|
|
|
+ Devuelve <code>true</code> si y sólo si la longitud del string <code>$valor</code>
|
|
|
+ es por lo menos un mínimo y no mayor a un máximo
|
|
|
+ (cuando la opción max no es <code>null</code>).
|
|
|
+ Desde la versión 1.5.0, el método <code>setMin()</code> lanza una
|
|
|
+ excepción si la longitud mínima tiene un valor mayor que la longitud
|
|
|
+ máxima establecida, y el método <code>setMax()</code> lanza una excepción si la
|
|
|
+ longitud máxima se fija a un valor inferior que la longitud
|
|
|
+ mínima establecida. Desde la versión 1.0.2, esta clase soporta UTF-8 y a otras
|
|
|
+ codificaciones, basado en el valor actual de:
|
|
|
+ <ulink url="http://www.php.net/manual/en/ref.iconv.php#iconv.configuration"><code>iconv.internal_encoding</code></ulink>.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.validate.validator_chains" xml:base="module_specs/Zend_Validate-ValidatorChains.xml">
|
|
|
+
|
|
|
+ <title>Cadenas de Validadores</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Frecuentemente deben aplicarse múltiples validaciones a algún valor en
|
|
|
+ un orden particular.
|
|
|
+ El siguiente código demuestra una forma de resolver el ejemplo de la
|
|
|
+ <link linkend="zend.validate.introduction">introducción</link>, donde el
|
|
|
+ nombre de usuario debe tener entre 6 y 12 caracteres alfanuméricos.
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+// Crea una cadena de validadores y le agrega validadores
|
|
|
+$validatorChain = new Zend_Validate();
|
|
|
+$validatorChain->addValidator(new Zend_Validate_StringLength(6, 12))
|
|
|
+ ->addValidator(new Zend_Validate_Alnum());
|
|
|
+
|
|
|
+// Valida el username
|
|
|
+if ($validatorChain->isValid($username)) {
|
|
|
+ // username pasó la validación
|
|
|
+} else {
|
|
|
+ // username falló en la validación; muestre las razones
|
|
|
+ foreach ($validatorChain->getMessages() as $message) {
|
|
|
+ echo "$message\n";
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ Los validadores se ejecutan en el orden en que se agregaron a <code>Zend_Validate</code>.
|
|
|
+ En el ejemplo anterior, el nombre de usuario, primero se comprueba que
|
|
|
+ su longitud esté entre 6 y 12 caracteres y luego se controla para garantizar
|
|
|
+ que sólo contiene caracteres alfanuméricos.
|
|
|
+ La segunda validación; de caracteres alfanuméricos; se realiza independientemente
|
|
|
+ de que la primera validación; de longitud entre 6 y 12 caracteres; tenga éxito.
|
|
|
+ Esto significa que si ambas validaciones fallan, <code>getMessages()</code>
|
|
|
+ devolverá mensajes de fracaso desde ambos validadores.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En algunos casos tiene sentido detener la cadena de validación si falla
|
|
|
+ alguno de los procesos de validación.
|
|
|
+ <code>Zend_Validate</code> acepta tales casos pasando como segundo
|
|
|
+ parámetro el método <code>addValidator()</code>.
|
|
|
+ Poniendo <code>$breakChainOnFailure</code> a <code>true</code>,
|
|
|
+ el validador agregado quebrará la cadena de ejecución por el fracaso,
|
|
|
+ que evita correr cualquier otra validación que se decida que es
|
|
|
+ innecesaria o inapropiada para la situación.
|
|
|
+ Si el ejemplo anterior fue escrito como sigue, entonces el sistema
|
|
|
+ de validación alfanumérica no se ejecutará si falla la longitud del
|
|
|
+ string de validación:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$validatorChain->addValidator(new Zend_Validate_StringLength(6, 12), true)
|
|
|
+ ->addValidator(new Zend_Validate_Alnum());
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cualquier objeto que implemente <code>Zend_Validate_Interface</code>
|
|
|
+ puede ser utilizado en una cadena de validación.
|
|
|
+ </para>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="zend.validate.writing_validators" xml:base="module_specs/Zend_Validate-WritingValidators.xml">
|
|
|
+
|
|
|
+ <title>Escribiendo Validadores</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend_Validate provee un conjunto de validadores que suelen necesitarse,
|
|
|
+ pero inevitablemente, los desarrolladores quiere escribir sus propios
|
|
|
+ validadores personalizados para sus necesidades particulares.
|
|
|
+ La tarea de escribir un validador personalizado se describe en esta sección.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <code>Zend_Validate_Interface</code> define tres métodos, isValid(),
|
|
|
+ getMessages(), y getErrors(), que pueden ser implementadas por clases de usuario
|
|
|
+ a fin de crear objetos de validación personalizados.
|
|
|
+ Un objeto que implementa una interfaz <code>Zend_Validate_Interface</code>
|
|
|
+ puede añadirse a una cadena de validación con <code>Zend_Validate::addValidator()</code>.
|
|
|
+ Tales objetos también pueden ser usados con
|
|
|
+ <link linkend="zend.filter.input"><code>Zend_Filter_Input</code></link>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ De la descripción anterior de <code>Zend_Validate_Interface</code>, podrá inferir
|
|
|
+ que las clases de validación que proporciona Zend Framework devuelven un
|
|
|
+ valor booleano para cuando un valor se valida satisfactoriamente o no.
|
|
|
+ También proporcionan información sobre <emphasis role="bold">por qué</emphasis>
|
|
|
+ un valor falló en la validación.
|
|
|
+ La disponibilidad de las razones para los fracasos de validación puede ser
|
|
|
+ valiosa para una aplicación por diversos motivos, tales como proporcionar
|
|
|
+ estadísticas para análisis de usabilidad.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La funcionalidad de los mensajes de validación básica de fallos están
|
|
|
+ implementados en <code>Zend_Validate_Abstract</code>.
|
|
|
+ A fin de incluir esta funcionalidad al crear una clase de validación,
|
|
|
+ simplemente extienda <code>Zend_Validate_Abstract</code>.
|
|
|
+ En la extensión de la clase deberá aplicar la lógica del método
|
|
|
+ <code>isValid()</code> y definir las variables y plantillas de mensajes
|
|
|
+ que correspondan a los tipos de fallos de validación que puedan suceder.
|
|
|
+ Si falla un valor en su test de validación, entonces <code>isValid()</code>
|
|
|
+ deberá devolver <code>false</code>.
|
|
|
+ Si el valor pasa su test de validación, entonces <code>isValid()</code>
|
|
|
+ deberá devolver <code>true</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ En general, el método <code>isValid()</code> no debería arrojar
|
|
|
+ excepciones, salvo que sea imposible determinar si el valor de entrada
|
|
|
+ es válido o no.
|
|
|
+ Algunos ejemplos de casos razonables para lanzar una excepción podría ser
|
|
|
+ si un archivo no puede abrirse, que un servidor LDAP no pudiera ser
|
|
|
+ contactado, o una conexión a una base de datos no estuviera disponible.
|
|
|
+ Estos son casos en los que puede ser necesario determinar el éxito o
|
|
|
+ fracaso de la validación.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.validate.writing_validators.example.simple">
|
|
|
+
|
|
|
+ <title>Crear una Clase de Validación sencilla</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El siguiente ejemplo demuestra cómo podría escribirse un sencillo
|
|
|
+ validador personalizado.
|
|
|
+ En este caso las reglas de validación son simplemente que el valor
|
|
|
+ de entrada debe ser de punto flotante.
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class MyValid_Float extends Zend_Validate_Abstract
|
|
|
+{
|
|
|
+ const FLOAT = 'float';
|
|
|
+
|
|
|
+ protected $_messageTemplates = array(
|
|
|
+ self::FLOAT => "'%value%' no es un valor de punto flotante"
|
|
|
+ );
|
|
|
+
|
|
|
+ public function isValid($value)
|
|
|
+ {
|
|
|
+ $this->_setValue($value);
|
|
|
+
|
|
|
+ if (!is_float($value)) {
|
|
|
+ $this->_error();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ La clase define una plantilla para su único mensaje de fallo de
|
|
|
+ validación, que incluye el mágico parámetro <code>%value%</code>.
|
|
|
+ La llamada a <code>_setValue()</code> prepara al objeto para insertar
|
|
|
+ automáticamente en el mensaje de fallo al valor probado, si éste
|
|
|
+ falla en la validación.
|
|
|
+ La llamada a <code>_error()</code> sigue las pistas para establecer
|
|
|
+ una razón por el fracaso de la validación.
|
|
|
+ Dado que esta clase sólo define un mensaje de fallo, no es necesario
|
|
|
+ darle a <code>_error()</code> el nombre de la plantilla del mensaje
|
|
|
+ de fallo.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <example id="zend.validate.writing_validators.example.conditions.dependent">
|
|
|
+
|
|
|
+ <title>Escribiendo una Clase de Validación habiendo Condiciones Dependientes </title>
|
|
|
+ <para>
|
|
|
+ El siguiente ejemplo muestra un conjunto de reglas de validación
|
|
|
+ más complejo, donde es necesario que el valor de entrada ser numérico
|
|
|
+ y dentro del límite de un rango de valores mínimos y máximos.
|
|
|
+ Un valor de entrada podría fallar en la validación exactamente por una
|
|
|
+ de las siguientes razones:
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>El valor de entrada no es numérico.</para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>El valor de entrada es menor que el valor mínimo permitido.</para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>El valor de entrada es mayor que el valor máximo permitido.</para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Estas razones en el fallo de validación, son traducidas a las definiciones en la clase:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class MyValid_NumericBetween extends Zend_Validate_Abstract
|
|
|
+{
|
|
|
+ const MSG_NUMERIC = 'msgNumeric';
|
|
|
+ const MSG_MINIMUM = 'msgMinimum';
|
|
|
+ const MSG_MAXIMUM = 'msgMaximum';
|
|
|
+
|
|
|
+ public $minimum = 0;
|
|
|
+ public $maximum = 100;
|
|
|
+
|
|
|
+ protected $_messageVariables = array(
|
|
|
+ 'min' => 'minimum',
|
|
|
+ 'max' => 'maximum'
|
|
|
+ );
|
|
|
+
|
|
|
+ protected $_messageTemplates = array(
|
|
|
+ self::MSG_NUMERIC => "'%value%' no es numérico",
|
|
|
+ self::MSG_MINIMUM => "'%value%' debe ser al menos '%min%'",
|
|
|
+ self::MSG_MAXIMUM => "'%value%' debe ser no mayor a '%max%'"
|
|
|
+ );
|
|
|
+
|
|
|
+ public function isValid($value)
|
|
|
+ {
|
|
|
+ $this->_setValue($value);
|
|
|
+
|
|
|
+ if (!is_numeric($value)) {
|
|
|
+ $this->_error(self::MSG_NUMERIC);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($value < $this->minimum) {
|
|
|
+ $this->_error(self::MSG_MINIMUM);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($value > $this->maximum) {
|
|
|
+ $this->_error(self::MSG_MAXIMUM);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ Las propiedades públicas <code>$minimum</code> y <code>$maximum</code>
|
|
|
+ se han establecido para proporcionar los límites mínimo y máximo,
|
|
|
+ respectivamente, de un valor a validar.
|
|
|
+ La clase también define dos variables de mensajes que corresponden a
|
|
|
+ las propiedades públicas y permiten usar <code>min</code> y <code>max</code>
|
|
|
+ en plantillas de mensajes como parámetros mágicos, al igual que con
|
|
|
+ <code>value</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+
|
|
|
+ Tenga en cuenta que si cualquiera de las comprobaciones de validación
|
|
|
+ falla en <code>isValid()</code>, ya está preparado un mensaje apropiado,
|
|
|
+ y el método inmediatamente devuelve <code>false</code>.
|
|
|
+ Estas reglas de validación son por lo tanto secuencialmente dependientes.
|
|
|
+ Es decir, si uno de los tests falla, no hay necesidad de poner a
|
|
|
+ prueba las posteriores reglas de validación.
|
|
|
+ Sin embargo, esta necesidad no será el caso.
|
|
|
+ El siguiente ejemplo ilustra cómo escribir una clase con reglas de
|
|
|
+ validación independientes, donde el objeto validación puede devolver
|
|
|
+ múltiples razones por las cuales fracasó un intento de validación en
|
|
|
+ particular.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <example id="zend.validate.writing_validators.example.conditions.independent">
|
|
|
+
|
|
|
+ <title>Validación con Condiciones Independientes, Múltiples Razones del Fracaso</title>
|
|
|
+ <para>
|
|
|
+ Considere escribir una clase de validación y control de
|
|
|
+ contraseñas - cuando es necesario que un usuario elija una
|
|
|
+ contraseña que cumple determinados criterios para ayudar a tener
|
|
|
+ cuentas de usuario seguras. Supongamos que la seguridad de la contraseña
|
|
|
+ aplica criterios que fuerzan a lo siguiente:
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>debe tener al menos una longitud de 8 caracteres,</para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>contener al menos una letra en mayúscula,</para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>contener al menos una letra en minúscula,</para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>contener al menos un dígito.</para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La siguiente clase implementa estos criterios de validación:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class MyValid_PasswordStrength extends Zend_Validate_Abstract
|
|
|
+{
|
|
|
+ const LENGTH = 'length';
|
|
|
+ const UPPER = 'upper';
|
|
|
+ const LOWER = 'lower';
|
|
|
+ const DIGIT = 'digit';
|
|
|
+
|
|
|
+ protected $_messageTemplates = array(
|
|
|
+ self::LENGTH => "'%value%' debe tener al menos una longitud de 8 caracteres",
|
|
|
+ self::UPPER => "'%value%' debe contener al menos una letra en mayúscula",
|
|
|
+ self::LOWER => "'%value%' debe contener al menos una letra en minúscula",
|
|
|
+ self::DIGIT => "'%value%' debe contener al menos un dígito"
|
|
|
+ );
|
|
|
+
|
|
|
+ public function isValid($value)
|
|
|
+ {
|
|
|
+ $this->_setValue($value);
|
|
|
+
|
|
|
+ $isValid = true;
|
|
|
+
|
|
|
+ if (strlen($value) < 8) {
|
|
|
+ $this->_error(self::LENGTH);
|
|
|
+ $isValid = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!preg_match('/[A-Z]/', $value)) {
|
|
|
+ $this->_error(self::UPPER);
|
|
|
+ $isValid = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!preg_match('/[a-z]/', $value)) {
|
|
|
+ $this->_error(self::LOWER);
|
|
|
+ $isValid = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!preg_match('/\d/', $value)) {
|
|
|
+ $this->_error(self::DIGIT);
|
|
|
+ $isValid = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return $isValid;
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ Las cuatro pruebas de criterio en <code>isValid()</code> no devuelven
|
|
|
+ inmediatamente <code>false</code>.
|
|
|
+ Esto permite a la clase de validación a proporcionar <emphasis role="bold">todas</emphasis>
|
|
|
+ las razones por las que la contraseña de entrada no cumplió los requisitos
|
|
|
+ de validación.
|
|
|
+ Si, por ejemplo, un usuario ingresara el string "<code>#$%</code>"
|
|
|
+ como contraseña, <code>isValid()</code> causaría que los cuatro
|
|
|
+ mensajes de fracaso de validación sean devueltos por un llamado posterior
|
|
|
+ a <code>getMessages()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </example>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ </chapter>
|
|
|
+ <chapter id="zend.version">
|
|
|
+ <title>Zend_Version</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Version.xml"/>
|
|
|
+ </chapter>
|
|
|
+ <chapter id="zend.view">
|
|
|
+ <title>Zend_View</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_View-Introduction.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_View-Controllers.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_View-Scripts.xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_View-Helpers.xml" parse="xml"/>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_View-Abstract.xml"/>
|
|
|
+ </chapter>
|
|
|
+ <chapter id="zend.wildfire">
|
|
|
+ <title>Zend_Wildfire</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_Wildfire.xml"/>
|
|
|
+ </chapter>
|
|
|
+ <chapter id="zend.xmlrpc">
|
|
|
+ <title>Zend_XmlRpc</title>
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_XmlRpc.xml"/>
|
|
|
+ <sect1 id="zend.xmlrpc.client" xml:base="module_specs/Zend_XmlRpc_Client.xml">
|
|
|
+ <title>Zend_XmlRpc_Client</title>
|
|
|
+
|
|
|
+ <sect2 id="zend.xmlrpc.client.introduction">
|
|
|
+ <title>Introdución</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend Framework provee soporte para consumo remoto para servicios XML-RPC
|
|
|
+ como un cliente en el paquete <code>Zend_XmlRpc_Client</code>
|
|
|
+ . Su mejor característica es la conversión atuomática de tipos
|
|
|
+ entre PHP y XML-RPC, un servidor de objeto proxy, y acceso a
|
|
|
+ capacidades de instrospección del servidor.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+
|
|
|
+ <sect2 id="zend.xmlrpc.client.method-calls">
|
|
|
+ <title>Method Calls</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El constructor de <code>Zend_XmlRpc_Client</code> recibe la
|
|
|
+ URL del servidor XML-RPC como su primer parámetro.
|
|
|
+ La nueva instacia devuelta pu7ede ser usada para llamar cualquier número de métodos remotos en el punto final.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para llamar un método remoto con el cliente XML-RPC, instáncealo
|
|
|
+ y usa el método de instancia <code>call()</code> . El código de ejemplo a continuación utiliza una demostración en el servidor XML-RPC en el sitio wed del Zend Framework
|
|
|
+ . Puede utilizarlo para probar o explorar los componentes
|
|
|
+ <code>Zend_XmlRpc</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.xmlrpc.client.method-calls.example-1">
|
|
|
+ <title>XML-RPC Method Call</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
|
|
|
+
|
|
|
+echo $client->call('test.sayHello');
|
|
|
+
|
|
|
+// hello
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El valor XML-RPC devuelto desde la llamada al método remoto automáticamente será convertida al tipo nativo PHP equivalente
|
|
|
+
|
|
|
+ . En el ejemplo anterior, es devuelto un <code>string</code> PHP
|
|
|
+ y está listo para ser usada inmediatamente.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El primer parámetro del método <code>call()</code> recibe el nombre del método remoto a llamar. Si el método remoto requiere algún parámetro, este puede ser enviado por el suministro de un segundo, parámetro opcional a <code>call()</code> con un <code>array</code> de
|
|
|
+ valores para pasar el método remoto:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.xmlrpc.client.method-calls.example-2">
|
|
|
+ <title>XML-RPC Method Call with Parameters</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
|
|
|
+
|
|
|
+$arg1 = 1.1;
|
|
|
+$arg2 = 'foo';
|
|
|
+
|
|
|
+$result = $client->call('test.sayHello', array($arg1, $arg2));
|
|
|
+
|
|
|
+// $result es un tipo nativo PHP
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ si el método remoto no requiere parámetros, este parámetro opcional
|
|
|
+ podrá ser excluido o se puede pasar un <code>array()</code>
|
|
|
+ vacío. El array de parámeters para el método repoto puede contener tipos nativos PHPs, objetos <code>Zend_XmlRpc_Value</code>
|
|
|
+ , o una combinación de estos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El método <code>call()</code> convertirá automáticamente la respuesta
|
|
|
+ XML-RPC y devolverá su tipo nativo PHP equivalente. Un objeto
|
|
|
+ <code>Zend_XmlRpc_Response</code> para el valor devuelto también estará
|
|
|
+ disponible para llamar el método <code>getLastResponse()</code>
|
|
|
+ después de la llamada.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.xmlrpc.value.parameters">
|
|
|
+ <title>Tipos y Conversiones</title>
|
|
|
+ <para>
|
|
|
+ Algunas llamadas a métodos remoto requieren parámetros. Estos son
|
|
|
+ dados al método <code>call()</code> de <code>Zend_XmlRpc_Client</code>
|
|
|
+ como un array en el segundo parámetro. Cada parámetro puede ser dado
|
|
|
+ como cualquier tipo nativo PHP ya que este será convertido automáticamente,
|
|
|
+ o como un objeto que representa un tipo específico de XML-RPC
|
|
|
+ (uno de los objetos <code>Zend_XmlRpc_Value</code>).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.xmlrpc.value.parameters.php-native">
|
|
|
+ <title>Tipos Nativos PHP como Parámetro</title>
|
|
|
+ <para>
|
|
|
+ Los parámetros pueden ser pasados a <code>call()</code> como variables
|
|
|
+ PHP nativas, ya sea un <code>string</code>,
|
|
|
+ <code>integer</code>, <code>float</code>,
|
|
|
+ <code>boolean</code>, <code>array</code>, o un
|
|
|
+ <code>object</code>. En este caso, cada tipo PHP nativo será
|
|
|
+ autodetectada y convertida en uno de los tipos XML-RPC
|
|
|
+ de acuerdo con esta tabla:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <table id="zend.xmlrpc.value.parameters.php-native.table-1">
|
|
|
+ <title>Tipos de Conversión entre PHP y XML-RPC</title>
|
|
|
+ <tgroup cols="2">
|
|
|
+ <thead>
|
|
|
+ <row>
|
|
|
+ <entry>Tipo Nativo PHP</entry>
|
|
|
+ <entry>Tipo XML-RPC</entry>
|
|
|
+ </row>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ <row>
|
|
|
+ <entry>integer</entry>
|
|
|
+ <entry>int</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>double</entry>
|
|
|
+ <entry>double</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>boolean</entry>
|
|
|
+ <entry>boolean</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>string</entry>
|
|
|
+ <entry>string</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>array</entry>
|
|
|
+ <entry>array</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>array asociativo</entry>
|
|
|
+ <entry>struct</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>object</entry>
|
|
|
+ <entry>array</entry>
|
|
|
+ </row>
|
|
|
+ </tbody>
|
|
|
+ </tgroup>
|
|
|
+ </table>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <title>¿A qué tipo se convierten los arrays Vacios?</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Pasar un array vacío a un método XML-RPC es problemático,
|
|
|
+ as it could represent either an array or a struct.
|
|
|
+ <code>Zend_XmlRpc_Client</code> detects such conditions and
|
|
|
+ makes a request to the server's
|
|
|
+ <code>system.methodSignature</code> method to determine the
|
|
|
+ appropriate XML-RPC type to cast to.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ However, this in itself can lead to issues. First off,
|
|
|
+ servers that do not support
|
|
|
+ <code>system.methodSignature</code> will log failed
|
|
|
+ requests, and <code>Zend_XmlRpc_Client</code> will resort to
|
|
|
+ casting the value to an XML-RPC array type. Additionally,
|
|
|
+ this means that any call with array arguments will result in
|
|
|
+ an additional call to the remote server.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ To disable the lookup entirely, you can call the
|
|
|
+ <code>setSkipSystemLookup()</code> method prior to making
|
|
|
+ your XML-RPC call:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$client->setSkipSystemLookup(true);
|
|
|
+$result = $client->call('foo.bar', array(array()));
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </note>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.xmlrpc.value.parameters.xmlrpc-value">
|
|
|
+ <title><code>Zend_XmlRpc_Value</code> Objects as Parameters</title>
|
|
|
+ <para>
|
|
|
+ Parameters may also be created as <code>Zend_XmlRpc_Value</code>
|
|
|
+ instances to specify an exact XML-RPC type. The primary reasons
|
|
|
+ for doing this are:
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ When you want to make sure the correct parameter
|
|
|
+ type is passed to the procedure (i.e. the
|
|
|
+ procedure requires an integer and you may get it
|
|
|
+ from a database as a string)
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ When the procedure requires <code>base64</code> or
|
|
|
+ <code>dateTime.iso8601</code> type (which doesn't exists as a
|
|
|
+ PHP native type)
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ When auto-conversion may fail (i.e. you want to
|
|
|
+ pass an empty XML-RPC struct as a parameter. Empty
|
|
|
+ structs are represented as empty arrays in PHP
|
|
|
+ but, if you give an empty array as a parameter it
|
|
|
+ will be auto-converted to an XML-RPC array since
|
|
|
+ it's not an associative array)
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ There are two ways to create a <code>Zend_XmlRpc_Value</code>
|
|
|
+ object: instantiate one of the <code>Zend_XmlRpc_Value</code>
|
|
|
+ subclasses directly, or use the static factory method
|
|
|
+ <code>Zend_XmlRpc_Value::getXmlRpcValue()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <table id="zend.xmlrpc.value.parameters.xmlrpc-value.table-1">
|
|
|
+ <title><code>Zend_XmlRpc_Value</code> Objects for XML-RPC Types</title>
|
|
|
+ <tgroup cols="3">
|
|
|
+ <thead>
|
|
|
+ <row>
|
|
|
+ <entry>XML-RPC Type</entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value</code> Constant</entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value</code> Object</entry>
|
|
|
+ </row>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ <row>
|
|
|
+ <entry>int</entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER</code></entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value_Integer</code></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>double</entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_DOUBLE</code></entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value_Double</code></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>boolean</entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_BOOLEAN</code></entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value_Boolean</code></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>string</entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_STRING</code></entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value_String</code></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>base64</entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_BASE64</code></entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value_Base64</code></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>dateTime.iso8601</entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME</code></entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value_DateTime</code></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>array</entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_ARRAY</code></entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value_Array</code></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>struct</entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value::XMLRPC_TYPE_STRUCT</code></entry>
|
|
|
+ <entry><code>Zend_XmlRpc_Value_Struct</code></entry>
|
|
|
+ </row>
|
|
|
+ </tbody>
|
|
|
+ </tgroup>
|
|
|
+ </table>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <note>
|
|
|
+ <title>Automatic Conversion</title>
|
|
|
+ <para>
|
|
|
+ When building a new <code>Zend_XmlRpc_Value</code>
|
|
|
+ object, its value is set by a PHP type. The PHP type
|
|
|
+ will be converted to the specified type using
|
|
|
+ PHP casting. For example, if a string is given as a
|
|
|
+ value to the <code>Zend_XmlRpc_Value_Integer</code>
|
|
|
+ object, it will be converted using
|
|
|
+ <code>(int)$value</code>.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.xmlrpc.client.requests-and-responses">
|
|
|
+ <title>Server Proxy Object</title>
|
|
|
+ <para>
|
|
|
+ Another way to call remote methods with the XML-RPC client is to
|
|
|
+ use the server proxy. This is a PHP object that proxies a remote
|
|
|
+ XML-RPC namespace, making it work as close to a native PHP object
|
|
|
+ as possible.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ To instantiate a server proxy, call the <code>getProxy()</code>
|
|
|
+ instance method of <code>Zend_XmlRpc_Client</code>. This will
|
|
|
+ return an instance of <code>Zend_XmlRpc_Client_ServerProxy</code>.
|
|
|
+ Any method call on the server proxy object will be forwarded to
|
|
|
+ the remote, and parameters may be passed like any other PHP
|
|
|
+ method.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.xmlrpc.client.requests-and-responses.example-1">
|
|
|
+ <title>Proxy the Default Namespace</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
|
|
|
+
|
|
|
+$server = $client->getProxy(); // Proxy the default namespace
|
|
|
+
|
|
|
+$hello = $server->test->sayHello(1, 2); // test.Hello(1, 2) returns "hello"
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The <code>getProxy()</code> method receives an optional argument
|
|
|
+ specifying which namespace of the remote server to proxy. If it
|
|
|
+ does not receive a namespace, the default namespace will be
|
|
|
+ proxied. In the next example, the <code>test</code> namespace
|
|
|
+ will be proxied:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.xmlrpc.client.requests-and-responses.example-2">
|
|
|
+ <title>Proxy Any Namespace</title>
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
|
|
|
+
|
|
|
+$test = $client->getProxy('test'); // Proxy the "test" namespace
|
|
|
+
|
|
|
+$hello = $test->sayHello(1, 2); // test.Hello(1,2) returns "hello"
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If the remote server supports nested namespaces of any depth,
|
|
|
+ these can also be used through the server proxy. For example, if
|
|
|
+ the server in the example above had a method
|
|
|
+ <code>test.foo.bar()</code>, it could be called as
|
|
|
+ <code>$test->foo->bar()</code>.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+
|
|
|
+ <sect2 id="zend.xmlrpc.client.error-handling">
|
|
|
+ <title>Error Handling</title>
|
|
|
+ <para>
|
|
|
+ Two kinds of errors can occur during an XML-RPC method call: HTTP
|
|
|
+ errors and XML-RPC faults. The <code>Zend_XmlRpc_Client</code>
|
|
|
+ recognizes each and provides the ability to detect and trap them
|
|
|
+ independently.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="zend.xmlrpc.client.error-handling.http">
|
|
|
+ <title>HTTP Errors</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If any HTTP error occurs, such as the remote HTTP server
|
|
|
+ returns a <code>404 Not Found</code>, a
|
|
|
+ <code>Zend_XmlRpc_Client_HttpException</code> will be thrown.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.xmlrpc.client.error-handling.http.example-1">
|
|
|
+ <title>Handling HTTP Errors</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$client = new Zend_XmlRpc_Client('http://foo/404');
|
|
|
+
|
|
|
+try {
|
|
|
+
|
|
|
+ $client->call('bar', array($arg1, $arg2));
|
|
|
+
|
|
|
+} catch (Zend_XmlRpc_Client_HttpException $e) {
|
|
|
+
|
|
|
+ // $e->getCode() returns 404
|
|
|
+ // $e->getMessage() returns "Not Found"
|
|
|
+
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Regardless of how the XML-RPC client is used, the
|
|
|
+ <code>Zend_XmlRpc_Client_HttpException</code> will be thrown
|
|
|
+ whenever an HTTP error occurs.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="zend.xmlrpc.client.error-handling.faults">
|
|
|
+ <title>XML-RPC Faults</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ An XML-RPC fault is analogous to a PHP exception. It is a
|
|
|
+ special type returned from an XML-RPC method call that has
|
|
|
+ both an error code and an error message. XML-RPC faults are
|
|
|
+ handled differently depending on the context of how the
|
|
|
+ <code>Zend_XmlRpc_Client</code> is used.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ When the <code>call()</code> method or the server
|
|
|
+ proxy object is used, an XML-RPC fault will result in a
|
|
|
+ <code>Zend_XmlRpc_Client_FaultException</code> being thrown.
|
|
|
+ The code and message of the exception will map directly to
|
|
|
+ their respective values in the original XML-RPC fault
|
|
|
+ response.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.xmlrpc.client.error-handling.faults.example-1">
|
|
|
+ <title>Handling XML-RPC Faults</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
|
|
|
+
|
|
|
+try {
|
|
|
+
|
|
|
+ $client->call('badMethod');
|
|
|
+
|
|
|
+} catch (Zend_XmlRpc_Client_FaultException $e) {
|
|
|
+
|
|
|
+ // $e->getCode() returns 1
|
|
|
+ // $e->getMessage() returns "Unknown method"
|
|
|
+
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ When the <code>call()</code> method is used to make the
|
|
|
+ request, the <code>Zend_XmlRpc_Client_FaultException</code> will be
|
|
|
+ thrown on fault. A <code>Zend_XmlRpc_Response</code> object
|
|
|
+ containing the fault will also be available by calling
|
|
|
+ <code>getLastResponse()</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ When the <code>doRequest()</code> method is used to make the
|
|
|
+ request, it will not throw the exception. Instead, it will
|
|
|
+ return a <code>Zend_XmlRpc_Response</code> object returned
|
|
|
+ will containing the fault. This can be checked with
|
|
|
+ <code>isFault()</code> instance method of
|
|
|
+ <code>Zend_XmlRpc_Response</code>.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.xmlrpc.client.introspection">
|
|
|
+ <title>Server Introspection</title>
|
|
|
+ <para>
|
|
|
+ Some XML-RPC servers support the de facto introspection methods under the XML-RPC
|
|
|
+ <code>system.</code> namespace. <code>Zend_XmlRpc_Client</code> provides special
|
|
|
+ support for servers with these capabilities.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A <code>Zend_XmlRpc_Client_ServerIntrospection</code> instance may be retrieved by calling
|
|
|
+ the <code>getIntrospector()</code> method of <code>Zend_XmlRpcClient</code>. It can
|
|
|
+ then be used to perform introspection operations on the server.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.xmlrpc.client.request-to-response">
|
|
|
+ <title>From Request to Response</title>
|
|
|
+ <para>
|
|
|
+ Under the hood, the <code>call()</code> instance method of <code>Zend_XmlRpc_Client</code>
|
|
|
+ builds a request object (<code>Zend_XmlRpc_Request</code>) and sends it to another method,
|
|
|
+ <code>doRequest()</code>, that returns a response object (<code>Zend_XmlRpc_Response</code>).
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The <code>doRequest()</code> method is also available for use directly:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="zend.xmlrpc.client.request-to-response.example-1">
|
|
|
+ <title>Processing Request to Response</title>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');
|
|
|
+
|
|
|
+$request = new Zend_XmlRpc_Request();
|
|
|
+$request->setMethod('test.sayHello');
|
|
|
+$request->setParams(array('foo', 'bar'));
|
|
|
+
|
|
|
+$client->doRequest($request);
|
|
|
+
|
|
|
+// $server->getLastRequest() returns instanceof Zend_XmlRpc_Request
|
|
|
+// $server->getLastResponse() returns instanceof Zend_XmlRpc_Response
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </example>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Whenever an XML-RPC method call is made by the client through any
|
|
|
+ means, either the <code>call()</code> method,
|
|
|
+ <code>doRequest()</code> method, or server proxy, the last request
|
|
|
+ object and its resultant response object will always be available
|
|
|
+ through the methods <code>getLastRequest()</code> and
|
|
|
+ <code>getLastResponse()</code> respectively.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="zend.xmlrpc.client.http-client">
|
|
|
+ <title>HTTP Client and Testing</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In all of the prior examples, an HTTP client was never specified.
|
|
|
+ When this is the case, a new instance of
|
|
|
+ <code>Zend_Http_Client</code> will be created with its default
|
|
|
+ options and used by <code>Zend_XmlRpc_Client</code> automatically.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The HTTP client can be retrieved at any time with the
|
|
|
+ <code>getHttpClient()</code> method. For most cases, the default
|
|
|
+ HTTP client will be sufficient. However, the
|
|
|
+ <code>setHttpClient()</code> method allows for a different HTTP
|
|
|
+ client instance to be injected.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The <code>setHttpClient()</code> is particularly useful for unit testing. When combined
|
|
|
+ with the <code>Zend_Http_Client_Adapter_Test</code>, remote services can be mocked
|
|
|
+ out for testing. See the unit tests for <code>Zend_XmlRpc_Client</code> for examples
|
|
|
+ of how to do this.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="module_specs/Zend_XmlRpc_Server.xml"/>
|
|
|
+ </chapter>
|
|
|
+ <appendix id="requirements" xml:base="ref/requirements.xml">
|
|
|
+
|
|
|
+ <title>Zend Framework Requirements</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend Framework requires a PHP 5 interpreter with a web server configured
|
|
|
+ to handle PHP scripts correctly. Some features require additional extensions or
|
|
|
+ web server features; in most cases the framework can be used without them, although
|
|
|
+ performance may suffer or ancillary features may not be fully functional. An example
|
|
|
+ of such a dependency is mod_rewrite in an Apache environment, which can be used to
|
|
|
+ implement "pretty URL's" like "http://www.example.com/user/edit". If mod_rewrite is
|
|
|
+ not enabled, ZF can be configured to support URL's such as "http://www.example.com?controller=user&action=edit".
|
|
|
+ Pretty URL's may be used to shorten URL's for textual representation or search engine optimization (SEO),
|
|
|
+ but they do not directly affect the functionality of the application.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect1 id="requirements.version">
|
|
|
+
|
|
|
+ <title>PHP Version</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend recommends PHP 5.2.3 or higher for critical security and performance enhancements, although
|
|
|
+ Zend Framework requires only PHP 5.1.4 or later.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend Framework has an extensive collection of unit tests, which you can run using PHPUnit 3.0 or later.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect1>
|
|
|
+
|
|
|
+ <sect1 id="requirements.extensions">
|
|
|
+
|
|
|
+ <title>PHP Extensions</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You will find a table listing all extensions typically found in PHP
|
|
|
+ and how they are used in Zend Framework below. You should verify that the extensions on
|
|
|
+ which ZF components you'll be using in your application are available in your PHP environments.
|
|
|
+ Many applications will not require every extension listed below.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A dependency of type "hard" indicates that the components or classes
|
|
|
+ cannot function properly if the respective extension is not available,
|
|
|
+ while a dependency of type "soft" indicates that the component may use
|
|
|
+ the extension if it is available but will function properly if it is not.
|
|
|
+ Many components will automatically use certain extensions if they are available
|
|
|
+ to optimize performance but will execute code with similar functionality in the
|
|
|
+ component itself if the extensions are unavailable.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <table frame="all" id="requirements.extensions.table-1">
|
|
|
+ <title>PHP Extensions Used in Zend Framework by Component</title>
|
|
|
+ <tgroup cols="3">
|
|
|
+ <!-- <colspec colwidth='1in'/>
|
|
|
+ <colspec colwidth='1in'/>
|
|
|
+ <colspec colwidth='3in'/> -->
|
|
|
+ <thead>
|
|
|
+ <row>
|
|
|
+ <entry>Extension</entry>
|
|
|
+ <entry>Dependency Type</entry>
|
|
|
+ <entry>Used by Zend Framework Components</entry>
|
|
|
+ </row>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.apc.php"><code>apc</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.cache.backends.html"><code>Zend_Cache_Backend_Apc</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.bc.php"><code>bcmath</code></ulink></emphasis></entry>
|
|
|
+ <entry>Soft</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.locale.html"><code>Zend_Locale</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://pecl.php.net/package/Bitset"><code>bitset</code></ulink></emphasis></entry>
|
|
|
+ <entry>Soft</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.search.lucene.html"><code>Zend_Search_Lucene</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.bzip2.php"><code>bz2</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.calendar.php"><code>calendar</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.com.php"><code>com_dotnet</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="8" valign="middle"><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.ctype.php"><code>ctype</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="8" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.auth.adapter.http.html"><code>Zend_Auth_Adapter_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.gdata.html"><code>Zend_Gdata</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http_Client</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.pdf.html"><code>Zend_Pdf</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.rest.client.html"><code>Zend_Rest_Client</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.rest.server.html"><code>Zend_Rest_Server</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.search.lucene.html"><code>Zend_Search_Lucene</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.uri.html"><code>Zend_Uri</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.validate.html"><code>Zend_Validate</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.curl.php"><code>curl</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.client.adapters.html"><code>Zend_Http_Client_Adapter_Curl</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.datetime.php"><code>date</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.dba.php"><code>dba</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.dbase.php"><code>dbase</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="10" valign="middle"><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>dom</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="10" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.feed.html"><code>Zend_Feed</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.gdata.html"><code>Zend_Gdata</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.log.formatters.html"><code>Zend_Log_Formatter_Xml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.rest.server.html"><code>Zend_Rest_Server</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.search.lucene.html"><code>Zend_Search_Lucene</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.service.amazon.html"><code>Zend_Service_Amazon</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.service.delicious.html"><code>Zend_Service_Delicious</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.service.flickr.html"><code>Zend_Service_Flickr</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.service.simpy.html"><code>Zend_Service_Simpy</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.service.yahoo.html"><code>Zend_Service_Yahoo</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.xmlrpc.html"><code>Zend_XmlRpc</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.exif.php"><code>exif</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.fbsql.php"><code>fbsql</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.fdf.php"><code>fdf</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.filter.php"><code>filter</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.ftp.php"><code>ftp</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.image.php"><code>gd</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.pdf.html"><code>Zend_Pdf</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.gettext.php"><code>gettext</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.gmp.php"><code>gmp</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.hash.php"><code>hash</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.auth.adapter.http.html"><code>Zend_Auth_Adapter_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.ibm-db2.php"><code>ibm_db2</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Db2</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="7" valign="middle"><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.iconv.php"><code>iconv</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="7" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.currency.html"><code>Zend_Currency</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.locale.parsing.html"><code>Zend_Locale_Format</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.mime.html"><code>Zend_Mime</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.pdf.html"><code>Zend_Pdf</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.search.lucene.html"><code>Zend_Search_Lucene</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.service.audioscrobbler.html"><code>Zend_Service_Audioscrobbler</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.service.flickr.html"><code>Zend_Service_Flickr</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.xmlrpc.client.html"><code>Zend_XmlRpc_Client</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.imap.php"><code>imap</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.ifx.php"><code>informix</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.ibase.php"><code>interbase</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>Zend_Db_Adapter_Firebird</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.json.php"><code>json</code></ulink></emphasis></entry>
|
|
|
+ <entry>Soft</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.json.html"><code>Zend_Json</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.ldap.php"><code>ldap</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>DOM</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.simplexml.php"><code>SimpleXML</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.xslt.php"><code>XSLT</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.mbstring.php"><code>mbstring</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.feed.html"><code>Zend_Feed</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.mcrypt.php"><code>mcrypt</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.memcache.php"><code>memcache</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.cache.backends.html"><code>Zend_Cache_Backend_Memcached</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.mhash.php"><code>mhash</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.mime-magic.php"><code>mime_magic</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http_Client</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.ming.php"><code>ming</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.msql.php"><code>msql</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.mssql.php"><code>mssql</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.mysql.php"><code>mysql</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.mysqli.php"><code>mysqli</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Mysqli</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.ncurses.php"><code>ncurses</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.oci8.php"><code>oci8</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Oracle</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.uodbc.php"><code>odbc</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.openssl.php"><code>openssl</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.pcntl.php"><code>pcntl</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.pcre.php"><code>pcre</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>Virtually all components</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.pdo.php"><code>pdo</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>All PDO database adapters</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.pdo-dblib.php"><code>pdo_dblib</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.pdo-firebird.php"><code>pdo_firebird</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><code>pdo_mssql</code></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Pdo_Mssql</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.pdo-mysql.php"><code>pdo_mysql</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Pdo_Mysql</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.pdo-oci.php"><code>pdo_oci</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Pdo_Oci</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.pdo-pgsql.php"><code>pdo_pgsql</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Pdo_Pgsql</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.pdo-sqlite.php"><code>pdo_sqlite</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Pdo_Sqlite</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.pgsql.php"><code>pgsql</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.posix.php"><code>posix</code></ulink></emphasis></entry>
|
|
|
+ <entry>Soft</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.mail.html"><code>Zend_Mail</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.pspell.php"><code>pspell</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.readline.php"><code>readline</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.recode.php"><code>recode</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="9" valign="middle"><emphasis role="strong"><ulink url="http://www.php.net/manual/en/language.oop5.reflection.php"><code>Reflection</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="9" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.controller.html"><code>Zend_Controller</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.filter.html"><code>Zend_Filter</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.filter.input.html"><code>Zend_Filter_Input</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.json.html"><code>Zend_Json</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.log.html"><code>Zend_Log</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.rest.server.html"><code>Zend_Rest_Server</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.server.reflection.html"><code>Zend_Server_Reflection</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.validate.html"><code>Zend_Validate</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.view.html"><code>Zend_View</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.xmlrpc.server.html"><code>Zend_XmlRpc_Server</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.session.php"><code>session</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.controller.actionhelpers.html"><code>Zend_Controller_Action_Helper_Redirector</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.session.html"><code>Zend_Session</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.shmop.php"><code>shmop</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry/>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="4" valign="middle"><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.simplexml.php"><code>SimpleXML</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="4" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.config.adapters.xml.html"><code>Zend_Config_Xml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.feed.html"><code>Zend_Feed</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.rest.client.html"><code>Zend_Rest_Client</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.service.audioscrobbler.html"><code>Zend_Service_Audioscrobbler</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.xmlrpc.html"><code>Zend_XmlRpc</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.soap.php"><code>soap</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.service.strikeiron.html"><code>Zend_Service_StrikeIron</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.sockets.php"><code>sockets</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.spl.php"><code>SPL</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>Virtually all components</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.sqlite.php"><code>SQLite</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.cache.backends.html">Zend_Cache_Backend_Sqlite</ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><code>standard</code></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>Virtually all components</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.sybase.php"><code>sybase</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong">sysvmsg</emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong">sysvsem</emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>--</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong">sysvshm</emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.tidy.php"><code>tidy</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.tokenizer.php"><code>tokenizer</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.wddx.php"><code>wddx</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.xml.php"><code>xml</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.translate.adapter.html"><code>Zend_Translate_Adapter_Qt</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.translate.adapter.html"><code>Zend_Translate_Adapter_Tmx</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.translate.adapter.html"><code>Zend_Translate_Adapter_Xliff</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.xmlreader.php"><code>XMLReader</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.xmlrpc.php"><code>xmlrpc</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.xmlwriter.php"><code>XMLWriter</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.xsl.php"><code>xsl</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.zip.php"><code>zip</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://www.php.net/manual/en/ref.zlib.php"><code>zlib</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.pdf.html"><code>Zend_Pdf</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.memcache.php"><code>Memcache</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ </tbody>
|
|
|
+ </tgroup>
|
|
|
+ </table>
|
|
|
+
|
|
|
+ </sect1>
|
|
|
+
|
|
|
+ <sect1 id="requirements.zendcomponents">
|
|
|
+
|
|
|
+ <title>Zend Framework Components</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Below is a table that lists all available Zend Framework Components
|
|
|
+ and which PHP extension they need. This can help guide you
|
|
|
+ to know which extensions are required for your application.
|
|
|
+ Not all extensions used by Zend Framework are required for every
|
|
|
+ application.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A dependency of type "hard" indicates that the components or classes
|
|
|
+ cannot function properly if the respective extension is not available,
|
|
|
+ while a dependency of type "soft" indicates that the component may use
|
|
|
+ the extension if it is available but will function properly if it is not.
|
|
|
+ Many components will automatically use certain extensions if they are available
|
|
|
+ to optimize performance but will execute code with similar functionality in the
|
|
|
+ component itself if the extensions are unavailable.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <table frame="all" id="requirements.zendcomponents.table-1">
|
|
|
+ <title>Zend Framework Components and the PHP Extensions they use</title>
|
|
|
+ <tgroup cols="4">
|
|
|
+ <!-- <colspec colwidth='3in'/>
|
|
|
+ <colspec colwidth='1in'/>
|
|
|
+ <colspec colwidth='3in'/>
|
|
|
+ <colspec colwidth='3in'/> -->
|
|
|
+ <thead>
|
|
|
+ <row>
|
|
|
+ <entry>Zend Framework Components</entry>
|
|
|
+ <entry>Dependency Type</entry>
|
|
|
+ <entry>Subclass</entry>
|
|
|
+ <entry>PHP Extension</entry>
|
|
|
+ </row>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong">All Components</emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="2" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.pcre.php"><code>pcre</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.spl.php"><code>SPL</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><code>standard</code></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.acl.html"><code>Zend_Acl</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.auth.html"><code>Zend_Auth</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="1" valign="middle"><ulink url="http://framework.zend.com/manual/en/zend.auth.adapter.http.html"><code>Zend_Auth_Adapter_Http</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.ctype.php"><code>ctype</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.hash.php"><code>hash</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.cache.html"><code>Zend_Cache</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.cache.backends.html"><code>Zend_Cache_Backend_Apc</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.apc.php"><code>apc</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.cache.backends.html"><code>Zend_Cache_Backend_Memcached</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.memcache.php"><code>memcache</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.cache.backends.html"><code>Zend_Cache_Backend_Sqlite</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.sqlite.php"><code>sqlite</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.cache.backends.html"><code>Zend_Cache_Backend_Zlib</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.zlib.php"><code>zlib</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.config.html"><code>Zend_Config</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="1" valign="middle"><ulink url="http://framework.zend.com/manual/en/zend.config.adapters.xml.html"><code>Zend_Config_Xml</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.simplexml.php"><code>SimpleXML</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.console.getopt.html"><code>Zend_Console_Getopt</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.controller.html"><code>Zend_Controller</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/language.oop5.reflection.php"><code>Reflection</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.controller.actionhelpers.html"><code>Zend_Controller_Action_Helper_Redirector</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.session.php"><code>session</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.currency.html"><code>Zend_Currency</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.iconv.php"><code>iconv</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.date.html"><code>Zend_Date</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="8" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="8" valign="middle">Hard</entry>
|
|
|
+ <entry>All PDO Adapters</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.pdo.php"><code>pdo</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Db2</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.ibm-db2.php"><code>ibm_db2</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Mysqli</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.mysqli.php"><code>mysqli</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Oracle</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.oci8.php"><code>oci8</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Pdo_Mssql</code></ulink></entry>
|
|
|
+ <entry>pdo_mssql</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Pdo_Mysql</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.pdo-mysql.php"><code>pdo_mysql</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Pdo_Oci</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.pdo-oci.php"><code>pdo_oci</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Pdo_Pgsql</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.pdo-pgsql.php"><code>pdo_pgsql</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db_Adapter_Pdo_Sqlite</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.pdo-sqlite.php"><code>pdo_sqlite</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.debug.html"><code>Zend_Debug</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.feed.html"><code>Zend_Feed</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="3" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>dom</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.mbstring.php"><code>mbstring</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.simplexml.php"><code>SimpleXML</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.filter.html"><code>Zend_Filter</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/language.oop5.reflection.php"><code>Reflection</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.form.html"><code>Zend_Form</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.gdata.html"><code>Zend_Gdata</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.gdata.html"><code>Zend_Gdata_App</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.ctype.php"><code>ctype</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>dom</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.client.adapters.html"><code>Zend_Http_Client_Adapter_Curl</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.curl.php"><code>curl</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http_Client</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.ctype.php"><code>ctype</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.mime-magic.php"><code>mime_magic</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.infocard.html"><code>Zend_InfoCard</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.json.html"><code>Zend_Json</code></ulink></emphasis></entry>
|
|
|
+ <entry>Soft</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.json.php"><code>json</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/language.oop5.reflection.php"><code>Reflection</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.layout.html"><code>Zend_Layout</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.ldap.html"><code>Zend_Ldap</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.locale.html"><code>Zend_Locale</code></ulink></emphasis></entry>
|
|
|
+ <entry>Soft</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.locale.html"><code>Zend_Locale_Math</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.bc.php"><code>bcmath</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.locale.parsing.html"><code>Zend_Locale_Format</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.iconv.php"><code>iconv</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.log.html"><code>Zend_Log</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="1" valign="middle"><ulink url="http://framework.zend.com/manual/en/zend.log.formatters.html"><code>Zend_Log_Formatter_Xml</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>dom</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/language.oop5.reflection.php"><code>Reflection</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.mail.html"><code>Zend_Mail</code></ulink></emphasis></entry>
|
|
|
+ <entry>Soft</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.posix.php"><code>posix</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.measure.html"><code>Zend_Measure</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.memory.html"><code>Zend_Memory</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.mime.html"><code>Zend_Mime</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.mime.html"><code>Zend_Mime_Decode</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.iconv.php"><code>iconv</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.openid.html"><code>Zend_OpenId</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.pdf.html"><code>Zend_Pdf</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="3" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.ctype.php"><code>ctype</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.image.php"><code>gd</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.iconv.php"><code>iconv</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.zlib.php"><code>zlib</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.registry.html"><code>Zend_Registry</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.request.html"><code>Zend_Request</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="6" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.rest.html"><code>Zend_Rest</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="6" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="2" valign="middle"><ulink url="http://framework.zend.com/manual/en/zend.rest.client.html"><code>Zend_Rest_Client</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.ctype.php"><code>ctype</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.simplexml.php"><code>SimpleXML</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><ulink url="http://framework.zend.com/manual/en/zend.rest.server.html"><code>Zend_Rest_Server</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.ctype.php"><code>ctype</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>dom</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/language.oop5.reflection.php"><code>Reflection</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="4" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.search.lucene.html"><code>Zend_Search_Lucene</code></ulink></emphasis></entry>
|
|
|
+ <entry>Soft</entry>
|
|
|
+ <entry morerows="4" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://pecl.php.net/package/Bitset"><code>bitset</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.ctype.php"><code>ctype</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>dom</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.iconv.php"><code>iconv</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.server.reflection.html"><code>Zend_Server_Reflection</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/language.oop5.reflection.php"><code>Reflection</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.akismet.html"><code>Zend_Service_Akismet</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.amazon.html"><code>Zend_Service_Amazon</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="1" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>dom</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.audioscrobbler.html"><code>Zend_Service_Audioscrobbler</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="2" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.iconv.php"><code>iconv</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.simplexml.php"><code>SimpleXML</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.delicious.html"><code>Zend_Service_Delicious</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="1" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>dom</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.flickr.html"><code>Zend_Service_Flickr</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="2" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>dom</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.iconv.php"><code>iconv</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.nirvanix.html"><code>Zend_Service_Nirvanix</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.simpy.html"><code>Zend_Service_Simpy</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="1" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>dom</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.slideshare.html"><code>Zend_Service_SlideShare</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.strikeiron.html"><code>Zend_Service_StrikeIron</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.soap.php"><code>soap</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.technorati.html"><code>Zend_Service_Technorati</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.yahoo.html"><code>Zend_Service_Yahoo</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="1" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>dom</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.session.html"><code>Zend_Session</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.session.php"><code>session</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.timesync.html"><code>Zend_TimeSync</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.translate.html"><code>Zend_Translate</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.translate.adapter.html"><code>Zend_Translate_Adapter_Qt</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.xml.php"><code>xml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.translate.adapter.html"><code>Zend_Translate_Adapter_Tmx</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.xml.php"><code>xml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.translate.adapter.html"><code>Zend_Translate_Adapter_Xliff</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.xml.php"><code>xml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.uri.html"><code>Zend_Uri</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.ctype.php"><code>ctype</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.validate.html"><code>Zend_Validate</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="1" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.ctype.php"><code>ctype</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/language.oop5.reflection.php"><code>Reflection</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.version.html"><code>Zend_Version</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.validate.html"><code>Zend_Validate</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/language.oop5.reflection.php"><code>Reflection</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="4" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.xmlrpc.html"><code>Zend_XmlRpc</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="4" valign="middle">Hard</entry>
|
|
|
+ <entry morerows="2" valign="middle">---</entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.dom.php"><code>dom</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.libxml.php"><code>libxml</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.simplexml.php"><code>SimpleXML</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.xmlrpc.client.html"><code>Zend_XmlRpc_Client</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/ref.iconv.php"><code>iconv</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.xmlrpc.server.html"><code>Zend_XmlRpc_Server</code></ulink></entry>
|
|
|
+ <entry><ulink url="http://www.php.net/manual/en/language.oop5.reflection.php"><code>Reflection</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ </tbody>
|
|
|
+ </tgroup>
|
|
|
+ </table>
|
|
|
+
|
|
|
+ </sect1>
|
|
|
+
|
|
|
+ <sect1 id="requirements.dependencies">
|
|
|
+
|
|
|
+ <title>Zend Framework Dependencies</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Below you can find a table listing Zend Framework Components
|
|
|
+ and their dependencies to other Zend Framework Components. This
|
|
|
+ can help you if you need to have only single components instead
|
|
|
+ of the complete Zend Framework.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ A dependency of type "hard" indicates that the components or classes
|
|
|
+ cannot function properly if the respective dependent component is not available,
|
|
|
+ while a dependency of type "soft" indicates that the component may need
|
|
|
+ the dependent component in special situations or with special adapters.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ Even if it's possible to seperate single components for
|
|
|
+ usage from the complete Zend Framework you should keep
|
|
|
+ in mind that this can lead to problems when files are missed
|
|
|
+ or components are used dynamically.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <table frame="all" id="requirements.dependencies.table-1">
|
|
|
+ <title>Zend Framework Components and their dependency to other Zend Framework Components</title>
|
|
|
+ <tgroup cols="3">
|
|
|
+ <colspec colwidth="2in"/>
|
|
|
+ <colspec colwidth="1in"/>
|
|
|
+ <colspec colwidth="4in"/>
|
|
|
+ <thead>
|
|
|
+ <row>
|
|
|
+ <entry>Zend Framework Component</entry>
|
|
|
+ <entry>Dependency Type</entry>
|
|
|
+ <entry>Dependent Zend Framework Component</entry>
|
|
|
+ </row>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.acl.html"><code>Zend_Acl</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="5" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.auth.html"><code>Zend_Auth</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="4" valign="middle">Soft</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.infocard.html"><code>Zend_InfoCard</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.ldap.html"><code>Zend_Ldap</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.openid.html"><code>Zend_OpenId</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.session.html"><code>Zend_Session</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.cache.html"><code>Zend_Cache</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.config.html"><code>Zend_Config</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.console.getopt.html"><code>Zend_Console_Getopt</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.json.html"><code>Zend_Json</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="9" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.controller.html"><code>Zend_Controller</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="9" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.config.html"><code>Zend_Config</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.filter.html"><code>Zend_Filter</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.json.html"><code>Zend_Json</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.layout.html"><code>Zend_Layout</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.registry.html"><code>Zend_Registry</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.session.html"><code>Zend_Session</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.uri.html"><code>Zend_Uri</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.view.html"><code>Zend_View</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.currency.html"><code>Zend_Currency</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.locale.html"><code>Zend_Locale</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.date.html"><code>Zend_Date</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.locale.html"><code>Zend_Locale</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.db.html"><code>Zend_Db</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.config.html"><code>Zend_Config</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.registry.html"><code>Zend_Registry</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.debug.html"><code>Zend_Debug</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.feed.html"><code>Zend_Feed</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.uri.html"><code>Zend_Uri</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.filter.html"><code>Zend_Filter</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.locale.html"><code>Zend_Locale</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.validate.html"><code>Zend_Validate</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="7" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.form.html"><code>Zend_Form</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="7" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.controller.html"><code>Zend_Controller</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.filter.html"><code>Zend_Filter</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.json.html"><code>Zend_Json</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.registry.html"><code>Zend_Registry</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.session.html"><code>Zend_Session</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.validate.html"><code>Zend_Validate</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="4" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.gdata.html"><code>Zend_Gdata</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="4" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.mime.html"><code>Zend_Mime</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.version.html"><code>Zend_Version</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.uri.html"><code>Zend_Uri</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.infocard.html"><code>Zend_InfoCard</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.json.html"><code>Zend_Json</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="4" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.layout.html"><code>Zend_Layout</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="4" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.controller.html"><code>Zend_Controller</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.filter.html"><code>Zend_Filter</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.view.html"><code>Zend_View</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.ldap.html"><code>Zend_Ldap</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.locale.html"><code>Zend_Locale</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.log.html"><code>Zend_Log</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.mail.html"><code>Zend_Mail</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.mime.html"><code>Zend_Mime</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.validate.html"><code>Zend_Validate</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.measure.html"><code>Zend_Measure</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.locale.html"><code>Zend_Locale</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.memory.html"><code>Zend_Memory</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.cache.html"><code>Zend_Cache</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.mime.html"><code>Zend_Mime</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.openid.html"><code>Zend_OpenId</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.controller.html"><code>Zend_Controller</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.session.html"><code>Zend_Session</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.pdf.html"><code>Zend_Pdf</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.log.html"><code>Zend_Log</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.memory.html"><code>Zend_Memory</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.registry.html"><code>Zend_Registry</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.request.html"><code>Zend_Request</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.rest.html"><code>Zend_Rest</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.server.html"><code>Zend_Server</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.service.html"><code>Zend_Service</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.uri.html"><code>Zend_Uri</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.search.lucene.html"><code>Zend_Search_Lucene</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.server.reflection.html"><code>Zend_Server_Reflection</code></ulink></emphasis></entry>
|
|
|
+ <entry>Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.akismet.html"><code>Zend_Service_Akismet</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.uri.html"><code>Zend_Uri</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.version.html"><code>Zend_Version</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.amazon.html"><code>Zend_Service_Amazon</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.rest.html"><code>Zend_Rest</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.audioscrobbler.html"><code>Zend_Service_Audioscrobbler</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="4" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.delicious.html"><code>Zend_Service_Delicious</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="4" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.date.html"><code>Zend_Date</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.json.html"><code>Zend_Json</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.rest.html"><code>Zend_Rest</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.flickr.html"><code>Zend_Service_Flickr</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.rest.html"><code>Zend_Rest</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.validate.html"><code>Zend_Validate</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.nirvanix.html"><code>Zend_Service_Nirvanix</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.simpy.html"><code>Zend_Service_Simpy</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.rest.html"><code>Zend_Rest</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.slideshare.html"><code>Zend_Service_SlideShare</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.cache.html"><code>Zend_Cache</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.strikeiron.html"><code>Zend_Service_StrikeIron</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="5" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.technorati.html"><code>Zend_Service_Technorati</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="5" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.date.html"><code>Zend_Date</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.locale.html"><code>Zend_Locale</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.rest.html"><code>Zend_Rest</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.uri.html"><code>Zend_Uri</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="3" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.service.yahoo.html"><code>Zend_Service_Yahoo</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Http</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.rest.html"><code>Zend_Rest</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.validate.html"><code>Zend_Validate</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.session.html"><code>Zend_Session</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.timesync.html"><code>Zend_TimeSync</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.date.html"><code>Zend_Date</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.translate.html"><code>Zend_Translate</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.locale.html"><code>Zend_Locale</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.uri.html"><code>Zend_Uri</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.validate.html"><code>Zend_Validate</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="5" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.validate.html"><code>Zend_Validate</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="3" valign="middle">Soft</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.date.html"><code>Zend_Date</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.filter.html"><code>Zend_Filter</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.locale.html"><code>Zend_Locale</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.registry.html"><code>Zend_Registry</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="1" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.version.html"><code>Zend_Version</code></ulink></emphasis></entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ <entry>---</entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="6" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.view.html"><code>Zend_View</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="6" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.controller.html"><code>Zend_Controller</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.json.html"><code>Zend_Json</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.layout.html"><code>Zend_Layout</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.loader.html"><code>Zend_Loader</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.locale.html"><code>Zend_Locale</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.registry.html"><code>Zend_Registry</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry morerows="2" valign="middle"><emphasis role="strong"><ulink url="http://framework.zend.com/manual/en/zend.xmlrpc.html"><code>Zend_XmlRpc</code></ulink></emphasis></entry>
|
|
|
+ <entry morerows="2" valign="middle">Hard</entry>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.exception.html"><code>Zend_Exception</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.http.html"><code>Zend_Registry</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ <row>
|
|
|
+ <entry><ulink url="http://framework.zend.com/manual/en/zend.server.html"><code>Zend_Server</code></ulink></entry>
|
|
|
+ </row>
|
|
|
+ </tbody>
|
|
|
+ </tgroup>
|
|
|
+ </table>
|
|
|
+
|
|
|
+ </sect1>
|
|
|
+
|
|
|
+
|
|
|
+</appendix><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+
|
|
|
+Note:
|
|
|
+All added classes listed below... all 3 tables use this as reference.
|
|
|
+Acl
|
|
|
+Auth
|
|
|
+Cache
|
|
|
+Config
|
|
|
+Console_GetOpt
|
|
|
+Controller
|
|
|
+Currency
|
|
|
+Date
|
|
|
+Db
|
|
|
+Debug
|
|
|
+Exception
|
|
|
+Feed
|
|
|
+Filter
|
|
|
+Form
|
|
|
+Gdata
|
|
|
+Http
|
|
|
+InfoCard
|
|
|
+Json
|
|
|
+Layout
|
|
|
+Ldap
|
|
|
+Loader
|
|
|
+Locale
|
|
|
+Log
|
|
|
+Mail
|
|
|
+Measure
|
|
|
+Memory
|
|
|
+Mime
|
|
|
+OpenId
|
|
|
+Pdf
|
|
|
+Registry
|
|
|
+Request
|
|
|
+Rest
|
|
|
+Search_Lucene
|
|
|
+Server_Reflection
|
|
|
+Service_Akismet
|
|
|
+Service_Amazon
|
|
|
+Service_Audioscrobbler
|
|
|
+Service_Delicious
|
|
|
+Service_Flickr
|
|
|
+Service_Nirvanix
|
|
|
+Service_Simpy
|
|
|
+Service_SlideShare
|
|
|
+Service_StrikeIron
|
|
|
+Service_Technorati
|
|
|
+Service_Yahoo
|
|
|
+Session
|
|
|
+TimeSync
|
|
|
+Translate
|
|
|
+Uri
|
|
|
+Validate
|
|
|
+Version
|
|
|
+View
|
|
|
+XmlRpc
|
|
|
+-->
|
|
|
+ <appendix id="coding-standard" xml:base="ref/coding_standard.xml">
|
|
|
+ <title>Est�ndares de c�digo Zend Framework para PHP</title>
|
|
|
+ <sect1 id="coding-standard.overview">
|
|
|
+ <title>Introducci�n</title>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.overview.scope">
|
|
|
+ <title>Alcance</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Este documento provee las pautas para el formato del c�digo y la documentaci�n a personas y equipos que contribuyan con Zend Framework. Muchos de los desarrolladores que usan Zend Framework han encontrado �tiles estos est�ndares debido a que el estilo de su c�digo permanece consistente con otros c�digos fuente basados en Zend Framework. Tambi�n debe resaltarse que especificar completamente los est�ndares de c�digo requiere un esfuerzo significativo.
|
|
|
+
|
|
|
+ Nota: A veces, los desarrolladores consideran el establecimiento de est�ndares m�s importante que lo que el est�ndar sugiere realmente al nivel m�s detallado de dise�o. Estas pautas en los est�ndares de c�digo de Zend Framework han demostrado funcionar bien en otros projectos ZF. Puede modificar estos est�ndares o usarlos en consonancia con los t�rminos de nuestra <ulink url="http://framework.zend.com/license">licencia</ulink>
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Temas incluidos en los est�ndares de c�digo ZF:
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>Dar formato a archivos PHP</para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>Convenciones de nombrado</para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>Estilo de c�digo</para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>Documentaci�n integrada</para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.overview.goals">
|
|
|
+ <title>Objetivos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los est�ndares de c�digo resultan importantes en cualquier proyecto de desarrollo, pero son
|
|
|
+ especialmente importantes cuando muchos desarrolladores trabajan en el mismo proyecto. Los
|
|
|
+ est�ndares de c�digo ayudan a asegurar que el c�digo tenga una alta calidad, menos errores,
|
|
|
+ y pueda ser mantenido f�cilmente.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+ </sect1>
|
|
|
+
|
|
|
+ <sect1 id="coding-standard.php-file-formatting">
|
|
|
+ <title>Formato de archivos PHP</title>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.php-file-formatting.general">
|
|
|
+ <title>General</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para archivos que contengan �nicamente c�digo PHP, la etiqueta de cierre ("?>") no est� permitida. No es requerida por PHP, y omitirla evita la inyecci�n de espacios en blanco en la respuesta.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <emphasis>IMPORTANTE:</emphasis> La inclusi�n de datos binarios arbitrarios permitidos por <code>__HALT_COMPILER()</code>
|
|
|
+ est� prohibida en los archivos PHP de Zend Framework, as� como en cualquier fichero derivado. El uso de esta caracter�stica s�lo est� permitido en algunos scripts de instalaci�n.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.php-file-formatting.indentation">
|
|
|
+ <title>Identaci�n</title>
|
|
|
+
|
|
|
+ <para>La identaci�n suele est�r compuesta por 4 espacios. Las tabulaciones no est�n permitidas.</para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.php-file-formatting.max-line-length">
|
|
|
+ <title>Tama�o m�ximo de l�nea</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La longitud recomendable para una l�nea de c�digo es de 80 caracteres. Esto significa que los desarrolladores de Zend deber�an intentar mantener cada l�nea de su c�digo por debajo de los 80 caracteres, siempre que sea posible. No obstante, l�neas m�s largas pueden ser aceptables en algunas situaciones. El tama�o m�ximo de cualquier l�nea de c�digo PHP es de 120 caracteres.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.php-file-formatting.line-termination">
|
|
|
+ <title>Final de l�nea</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El Final de L�nea sigue la convenci�n de archivos de texto Unix. Las l�neas deben acabar con un car�cter linefeed (LF). Los caracteres Linefeed est�n representados con el n�mero 10 ordinal, o el n�mero 0x0A hexadecimal.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Nota: No use retornos de carro (carriage returns, CR) como en las fuentes de Apple (0x0D) o la combinaci�n de retorno de carro/linefeed (CRLF) est�ndar para sistemas operativos Windows (0x0D, 0x0A).
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+ </sect1>
|
|
|
+
|
|
|
+ <sect1 id="coding-standard.naming-conventions">
|
|
|
+ <title>Convenciones de nombrado</title>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.naming-conventions.classes">
|
|
|
+ <title>Clases</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend Framework se estandariza en una convenci�n de nombrado de clases donde los
|
|
|
+ nombres de las clases apuntan directamente a las carpetas en las que est�n contenidas.
|
|
|
+ La carpeta ra�z de la librer�a est�ndar de ZF es la carpeta "Zend/", mientras que la carpeta ra�z de las
|
|
|
+ librer�as extra de ZF es la carpeta "ZendX/". Todas las clases Zend Framework est�n almacenadas
|
|
|
+ jer�rquicamente bajo estas carpetas ra�z.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los nombres de clase pueden contener s�lo caracteres alfanum�ricos. Los n�meros est�n permitidos en los nombres de clase, pero desaconsejados en la mayor�a de casos. Las barras bajas (_) est�n permitidas s�lo como separador de ruta (el archivo "Zend/Db/Table.php" debe apuntar al nombre de clase "Zend_Db_Table").
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si el nombre de una clase est� compuesto por m�s de una palabra, la primera letra de
|
|
|
+ cada palabra debe aparecer en may�sculas. Poner en may�sculas las letras siguientes no est� permitido,
|
|
|
+ ej: "Zend_PDF" no est� permitido, mientras que "Zend_Pdf" es admisible.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Estas convenciones definen un mecanismo de pseudo-espacio de nombres para Zend Framework. Zend Framework adoptar� la funcionalidad PHP de espacio de nombres cuando est� disponible y sea factible su uso en las aplicaciones de nuestros desarrolladores.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Vea los nombres de clase en las librer�as estandar y adicionales (extras) como ejemplos de esta convenci�n de nombres.
|
|
|
+
|
|
|
+ <emphasis>IMPORTANTE:</emphasis> El c�digo que deba distribuirse junto a las librer�as ZF, pero no forma parte de las librer�as est�ndar o extras de Zend (e.g.: c�digo o librer�as que no est�n distribu�das por Zend) no puede empezar nunca por "Zend_" o "ZendX_".
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.naming-conventions.filenames">
|
|
|
+ <title>Nombres de archivo</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para cualquier otro archivo, s�lo caracteres alfanum�ricos, barras bajas (_) y guiones (-) est�n permitidos. Los espacios en blanco est�n estrictamente prohibidos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cualquier archivo que contenga c�digo PHP debe terminar con la extensi�n ".php", con la excepci�n de los scripts de vista. Los siguientes ejemplos muestran nombres de archivo admisibles para clases de Zend Framework..:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+Zend/Db.php
|
|
|
+
|
|
|
+Zend/Controller/Front.php
|
|
|
+
|
|
|
+Zend/View/Helper/FormRadio.php
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ Los nombres de archivo deben apuntar a nombres de clases como se describe arriba.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.naming-conventions.functions-and-methods">
|
|
|
+ <title>Funciones y M�todos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los nombres de funciones pueden contener �nicamente caracteres alfanum�ricos. Las barras bajas (_)
|
|
|
+ no est�n permitidas.
|
|
|
+ Los n�meros est�n permitidos en los nombres de funci�n pero no se aconseja en la
|
|
|
+ mayor�a de casos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los nombres de funciones deben empezar siempre con una letra min�scula. Cuando un nombre de funci�n consiste en
|
|
|
+ m�s de una palabra, la primera letra de cada nueva palabra debe estar en may�sculas. Esto es llamado com�nmente como formato "camelCase".
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por norma general, se recomienda la elocuencia. Los nombres de funci�n deben ser lo suficientemente elocuentes como para describir su prop�sito y comportamiento.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Estos son ejemplos de nombres de funciones admisibles:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+filterInput()
|
|
|
+
|
|
|
+getElementById()
|
|
|
+
|
|
|
+widgetFactory()
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para programaci�n orientada a objetos, los accesores para instancia o variables est�ticas deben ir antepuestos con un
|
|
|
+ "get" o un "set". Al implementar patrones de dise�o, tales como el patr�n singleton o el patr�n factory, el nombre del m�todo debe contener en la pr�ctica el nombre del patr�n para describir su comportamiento de form�s m�s completa.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para m�todos en objetos que son declarados con el modificador "private" o "protected",
|
|
|
+ el primer car�cter del nombre de la variable debe ser una barra baja (_). �ste es el �nico
|
|
|
+ uso admisible de una barra baja en un nombre de m�todo. Los m�todos declarados como p�blicos
|
|
|
+ no deber�an contener nunca una barra baja.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las funciones de alcance global (tambi�n llamadas "funciones flotantes") est�n permitidas pero desaconsejadas en la mayor�a de casos.
|
|
|
+ Considere envolver esas funciones en una clase est�tica.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.naming-conventions.variables">
|
|
|
+ <title>Variables</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los nombres de variables pueden contener caracteres alfanum�ricos. Las barras bajas (_)
|
|
|
+ no est�n permitidas.
|
|
|
+ Los n�meros est�n permitidos en los nombres de variable pero no se aconseja en la
|
|
|
+ mayor�a de casos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para las variables de instancia que son declaradas con el modificador "private" o "protected",
|
|
|
+ el primer car�cter de la variable debe ser una �nica barra baja (_). �ste es el �nico caso admisible de una barra baja en el nombre de una variable. Las variables declaradas como "public" no pueden empezar nunca por barra baja.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Al igual que los nombres de funciones (ver secci�n 3.3), los nombres de variables deben empezar siempre con una letra en min�scula y seguir la convenci�n "camelCaps".
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por norma general, se recomienda la elocuencia. Las variables deber�an ser siempre tan elocuentes como pr�cticas para describir los datos que el desarrollador pretende almacenar en ellas. Variables escuetas como "$i" y "$n" est�n desaconsejadas, salvo para el contexto de los bucles m�s peque�os. Si un bucle contiene m�s de 20 l�neas de c�digo, las variables de �ndice deber�an tener nombres m�s descriptivos.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.naming-conventions.constants">
|
|
|
+ <title>Constantes</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las constantes pueden contener tanto caracteres alfanum�ricos como barras bajas (_). Los n�meros est�n permitidos.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todos las letras pertenecientes al nombre de una constante deben aparecer en may�sculas.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las palabras dentro del nombre de una constante deben separarse por barras bajas (_). Por ejemplo, <code>EMBED_SUPPRESS_EMBED_EXCEPTION</code> est� permitido, pero
|
|
|
+ <code>EMBED_SUPPRESSEMBEDEXCEPTION</code> no.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las constantes deben ser definidas como miembros de clase con el modificador "const". Definir constantes en el alcance global con la funci�n "define" est� permitido pero no recomendado.
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+ </sect1>
|
|
|
+
|
|
|
+ <sect1 id="coding-standard.coding-style">
|
|
|
+ <title>Estilo de c�digo</title>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.coding-style.php-code-demarcation">
|
|
|
+ <title>Demarcaci�n de c�digo PHP</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El c�digo PHP debe estar delimitado siempre por la forma completa de las etiquetas PHP est�ndar:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+<?php
|
|
|
+
|
|
|
+?>
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las etiquetas cortas (short tags) no se permiten nunca. Para archivos que contengan �nicamente c�digo PHP, la etiqueta de cierrre debe omitirse siempre (Ver <xref linkend="coding-standard.php-file-formatting.general"/>).
|
|
|
+ </para>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.coding-style.strings">
|
|
|
+ <title>Cadenas</title>
|
|
|
+
|
|
|
+ <sect3 id="coding-standard.coding-style.strings.literals">
|
|
|
+ <title>Literales cadena</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cuando una cadena es literal (no contiene sustituci�n de variables), el ap�strofo o "comilla"
|
|
|
+ deber�a ser usado siempre para delimitar la cadena:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$a = 'Example String';
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="coding-standard.coding-style.strings.literals-containing-apostrophes">
|
|
|
+ <title>Literales Cadena que Contengan Ap�strofos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cuando el propio literal cadena contega ap�strofos, es permitido delimitar la cadena
|
|
|
+ con "dobles comillas". Esto es especialmente �til para sentencias SQL:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$sql = "SELECT `id`, `name` from `people` WHERE `name`='Fred' OR `name`='Susan'";
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ Esta sint�xis es preferible a escapar ap�strofes, ya ques mucho m�s f�cil de leer.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="coding-standard.coding-style.strings.variable-substitution">
|
|
|
+ <title>Sustituci�n de Variables</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La sustituci�n de variables est� permitida en cualquiera de estas formas:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$greeting = "Hello $name, welcome back!";
|
|
|
+
|
|
|
+$greeting = "Hello {$name}, welcome back!";
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Por consistencia, esta forma no est� permitida:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$greeting = "Hello ${name}, welcome back!";
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="coding-standard.coding-style.strings.string-concatenation">
|
|
|
+ <title>Concatenaci�n de cadenas</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las cadenas deben ser concatenadas usando el operador punto ("."). Un espacio debe a�adirse
|
|
|
+ siempre antes y despu�s del operador "." para mejorar la legibilidad:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$company = 'Zend' . ' ' . 'Technologies';
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Al concatenar cadenas con el operador ".", se recomienda partir la sentencia en
|
|
|
+ m�ltiples l�neas para mejorar la legibilidad. En estos casos, cada linea sucesiva
|
|
|
+ debe llevar un margen de espacios en blanco de forma que el operador
|
|
|
+ "." est� alineado bajo el operador "=":
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$sql = "SELECT `id`, `name` FROM `people` "
|
|
|
+ . "WHERE `name` = 'Susan' "
|
|
|
+ . "ORDER BY `name` ASC ";
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.coding-style.arrays">
|
|
|
+ <title>Arrays</title>
|
|
|
+
|
|
|
+ <sect3 id="coding-standard.coding-style.arrays.numerically-indexed">
|
|
|
+ <title>Arrays Indexados Num�ricamente</title>
|
|
|
+
|
|
|
+ <para>No est�n permitidos n�meros negativos como �ndices.</para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Un array indexado puede empezar por cualquier valor no negativo, sin embargo, no se recomiendan �ndices base distintos a 0.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Al declarar arrays indexados con la funci�n <code>array</code>, un espacio de separaci�n deben a�adirse despu�s de cada delimitador coma para mejorar la legibilidad:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$sampleArray = array(1, 2, 3, 'Zend', 'Studio');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Se permite declarar arrays indexados multil�nea usando la construcci�n "array".
|
|
|
+ En este caso, cada l�nea sucesiva debe ser tabulada con cuatro espacios de forma que el principio de cada l�nea est� alineado:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$sampleArray = array(1, 2, 3, 'Zend', 'Studio',
|
|
|
+ $a, $b, $c,
|
|
|
+ 56.44, $d, 500);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="coding-standard.coding-style.arrays.associative">
|
|
|
+ <title>Arrays Asociativos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Al declarar arrays asociativos con la construcci�n <code>array</code>, se recomienda partir la declaraci�n en m�ltiples l�neas. En este caso, cada l�nea sucesiva debe ser tabulada con cuatro espacios de forma que tanto las llaves como los valores est�n alineados:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$sampleArray = array('firstKey' => 'firstValue',
|
|
|
+ 'secondKey' => 'secondValue');
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.coding-style.classes">
|
|
|
+ <title>Clases</title>
|
|
|
+
|
|
|
+ <sect3 id="coding-standard.coding-style.classes.declaration">
|
|
|
+ <title>Declaraci�n de clases</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las Clases deben ser nombradas de acuerdo a las convenciones de nombrado de Zend Framework.
|
|
|
+ </para><para>
|
|
|
+ La llave "{" deber� escribirse siempre en la l�nea debajo del nombre de la clase ("one true brace").
|
|
|
+ </para><para>
|
|
|
+ Cada clase debe contener un bloque de documentaci�n acorde con el est�ndar de PHPDocumentor.
|
|
|
+ </para><para>
|
|
|
+ Todo el c�digo contenido en una clase debe ser separado con cuatro espacios.
|
|
|
+ </para><para>
|
|
|
+ �nicamente una clase est� permitida en cada archivo PHP.
|
|
|
+ </para><para>
|
|
|
+ Incluir c�digo adicional en archivos de clase est� permitido pero desaconsejado.
|
|
|
+ En archivos de ese tipo, dos l�neas en blanco deben separar la clase de cualquier c�digo PHP adicional en el archivo de clase.
|
|
|
+ </para><para>
|
|
|
+ A continuaci�n se muestra un ejemplo de una declaraci�n de clase admisible:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+/**
|
|
|
+ * Bloque de Documentaci�n aqu�
|
|
|
+ */
|
|
|
+class SampleClass
|
|
|
+{
|
|
|
+ // el contenido de la clase
|
|
|
+ // debe separarse con cuatro espacios
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="coding-standard.coding-style.classes.member-variables">
|
|
|
+ <title>Variables de miembros de clase</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las variables de miembros de clase deben ser nombradas de acuerdo con las conveciones de nombrado de variables de Zend Framework.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Cualquier variable declarada en una clase debe ser listada en la parte superior de la clase, por encima de las declaraciones de cualquier m�todo.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ La construcci�n <code>var</code> no est� permitido. Las variables de miembro siempre declaran su visibilidad usando uno los modificadores <code>private</code>, <code>protected</code>,
|
|
|
+ o <code>public</code>. Dar acceso a las variables de miembro declar�ndolas directamente como public est� permitido pero no se aconseja en favor de accesor methods (set/get).
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.coding-style.functions-and-methods">
|
|
|
+ <title>Funciones y M�todos</title>
|
|
|
+
|
|
|
+ <sect3 id="coding-standard.coding-style.functions-and-methods.declaration">
|
|
|
+ <title>Declaraci�n de Funciones y M�todos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las Funciones deben ser nombradas de acuerdo a las convenciones de nombrado de Zend Framework.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Los m�todos dentro de clases deben declarar siempre su visibilidad usando un modificador <code>private</code>, <code>protected</code>,
|
|
|
+ o <code>public</code>.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Como en las clases, la llave "{" debe ser escrita en la l�nea siguiente al nombre de la funci�n ("one true brace" form).
|
|
|
+
|
|
|
+ No est� permitido un espacio entre el nombre de la funci�n y el par�ntesis de apertura para los argumentos.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Las funciones de alcance global no est�n permitidas.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Lo siguiente es un ejemplo de una declaraci�n admisible de una funci�n en una clase:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+/**
|
|
|
+ * Bloque de Documentaci�n aqu�
|
|
|
+ */
|
|
|
+class Foo
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * Bloque de Documentaci�n aqu�
|
|
|
+ */
|
|
|
+ public function bar()
|
|
|
+ {
|
|
|
+ // el contenido de la funci�n
|
|
|
+ // debe separarse con cuatro espacios
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <emphasis>NOTA:</emphasis> El paso por referencia es el �nico mecanismo de paso de par�metros permitido en una declaraci�n de m�todo.
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+/**
|
|
|
+ * Bloque de Documentaci�n aqu�
|
|
|
+ */
|
|
|
+class Foo
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * Bloque de Documentaci�n aqu�
|
|
|
+ */
|
|
|
+ public function bar(&$baz)
|
|
|
+ {}
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La llamada por referencia est� estrictamente prohibida.
|
|
|
+ </para>
|
|
|
+
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El valor de retorno no debe estar indicado entre par�ntesis. Esto podr�a afectar a la legibilidad, adem�s
|
|
|
+ de romper el c�digo si un m�todo se modifica posteriormente para que devuelva por referencia.
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+/**
|
|
|
+ * Bloque de Documentaci�n aqu�
|
|
|
+ */
|
|
|
+class Foo
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * INCORRECTO
|
|
|
+ */
|
|
|
+ public function bar()
|
|
|
+ {
|
|
|
+ return($this->bar);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * CORRECTO
|
|
|
+ */
|
|
|
+ public function bar()
|
|
|
+ {
|
|
|
+ return $this->bar;
|
|
|
+ }
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="coding-standard.coding-style.functions-and-methods.usage">
|
|
|
+ <title>Uso de Funciones y M�todos</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Los argumentos de la funci�n tendr�an que estar separados por un �nico espacio posterior despu�s del delimitador coma.
|
|
|
+ A continuaci�n se muestra un ejemplo de una invocaci�n admisible de una funci�n que recibe tres argumentos:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+threeArguments(1, 2, 3);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La llamada por referencia est� estrictamente prohibida. Vea la secci�n de declaraciones de funciones para el m�todo correcto de pasar argumentos por referencia.
|
|
|
+ </para>
|
|
|
+ <para>
|
|
|
+ Al pasar arrays como argumentos a una funci�n, la llamada a la funci�n puede incluir el indicador "hint" y puede separarse en m�ltiples l�neas para aumentar la legibilidad. En esos casos, se aplican las pautas normales para escribir arrays:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+threeArguments(array(1, 2, 3), 2, 3);
|
|
|
+
|
|
|
+threeArguments(array(1, 2, 3, 'Zend', 'Studio',
|
|
|
+ $a, $b, $c,
|
|
|
+ 56.44, $d, 500), 2, 3);
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standard.coding-style.control-statements">
|
|
|
+ <title>Sentencias de Control</title>
|
|
|
+
|
|
|
+ <sect3 id="coding-standard.coding-style.control-statements.if-else-elseif">
|
|
|
+ <title>If/Else/Elseif</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las sentencias de control basadas en las construcciones <code>if</code> y <code>elseif</code>
|
|
|
+ deben tener un solo espacio en blanco antes del par�ntesis de apertura del condicional y un solo espacio en blanco despu�s del par�ntesis de cierre.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Dentro de las sentencias condicionales entre par�ntesis, los operadores deben separarse con espacios, por legibilidad. Se aconseja el uso de par�ntesis internos para mejorar la agrupaci�n l�gica en expresiones condicionales m�s largas.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La llave de apertura "{" se escribe en la misma l�nea que la sentencia condicional. La llave de cierre "}" se escribe siempre en su propia l�nea. Cualquier contenido dentro de las llaves debe separarse con cuatro espacios en blanco.
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+if ($a != 2) {
|
|
|
+ $a = 2;
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Para las declaraciones "if" que incluyan "elseif" o "else", las convenciones de formato son similares a la construcci�n "if". Los ejemplos siguientes demuestran el formato correcto para declaraciones "if" con construcciones "else" y/o "elseif":
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+if ($a != 2) {
|
|
|
+ $a = 2;
|
|
|
+} else {
|
|
|
+ $a = 7;
|
|
|
+}
|
|
|
+
|
|
|
+if ($a != 2) {
|
|
|
+ $a = 2;
|
|
|
+} elseif ($a == 3) {
|
|
|
+ $a = 4;
|
|
|
+} else {
|
|
|
+ $a = 7;
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ PHP permite escribir sentencias sin llaves -{}- en algunas circunstancias.
|
|
|
+ Este est�ndar de c�digo no hace ninguna diferenciaci�n- toda sentencia "if",
|
|
|
+ "elseif" o "else" debe usar llaves.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ El uso de la construcci�n "elseif" est� permitido pero no se aconseja, en favor de
|
|
|
+ la combinaci�n "else if".
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="coding-standards.coding-style.control-statements.switch">
|
|
|
+ <title>Switch</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Las declaraciones de control escritas con la declaraci�n "switch" deben tener un �nico espacio en blanco antes del par�ntesis de apertura del condicional y despu�s del par�ntesis de cierre.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todo contenido dentro de una declaraci�n "switch" debe separarse usando cuatro espacios. El contenido dentro de cada declaraci�n "case" debe separarse usando cuatro espacios adicionales.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+switch ($numPeople) {
|
|
|
+ case 1:
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 2:
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+}
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ La construcci�n <code>default</code> no debe omitirse nunca en una declaraci�n <code>switch</code>.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <emphasis>NOTA:</emphasis> En ocasiones, resulta �til escribir una declaraci�n <code>case</code> que salta al
|
|
|
+ siguiente case al no incluir un <code>break</code> o <code>return</code> dentro de ese case. Para distinguir
|
|
|
+ estos casos de posibles errores, cualquier declaraci�n donde <code>break</code> o <code>return</code> sean
|
|
|
+ omitidos deber�n contener un comentario indicando que se omitieron intencionadamente.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="coding-standards.inline-documentation">
|
|
|
+ <title>Documentaci�n integrada</title>
|
|
|
+
|
|
|
+ <sect3 id="coding-standards.inline-documentation.documentation-format">
|
|
|
+ <title>Formato de documentaci�n</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todos los bloques de documentaci�n ("docblocks") deben ser compatibles con el formato de phpDocumentor.
|
|
|
+ Describir el formato de phpDocumentor est� fuera del alcance de este documento.
|
|
|
+ Para m�s informaci�n, visite: <ulink url="http://phpdoc.org/">http://phpdoc.org/</ulink>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Todos los archivos de clase deben contener un bloque de documentaci�n "a nivel de archivo" al principio de cada archivo y un bloque de documentaci�n "a nivel de clase" inmediatamente antes de cada clase. Ejemplo de estos bloques de documentaci�n pueden encontrarse debajo.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="coding-standards.inline-documentation.files">
|
|
|
+ <title>Archivo</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cada archivo que contenga c�digo PHP debe tener un bloque de documentaci�n al principio del archivo que contenga como m�nimo las siguientes etiquetas phpDocumentor:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+/**
|
|
|
+ * Descripci�n corta del fichero
|
|
|
+ *
|
|
|
+ * Descripci�n larga del fichero (si la hubiera)...
|
|
|
+ *
|
|
|
+ * LICENSE: Informaci�n sobre la licencia
|
|
|
+ *
|
|
|
+ * @copyright 2008 Zend Technologies
|
|
|
+ * @license http://framework.zend.com/license BSD License
|
|
|
+ * @version $Id:$
|
|
|
+ * @link http://framework.zend.com/package/PackageName
|
|
|
+ * @since File available since Release 1.5.0
|
|
|
+*/
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="coding-standards.inline-documentation.classes">
|
|
|
+ <title>Clases</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cada clase debe contener un bloque de documentaci�n que contenga como m�nimo las siguientes etiquetas phpDocumentor:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+/**
|
|
|
+ * Descripci�n corta de la clase
|
|
|
+ *
|
|
|
+ * Descripci�n larga de la clase (si la hubiera)...
|
|
|
+ *
|
|
|
+ * @copyright 2008 Zend Technologies
|
|
|
+ * @license http://framework.zend.com/license BSD License
|
|
|
+ * @version Release: @package_version@
|
|
|
+ * @link http://framework.zend.com/package/PackageName
|
|
|
+ * @since Class available since Release 1.5.0
|
|
|
+ * @deprecated Class deprecated in Release 2.0.0
|
|
|
+ */
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="coding-standards.inline-documentation.functions">
|
|
|
+ <title>Funciones</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Cada funci�n, incluyendo m�todos de objeto, debe contener un bloque de documentaci�n que contenga como m�nimo:
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>Una descripci�n de la funci�n</para></listitem>
|
|
|
+ <listitem><para>Todos los argumentos</para></listitem>
|
|
|
+ <listitem><para>Todos los posibles valores de retorno</para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ No es necesario incluir la etiqueta "@access" si el nivel de acceso es
|
|
|
+ conocido de antemano por el modificador "public", "private", o "protected"
|
|
|
+ usado para declarar la funci�n.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Si una funci�n/m�todo puede lanzar una excepci�n, utilice @throws para todos los tipos
|
|
|
+ de excepciones conocidas:
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+@throws exceptionclass [description]
|
|
|
+]]>
|
|
|
+ </programlisting>
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+ </sect1>
|
|
|
+
|
|
|
+</appendix><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <appendix id="performance">
|
|
|
+ <title>Guía de rendimiento de Zend Framework</title>
|
|
|
+ <sect1 id="performance.introduction" xml:base="ref/performance-introduction.xml">
|
|
|
+ <title>Introduction</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The purpose of this appendix is to provide some concrete strategies for
|
|
|
+ improving the performance of your Zend Framework applications. The guide
|
|
|
+ is presented in a "Question:Answer" format, and broken into areas of
|
|
|
+ concern.
|
|
|
+ </para>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="performance.classloading" xml:base="ref/performance-classloading.xml">
|
|
|
+ <title>Class Loading</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Anyone who ever performs profiling of a Zend Framework application will
|
|
|
+ immediately recognize that class loading is relatively expensive in Zend
|
|
|
+ Framework. Between the sheer number of class files that need to be
|
|
|
+ loaded for many components, to the use of plugins that do not have a 1:1
|
|
|
+ relationship between their class name and the filesystem, the various
|
|
|
+ calls to <code>include_once</code> and <code>require_once</code> can be
|
|
|
+ problematic. This chapter intends to provide some concrete solutions to
|
|
|
+ these issues.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="performance.classloading.includepath">
|
|
|
+ <title>How can I optimize my include_path?</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ One trivial optimization you can do to increase the speed of class
|
|
|
+ loading is to pay careful attention to your include_path. In
|
|
|
+ particular, you should do four things: use absolute paths (or paths
|
|
|
+ relative to absolute paths), reduce the number of include paths you
|
|
|
+ define, have your Zend Framework include_path as early as possible,
|
|
|
+ and only include the current directory path at the end of your
|
|
|
+ include_path.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="performance.classloading.includepath.abspath">
|
|
|
+ <title>Use absolute paths</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ While this may seem a micro-optimization, the fact is that if
|
|
|
+ you don't, you'll get very little benefit from PHP's realpath
|
|
|
+ cache, and as a result, opcode caching will not perform nearly
|
|
|
+ as you may expect.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ There are two easy ways to ensure this. First, you can hardcode
|
|
|
+ the paths in your php.ini, httpd.conf, or .htaccess. Second, you
|
|
|
+ can use PHP's <code>realpath()</code> function when setting your
|
|
|
+ include_path:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$paths = array(
|
|
|
+ realpath(dirname(__FILE__) . '/../library'),
|
|
|
+ '.',
|
|
|
+);
|
|
|
+set_include_path(implode(PATH_SEPARATOR, $paths);
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You <emphasis>can</emphasis> use relative paths -- so long as
|
|
|
+ they are relative to an absolute path:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+define('APPLICATION_PATH', realpath(dirname(__FILE__)));
|
|
|
+$paths = array(
|
|
|
+ APPLICATION_PATH . '/../library'),
|
|
|
+ '.',
|
|
|
+);
|
|
|
+set_include_path(implode(PATH_SEPARATOR, $paths);
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ However, even so, it's typically a trivial task to simply pass
|
|
|
+ the path to <code>realpath()</code>.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="performance.classloading.includepath.reduce">
|
|
|
+ <title>Reduce the number of include paths you define</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Include paths are scanned in the order in which they appear in
|
|
|
+ the include_path. Obviously, this means that you'll get a result
|
|
|
+ faster if the file is found on the first scan rather than the
|
|
|
+ last. Thus, a rather obvious enhancement is to simply reduce the
|
|
|
+ number of paths in your include_path to only what you need. Look
|
|
|
+ through each include_path you've defined, and determine if you
|
|
|
+ actually have any functionality in that path that is used in
|
|
|
+ your application; if not, remove it.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Another optimization is to combine paths. For instance, Zend
|
|
|
+ Framework follows PEAR naming conventions; thus, if you are
|
|
|
+ using PEAR libraries (or libraries from another framework or
|
|
|
+ component library that follows PEAR CS), try to put all of these
|
|
|
+ libraries on the same include_path. This can often be achieved
|
|
|
+ by something as simple as symlinking one or more libraries into
|
|
|
+ a common directory.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="performance.classloading.includepath.early">
|
|
|
+ <title>Define your Zend Framework include_path as early as possible</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Continuing from the previous suggestion, another obvious
|
|
|
+ optimization is to define your Zend Framework include_path as
|
|
|
+ early as possible in your include_path. In most cases, it should
|
|
|
+ be the first path in the list. This ensures that files included
|
|
|
+ from Zend Framework are found on the first scan.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="performance.classloading.includepath.currentdir">
|
|
|
+ <title>Define the current directory last, or not at all</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Most include_path examples show using the current directory, or
|
|
|
+ '.'. This is convenient for ensuring that scripts in the same
|
|
|
+ directory as the file requiring them can be loaded. However,
|
|
|
+ these same examples typically show this path item as the first
|
|
|
+ item in the include_path -- which means that the current
|
|
|
+ directory tree is always scanned first. In most cases, with Zend
|
|
|
+ Framework applications, this is not desired, and the path may be
|
|
|
+ safely pushed to the last item in the list.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <example id="performance.classloading.includepath.example">
|
|
|
+ <title>Example: Optimized include_path</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Let's put all of these suggestions together. Our assumption will
|
|
|
+ be that you are using one or more PEAR libraries in conjunction
|
|
|
+ with Zend Framework -- perhaps the PHPUnit and Archive_Tar
|
|
|
+ libraries -- and that you occasionally need to include
|
|
|
+ files relative to the current file.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ First, we'll create a library directory in our project. Inside
|
|
|
+ that directory, we'll symlink our Zend Framework's library/Zend
|
|
|
+ directory, as well as the necessary directories from our PEAR
|
|
|
+ installation:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+library
|
|
|
+ Archive/
|
|
|
+ PEAR/
|
|
|
+ PHPUnit/
|
|
|
+ Zend/
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This allows us to add our own library code if necessary, while
|
|
|
+ keeping shared libraries intact.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Next, we'll opt to create our include_path programmatically
|
|
|
+ within our public/index.php file. This allows us to move our
|
|
|
+ code around on the filesystem, without needing to edit the
|
|
|
+ include_path every time.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ We'll borrow ideas from each of the suggestions above: we'll use
|
|
|
+ absolute paths, as determined using <code>realpath()</code>;
|
|
|
+ we'll include the Zend Framework include path early; we've
|
|
|
+ already consolidated include_paths; and we'll put the current
|
|
|
+ directory as the last path. In fact, we're doing really well
|
|
|
+ here -- we're going to end up with only two paths.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+$paths = array(
|
|
|
+ realpath(dirname(__FILE__) . '/../library'),
|
|
|
+ '.'
|
|
|
+);
|
|
|
+set_include_path(implode(PATH_SEPARATOR, $paths));
|
|
|
+]]></programlisting>
|
|
|
+ </example>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="performance.classloading.striprequires">
|
|
|
+ <title>How can I eliminate unnecessary require_once statements?</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Lazy loading is an optimization technique designed to push the
|
|
|
+ expensive operation of loading a class file until the last possible
|
|
|
+ moment -- i.e., when instantiating an object of that class, calling
|
|
|
+ a static class method, or referencing a class constant or static
|
|
|
+ property. PHP supports this via autoloading, which allows you to
|
|
|
+ define one or more callbacks to execute in order to map a class name
|
|
|
+ to a file.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ However, most benefits you may reap from autoloading are negated if
|
|
|
+ your library code is still performing require_once calls -- which is
|
|
|
+ precisely the case with Zend Framework. So, the question is: how can
|
|
|
+ you eliminate those require_once calls in order to maximize
|
|
|
+ autoloader performance?
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="performance.classloading.striprequires.sed">
|
|
|
+ <title>Strip require_once calls with find and sed</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ An easy way to strip require_once calls is to use the unix
|
|
|
+ utilities 'find' and 'sed' in conjunction to comment out each
|
|
|
+ call. Try executing the following statements (where '%'
|
|
|
+ indicates the shell prompt):
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="shell"><![CDATA[
|
|
|
+% cd path/to/ZendFramework/library
|
|
|
+% find . -name '*.php' -print0 | xargs -0 \
|
|
|
+ sed --regexp-extended --in-place 's/(require_once)/\/\/ \1/g'
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This one-liner (broken into two lines for readability) iterates
|
|
|
+ through each PHP file and tells it to replace each instance of
|
|
|
+ 'require_once' with '// require_once', effectively commenting
|
|
|
+ out each such statement.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This command could be added to an automated build or release
|
|
|
+ process trivially, helping boost performance in your production
|
|
|
+ application. It should be noted, however, that if you use this
|
|
|
+ technique, you <emphasis>must</emphasis> utilize autoloading;
|
|
|
+ you can do that from your "public/index.php" file with the
|
|
|
+ following code:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+require_once 'Zend/Loader.php'; // one require_once is still necessary
|
|
|
+Zend_Loader::registerAutoload();
|
|
|
+]]></programlisting>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="performance.classloading.pluginloader">
|
|
|
+ <title>How can I speed up plugin loading?</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Many components have plugins, which allow you to create your own
|
|
|
+ classes to utilize with the component, as well as to override
|
|
|
+ existing, standard plugins shipped with Zend Framework. This
|
|
|
+ provides important flexibility to the framework, but at a price:
|
|
|
+ plugin loading is a fairly expensive task.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The plugin loader allows you to register class prefix / path pairs,
|
|
|
+ allowing you to specify class files in non-standard paths. Each
|
|
|
+ prefix can have multiple paths associated with it.
|
|
|
+ Internally, the plugin loader loops through each prefix, and then
|
|
|
+ through each path attached to it, testing to see if the file exists
|
|
|
+ and is readable on that path. It then loads it, and tests to see
|
|
|
+ that the class it is looking for is available. As you might imagine,
|
|
|
+ this can lead to many stat calls on the filesystem.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Multiply this by the number of components that use the PluginLoader,
|
|
|
+ and you get an idea of the scope of this issue. At the time of this
|
|
|
+ writing, the following components made use of the PluginLoader:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>Zend_Controller_Action_HelperBroker</code>: helpers
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>Zend_Dojo</code>: view helpers, form elements and decorators
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>Zend_File_Transfer</code>: adapters
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>Zend_Filter_Inflector</code>: filters (used by the
|
|
|
+ ViewRenderer action helper and Zend_Layout)
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>Zend_Filter_Input</code>: filters and validators
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>Zend_Form</code>: elements, validators, filters,
|
|
|
+ decorators, captcha and file transfer adapters
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>Zend_Paginator</code>: adapters
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>Zend_View</code>: helpers, filters
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ How can you reduce the number of such calls made?
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="performance.classloading.pluginloader.includefilecache">
|
|
|
+ <title>Use the PluginLoader include file cache</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend Framework 1.7.0 adds an include file cache to the
|
|
|
+ PluginLoader. This functionality writes "include_once" calls to
|
|
|
+ a file, which you can then include in your bootstrap. While this
|
|
|
+ introduces extra include_once calls to your code, it also
|
|
|
+ ensures that the PluginLoader returns as early as possible.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The PluginLoader documentation <link linkend="zend.loader.pluginloader.performance.example">includes
|
|
|
+ a complete example of its use</link>.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="performance.localization" xml:base="ref/performance-localization.xml">
|
|
|
+ <title>Internationalization (i18n) and Localization (l10n)</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Internationalizing and localizing a site are fantastic ways to expand
|
|
|
+ your audience and ensure that all visitors can get to the information
|
|
|
+ they need. However, it often comes with a performance penalty. Below
|
|
|
+ are some strategies you can employ to reduce the overhead of i18n and
|
|
|
+ l10n.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="performance.localization.translationadapter">
|
|
|
+ <title>Which translation adapter should I use?</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Not all translation adapters are made equal. Some have more
|
|
|
+ features than others, and some are more performant than others.
|
|
|
+ Additionally, you may have business requirements that force you to
|
|
|
+ use a particular adapter. However, if you have a choice, which
|
|
|
+ adapters are fastest?
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="performance.localization.translationadapter.fastest">
|
|
|
+ <title>Use non-XML translation adapters for greatest speed</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Zend Framework ships with a variety of translation adapters.
|
|
|
+ Fully half of them utilize an XML format, incurring memory and
|
|
|
+ performance overhead. Fortunately, there are several adapters
|
|
|
+ that utilize other formats that can be parsed much more
|
|
|
+ quickly. In order of speed, from fastest to slowest, they are:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>Array</emphasis>: this is the fastest, as it is,
|
|
|
+ by definition, parsed into a native PHP format immediately
|
|
|
+ on inclusion.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>CSV</emphasis>: uses <code>fgetcsv()</code> to
|
|
|
+ parse a CSV file and transform it into a native PHP format.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>INI</emphasis>: uses
|
|
|
+ <code>parse_ini_file()</code> to parse an INI file and
|
|
|
+ transform it into a native PHP format. This and the CSV
|
|
|
+ adapter are roughly equivalent performance-wise.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <emphasis>Gettext</emphasis>: the Zend Framework gettext
|
|
|
+ adapter does <emphasis>not</emphasis> use the gettext
|
|
|
+ extension as it is not threadsafe and does not allow
|
|
|
+ specifying more than one locale per server. As a result, it
|
|
|
+ is slower than using the gettext extension directly, but,
|
|
|
+ because the gettext format is binary, it's faster to parse
|
|
|
+ than XML.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ If high performance is one of your concerns, we suggest
|
|
|
+ utilizing one of the above adapters.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="performance.localization.cache">
|
|
|
+ <title>How can I make translation and localization even faster?</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Maybe, for business reasons, you're limited to an XML-based
|
|
|
+ translation adapter. Or perhaps you'd like to speed things up even
|
|
|
+ more. Or perhaps you want to make l10n operations faster. How can
|
|
|
+ you do this?
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="performance.localization.cache.usage">
|
|
|
+ <title>Use translation and localization caches</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Both <code>Zend_Translate</code> and <code>Zend_Locale</code>
|
|
|
+ implement caching functionality that can greatly affect
|
|
|
+ performance. In the case of each, the major bottleneck is
|
|
|
+ typically reading the files, not the actual lookups; using a
|
|
|
+ cache eliminates the need to read the translation and/or
|
|
|
+ localization files.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You can read about caching of translation and localization
|
|
|
+ strings in the following locations:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <link linkend="zend.translate.adapter.caching"><code>Zend_Translate</code>
|
|
|
+ adapter caching</link>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+
|
|
|
+ <listitem>
|
|
|
+ <para>
|
|
|
+ <link linkend="zend.locale.cache"><code>Zend_Locale</code>
|
|
|
+ caching</link>
|
|
|
+ </para>
|
|
|
+ </listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <sect1 id="performance.view" xml:base="ref/performance-view.xml">
|
|
|
+ <title>View Rendering</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ When using Zend Framework's MVC layer, chances are you will be using
|
|
|
+ <code>Zend_View</code>. <code>Zend_View</code> is relatively performant
|
|
|
+ when compared to other view or templating engines; since view scripts
|
|
|
+ are written in PHP, you do not incur the overhead of compiling custom
|
|
|
+ markup to PHP, nor do you need to worry that the compiled PHP is
|
|
|
+ unoptimized. However, <code>Zend_View</code> presents its own issues:
|
|
|
+ extension is done via overloading (view helpers), and a number of view
|
|
|
+ helpers, while carrying out key functionality do so with a performance
|
|
|
+ cost.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect2 id="performance.view.pluginloader">
|
|
|
+ <title>How can I speed up resolution of view helpers?</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Most <code>Zend_View</code> "methods" are actually provided via
|
|
|
+ overloading to the helper system. This provides important
|
|
|
+ flexibility to Zend_View; instead of needing to extend Zend_View and
|
|
|
+ provide all the helper methods you may utilize in your application,
|
|
|
+ you can define your helper methods in separate classes and consume
|
|
|
+ them at will as if they were direct methods of Zend_View. This keeps
|
|
|
+ the view object itself relatively thin, and ensures that objects are
|
|
|
+ created only when needed.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Internally, <code>Zend_View</code> uses the <link linkend="zend.loader.pluginloader">PluginLoader</link> to look
|
|
|
+ up helper classes. This means that for each helper you call,
|
|
|
+ <code>Zend_View</code> needs to pass the helper name to the
|
|
|
+ PluginLoader, which then needs to determine the class name, load the
|
|
|
+ class file if necessary, and then return the class name so it may be
|
|
|
+ instantiated. Subsequent uses of the helper are much faster, as
|
|
|
+ <code>Zend_View</code> keeps an internal registry of loaded helpers,
|
|
|
+ but if you use many helpers, the calls add up.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The question, then, is: how can you speed up helper resolution?
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="performance.view.pluginloader.cache">
|
|
|
+ <title>Use the PluginLoader include file cache</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The simplest, cheapest solution is the same as for <link linkend="performance.classloading.pluginloader">general
|
|
|
+ PluginLoader performance</link>: <link linkend="zend.loader.pluginloader.performance.example">use
|
|
|
+ the PluginLoader include file cache</link>. Anecdotal
|
|
|
+ evidence has shown this technique to provide a 25-30%
|
|
|
+ performance gain on systems without an opcode cache, and a
|
|
|
+ 40-65% gain on systems with an opcode cache.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="performance.view.pluginloader.extend">
|
|
|
+ <title>Extend Zend_View to provide often used helper methods</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Another solution for those seeking to tune performance even
|
|
|
+ further is to extend <code>Zend_View</code> to manually add the
|
|
|
+ helper methods they most use in their application. Such helper
|
|
|
+ methods may simply manually instantiate the appropriate helper
|
|
|
+ class and proxy to it, or stuff the full helper implementation
|
|
|
+ into the method.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_View extends Zend_View
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * @var array Registry of helper classes used
|
|
|
+ */
|
|
|
+ protected $_localHelperObjects = array();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Proxy to url view helper
|
|
|
+ *
|
|
|
+ * @param array $urlOptions Options passed to the assemble method of the Route object.
|
|
|
+ * @param mixed $name The name of a Route to use. If null it will use the current Route
|
|
|
+ * @param bool $reset Whether or not to reset the route defaults with those provided
|
|
|
+ * @return string Url for the link href attribute.
|
|
|
+ */
|
|
|
+ public function url(array $urlOptions = array(), $name = null,
|
|
|
+ $reset = false, $encode = true
|
|
|
+ ) {
|
|
|
+ if (!array_key_exists('url', $this->_localHelperObjects)) {
|
|
|
+ $this->_localHelperObjects['url'] = new Zend_View_Helper_Url();
|
|
|
+ $this->_localHelperObjects['url']->setView($view);
|
|
|
+ }
|
|
|
+ $helper = $this->_localHelperObjects['url'];
|
|
|
+ return $helper->url($urlOptions, $name, $reset, $encode);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Echo a message
|
|
|
+ *
|
|
|
+ * Direct implementation.
|
|
|
+ *
|
|
|
+ * @param string $string
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public function message($string)
|
|
|
+ {
|
|
|
+ return "<h1>" . $this->escape($message) . "</h1>\n";
|
|
|
+ }
|
|
|
+}
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Either way, this technique will substantially reduce the
|
|
|
+ overhead of the helper system by avoiding calls to the
|
|
|
+ PluginLoader entirely, and either benefiting from autoloading or
|
|
|
+ bypassing it altogether.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="performance.view.partial">
|
|
|
+ <title>How can I speed up view partials?</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Those who use partials heavily and who profile their applications
|
|
|
+ will often immediately notice that the <code>partial()</code> view
|
|
|
+ helper incurs a lot of overhead, due to the need to clone the view
|
|
|
+ object. Is it possible to speed this up?
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="performance.view.partial.render">
|
|
|
+ <title>Use partial() only when really necessary</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The <code>partial()</code> view helper accepts three arguments:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ <code>$name</code>: the name of the view script to render
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>$module</code>: the name of the module in which the
|
|
|
+ view script resides; or, if no third argument is provided
|
|
|
+ and this is an array or object, it will be the
|
|
|
+ <code>$model</code> argument.
|
|
|
+ </para></listitem>
|
|
|
+
|
|
|
+ <listitem><para>
|
|
|
+ <code>$model</code>: an array or object to pass to the
|
|
|
+ partial representing the clean data to assign to the view.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The power and use of <code>partial()</code> come from the second
|
|
|
+ and third arguments. The <code>$module</code> argument allows
|
|
|
+ <code>partial()</code> to temporarily add a script path for the
|
|
|
+ given module so that the partial view script will resolve to
|
|
|
+ that module; the <code>$model</code> argument allows you to
|
|
|
+ explicitly pass variables for use with the partial view.
|
|
|
+ If you're not passing either argument, <emphasis>use
|
|
|
+ <code>render()</code> instead</emphasis>!
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Basically, unless you are actually passing variables to the
|
|
|
+ partial and need the clean variable scope, or rendering a view
|
|
|
+ script from another MVC module, there is no reason to incur the
|
|
|
+ overhead of <code>partial()</code>; instead, use
|
|
|
+ <code>Zend_View</code>'s built-in <code>render()</code> method
|
|
|
+ to render the view script.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+
|
|
|
+ <sect2 id="performance.view.action">
|
|
|
+ <title>How can I speed up calls to the action() view helper?</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Version 1.5.0 introduced the <code>action()</code> view helper,
|
|
|
+ which allows you to dispatch an MVC action and capture its rendered
|
|
|
+ content. This provides an important step towards the DRY principle,
|
|
|
+ and promotes code reuse. However, as those who profile their
|
|
|
+ applications will quickly realize, it, too, is an expensive
|
|
|
+ operation. Internally, the <code>action()</code> view helper needs
|
|
|
+ to clone new request and response objects, invoke the dispatcher,
|
|
|
+ invoke the requested controller and action, etc.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ How can you speed it up?
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <sect3 id="performance.view.action.actionstack">
|
|
|
+ <title>Use the ActionStack when possible</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Introduced at the same time as the <code>action()</code> view
|
|
|
+ helper, the <link linkend="zend.controller.actionhelpers.actionstack">ActionStack</link>
|
|
|
+ consists of an action helper and a front controller plugin.
|
|
|
+ Together, they allow you to push additional actions to invoke
|
|
|
+ during the dispatch cycle onto a stack. If you are calling
|
|
|
+ <code>action()</code> from your layout view scripts, you may
|
|
|
+ want to instead use the ActionStack, and render your views to
|
|
|
+ discrete response segments. As an example, you could write a
|
|
|
+ <code>dispatchLoopStartup()</code> plugin like the following to
|
|
|
+ add a login form box to each page:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class LoginPlugin extends Zend_Controller_Plugin_Abstract
|
|
|
+{
|
|
|
+ protected $_stack;
|
|
|
+
|
|
|
+ public function dispatchLoopStartup(
|
|
|
+ Zend_Controller_Request_Abstract $request
|
|
|
+ ) {
|
|
|
+ $stack = $this->getStack();
|
|
|
+ $loginRequest = new Zend_Controller_Request_Simple();
|
|
|
+ $loginRequest->setControllerName('user')
|
|
|
+ ->setActionName('index')
|
|
|
+ ->setParam('responseSegment', 'login');
|
|
|
+ $stack->pushStack($loginRequest);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function getStack()
|
|
|
+ {
|
|
|
+ if (null === $this->_stack) {
|
|
|
+ $front = Zend_Controller_Front::getInstance();
|
|
|
+ if (!$front->hasPlugin('Zend_Controller_Plugin_ActionStack')) {
|
|
|
+ $stack = new Zend_Controller_Plugin_ActionStack();
|
|
|
+ $front->registerPlugin($stack);
|
|
|
+ } else {
|
|
|
+ $stack = $front->getPlugin('ActionStack')
|
|
|
+ }
|
|
|
+ $this->_stack = $stack;
|
|
|
+ }
|
|
|
+ return $this->_stack;
|
|
|
+ }
|
|
|
+}
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The <code>UserController::indexAction()</code> method might then
|
|
|
+ use the <code>responseSegment</code> parameter to indicate which
|
|
|
+ response segment to render to. In the layout script, you would
|
|
|
+ then simply render that response segment:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+<?= $this->layout()->login ?>
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ While the ActionStack still requires a dispatch cycle, this is
|
|
|
+ still cheaper than the <code>action()</code> view helper as it
|
|
|
+ does not need to clone objects and reset internal state.
|
|
|
+ Additionally, it ensures that all pre/post dispatch plugins are
|
|
|
+ invoked, which may be of particular concern if you are using
|
|
|
+ front controller plugins for handling ACLs to particular
|
|
|
+ actions.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+
|
|
|
+ <sect3 id="performance.view.action.model">
|
|
|
+ <title>Favor helpers that query the model over action()</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In most cases, using <code>action()</code> is simply overkill.
|
|
|
+ If you have most business logic nested in your models and are
|
|
|
+ simply querying the model and passing the results to a view
|
|
|
+ script, it will typically be faster and cleaner to simply write
|
|
|
+ a view helper that pulls the model, queries it, and does
|
|
|
+ something with that information.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ As an example, consider the following controller action and view
|
|
|
+ script:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class BugController extends Zend_Controller_Action
|
|
|
+{
|
|
|
+ public function listAction()
|
|
|
+ {
|
|
|
+ $model = new Bug();
|
|
|
+ $this->view->bugs = $model->fetchActive();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// bug/list.phtml:
|
|
|
+echo "<ul>\n";
|
|
|
+foreach ($this->bugs as $bug) {
|
|
|
+ printf("<li><b>%s</b>: %s</li>\n", $this->escape($bug->id), $this->escape($bug->summary));
|
|
|
+}
|
|
|
+echo "</ul>\n";
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Using <code>action()</code>, you would then invoke it with the
|
|
|
+ following:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+<?= $this->action('list', 'bug') ?>
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This could be refactored to a view helper that looks like the
|
|
|
+ following:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+class My_View_Helper_BugList extends Zend_View_Helper_Abstract
|
|
|
+{
|
|
|
+ public function direct()
|
|
|
+ {
|
|
|
+ $model = new Bug();
|
|
|
+ $html = "<ul>\n";
|
|
|
+ foreach ($model->fetchActive() as $bug) {
|
|
|
+ $html .= sprintf(
|
|
|
+ "<li><b>%s</b>: %s</li>\n",
|
|
|
+ $this->view->escape($bug->id),
|
|
|
+ $this->view->escape($bug->summary)
|
|
|
+ );
|
|
|
+ }
|
|
|
+ $html .= "</ul>\n";
|
|
|
+ return $html;
|
|
|
+ }
|
|
|
+}
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ You would then invoke the helper as follows:
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <programlisting role="php"><![CDATA[
|
|
|
+<?= $this->bugList() ?>
|
|
|
+]]></programlisting>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ This has two benefits: it no longer incurs the overhead of the
|
|
|
+ <code>action()</code> view helper, and also presents a more
|
|
|
+ semantically understandable API.
|
|
|
+ </para>
|
|
|
+ </sect3>
|
|
|
+ </sect2>
|
|
|
+</sect1><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ </appendix>
|
|
|
+ <appendix id="copyrights" xml:base="ref/copyrights.xml">
|
|
|
+ <title>Copyright Information</title>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The following copyrights are applicable to portions of Zend Framework.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Copyright © 2005-<?dbtimestamp format="Y"?> Zend Technologies Inc.
|
|
|
+ (<ulink url="http://www.zend.com"/>)
|
|
|
+ </para>
|
|
|
+
|
|
|
+</appendix><!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|
|
|
+ <index id="the.index"/>
|
|
|
+</book>
|
|
|
+<!--
|
|
|
+vim:se ts=4 sw=4 et:
|
|
|
+-->
|