Академический Документы
Профессиональный Документы
Культура Документы
Traduccin al 38.7% - Actualizado el 14 de Noviembre del 2009 - Revisin Nro.471 Para obtener la versin ms actual del manual ir a http://manual.zfdes.com
Algunos de los documentos publicados an no han sido revisados y es posible que contenga errores. Si deseas puedes enviarnos un mensaje a zendframeworkspanish@googlegroups.com con sugerencias y/o para informarnos de algn error.
Colaboradores
Pedro Boda Kattia Ninahuanca Javier Martinez Benjamn Gonzales
Actualmente presentamos a los colaboradores ms activos en la portada del manual. Esto no quiere decir que no existan ms colaboradores que tambin trabajan en el manual o que hayan ayudado de manera activa en un pasado. Existen tambin muchas personas que ayudan con sus observaciones a los cuales le estamos infinitamente agradecidos. Si deseas unirte al grupo de traductores puedes enviarnos un mail a zendframeworkspanish@googlegroups.com solicitando tu inclusin
Compilado por
Benjamn Gonzales (http://www.codigolinea.com)
ndice de Contenidos
1. Introduccin a Zend Framework ........................................................................................................ 1 Descripcin general .................................................................................................................... 1 Instalacin ................................................................................................................................ 1 2. Zend_Acl ...................................................................................................................................... 3 Introduccin .............................................................................................................................. 3 Acerca de los Recursos ....................................................................................................... 3 Acerca de las Reglas ........................................................................................................... 3 Creando las Listas de Control de Acceso (ACL) ...................................................................... 4 Registrando Roles ............................................................................................................... 5 Definiendo Controles de Acceso ........................................................................................... 6 Consultando la ACL ........................................................................................................... 7 Perfeccionamiento de los controles de acceso .................................................................................. 7 Definir mejor los controles de acceso ..................................................................................... 7 Eliminar los controles de acceso ........................................................................................... 9 Uso Avanzado .......................................................................................................................... 10 Almacenamiento Permanente de los Datos ACL ..................................................................... 10 Escribiendo reglas condicionales ACL con aserciones ........................................................... 10 3. Zend_Amf ................................................................................................................................... 13 Introduccin ............................................................................................................................. 13 Zend_Amf_Server ..................................................................................................................... 13 Conectndose al Servidor desde Flex .................................................................................... 15 Manejo de errores ............................................................................................................. 16 Respuestas de AMF .......................................................................................................... 17 Objetos tipados ................................................................................................................. 17 Recursos .......................................................................................................................... 19 Conectndose al Servidor desde Flash .................................................................................. 19 Authentication .................................................................................................................. 21 4. Zend_Application .......................................................................................................................... 23 Introduccin ............................................................................................................................. 23 Inicio rpido con Zend_Application ............................................................................................. 23 Usando Zend_Tool ............................................................................................................ 23 Aadir Zend_Application a su aplicacin .............................................................................. 25 Agregando y Creando Recursos ........................................................................................... 27 Prximos pasos con Zend_Application ................................................................................. 28 Teora de Operacin .................................................................................................................. 28 Bootstrapping ................................................................................................................... 29 Plugins de Recursos .......................................................................................................... 34 Ejemplos ................................................................................................................................. 36 Funcionalidad Bsica ................................................................................................................. 39 Zend_Application .............................................................................................................. 39 Zend_Application_Bootstrap_Bootstrapper ............................................................................ 42 Zend_Application_Bootstrap_ResourceBootstrapper ................................................................ 43 Zend_Application_Bootstrap_BootstrapAbstract ..................................................................... 44 Zend_Application_Bootstrap_Bootstrap ................................................................................ 47 Zend_Application_Resource_Resource .................................................................................. 47 Zend_Application_Resource_ResourceAbstract ...................................................................... 47 Plugins de Recursos Disponibles ................................................................................................. 49 Zend_Application_Resource_Db .......................................................................................... 49 Zend_Application_Resource_Frontcontroller .......................................................................... 50 Zend_Application_Resource_Layout ..................................................................................... 51 Zend_Application_Resource_Modules .................................................................................. 52
iii
Zend_Application_Resource_Navigation ............................................................................... 53 Zend_Application_Resource_Router ..................................................................................... 54 Zend_Application_Resource_Session .................................................................................... 54 Zend_Application_Resource_View ....................................................................................... 55 5. Zend_Auth ................................................................................................................................... 57 Introduccin ............................................................................................................................. 57 Adaptadores ..................................................................................................................... 57 Resultados ....................................................................................................................... 58 Persistencia de Identidad .................................................................................................... 59 Uso ................................................................................................................................ 61 Tabla de base de datos de autenticacin ........................................................................................ 63 Introduccin ..................................................................................................................... 63 Advanced Usage: Manteniendo el resultado del Objeto DbTable ................................................ 65 Ejemplo de Uso Avanzado ................................................................................................. 66 Autenticacin "Digest" ............................................................................................................... 67 Introduccin ..................................................................................................................... 67 Detalles Especficos .......................................................................................................... 68 Identidad ......................................................................................................................... 68 Adaptador de Autenticacin HTTP .............................................................................................. 68 Introduccin ..................................................................................................................... 68 Descripcin del diseo ....................................................................................................... 69 Opciones de Configuracin ................................................................................................. 69 Resolvers ......................................................................................................................... 70 Uso Bsico ...................................................................................................................... 70 LDAP Authentication ................................................................................................................ 71 Introduction ..................................................................................................................... 71 Usage ............................................................................................................................. 72 The API .......................................................................................................................... 73 Server Options ................................................................................................................. 75 Collecting Debugging Messages .......................................................................................... 77 Common Options for Specific Servers .................................................................................. 78 Autenticacin con Open ID ....................................................................................................... 79 Introduccin ..................................................................................................................... 79 Caractersticas .................................................................................................................. 80 6. Zend_Cache ................................................................................................................................. 83 Introduccin ............................................................................................................................. 83 The Theory of Caching .............................................................................................................. 85 The Zend_Cache Factory Method ........................................................................................ 85 Tagging Records ............................................................................................................... 86 Cleaning the Cache ........................................................................................................... 86 Zend_Cache Frontends ............................................................................................................... 87 Zend_Cache_Core ............................................................................................................. 87 Zend_Cache_Frontend_Output ............................................................................................ 90 Zend_Cache_Frontend_Function .......................................................................................... 91 Zend_Cache_Frontend_Class .............................................................................................. 91 Zend_Cache_Frontend_File ................................................................................................ 93 Zend_Cache_Frontend_Page ............................................................................................... 94 Zend_Cache Backends ............................................................................................................... 98 Zend_Cache_Backend_File ................................................................................................. 98 Zend_Cache_Backend_Sqlite .............................................................................................. 99 Zend_Cache_Backend_Memcached .................................................................................... 100 Zend_Cache_Backend_Apc ............................................................................................... 101 Zend_Cache_Backend_Xcache .......................................................................................... 101 Zend_Cache_Backend_ZendPlatform .................................................................................. 101
iv
Zend_Cache_Backend_TwoLevels ..................................................................................... Zend_Cache_Backend_ZendServer_Disk and Zend_Cache_Backend_ZendServer_ShMem ........... 7. Zend_Captcha ............................................................................................................................. Introduccin ........................................................................................................................... Captcha Operation ................................................................................................................... CAPTCHA Adapters ............................................................................................................... Zend_Captcha_Word ....................................................................................................... Zend_Captcha_Dumb ....................................................................................................... Zend_Captcha_Figlet ....................................................................................................... Zend_Captcha_Image ....................................................................................................... Zend_Captcha_ReCaptcha ................................................................................................ 8. Zend_CodeGenerator .................................................................................................................... Introduccin ........................................................................................................................... Teora de Operacin ........................................................................................................ Ejemplos de Zend_CodeGenerator ............................................................................................. Referencias de Zend_CodeGenerator .......................................................................................... Clases Abstractas e Interfaces ............................................................................................ Clases Concretas de CodeGenerator ................................................................................... 9. Zend_Config ............................................................................................................................... Introduccin ........................................................................................................................... Aspectos Tericos ................................................................................................................... Zend_Config_Ini ..................................................................................................................... Zend_Config_Xml ................................................................................................................... 10. Zend_Config_Writer ................................................................................................................... Zend_Config_Writer ................................................................................................................ 11. Zend_Console_Getopt ................................................................................................................. Introduction ............................................................................................................................ Declaring Getopt Rules ............................................................................................................ Declaring Options with the Short Syntax ............................................................................. Declaring Options with the Long Syntax ............................................................................. Fetching Options and Arguments ............................................................................................... Handling Getopt Exceptions .............................................................................................. Fetching Options by Name ............................................................................................... Reporting Options ........................................................................................................... Fetching Non-option Arguments ........................................................................................ Configuring Zend_Console_Getopt ............................................................................................. Adding Option Rules ....................................................................................................... Adding Help Messages .................................................................................................... Adding Option Aliases ..................................................................................................... Adding Argument Lists .................................................................................................... Adding Configuration ...................................................................................................... 12. Zend_Controller ......................................................................................................................... Inicio rpido a Zend_Controller ................................................................................................. Introduccin ................................................................................................................... Quick Start .................................................................................................................... Conceptos Bsicos de Zend_Controller ....................................................................................... El Front Controller .................................................................................................................. Introduccin ................................................................................................................... Mtodos Bsicos ............................................................................................................. Mtodos Accessor Ambientales ......................................................................................... Parmetros de Front Controller .......................................................................................... Extendiendo el Front Controller ......................................................................................... La solicitud del Objeto ............................................................................................................. Introduccin ...................................................................................................................
101 103 105 105 105 106 106 107 107 107 108 109 109 109 111 118 118 119 125 125 126 127 129 133 133 135 135 136 136 136 137 137 137 138 138 139 139 139 139 140 140 143 143 143 143 146 149 149 150 151 152 153 154 154
Solicitud HTTP ............................................................................................................... Subclassing the Request Object ......................................................................................... El Router Standard .................................................................................................................. Introduccin ................................................................................................................... Usando un Router ........................................................................................................... Operacin Bsica del Rewrite Router .................................................................................. Routes por Defecto .......................................................................................................... URL Base y Subdirectorios ............................................................................................... Parmetros Globales ........................................................................................................ Tipos de Route ............................................................................................................... Usando Zend_Config con RewriteRouter ......................................................................... Subclassing del Router ..................................................................................................... El Despachador ....................................................................................................................... Introduccin ................................................................................................................... Subclaseando el Despachador ............................................................................................ Controladores de Accin .......................................................................................................... Introduccin ................................................................................................................... Inicializacin de Objectos ................................................................................................. Ganchos de Pre- and Post-Despacho ................................................................................... Accessors (Accededores) .................................................................................................. Integracin de Vistas ....................................................................................................... Mtodos Utilitarios .......................................................................................................... Controladores de Accin y haciendo Subclases ..................................................................... Action Helpers ....................................................................................................................... Introduction .................................................................................................................... Helper Initialization ......................................................................................................... The Helper Broker .......................................................................................................... Built-in Action Helpers .................................................................................................... Writing Your Own Helpers ............................................................................................... The Response Object ............................................................................................................... Usage ............................................................................................................................ Manipulating Headers ...................................................................................................... Named Segments ............................................................................................................ Testing for Exceptions in the Response Object ..................................................................... Subclassing the Response Object ....................................................................................... Plugins .................................................................................................................................. Introduction .................................................................................................................... Writing Plugins ............................................................................................................... Using Plugins ................................................................................................................. Retrieving and Manipulating Plugins .................................................................................. Plugins Included in the Standard Distribution ....................................................................... Using a Conventional Modular Directory Structure ....................................................................... Introduction .................................................................................................................... Specifying Module Controller Directories ............................................................................ Routing to Modules ......................................................................................................... Module or Global Default Controller .................................................................................. Excepciones MVC ................................................................................................................... Introduccin ................................................................................................................... Manejando las Excepciones .............................................................................................. Excepciones MVC que Usted Pueda Encontrar ..................................................................... 13. Zend_Currency .......................................................................................................................... Introduction to Zend_Currency .................................................................................................. Why use Zend_Currency? ................................................................................................. How to Work with Currencies ...................................................................................................
154 157 158 158 160 160 161 163 163 163 174 175 176 176 177 180 180 182 182 182 183 185 185 187 187 187 188 189 217 217 217 219 220 221 222 222 222 222 223 224 224 229 229 230 231 231 232 232 232 233 237 237 237 237
vi
Creating and Output String from a Currency ........................................................................ 239 Changing the Format of a Currency .................................................................................... 239 Reference Methods for Zend_Currency ............................................................................... 241 Settings new default values ............................................................................................... 242 Zend_Currency Performance Optimization ........................................................................... 242 14. Zend_Date ................................................................................................................................ 245 Introduccin ........................................................................................................................... 245 Asigne Siempre una Zona Horaria por Defecto ..................................................................... 245 Por Qu Usar Zend_Date? ............................................................................................... 245 Theory of Operation ................................................................................................................ 246 Internals ........................................................................................................................ 246 Basic Methods ........................................................................................................................ 247 Current Date .................................................................................................................. 247 Zend_Date by Ejemplo .................................................................................................... 247 Zend_Date API Overview ......................................................................................................... 249 Opciones Zend_Date ........................................................................................................ 249 Working with Date Values ................................................................................................ 250 Basic Zend_Date Operations Common to Many Date Parts ..................................................... 251 Comparing Dates ............................................................................................................ 254 Getting Dates and Date Parts ............................................................................................ 255 Working with Fractions of Seconds .................................................................................... 256 Sunrise / Sunset .............................................................................................................. 256 Creation of Dates .................................................................................................................... 257 Create the Actual Date ..................................................................................................... 257 Create a Date from Database ............................................................................................. 257 Create Dates from an Array .............................................................................................. 258 Constants for General Date Functions ......................................................................................... 258 Using Constants .............................................................................................................. 259 List of All Constants ....................................................................................................... 259 Self-Defined OUTPUT Formats with ISO ............................................................................ 263 Self-Defined OUTPUT Formats Using PHP's date() Format Specifiers ...................................... 266 Working Ejemplos ................................................................................................................... 268 Checking Dates ............................................................................................................... 268 Sunrise and Sunset .......................................................................................................... 269 Time Zones .................................................................................................................... 271 15. Zend_Db .................................................................................................................................. 273 Zend_Db_Adapter ................................................................................................................... 273 Conexin a una Base de Datos utilizando un Adaptador ....................................................... 273 La base de datos de ejemplo ............................................................................................. 278 Reading Query Results ..................................................................................................... 279 Writing Changes to the Database ....................................................................................... 282 Quoting Values and Identifiers .......................................................................................... 285 Controlling Database Transactions ..................................................................................... 288 Listing and Describing Tables ........................................................................................... 289 Closing a Connection ....................................................................................................... 290 Running Other Database Statements ................................................................................... 291 Retrieving Server Version ................................................................................................. 291 Notes on Specific Adapters ............................................................................................... 291 Zend_Db_Statement ................................................................................................................. 294 Creando una Declaracin .................................................................................................. 294 Ejecutando la declaracin ................................................................................................. 295 Extrayendo Resultados de una declaracin SELECT .............................................................. 295 Zend_Db_Profiler .................................................................................................................... 298 Introduccin ................................................................................................................... 298
vii
Usando el Perfilador ........................................................................................................ Uso avanzado del Perfilador .............................................................................................. Perfiladores Especializados ............................................................................................... Zend_Db_Select ...................................................................................................................... Descripcin del Objeto Select ............................................................................................ Creando un Objeto Select ................................................................................................. Construyendo consultas Select ........................................................................................... Ejecutando consultas Select .............................................................................................. Otros Mtodos ................................................................................................................ Zend_Db_Table ...................................................................................................................... Introduction .................................................................................................................... Defining a Table Class ..................................................................................................... Creating an Instance of a Table ......................................................................................... Inserting Rows to a Table ................................................................................................. Updating Rows in a Table ................................................................................................ Deleting Rows from a Table ............................................................................................. Finding Rows by Primary Key .......................................................................................... Querying for a Set of Rows .............................................................................................. Querying for a Single Row ............................................................................................... Retrieving Table Metadata Information ............................................................................... Caching Table Metadata ................................................................................................... Customizing and Extending a Table Class ........................................................................... Zend_Db_Table_Row .............................................................................................................. Introduction .................................................................................................................... Fetching a Row .............................................................................................................. Writing rows to the database ............................................................................................. Serializing and unserializing rows ...................................................................................... Extending the Row class .................................................................................................. Zend_Db_Table_Rowset ........................................................................................................... Introduction .................................................................................................................... Fetching a Rowset ........................................................................................................... Retrieving Rows from a Rowset ........................................................................................ Retrieving a Rowset as an Array ........................................................................................ Serializing and Unserializing a Rowset ............................................................................... Extending the Rowset class ............................................................................................... Zend_Db_Table Relationships ................................................................................................... Introduction .................................................................................................................... Defining Relationships ..................................................................................................... Fetching a Dependent Rowset ........................................................................................... Fetching a Parent Row ..................................................................................................... Fetching a Rowset via a Many-to-many Relationship ............................................................. Cascading Write Operations .............................................................................................. Zend_Db_Table_Definition ....................................................................................................... Introduction .................................................................................................................... Basic Usage ................................................................................................................... Advanced Usage ............................................................................................................. 16. Zend_Debug ............................................................................................................................. Mostrar informacin de variables(Dumping Variables) ................................................................... 17. Zend_Dojo ................................................................................................................................ Introduccin ........................................................................................................................... Zend_Dojo_Data: Envolturas de dojo.data ................................................................................... Uso de Zend_Dojo_Data .................................................................................................. Agregando metadatos a sus contenedores ............................................................................ Casos Avanzados de Uso ..................................................................................................
299 300 302 303 303 303 304 316 317 319 319 319 322 323 325 326 326 327 331 331 332 334 337 337 337 339 341 342 345 345 345 346 348 348 349 350 350 351 353 354 356 358 360 360 360 361 363 363 365 365 365 365 367 367
viii
18.
19. 20.
21.
Ayudantes de Dojo View ......................................................................................................... dojo() Ayudante de Vista .................................................................................................. Ayudantes de Vistas Especficos de Dijit ............................................................................. Elementos y Decoradores de Dojo Form ..................................................................................... Decoradores de Forms Especficos de Dijit .......................................................................... Elementos de Formularios Dijit-Specific ............................................................................. Ejemplos de Dojo Form ................................................................................................... Zend_Dojo build layer support .................................................................................................. Introduction .................................................................................................................... Generating Custom Module Layers with Zend_Dojo_BuildLayer ............................................. Generating Build Profiles with Zend_Dojo_BuildLayer .......................................................... Zend_Dom ................................................................................................................................ Introduccin ........................................................................................................................... Zend_Dom_Query ................................................................................................................... Theory of Operation ........................................................................................................ Methods Available .......................................................................................................... Zend_Exception ......................................................................................................................... Using Exceptions .................................................................................................................... Zend_Feed ................................................................................................................................ Introduction ............................................................................................................................ Importing Feeds ...................................................................................................................... Custom feeds .................................................................................................................. Retrieving Feeds from Web Pages ............................................................................................. Consuming an RSS Feed .......................................................................................................... Consuming an Atom Feed ........................................................................................................ Consuming a Single Atom Entry ............................................................................................... Modifying Feed and Entry structures .......................................................................................... Custom Feed and Entry Classes ................................................................................................. Zend_Feed_Reader .................................................................................................................. Introduction .................................................................................................................... Importing Feeds .............................................................................................................. Retrieving Underlying Feed and Entry Sources ..................................................................... Cache Support and Intelligent Requests ............................................................................... Locating Feed URIs from Websites .................................................................................... Retrieving Feed Information .............................................................................................. Retrieving Entry/Item Information ...................................................................................... Extending Feed and Entry APIs ......................................................................................... Zend_File ................................................................................................................................. Zend_File_Transfer ................................................................................................................. Supported Adapters for Zend_File_Transfer ......................................................................... Options for Zend_File_Transfer ......................................................................................... Checking Files ................................................................................................................ Additional File Informations ............................................................................................. Progress for file uploads ................................................................................................... Validators for Zend_File_Transfer .............................................................................................. Using Validators with Zend_File_Transfer ........................................................................... Count Validator .............................................................................................................. Crc32 Validator .............................................................................................................. ExcludeExtension Validator .............................................................................................. ExcludeMimeType Validator ............................................................................................. Exists Validator .............................................................................................................. Extension Validator ......................................................................................................... FilesSize Validator .......................................................................................................... ImageSize Validator ........................................................................................................
369 369 374 387 388 389 405 412 412 413 416 419 419 419 419 420 423 423 425 425 426 426 431 431 432 433 434 435 436 436 437 438 439 440 441 443 445 451 451 452 452 452 453 454 456 457 459 460 460 461 461 462 463 463
ix
IsCompressed Validator .................................................................................................... 464 IsImage Validator ............................................................................................................ 465 Hash Validator ................................................................................................................ 465 Md5 Validator ................................................................................................................ 466 MimeType Validator ........................................................................................................ 466 NotExists Validator ......................................................................................................... 467 Sha1 Validator ................................................................................................................ 468 Size Validator ................................................................................................................. 468 WordCount Validator ....................................................................................................... 469 Filters for Zend_File_Transfer ................................................................................................... 469 Using filters with Zend_File_Transfer ................................................................................. 470 Decrypt filter .................................................................................................................. 471 Encrypt filter .................................................................................................................. 472 LowerCase filter ............................................................................................................. 472 Rename filter .................................................................................................................. 473 UpperCase filter .............................................................................................................. 474 22. Zend_Filter ............................................................................................................................... 475 Introduccin ........................................................................................................................... 475 Qu es un filtro? ........................................................................................................... 475 Uso bsico de los filtros ................................................................................................... 475 Usando el mtodo esttico staticFilter() .............................................................................. 476 Standard Filter Classes ............................................................................................................. 477 Alnum ........................................................................................................................... 477 Alpha ............................................................................................................................ 477 BaseName ...................................................................................................................... 477 Callback ........................................................................................................................ 477 Compress and Decompress ............................................................................................... 478 Decrypt ......................................................................................................................... 483 Digits ............................................................................................................................ 485 Dir ................................................................................................................................ 485 Encrypt .......................................................................................................................... 485 HtmlEntities ................................................................................................................... 488 Int ................................................................................................................................ 488 LocalizedToNormalized .................................................................................................... 488 NormalizedToLocalized .................................................................................................... 490 Null .............................................................................................................................. 492 StripNewlines ................................................................................................................. 493 RealPath ........................................................................................................................ 493 StringToLower ................................................................................................................ 494 StringToUpper ................................................................................................................ 494 StringTrim ..................................................................................................................... 494 StripTags ....................................................................................................................... 495 Filter Chains .......................................................................................................................... 495 Writing Filters ........................................................................................................................ 495 Zend_Filter_Input .................................................................................................................... 496 Declaring Filter and Validator Rules ................................................................................... 496 Creating the Filter and Validator Processor .......................................................................... 497 Retrieving Validated Fields and other Reports ...................................................................... 498 Using Metacommands to Control Filter or Validator Rules ..................................................... 501 Adding Filter Class Namespaces ........................................................................................ 506 Zend_Filter_Inflector ............................................................................................................... 507 Operation ....................................................................................................................... 507 Setting Paths To Alternate Filters ....................................................................................... 508 Setting the Inflector Target ............................................................................................... 508
Inflection Rules .............................................................................................................. Utility Methods ............................................................................................................... Using Zend_Config with Zend_Filter_Inflector ..................................................................... 23. Zend_Form ............................................................................................................................... Zend_Form ............................................................................................................................ Inicio rpido a Zend_Form ....................................................................................................... Creando un objeto formulario ............................................................................................ Aadir elementos al formulario ......................................................................................... Generar un formulario ...................................................................................................... Comprobar si un formulario es vlido ................................................................................. Obteniendo el estado de error ............................................................................................ Poniendo todo junto ........................................................................................................ Usando un objeto Zend_Config ......................................................................................... Conclusin ..................................................................................................................... Creando elementos de formulario usando Zend_Form_Element ....................................................... Cargadores de Plugin ....................................................................................................... Filters ............................................................................................................................ Validadores .................................................................................................................... Decoradores ................................................................................................................... Metadatos y atributos ....................................................................................................... Elementos Estndar ......................................................................................................... Mtodos de Zend_Form_Element ....................................................................................... Configuracin ................................................................................................................. Elementos personalizados ................................................................................................. Creando formularios usando Zend_Form ..................................................................................... Cargadores de Plugin ....................................................................................................... Elementos ...................................................................................................................... Grupos de visualizacin (display groups) ............................................................................. Subformularios ............................................................................................................... Metadatos y Atributos ...................................................................................................... Decoradores ................................................................................................................... Validacin ..................................................................................................................... Mtodos ........................................................................................................................ Configuracin ................................................................................................................. Formularios personalizados ............................................................................................... Creando un personalizado marcado de formulario usando Zend_Form_Decorator ................................ Operacin ...................................................................................................................... Decoradores estndar ....................................................................................................... Decoradores personalizados .............................................................................................. Generando decoradores individuales ................................................................................... Elementos Enviados en el Formulario Estandard de Zend Framework ............................................... Zend_Form_Element_Button ............................................................................................. Zend_Form_Element_Captcha ........................................................................................... Zend_Form_Element_Checkbox ......................................................................................... Zend_Form_Element_File ................................................................................................. Zend_Form_Element_Hidden ............................................................................................ Zend_Form_Element_Hash ............................................................................................... Zend_Form_Element_Image .............................................................................................. Zend_Form_Element_MultiCheckbox ................................................................................. Zend_Form_Element_Multiselect ....................................................................................... Zend_Form_Element_Password ......................................................................................... Zend_Form_Element_Radio .............................................................................................. Zend_Form_Element_Reset ............................................................................................... Zend_Form_Element_Select ..............................................................................................
509 511 512 513 513 513 513 513 516 517 517 518 519 520 520 521 522 524 528 531 532 532 535 536 537 538 538 542 546 547 549 551 552 555 557 558 559 559 559 562 563 563 563 564 565 568 568 568 568 569 570 570 570 570
xi
Zend_Form_Element_Submit ............................................................................................ Zend_Form_Element_Text ................................................................................................ Zend_Form_Element_Textarea .......................................................................................... Decoradores de Formulario (Form Decorartors) estndar contenidos en Zend Framework ...................... Zend_Form_Decorator_Callback ........................................................................................ Zend_Form_Decorator_Captcha ......................................................................................... Zend_Form_Decorator_Description .................................................................................... Zend_Form_Decorator_DtDdWrapper ................................................................................. Zend_Form_Decorator_Errors ............................................................................................ Zend_Form_Decorator_Fieldset ......................................................................................... Zend_Form_Decorator_File ............................................................................................... Zend_Form_Decorator_Form ............................................................................................. Zend_Form_Decorator_FormElements ................................................................................ Zend_Form_Decorator_FormErrors .................................................................................... Zend_Form_Decorator_HtmlTag ........................................................................................ Zend_Form_Decorator_Image ............................................................................................ Zend_Form_Decorator_Label ............................................................................................ Zend_Form_Decorator_PrepareElements ............................................................................. Zend_Form_Decorator_ViewHelper .................................................................................... Zend_Form_Decorator_ViewScript ..................................................................................... Internacionalizacin de Zend_Form ............................................................................................ Inicializando I18n en formularios ....................................................................................... Objetivos estndar I18n .................................................................................................... Uso avanzado de Zend_Form .................................................................................................... Notacin de array ............................................................................................................ Formularios Multi-Pgina ................................................................................................. 24. Zend_Gdata .............................................................................................................................. Introduction ............................................................................................................................ Structure of Zend_Gdata .................................................................................................. Interacting with Google Services ....................................................................................... Obtaining instances of Zend_Gdata classes .......................................................................... Google Data Client Authentication ..................................................................................... Dependencies ................................................................................................................. Creating a new Gdata client .............................................................................................. Common Query Parameters .............................................................................................. Fetching a Feed .............................................................................................................. Working with Multi-page Feeds ......................................................................................... Working with Data in Feeds and Entries ............................................................................. Updating Entries ............................................................................................................. Posting Entries to Google Servers ...................................................................................... Deleting Entries on Google Servers .................................................................................... Authenticating with AuthSub .................................................................................................... Creating an AuthSub authenticated Http Client ..................................................................... Revoking AuthSub authentication ...................................................................................... Using the Book Search Data API ............................................................................................... Authenticating to the Book Search service ........................................................................... Searching for books ......................................................................................................... Using community features ................................................................................................ Book collections and My Library ....................................................................................... Authenticating with ClientLogin ................................................................................................ Creating a ClientLogin authenticated Http Client .................................................................. Terminating a ClientLogin authenticated Http Client ............................................................. Using Google Calendar ............................................................................................................ Connecting To The Calendar Service ..................................................................................
571 571 571 571 572 572 572 572 573 573 573 573 573 573 574 574 574 575 575 575 577 577 578 578 578 581 591 591 591 592 592 593 593 593 594 595 595 596 596 596 597 597 598 599 599 599 599 601 603 604 605 605 605 606
xii
Retrieving A Calendar List ............................................................................................... Retrieving Events ............................................................................................................ Creating Events .............................................................................................................. Modifying Events ............................................................................................................ Deleting Events .............................................................................................................. Accessing Event Comments .............................................................................................. Using Google Documents List Data API ..................................................................................... Get a List of Documents .................................................................................................. Upload a Document ......................................................................................................... Searching the documents feed ........................................................................................... Using Google Health ............................................................................................................... Connect To The Health Service ......................................................................................... Profile Feed ................................................................................................................... Profile List Feed ............................................................................................................. Sending Notices to the Register Feed .................................................................................. Using Google Spreadsheets ....................................................................................................... Create a Spreadsheet ........................................................................................................ Get a List of Spreadsheets ................................................................................................ Get a List of Worksheets .................................................................................................. Interacting With List-based Feeds ...................................................................................... Interacting With Cell-based Feeds ...................................................................................... Using Google Apps Provisioning ............................................................................................... Setting the current domain ................................................................................................ Interacting with users ....................................................................................................... Interacting with nicknames ............................................................................................... Interacting with email lists ................................................................................................ Interacting with email list recipients ................................................................................... Handling errors ............................................................................................................... Using Google Base .................................................................................................................. Connect To The Base Service ........................................................................................... Retrieve Items ................................................................................................................ Insert, Update, and Delete Customer Items .......................................................................... Using Picasa Web Albums ....................................................................................................... Connecting To The Service ............................................................................................... Understanding and Constructing Queries ............................................................................. Retrieving Feeds And Entries ............................................................................................ Creating Entries .............................................................................................................. Deleting Entries .............................................................................................................. Using the YouTube Data API ................................................................................................... Authentication ................................................................................................................ Developer Keys and Client ID ........................................................................................... Retrieving public video feeds ............................................................................................ Retrieving video comments ............................................................................................... Retrieving playlist feeds ................................................................................................... Retrieving a list of a user's subscriptions ............................................................................. Retrieving a user's profile ................................................................................................. Uploading Videos to YouTube .......................................................................................... Browser-based upload ...................................................................................................... Checking upload status .................................................................................................... Other Functions .............................................................................................................. Catching Gdata Exceptions ....................................................................................................... 25. Zend_Http ................................................................................................................................ Introduction ............................................................................................................................ Using Zend_Http_Client ...................................................................................................
608 609 611 614 615 615 616 616 616 617 618 618 621 622 623 624 624 624 624 625 627 628 628 629 632 634 635 636 637 637 640 641 643 643 646 647 651 652 654 655 655 655 657 658 658 659 659 661 662 662 662 665 665 665
xiii
Configuration Parameters .................................................................................................. Performing Basic HTTP Requests ...................................................................................... Adding GET and POST parameters ................................................................................... Accessing Last Request and Response ................................................................................ Zend_Http_Client - Advanced Usage .......................................................................................... HTTP Redirections .......................................................................................................... Adding Cookies and Using Cookie Persistence ..................................................................... Setting Custom Request Headers ....................................................................................... File Uploads ................................................................................................................... Sending Raw POST Data ................................................................................................. HTTP Authentication ....................................................................................................... Sending Multiple Requests With the Same Client ................................................................. Zend_Http_Client - Connection Adapters .................................................................................... Overview ....................................................................................................................... The Socket Adapter ......................................................................................................... The Proxy Adapter .......................................................................................................... The cURL Adapter .......................................................................................................... The Test Adapter ............................................................................................................ Creating your own connection adapters ............................................................................... Zend_Http_Cookie and Zend_Http_CookieJar .............................................................................. Introduction .................................................................................................................... Instantiating Zend_Http_Cookie Objects .............................................................................. Zend_Http_Cookie getter methods ..................................................................................... Zend_Http_Cookie: Matching against a scenario ................................................................... The Zend_Http_CookieJar Class: Instantiation ...................................................................... Adding Cookies to a Zend_Http_CookieJar object ................................................................. Retrieving Cookies From a Zend_Http_CookieJar object ........................................................ Zend_Http_Response ............................................................................................................... Introduction .................................................................................................................... Boolean Tester Methods ................................................................................................... Accessor Methods ........................................................................................................... Static HTTP Response Parsers ........................................................................................... 26. Zend_InfoCard .......................................................................................................................... Introduction ............................................................................................................................ Basic Theory of Usage ..................................................................................................... Using as part of Zend_Auth .............................................................................................. Using the Zend_InfoCard component standalone ................................................................... Working with a Claims object ........................................................................................... Attaching Information Cards to existing accounts .................................................................. Creating Zend_InfoCard Adapters ...................................................................................... 27. Zend_Json ................................................................................................................................ Introduccin ........................................................................................................................... Uso Bsico ............................................................................................................................ Uso Avanzado de Zend_Json .................................................................................................... Objetos JSON ................................................................................................................. Codificando Objetos PHP ................................................................................................. Codificador/Decodificador Interno ...................................................................................... Expresiones JSON ........................................................................................................... Conversin de XML a JSON .................................................................................................... Zend_Json_Server - servidor JSON-RPC ..................................................................................... Detalles Avanzados ......................................................................................................... 28. Zend_Layout ............................................................................................................................. Introduccin ........................................................................................................................... Zend_Layout Quick Start ..........................................................................................................
665 666 667 668 668 668 668 669 670 671 671 671 673 673 673 675 677 677 680 681 681 681 683 684 685 685 686 687 687 687 688 689 691 691 691 691 693 694 694 695 697 697 697 697 697 698 698 698 699 700 703 709 709 709
xiv
Layout scripts ................................................................................................................. Using Zend_Layout with the Zend Framework MVC ............................................................. Using Zend_Layout as a Standalone Component ................................................................... Sample Layout ................................................................................................................ Zend_Layout Configuration Options ........................................................................................... Ejemplos ....................................................................................................................... Zend_Layout Advanced Usage .................................................................................................. Custom View Objects ...................................................................................................... Custom Front Controller Plugins ........................................................................................ Custom Action Helpers .................................................................................................... Custom Layout Script Path Resolution: Using the Inflector ..................................................... 29. Zend_Ldap ............................................................................................................................... Introduction ............................................................................................................................ Theory of operation ......................................................................................................... API overview ......................................................................................................................... Configuration / options ..................................................................................................... API Reference ................................................................................................................ Usage Scenarios ...................................................................................................................... Authentication scenarios ................................................................................................... Basic CRUD operations ................................................................................................... Extended operations ......................................................................................................... Tools .................................................................................................................................... Creation and modification of DN strings ............................................................................. Using the filter API to create search filters .......................................................................... Modify LDAP entries using the Attribute API ...................................................................... Object oriented access to the LDAP tree using Zend_Ldap_Node .................................................... Basic CRUD operations ................................................................................................... Extended operations ......................................................................................................... Tree traversal ................................................................................................................. Getting information from the LDAP server .................................................................................. RootDSE ....................................................................................................................... Schema Browsing ........................................................................................................... Serializing LDAP data to and from LDIF .................................................................................... Serialize a LDAP entry to LDIF ........................................................................................ Deserialize a LDIF string into a LDAP entry ....................................................................... 30. Zend_Loader ............................................................................................................................. Cargando archivos y clases dinmicamente .................................................................................. Cargando Archivos .......................................................................................................... Cargando Clases ............................................................................................................. Comprobando si un Archivo Puede Ser Ledo ...................................................................... Usando el Autoloader ...................................................................................................... The Autoloader ....................................................................................................................... Using the Autoloader ....................................................................................................... Selecting a Zend Framework version .................................................................................. The Autoloader Interface .................................................................................................. Autoloader Reference ....................................................................................................... Resource Autoloaders .............................................................................................................. Resource autoloader usage ................................................................................................ The Module Resource Autoloader ...................................................................................... Using Resource Autoloaders as Object Factories ................................................................... Resource Autoloader Reference ......................................................................................... Loading Plugins ...................................................................................................................... Basic Use Case ............................................................................................................... Manipulating Plugin Paths ................................................................................................
709 710 712 712 714 714 716 716 716 717 717 719 719 719 722 722 724 746 746 746 748 748 748 748 749 749 749 749 749 750 750 750 750 750 752 755 755 755 755 756 756 757 757 758 760 760 763 763 764 765 765 765 765 766
xv
Testing for Plugins and Retrieving Class Names ................................................................... Getting Better Performance for Plugins ............................................................................... 31. Zend_Locale ............................................................................................................................. Introduction ............................................................................................................................ What is Localization ........................................................................................................ What is a Locale? ........................................................................................................... How are Locales Represented? .......................................................................................... Selecting the Right Locale ................................................................................................ Usage of automatic Locales .............................................................................................. Using a default Locale ..................................................................................................... ZF Locale-Aware Classes ................................................................................................. Application wide locale .................................................................................................... Zend_Locale_Format::setOptions(array $options) .................................................................. Speed up Zend_Locale and its subclasses ............................................................................ Using Zend_Locale ................................................................................................................. Copying, Cloning, and Serializing Locale Objects ................................................................. Equality ......................................................................................................................... Default locales ................................................................................................................ Set a new locale ............................................................................................................. Getting the language and region ........................................................................................ Obtaining localized strings ................................................................................................ Obtaining translations for "yes" and "no" ............................................................................ Get a list of all known locales ........................................................................................... Detecting locales ............................................................................................................. Normalization and Localization ................................................................................................. Number normalization: getNumber($input, Array $options) .................................................... Number localization ......................................................................................................... Number testing ............................................................................................................... Float value normalization ................................................................................................. Floating point value localization ........................................................................................ Floating point value testing ............................................................................................... Integer value normalization ............................................................................................... Integer point value localization .......................................................................................... Integer value testing ........................................................................................................ Numeral System Conversion ............................................................................................. Working with Dates and Times ................................................................................................. Normalizing Dates and Times ........................................................................................... Testing Dates ................................................................................................................. Normalizing a Time ........................................................................................................ Testing Times ................................................................................................................. Supported locales .................................................................................................................... 32. Zend_Log ................................................................................................................................. Overview ............................................................................................................................... Creating a Log ............................................................................................................... Logging Messages ........................................................................................................... Destroying a Log ............................................................................................................ Using Built-in Priorities ................................................................................................... Adding User-defined Priorities .......................................................................................... Understanding Log Events ................................................................................................ Writers .................................................................................................................................. Writing to Streams .......................................................................................................... Writing to Databases ....................................................................................................... Writing to Firebug .......................................................................................................... Writing to Email .............................................................................................................
767 767 769 769 769 770 770 770 771 772 773 773 774 774 775 775 775 775 776 776 777 789 790 790 792 792 793 794 795 795 795 796 796 796 796 798 798 801 802 802 802 815 815 815 815 816 816 816 817 817 817 818 818 821
xvi
Writing to the System Log ............................................................................................... Stubbing Out the Writer ................................................................................................... Testing with the Mock ..................................................................................................... Compositing Writers ........................................................................................................ Formatters .............................................................................................................................. Simple Formatting ........................................................................................................... Formatting to XML ......................................................................................................... Filters .................................................................................................................................... Filtering for All Writers ................................................................................................... Filtering for a Writer Instance ........................................................................................... 33. Zend_Mail ................................................................................................................................ Introduction ............................................................................................................................ Getting started ................................................................................................................ Configuring the default sendmail transport ........................................................................... Sending via SMTP .................................................................................................................. Sending Multiple Mails per SMTP Connection ............................................................................. Using Different Transports ........................................................................................................ HTML E-Mail ........................................................................................................................ Attachments ........................................................................................................................... Adding Recipients ................................................................................................................... Controlling the MIME Boundary ............................................................................................... Additional Headers .................................................................................................................. Character Sets ........................................................................................................................ Encoding ............................................................................................................................... SMTP Authentication .............................................................................................................. Securing SMTP Transport ........................................................................................................ Reading Mail Messages ............................................................................................................ Simple example using Pop3 .............................................................................................. Opening a local storage .................................................................................................... Opening a remote storage ................................................................................................. Fetching messages and simple methods ............................................................................... Working with messages .................................................................................................... Checking for flags ........................................................................................................... Using folders .................................................................................................................. Advanced Use ................................................................................................................ 34. Zend_Measure ........................................................................................................................... Introduction ............................................................................................................................ Creation of Measurements ........................................................................................................ Creating measurements from integers and floats ................................................................... Creating measurements from strings ................................................................................... Measurements from localized strings .................................................................................. Outputting measurements .......................................................................................................... Automatic output ............................................................................................................ Outputting values ............................................................................................................ Output with unit of measurement ....................................................................................... Output as localized string ................................................................................................. Manipulating Measurements ...................................................................................................... Convert ......................................................................................................................... Add and subtract ............................................................................................................. Compare ........................................................................................................................ Compare ........................................................................................................................ Manually change values ................................................................................................... Manually change types ..................................................................................................... Types of measurements ............................................................................................................
822 823 823 824 824 824 825 826 826 826 829 829 829 829 830 830 832 832 832 833 834 834 834 834 835 835 836 836 836 837 837 838 840 841 843 847 847 847 847 848 848 849 849 850 850 850 850 851 851 852 853 853 853 854
xvii
35.
36.
37.
38.
Hints for Zend_Measure_Binary ........................................................................................ Hints for Zend_Measure_Number ...................................................................................... Roman numbers .............................................................................................................. Zend_Memory ........................................................................................................................... Overview ............................................................................................................................... Introduction .................................................................................................................... Theory of Operation ........................................................................................................ Memory Manager .................................................................................................................... Creating a Memory Manager ............................................................................................. Managing Memory Objects ............................................................................................... Memory Manager Settings ................................................................................................ Memory Objects ..................................................................................................................... Movable ........................................................................................................................ Locked .......................................................................................................................... Memory container 'value' property ..................................................................................... Memory container interface .............................................................................................. Zend_Mime .............................................................................................................................. Zend_Mime ............................................................................................................................ Introduction .................................................................................................................... Static Methods and Constants ............................................................................................ Instantiating Zend_Mime .................................................................................................. Zend_Mime_Message .............................................................................................................. Introduction .................................................................................................................... Instantiation ................................................................................................................... Adding MIME Parts ........................................................................................................ Boundary handling .......................................................................................................... parsing a string to create a Zend_Mime_Message object (experimental) ..................................... Zend_Mime_Part ..................................................................................................................... Introduction .................................................................................................................... Instantiation ................................................................................................................... Methods for rendering the message part to a string ................................................................ Zend_Navigation ....................................................................................................................... Introduction ............................................................................................................................ Pages and Containers ....................................................................................................... Separation of data (model) and rendering (view) ................................................................... Pages .................................................................................................................................... Common page features ..................................................................................................... Zend_Navigation_Page_Mvc ............................................................................................. Zend_Navigation_Page_Uri ............................................................................................... Creating custom page types .............................................................................................. Creating pages using the page factory ................................................................................. Containers .............................................................................................................................. Creating containers .......................................................................................................... Adding pages ................................................................................................................. Removing pages ............................................................................................................. Finding pages ................................................................................................................. Iterating containers .......................................................................................................... Other operations ............................................................................................................. Zend_OpenId ............................................................................................................................ Introduction ............................................................................................................................ What is OpenID? ............................................................................................................ How Does it Work? ........................................................................................................ Zend_OpenId Structure .................................................................................................... Supported OpenID Standards ............................................................................................
856 856 856 857 857 857 857 858 858 859 860 861 861 861 861 862 865 865 865 865 865 866 866 866 866 866 866 867 867 867 867 869 869 869 869 869 870 872 875 875 877 878 878 885 886 887 888 889 893 893 893 893 894 894
xviii
Zend_OpenId_Consumer Basics ................................................................................................. OpenID Authentication ..................................................................................................... Combining all Steps in One Page ....................................................................................... Consumer Realm ............................................................................................................. Immediate Check ............................................................................................................ Zend_OpenId_Consumer_Storage ....................................................................................... Simple Registration Extension ........................................................................................... Integration with Zend_Auth .............................................................................................. Integration with Zend_Controller ....................................................................................... Zend_OpenId_Provider ............................................................................................................. Quick Start .................................................................................................................... Combined Provide Scripts ................................................................................................ Simple Registration Extension ........................................................................................... Anything Else? ............................................................................................................... 39. Zend_Paginator .......................................................................................................................... Introduction ............................................................................................................................ Usage .................................................................................................................................... Paginating data collections ................................................................................................ The DbSelect and DbTableSelect adapter ............................................................................ Rendering pages with view scripts ..................................................................................... Configuration ......................................................................................................................... Advanced usage ...................................................................................................................... Custom data source adapters ............................................................................................. Custom scrolling styles .................................................................................................... Caching features ............................................................................................................. Zend_Paginator_AdapterAggregate Interface ........................................................................ 40. Zend_Pdf .................................................................................................................................. Introduccin ........................................................................................................................... Creando y Cargando Documentos PDF ....................................................................................... Guardar Cambios a Documentos PDF ......................................................................................... Trabajando con Pginas ............................................................................................................ Creacin de Pginas ........................................................................................................ Clonado de Pfinas. ......................................................................................................... Dibujo ................................................................................................................................... Geometra ...................................................................................................................... Colores .......................................................................................................................... Dibujo de Formas ........................................................................................................... Dibujo de Texto .............................................................................................................. Uso de Fuentes ............................................................................................................... Limitaciones de las fuentes PDF estndar. ........................................................................... Extraccin de las fuentes. ................................................................................................. Dibujo de Imgenes ......................................................................................................... Estilo de Dibujo de Lneas ............................................................................................... Estilo Relleno ................................................................................................................. Transformaciones Lineales ................................................................................................ Guardar/Restaurar el estado de los grficos. ......................................................................... Sealar el rea de recorte ................................................................................................. Estilos ........................................................................................................................... Transparencia ................................................................................................................. Interactive Features ................................................................................................................. Destinations ................................................................................................................... Actions .......................................................................................................................... Document Outline (bookmarks) ......................................................................................... Annotations ....................................................................................................................
894 894 896 896 897 897 901 903 904 905 905 908 909 910 911 911 911 911 912 913 917 918 918 918 919 920 921 921 921 922 923 923 923 924 924 924 925 927 928 931 931 933 934 934 935 936 937 938 941 941 941 946 948 950
xix
41.
42.
43.
44.
45.
Informacin del Documento y Metadatos. .................................................................................... Ejemplo de Uso del mdulo Zend_Pdf ........................................................................................ Zend_ProgressBar ...................................................................................................................... Zend_ProgressBar ................................................................................................................... Introduction .................................................................................................................... Basic Usage of Zend_Progressbar ...................................................................................... Persistent progress ........................................................................................................... Standard adapters ............................................................................................................ Zend_Queue .............................................................................................................................. Introduction ............................................................................................................................ Ejemplo usage ........................................................................................................................ Framework ............................................................................................................................. Introduction .................................................................................................................... Commonality among adapters ............................................................................................ Adapters ................................................................................................................................ Specific Adapters - Configuration settings ........................................................................... Notes for Specific Adapters .............................................................................................. Customizing Zend_Queue ......................................................................................................... Creating your own adapter ................................................................................................ Creating your own message class ....................................................................................... Creating your own message iterator class ............................................................................ Creating your own queue class ......................................................................................... Stomp ................................................................................................................................... Stomp - Supporting classes ............................................................................................... Zend_Reflection ........................................................................................................................ Introduction ............................................................................................................................ Zend_Reflection Ejemplos ........................................................................................................ Zend_Reflection Reference ....................................................................................................... Zend_Reflection_Docblock ............................................................................................... Zend_Reflection_Docblock_Tag ........................................................................................ Zend_Reflection_Docblock_Tag_Param .............................................................................. Zend_Reflection_Docblock_Tag_Return .............................................................................. Zend_Reflection_File ....................................................................................................... Zend_Reflection_Class ..................................................................................................... Zend_Reflection_Extension ............................................................................................... Zend_Reflection_Function ................................................................................................ Zend_Reflection_Method .................................................................................................. Zend_Reflection_Parameter ............................................................................................... Zend_Reflection_Property ................................................................................................. Zend_Registry ........................................................................................................................... Using the Registry .................................................................................................................. Setting Values in the Registry ........................................................................................... Getting Values from the Registry ....................................................................................... Constructing a Registry Object .......................................................................................... Accessing the Registry as an Array .................................................................................... Accessing the Registry as an Object ................................................................................... Querying if an Index Exists .............................................................................................. Extending the Registry ..................................................................................................... Unsetting the Static Registry ............................................................................................. Zend_Rest ................................................................................................................................ Introduction ............................................................................................................................ Zend_Rest_Client .................................................................................................................... Introduction .................................................................................................................... Responses ......................................................................................................................
951 953 959 959 959 959 959 959 963 963 963 964 965 965 965 966 968 970 970 971 972 972 972 972 973 973 973 975 975 975 976 976 976 976 977 977 977 977 978 979 979 979 979 979 980 980 981 981 982 983 983 983 983 983
xx
Request Arguments ......................................................................................................... 985 Zend_Rest_Server ................................................................................................................... 985 Introduction .................................................................................................................... 985 REST Server Usage ......................................................................................................... 986 Calling a Zend_Rest_Server Service ................................................................................... 986 Sending A Custom Status ................................................................................................. 986 Returning Custom XML Responses .................................................................................... 987 46. Zend_Search_Lucene .................................................................................................................. 989 Overview ............................................................................................................................... 989 Introduction .................................................................................................................... 989 Document and Field Objects ............................................................................................. 989 Understanding Field Types ............................................................................................... 990 HTML documents ........................................................................................................... 991 Word 2007 documents ..................................................................................................... 992 Powerpoint 2007 documents .............................................................................................. 993 Excel 2007 documents ..................................................................................................... 994 Building Indexes ..................................................................................................................... 995 Creating a New Index ...................................................................................................... 995 Updating Index ............................................................................................................... 995 Updating Documents ....................................................................................................... 996 Retrieving Index Size ...................................................................................................... 996 Index optimization ........................................................................................................... 997 Permissions .................................................................................................................... 998 Limitations ..................................................................................................................... 998 Searching an Index .................................................................................................................. 999 Building Queries ............................................................................................................. 999 Search Results .............................................................................................................. 1000 Limiting the Result Set ................................................................................................... 1001 Results Scoring ............................................................................................................. 1001 Search Result Sorting ..................................................................................................... 1002 Search Results Highlighting ............................................................................................ 1002 Query Language .................................................................................................................... 1004 Terms .......................................................................................................................... 1005 Fields .......................................................................................................................... 1005 Wildcards ..................................................................................................................... 1006 Term Modifiers ............................................................................................................. 1006 Range Searches ............................................................................................................. 1006 Fuzzy Searches ............................................................................................................. 1007 Matched terms limitation ................................................................................................ 1007 Proximity Searches ........................................................................................................ 1007 Boosting a Term ........................................................................................................... 1007 Boolean Operators ......................................................................................................... 1008 Grouping ...................................................................................................................... 1009 Field Grouping .............................................................................................................. 1009 Escaping Special Characters ............................................................................................ 1010 Query Construction API ......................................................................................................... 1010 Query Parser Exceptions ................................................................................................. 1010 Term Query .................................................................................................................. 1011 Multi-Term Query ......................................................................................................... 1011 Boolean Query .............................................................................................................. 1012 Wildcard Query ............................................................................................................. 1014 Fuzzy Query ................................................................................................................. 1014 Phrase Query ................................................................................................................ 1015 Range Query ................................................................................................................ 1017
xxi
Character Set ........................................................................................................................ UTF-8 and single-byte character set support ....................................................................... Default text analyzer ...................................................................................................... UTF-8 compatible text analyzers ...................................................................................... Extensibility ......................................................................................................................... Text Analysis ................................................................................................................ Tokens Filtering ............................................................................................................ Scoring Algorithms ........................................................................................................ Storage Containers ......................................................................................................... Interoperating with Java Lucene ............................................................................................... File Formats ................................................................................................................. Index Directory ............................................................................................................. Java Source Code .......................................................................................................... Advanced ............................................................................................................................. Starting from 1.6, handling index format transformations ...................................................... Using the index as static property ..................................................................................... Best Practices ....................................................................................................................... Field names .................................................................................................................. Indexing performance ..................................................................................................... Index during Shut Down ................................................................................................. Retrieving documents by unique id ................................................................................... Memory Usage ............................................................................................................. Encoding ...................................................................................................................... Index maintenance ......................................................................................................... 47. Zend_Server ............................................................................................................................ Introduction .......................................................................................................................... Zend_Server_Reflection .......................................................................................................... Introduction .................................................................................................................. Usage .......................................................................................................................... 48. Zend_Service ........................................................................................................................... Introduction .......................................................................................................................... Zend_Service_Akismet ........................................................................................................... Introduction .................................................................................................................. Verify an API key ......................................................................................................... Check for spam ............................................................................................................. Submitting known spam ................................................................................................. Submitting false positives (ham) ...................................................................................... Zend-specific Methods ................................................................................................... Zend_Service_Amazon ........................................................................................................... Introduction .................................................................................................................. Country Codes .............................................................................................................. Looking up a Specific Amazon Item by ASIN .................................................................... Performing Amazon Item Searches ................................................................................... Using the Alternative Query API ..................................................................................... Zend_Service_Amazon Classes ........................................................................................ Zend_Service_Amazon_Ec2 .................................................................................................... Introduction .................................................................................................................. What is Amazon Ec2? .................................................................................................... Static Methods .............................................................................................................. Zend_Service_Amazon_Ec2: Instances ...................................................................................... Instance Types .............................................................................................................. Running Amazon EC2 Instances ...................................................................................... Amazon Instance Utilities ............................................................................................... Zend_Service_Amazon_Ec2: Windows Instances ........................................................................
1018 1018 1018 1019 1020 1020 1022 1023 1024 1027 1027 1027 1027 1028 1028 1029 1030 1030 1031 1032 1033 1034 1034 1035 1037 1037 1037 1037 1037 1039 1039 1039 1039 1039 1040 1041 1041 1042 1042 1042 1043 1043 1044 1045 1045 1050 1050 1050 1050 1051 1051 1052 1054 1055
xxii
Windows Instances Usage ............................................................................................... Zend_Service_Amazon_Ec2: Reserved Instances ......................................................................... How Reserved Instances are Applied ................................................................................ Reserved Instances Usage ............................................................................................... Zend_Service_Amazon_Ec2: CloudWatch Monitoring ................................................................. CloudWatch Usage ........................................................................................................ Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI) ...................................................... AMI Information Utilities ............................................................................................... AMI Attribute Utilities ................................................................................................... Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS) ............................................................ Create EBS Volumes and Snapshots ................................................................................. Describing EBS Volumes and Snapshots ........................................................................... Attach and Detaching Volumes from Instances ................................................................... Deleting EBS Volumes and Snapshots .............................................................................. Zend_Service_Amazon_Ec2: Elastic IP Addresses ....................................................................... Zend_Service_Amazon_Ec2: Keypairs ...................................................................................... Zend_Service_Amazon_Ec2: Regions and Availability Zones ........................................................ Amazon EC2 Regions .................................................................................................... Amazon EC2 Availability Zones ...................................................................................... Zend_Service_Amazon_Ec2: Security Groups ............................................................................ Security Group Maintenance ............................................................................................ Authorizing Access ........................................................................................................ Revoking Access ........................................................................................................... Zend_Service_Amazon_S3 ...................................................................................................... Introduction .................................................................................................................. Registering with Amazon S3 ........................................................................................... API Documentation ....................................................................................................... Features ....................................................................................................................... Getting Started .............................................................................................................. Bucket operations .......................................................................................................... Object operations ........................................................................................................... Stream wrapper ............................................................................................................. Zend_Service_Amazon_Sqs ..................................................................................................... Introduction .................................................................................................................. Registering with Amazon SQS ......................................................................................... API Documentation ....................................................................................................... Features ....................................................................................................................... Getting Started .............................................................................................................. Queue operations ........................................................................................................... Message operations ........................................................................................................ Zend_Service_Audioscrobbler .................................................................................................. Introduction .................................................................................................................. Users ........................................................................................................................... Artists .......................................................................................................................... Tracks ......................................................................................................................... Tags ............................................................................................................................ Groups ......................................................................................................................... Forums ........................................................................................................................ Zend_Service_Delicious .......................................................................................................... Introduction .................................................................................................................. Retrieving posts ............................................................................................................ Zend_Service_Delicious_PostList ..................................................................................... Editing posts ................................................................................................................. Deleting posts ...............................................................................................................
1056 1057 1057 1058 1058 1059 1060 1060 1061 1062 1062 1063 1064 1064 1065 1066 1067 1067 1068 1068 1068 1069 1070 1071 1071 1071 1071 1071 1071 1072 1073 1074 1075 1075 1075 1075 1075 1076 1076 1077 1078 1078 1078 1080 1080 1081 1081 1081 1082 1082 1082 1083 1084 1084
xxiii
Adding new posts .......................................................................................................... Tags ............................................................................................................................ Bundles ....................................................................................................................... Public data ................................................................................................................... HTTP client .................................................................................................................. Zend_Service_Flickr .............................................................................................................. Introduction .................................................................................................................. Finding Flickr Users' Photos and Information ..................................................................... Finding photos From a Group Pool ................................................................................... Retrieving Flickr Image Details ....................................................................................... Zend_Service_Flickr Result Classes .................................................................................. Zend_Service_Nirvanix ........................................................................................................... Introduction .................................................................................................................. Registering with Nirvanix ............................................................................................... API Documentation ....................................................................................................... Features ....................................................................................................................... Getting Started .............................................................................................................. Understanding the Proxy ................................................................................................. Examining Results ......................................................................................................... Handling Errors ............................................................................................................. Zend_Service_ReCaptcha ........................................................................................................ Introduction .................................................................................................................. Simplest use ................................................................................................................. Hiding email addresses ................................................................................................... Zend_Service_Simpy .............................................................................................................. Introduction .................................................................................................................. Links ........................................................................................................................... Tags ............................................................................................................................ Notes ........................................................................................................................... Watchlists .................................................................................................................... Introduction .......................................................................................................................... Getting Started with Zend_Service_SlideShare .................................................................... The SlideShow object .................................................................................................... Retrieving a single slide show ......................................................................................... Retrieving Groups of Slide Shows .................................................................................... Zend_Service_SlideShare Caching policies ........................................................................ Changing the behavior of the HTTP Client ........................................................................ Zend_Service_StrikeIron ......................................................................................................... Overview ..................................................................................................................... Registering with StrikeIron .............................................................................................. Getting Started .............................................................................................................. Making Your First Query ................................................................................................ Examining Results ......................................................................................................... Handling Errors ............................................................................................................. Checking Your Subscription ............................................................................................ Zend_Service_StrikeIron: Bundled Services ............................................................................... ZIP Code Information .................................................................................................... U.S. Address Verification ............................................................................................... Sales & Use Tax Basic ................................................................................................... Zend_Service_StrikeIron: Advanced Uses .................................................................................. Using Services by WSDL ............................................................................................... Viewing SOAP Transactions ........................................................................................... Zend_Service_Technorati ........................................................................................................ Introduction ..................................................................................................................
1085 1085 1085 1086 1086 1087 1087 1087 1088 1088 1089 1090 1090 1091 1091 1091 1091 1092 1093 1093 1094 1094 1094 1095 1097 1097 1097 1099 1099 1100 1101 1101 1102 1104 1105 1106 1106 1106 1107 1107 1107 1108 1108 1109 1110 1110 1111 1111 1112 1113 1113 1113 1114 1114
xxiv
Getting Started .............................................................................................................. Making Your First Query ................................................................................................ Consuming Results ........................................................................................................ Handling Errors ............................................................................................................. Checking Your API Key Daily Usage ............................................................................... Available Technorati Queries ........................................................................................... Zend_Service_Technorati Classes ..................................................................................... Zend_Service_Twitter ............................................................................................................. Introduction .................................................................................................................. Authentication ............................................................................................................... Account Methods .......................................................................................................... Status Methods ............................................................................................................. User Methods ............................................................................................................... Direct Message Methods ................................................................................................. Friendship Methods ....................................................................................................... Favorite Methods ........................................................................................................... Block Methods .............................................................................................................. Zend_Service_Twitter_Search .......................................................................................... Zend_Service_Yahoo ............................................................................................................. Introduction .................................................................................................................. Searching the Web with Yahoo! ....................................................................................... Finding Images with Yahoo! ........................................................................................... Finding videos with Yahoo! ............................................................................................ Finding Local Businesses and Services with Yahoo! ............................................................ Searching Yahoo! News ................................................................................................. Searching Yahoo! Site Explorer Inbound Links ................................................................... Searching Yahoo! Site Explorer's PageData ........................................................................ Zend_Service_Yahoo Classes .......................................................................................... 49. Zend_Session .......................................................................................................................... Introduction .......................................................................................................................... Basic Usage .......................................................................................................................... Tutorial Ejemplos .......................................................................................................... Iterating Over Session Namespaces ................................................................................... Accessors for Session Namespaces ................................................................................... Advanced Usage ................................................................................................................... Starting a Session .......................................................................................................... Locking Session Namespaces .......................................................................................... Namespace Expiration .................................................................................................... Session Encapsulation and Controllers ............................................................................... Preventing Multiple Instances per Namespace ..................................................................... Working with Arrays ..................................................................................................... Using Sessions with Objects ............................................................................................ Using Sessions with Unit Tests ........................................................................................ Global Session Management .................................................................................................... Configuration Options .................................................................................................... Error: Headers Already Sent ............................................................................................ Session Identifiers ......................................................................................................... rememberMe(integer $seconds) ........................................................................................ forgetMe() .................................................................................................................... sessionExists() .............................................................................................................. destroy(bool $remove_cookie = true, bool $readonly = true) .................................................. stop() ........................................................................................................................... writeClose($readonly = true) ........................................................................................... expireSessionCookie() ....................................................................................................
1114 1115 1115 1117 1117 1118 1121 1124 1124 1125 1125 1126 1128 1128 1129 1130 1130 1131 1133 1133 1133 1133 1134 1134 1134 1134 1135 1135 1143 1143 1143 1144 1145 1145 1145 1145 1146 1147 1147 1148 1149 1150 1150 1151 1151 1154 1154 1156 1156 1156 1156 1156 1156 1157
xxv
50.
51.
52.
53.
54.
setSaveHandler(Zend_Session_SaveHandler_Interface $interface) .......................................... namespaceIsset($namespace) ........................................................................................... namespaceUnset($namespace) .......................................................................................... namespaceGet($namespace) ............................................................................................. getIterator() .................................................................................................................. Zend_Session_SaveHandler_DbTable ........................................................................................ Zend_Soap .............................................................................................................................. Zend_Soap_Server ................................................................................................................. Zend_Soap_Server constructor ......................................................................................... Methods to define Web Service API ................................................................................. Request and response objects handling .............................................................................. Zend_Soap_Client ................................................................................................................. Zend_Soap_Client Constructor ......................................................................................... Performing SOAP Requests ............................................................................................. WSDL Accessor .................................................................................................................... Zend_Soap_Wsdl constructor ........................................................................................... addMessage() method ..................................................................................................... addPortType() method .................................................................................................... addPortOperation() method .............................................................................................. addBinding() method ...................................................................................................... addBindingOperation() method ........................................................................................ addSoapBinding() method ............................................................................................... addSoapOperation() method ............................................................................................ addService() method ...................................................................................................... Type mapping ............................................................................................................... addDocumentation() method ............................................................................................ Get finalized WSDL document ........................................................................................ AutoDiscovery ...................................................................................................................... AutoDiscovery Introduction ............................................................................................. Class autodiscovering ..................................................................................................... Functions autodiscovering ............................................................................................... Autodiscovering Datatypes .............................................................................................. WSDL Binding Styles .................................................................................................... Zend_Tag ............................................................................................................................... Introduction .......................................................................................................................... Zend_Tag_Cloud ................................................................................................................... Decorators .................................................................................................................... Zend_Test ............................................................................................................................... Introduccin ......................................................................................................................... Zend_Test_PHPUnit ............................................................................................................... Bootstrapping your TestCase ........................................................................................... Testing your Controllers and MVC Applications ................................................................. Assertions .................................................................................................................... Ejemplos ...................................................................................................................... Zend_Test_PHPUnit_Db ......................................................................................................... Quickstart ..................................................................................................................... Usage, API and Extensions Points .................................................................................... Using the Database Testing Adapter ................................................................................. Zend_Text .............................................................................................................................. Zend_Text_Figlet .................................................................................................................. Zend_Text_Table ................................................................................................................... Zend_TimeSync ....................................................................................................................... Introduction .......................................................................................................................... Why Zend_TimeSync ? ..................................................................................................
1157 1157 1157 1157 1158 1158 1161 1161 1161 1162 1163 1165 1165 1166 1167 1167 1167 1168 1168 1169 1169 1169 1169 1169 1170 1171 1172 1172 1172 1173 1174 1175 1175 1177 1177 1177 1178 1181 1181 1181 1182 1184 1186 1188 1192 1193 1197 1199 1201 1201 1202 1205 1205 1205
xxvi
What is NTP ? .............................................................................................................. What is SNTP? ............................................................................................................. Problematic usage .......................................................................................................... Decide which server to use ............................................................................................. Working with Zend_TimeSync ................................................................................................ Generic Time Server Request .......................................................................................... Multiple Time Servers .................................................................................................... Protocols of Time Servers ............................................................................................... Using Ports for Time Servers .......................................................................................... Time Servers Options ..................................................................................................... Using Different Time Servers .......................................................................................... Information from Time Servers ........................................................................................ Handling Exceptions ...................................................................................................... 55. Zend_Tool_Framework ............................................................................................................. Introduction .......................................................................................................................... Usando la herramienta CLI ..................................................................................................... Architecture .......................................................................................................................... Registry ....................................................................................................................... Providers ...................................................................................................................... Loaders ........................................................................................................................ Manifests ..................................................................................................................... Clients ......................................................................................................................... Creando Proveedores para usar con Zend_Tool_Framework .......................................................... Shipped System Providers ....................................................................................................... The Version Provider ..................................................................................................... The Manifest Provider .................................................................................................... Extending and Configuring Zend_Tool_Framework ..................................................................... Customizing Zend_Tool Console Client ............................................................................. 56. Zend_Tool_Project ................................................................................................................... Introduction .......................................................................................................................... Create A Project .................................................................................................................... Zend Tool Project Providers .................................................................................................... 57. Zend_Translate ........................................................................................................................ Introduction .......................................................................................................................... Starting multi-lingual ..................................................................................................... Adapters for Zend_Translate ................................................................................................... How to decide which translation adapter to use ................................................................... Integrate self written Adapters ......................................................................................... Speedup all Adapters ..................................................................................................... Using Translation Adapters ..................................................................................................... Translation Source Structures .......................................................................................... Creating source files .............................................................................................................. Creating Array source files .............................................................................................. Creating Gettext source files ............................................................................................ Creating TMX source files .............................................................................................. Creating CSV source files ............................................................................................... Creating INI source files ................................................................................................. Additional features for translation ............................................................................................. Options for adapters ....................................................................................................... Handling languages ........................................................................................................ Automatic source detection ............................................................................................. Checking for translations ................................................................................................ How to log not found translations .................................................................................... Accessing source data ....................................................................................................
1205 1206 1206 1206 1206 1206 1207 1207 1208 1208 1209 1209 1209 1211 1211 1211 1212 1212 1212 1213 1214 1216 1217 1217 1217 1217 1218 1218 1221 1221 1221 1222 1223 1223 1223 1224 1224 1226 1227 1227 1229 1230 1231 1231 1232 1233 1233 1234 1234 1236 1238 1241 1242 1243
xxvii
58.
59.
60. 61.
Plural notations for Translation ................................................................................................ Traditional plural translations .......................................................................................... Modern plural translations ............................................................................................... Plural source files .......................................................................................................... Zend_Uri ................................................................................................................................ Zend_Uri ............................................................................................................................. Overview ..................................................................................................................... Creating a New URI ...................................................................................................... Manipulating an Existing URI ......................................................................................... URI Validation ............................................................................................................. Common Instance Methods ............................................................................................. Zend_Validate ......................................................................................................................... Introduccin ......................................................................................................................... Qu es un validador? .................................................................................................... Uso bsico de validadores ............................................................................................... Personalizar los mensajes ................................................................................................ Utilizando el mtodo esttico is() ................................................................................. Translating messages ...................................................................................................... Clases de Validacin Estndar ................................................................................................. Alnum ......................................................................................................................... Alpha .......................................................................................................................... Barcode ....................................................................................................................... Between ....................................................................................................................... Ccnum ......................................................................................................................... Date ............................................................................................................................ Db_RecordExists and Db_NoRecordExists ......................................................................... Digits .......................................................................................................................... Direccin de Email ........................................................................................................ Float ............................................................................................................................ GreaterThan .................................................................................................................. Hex ............................................................................................................................. Hostname (Nombre de Host) ........................................................................................... Iban ............................................................................................................................ InArray ........................................................................................................................ Int ............................................................................................................................... Ip ................................................................................................................................ LessThan ..................................................................................................................... NotEmpty ..................................................................................................................... Regex .......................................................................................................................... Sitemap Validators ......................................................................................................... StringLength ................................................................................................................. Cadenas de Validadores .......................................................................................................... Escribiendo Validadores ......................................................................................................... Validation Messages .............................................................................................................. Limit the size of a validation message ............................................................................... Zend_Version .......................................................................................................................... Getting the Zend Framework Version ....................................................................................... Zend_View ............................................................................................................................. Introduction .......................................................................................................................... Controller Script ............................................................................................................ View Script .................................................................................................................. Options ........................................................................................................................ Short Tags with View Scripts .......................................................................................... Utility Accessors ...........................................................................................................
1243 1244 1244 1245 1247 1247 1247 1247 1247 1248 1248 1251 1251 1251 1251 1252 1253 1253 1254 1254 1254 1255 1255 1255 1255 1255 1258 1258 1260 1260 1260 1260 1262 1263 1263 1263 1263 1263 1263 1263 1264 1264 1265 1269 1274 1275 1275 1277 1277 1277 1277 1278 1279 1279
xxviii
Controller Scripts .................................................................................................................. Assigning Variables ....................................................................................................... Rendering a View Script ................................................................................................. View Script Paths .......................................................................................................... View Scripts ......................................................................................................................... Escaping Output ............................................................................................................ Using Alternate Template Systems ................................................................................... View Helpers ........................................................................................................................ Initial Helpers ............................................................................................................... Helper Paths ................................................................................................................. Writing Custom Helpers ................................................................................................. Zend_View_Abstract .............................................................................................................. 62. Zend_Wildfire ......................................................................................................................... Zend_Wildfire ....................................................................................................................... 63. Zend_XmlRpc ......................................................................................................................... Introduction .......................................................................................................................... Zend_XmlRpc_Client ............................................................................................................. Introducin ................................................................................................................... Method Calls ................................................................................................................ Tipos y Conversiones ..................................................................................................... Server Proxy Object ....................................................................................................... Error Handling .............................................................................................................. Server Introspection ....................................................................................................... From Request to Response .............................................................................................. HTTP Client and Testing ................................................................................................ Zend_XmlRpc_Server ............................................................................................................ Introduction .................................................................................................................. Basic Usage .................................................................................................................. Server Structure ............................................................................................................ Conventions .................................................................................................................. Utilizing Namespaces ..................................................................................................... Custom Request Objects ................................................................................................. Custom Responses ......................................................................................................... Handling Exceptions via Faults ........................................................................................ Caching Server Definitions Between Requests .................................................................... Usage Ejemplos ............................................................................................................ A. Requisitos de Zend Framework ................................................................................................... Versin de PHP .................................................................................................................... Extensiones de PHP ............................................................................................................... Componentes de Zend Framework ............................................................................................ Dependencias de Zend Framework ........................................................................................... B. Notas de Migracin de Zend Framework ....................................................................................... Zend Framework 1.10 ............................................................................................................ Zend_File_Transfer ........................................................................................................ Zend_Validate ............................................................................................................... Zend Framework 1.9 .............................................................................................................. Zend_File_Transfer ........................................................................................................ Zend_Filter ................................................................................................................... Zend_Http_Client .......................................................................................................... Zend_Locale ................................................................................................................. Zend_View_Helper_Navigation ........................................................................................ Zend Framework 1.8 .............................................................................................................. Zend_Controller ............................................................................................................ Zend_Locale .................................................................................................................
1280 1280 1281 1281 1282 1282 1283 1289 1290 1338 1338 1340 1341 1341 1343 1343 1343 1343 1343 1344 1345 1346 1347 1347 1348 1348 1348 1348 1348 1349 1350 1350 1350 1350 1351 1351 1355 1355 1355 1363 1371 1380 1380 1380 1380 1381 1381 1382 1382 1383 1384 1385 1385 1385
xxix
Zend Framework 1.7 .............................................................................................................. Zend_Controller ............................................................................................................ Zend_File_Transfer ........................................................................................................ Zend_Locale ................................................................................................................. Zend_Translate .............................................................................................................. Zend_View ................................................................................................................... Zend Framework 1.6 .............................................................................................................. Zend_Controller ............................................................................................................ Zend_File_Transfer ........................................................................................................ Zend Framework 1.5 .............................................................................................................. Zend_Controller ............................................................................................................ Zend Framework 1.0 .............................................................................................................. Zend_Controller ............................................................................................................ Zend_Currency .............................................................................................................. Zend Framework 0.9 .............................................................................................................. Zend_Controller ............................................................................................................ Zend Framework 0.8 .............................................................................................................. Zend_Controller ............................................................................................................ Zend Framework 0.6 .............................................................................................................. Zend_Controller ............................................................................................................ C. Estndares de codificacin de Zend Framework para PHP ................................................................ Introduccin ......................................................................................................................... Alcance ....................................................................................................................... Objetivos ..................................................................................................................... Formato de archivos PHP ....................................................................................................... General ........................................................................................................................ Identacin .................................................................................................................... Tamao mximo de lnea ................................................................................................ Final de lnea ................................................................................................................ Convenciones de Nombres ...................................................................................................... Clases .......................................................................................................................... Clases Abstractas ......................................................................................................... Interfaces ..................................................................................................................... Nombres de Archivo ...................................................................................................... Funciones y Mtodos ..................................................................................................... Variables ...................................................................................................................... Constantes .................................................................................................................... Estilo de cdigo .................................................................................................................... Demarcacin de cdigo PHP ........................................................................................... Cadenas de Caracteres ................................................................................................... Arrays ......................................................................................................................... Clases .......................................................................................................................... Funciones y Mtodos ..................................................................................................... Sentencias de Control ..................................................................................................... Documentacin integrada ................................................................................................ D. Zend Framework Documentation Standard ..................................................................................... Overview ............................................................................................................................. Scope .......................................................................................................................... Documentation File Formatting ................................................................................................ XML Tags ................................................................................................................... Maximum Line Length ................................................................................................... Indentation ................................................................................................................... Line Termination ........................................................................................................... Empty tags ...................................................................................................................
1385 1385 1386 1389 1390 1391 1392 1392 1392 1393 1393 1394 1394 1396 1396 1396 1397 1397 1397 1398 1401 1401 1401 1401 1401 1401 1402 1402 1402 1402 1402 1402 1403 1403 1403 1404 1404 1405 1405 1405 1406 1407 1408 1411 1412 1415 1415 1415 1415 1415 1415 1415 1416 1416
xxx
Usage of whitespace within documents .............................................................................. Program Listings ........................................................................................................... Notes on specific inline tags ............................................................................................ Notes on specific block tags ............................................................................................ Recommendations .................................................................................................................. Use editors without autoformatting ................................................................................... Use Images .................................................................................................................. Use Case Ejemplos ........................................................................................................ Avoid Replicating phpdoc Contents .................................................................................. Use Links .................................................................................................................... E. Recommended Project Structure for Zend Framework MVC Applications ............................................ Overview ............................................................................................................................. Recommended Project Directory Structure ................................................................................. Module Structure ................................................................................................................... Rewrite Configuration Guide ................................................................................................... Apache HTTP Server ..................................................................................................... Microsoft Internet Information Server ............................................................................... F. Gua de Rendimiento de Zend Framework ..................................................................................... Introduction .......................................................................................................................... Class Loading ....................................................................................................................... How can I optimize my include_path? .............................................................................. How can I eliminate unnecessary require_once statements? ................................................... How can I speed up plugin loading? ................................................................................. Zend_Db Performance ............................................................................................................ How can I reduce overhead introduced by Zend_Db_Table for retrieving table metadata? ............ SQL generated with Zend_Db_Select s not hitting my indexes; how can I make it better? ............ Internationalization (i18n) and Localization (l10n) ....................................................................... Which translation adapter should I use? ............................................................................. How can I make translation and localization even faster? ...................................................... View Rendering .................................................................................................................... How can I speed up resolution of view helpers? .................................................................. How can I speed up view partials? ................................................................................... How can I speed up calls to the action() view helper? .......................................................... G. Copyright Information ................................................................................................................ Index ...........................................................................................................................................
1416 1419 1420 1421 1422 1422 1422 1422 1422 1422 1424 1424 1424 1426 1426 1426 1427 1429 1429 1429 1429 1431 1431 1432 1432 1433 1433 1433 1434 1434 1434 1435 1436 1439 1440
xxxi
Lista de tablas
2.1. Controles de Acceso para un CMS de ejemplo .................................................................................. 5 4.1. Zend_Application options ............................................................................................................. 39 4.2. Mtodos de Zend_Application ...................................................................................................... 40 4.3. Zend_Application_Bootstrap_Bootstrapper Interface ......................................................................... 42 4.4. Zend_Application_Bootstrap_ResourceBootstrapper Interface ............................................................. 43 4.5. Mtodos de Zend_Application_Bootstrap_BootstrapAbstract ............................................................... 44 4.6. Zend_Application_Resource_Resource Interface ............................................................................... 47 4.7. Zend_Application_Resource_ResourceAbstract Methods .................................................................... 47 5.1. Opciones de Configuracin ........................................................................................................... 69 5.2. Server Options ........................................................................................................................... 75 5.3. Debugging Messages ................................................................................................................... 77 5.4. Options for Active Directory ........................................................................................................ 78 5.5. Options for OpenLDAP ............................................................................................................... 79 6.1. Core Frontend Options ................................................................................................................ 87 6.2. Function Frontend Options ........................................................................................................... 91 6.3. Class Frontend Options ................................................................................................................ 92 6.4. File Frontend Options .................................................................................................................. 93 6.5. Page Frontend Options ................................................................................................................ 94 6.6. File Backend Options .................................................................................................................. 98 6.7. Sqlite Backend Options ............................................................................................................... 99 6.8. Memcached Backend Options ..................................................................................................... 100 6.9. Xcache Backend Options ............................................................................................................ 101 6.10. TwoLevels Backend Options ..................................................................................................... 102 9.1. Parmetros del constructor Zend_Config_Ini .................................................................................. 128 13.1. Constants for the selecting the currency description ....................................................................... 240 13.2. Constants for the selecting the position of the currency description ................................................... 240 14.1. Date Parts .............................................................................................................................. 252 14.2. Basic Operations ..................................................................................................................... 253 14.3. Date Comparison Methods ........................................................................................................ 254 14.4. Date Output Methods ............................................................................................................... 255 14.5. Date Output Methods ............................................................................................................... 256 14.6. Miscellaneous Methods ............................................................................................................ 257 14.7. Operations Involving Zend_Date::HOUR ..................................................................................... 259 14.8. Day Constants ........................................................................................................................ 259 14.9. Week Constants ...................................................................................................................... 260 14.10. Month Constants ................................................................................................................... 260 14.11. Year Constants ...................................................................................................................... 260 14.12. Time Constants ..................................................................................................................... 261 14.13. Timezone Constants ............................................................................................................... 261 14.14. Date Format Constants (formats include timezone) ...................................................................... 261 14.15. Date and Time Formats (format varies by locale) ........................................................................ 262 14.16. Constants for ISO 8601 Date Output ......................................................................................... 263 14.17. Constants for PHP Date Output ................................................................................................ 266 14.18. Types of Supported Horizons for Sunset and Sunrise .................................................................... 270 15.1. Metadata Fields Returned by describeTable() ............................................................................... 289 15.2. Constantes usedas por getPart() y reset() ..................................................................................... 318 20.1. Feed Level API Methods .......................................................................................................... 441 20.2. Extended Feed Level API Methods ............................................................................................. 442 20.3. Entry Level API Methods ......................................................................................................... 443 20.4. Extended Entry Level API Methods ............................................................................................ 444 20.5. Core Extensions (pre-registered) ................................................................................................ 445
xxxii
20.6. Non-Core Extensions (must register manually) ............................................................................. 445 21.1. Different notations of the rename filter and their meaning ............................................................... 473 24.1. Metadata used in the code-sample below ..................................................................................... 659 25.1. Zend_Http_Client configuration parameters .................................................................................. 665 25.2. Zend_Http_Client_Adapter_Socket configuration parameters ........................................................... 673 25.3. Zend_Http_Client configuration parameters .................................................................................. 676 29.1. Options for accountCanonicalForm ............................................................................................. 720 29.2. Zend_Ldap Options ................................................................................................................. 722 29.3. Zend_Ldap API ...................................................................................................................... 724 29.4. Zend_Ldap_Collection API ....................................................................................................... 729 29.5. Zend_Ldap_Attribute API ......................................................................................................... 730 29.6. Zend_Ldap_Dn API ................................................................................................................. 731 29.7. Zend_Ldap_Filter API .............................................................................................................. 733 29.8. Zend_Ldap_Node API .............................................................................................................. 735 29.9. Zend_Ldap_Node_RootDse API ................................................................................................ 738 29.10. Zend_Ldap_Node_RootDse_OpenLdap API ............................................................................... 740 29.11. Zend_Ldap_Node_RootDse_ActiveDirectory API ........................................................................ 741 29.12. Zend_Ldap_Node_RootDse_eDirectory API ............................................................................... 742 29.13. Zend_Ldap_Node_Schema API ................................................................................................ 742 29.14. Zend_Ldap_Node_Schema_AttributeType_Interface API .............................................................. 743 29.15. Zend_Ldap_Node_Schema_ObjectClass_Interface API ................................................................. 744 29.16. Zend_Ldap_Node_Schema_Item API ........................................................................................ 744 29.17. Zend_Ldap_Node_Schema_OpenLDAP API ............................................................................... 744 29.18. Zend_Ldap_Node_Schema_AttributeType_OpenLDAP API .......................................................... 745 29.19. Zend_Ldap_Node_Schema_ObjectClass_OpenLDAP API ............................................................. 745 29.20. Zend_Ldap_Node_Schema_AttributeType_ActiveDirectory API ..................................................... 745 29.21. Zend_Ldap_Node_Schema_ObjectClass_ActiveDirectory API ....................................................... 745 29.22. Zend_Ldif_Encoder API ......................................................................................................... 745 30.1. Zend_Loader_Autoloader Methods ............................................................................................. 760 31.1. Details for getTranslationList($type = null, $locale = null, $value = null) ........................................... 777 31.2. Details for getTranslation($value = null, $type = null, $locale = null) ................................................ 783 31.3. Differences between Zend Framework 1.0 and 1.5 ......................................................................... 788 31.4. Format tokens for self generated number formats ......................................................................... 794 31.5. Key values for getDate() with option 'fix_date' ............................................................................. 798 31.6. Return values .......................................................................................................................... 798 31.7. Format definition ..................................................................................................................... 800 31.8. Ejemplo formats ...................................................................................................................... 801 31.9. List of all supported languages .................................................................................................. 803 32.1. Firebug Logging Styles ............................................................................................................ 820 33.1. Mail Read Feature Overview ..................................................................................................... 836 33.2. Mail Folder Names .................................................................................................................. 842 34.1. List of measurement types ........................................................................................................ 854 37.1. Common page options .............................................................................................................. 870 37.2. MVC page options .................................................................................................................. 872 37.3. URI page options .................................................................................................................... 875 39.1. Adapters for Zend_Paginator ..................................................................................................... 911 39.2. Scrolling styles for Zend_Paginator ............................................................................................ 914 39.3. Properties available to view partials ............................................................................................ 917 39.4. Configuration methods for Zend_Paginator .................................................................................. 918 46.1. Zend_Search_Lucene_Field Types .............................................................................................. 991 48.1. Zend_Service_Amazon_Item Properties ..................................................................................... 1046 48.2. Zend_Service_Amazon_Image Properties ................................................................................... 1047 48.3. Zend_Service_Amazon_OfferSet Properties ................................................................................ 1047 48.4. Properties ............................................................................................................................. 1048
xxxiii
48.5. Zend_Service_Amazon_SimilarProduct Properties ....................................................................... 48.6. Zend_Service_Amazon_Accessories Properties ........................................................................... 48.7. Zend_Service_Amazon_CustomerReview Properties .................................................................... 48.8. Zend_Service_Amazon_EditorialReview Properties ...................................................................... 48.9. Zend_Service_Amazon_Listmania Properties .............................................................................. 48.10. Available Instance Types ....................................................................................................... 48.11. Valid Run Options ............................................................................................................... 48.12. Launch permissions fall into three categories ............................................................................ 48.13. Valid Attributes ................................................................................................................... 48.14. Methods for retrieving public data ........................................................................................... 48.15. Methods of the Zend_Service_Delicious_SimplePost class ........................................................... 48.16. Zend_Service_Flickr_ResultSet Properties ................................................................................ 48.17. Zend_Service_Flickr_Result Properties .................................................................................... 48.18. Zend_Service_Flickr_Image Properties ..................................................................................... 48.19. Zend_Service_ReCaptcha_MailHide options ............................................................................. 48.20. Zend_Service_Yahoo_ResultSet .............................................................................................. 48.21. Zend_Service_Yahoo_LocalResultSet Properties ........................................................................ 48.22. Zend_Service_Yahoo_Result Properties ................................................................................... 48.23. Zend_Service_Yahoo_WebResult Properties ............................................................................. 48.24. Zend_Service_Yahoo_ImageResult Properties ........................................................................... 48.25. Zend_Service_Yahoo_VideoResult Properties ........................................................................... 48.26. Zend_Service_Yahoo_LocalResult Properties ............................................................................ 48.27. Zend_Service_Yahoo_NewsResult Properties ............................................................................ 48.28. Zend_Service_Yahoo_Image Properties .................................................................................... 52.1. Zend_Test_PHPUnit_DatabaseTestCase API Methods .................................................................. 56.1. Project Provider Options ......................................................................................................... 56.2. Project Provider Options ......................................................................................................... 57.1. Adapters for Zend_Translate .................................................................................................... 57.2. Options for translation adapters ................................................................................................ 57.3. Plural support ........................................................................................................................ 59.1. Available Validation Messages ................................................................................................. 61.1. Sitemap XML elements .......................................................................................................... 63.1. Tipos de Conversin entre PHP y XML-RPC ............................................................................. 63.2. Zend_XmlRpc_Value Objects for XML-RPC Types ................................................................ A.1. Extensiones de PHP usadas en Zend Framework por Componente ................................................... A.2. Componentes de Zend Framework y las extensiones que usan de PHP .............................................. A.3. Componenetes de Zend Framework y sus dependencias a otros Componenetes de Zend Framework ........ B.1. Changed Validation Messages ................................................................................................... B.2. Available Validation Messages .................................................................................................. B.3. List of measurement types ........................................................................................................
1049 1049 1049 1050 1050 1051 1052 1060 1061 1086 1086 1089 1089 1090 1096 1136 1137 1138 1138 1138 1139 1139 1140 1141 1198 1221 1222 1224 1235 1245 1269 1330 1344 1345 1355 1363 1372 1380 1381 1383
xxxiv
Lista de Ejemplos
2.1. Herencia Mlltiple entre Roles ....................................................................................................... 4 3.1. Servidor AMF bsico .................................................................................................................. 13 3.2. Agregar cabeceras de mensaje a la respuesta de AMF ....................................................................... 17 4.1. Muestra de la Configuracion de Recursos del Adaptador DB (Base de Datos) ........................................ 50 4.2. Ejemplo Front Controller resource configuration .............................................................................. 51 4.3. Recuperar el Front Controller de su arranque (bootstrap) .................................................................... 51 4.4. Sample Layout configuration ........................................................................................................ 51 4.5. Configurando Mdulos ................................................................................................................ 52 4.6. Recuperando el bootstrap de un mdulo especfico ........................................................................... 53 4.7. Sample Navigation resource configuration ....................................................................................... 53 4.8. Sample Router Resource configuration ........................................................................................... 54 4.9. Configuracin de recursos de la Sesin Ejemplo .............................................................................. 54 4.10. Ejemplo de configuracin del recurso Vista ................................................................................... 55 5.1. Modifying the Session Namespace ................................................................................................. 59 5.2. Usando una Clase de Almacenamiento Personalizada ........................................................................ 60 5.3. Uso Bsico ................................................................................................................................ 63 6.1. Obtener un frontend con Zend_Cache::factory() .............................................................................. 83 6.2. Almacenando en cach un resultado de consulta a una base de datos .................................................... 83 6.3. El almacenamiento en cach de salida con la interfaz de salida Zend_Cache ......................................... 84 8.1. Generando clases PHP ............................................................................................................... 111 8.2. Generando clases PHP con propiedades de clase ............................................................................. 112 8.3. Generando clases PHP con mtodos de clase ................................................................................. 113 8.4. Generando archivos PHP ............................................................................................................ 115 8.5. Sembrando la generacin de cdigo para un archivo PHP via reflection ............................................... 117 8.6. Sembrando la generacin de clases PHP via reflection ..................................................................... 117 8.7. Sembrando la generacin de mtodos PHP via reflection .................................................................. 118 9.1. Usando Zend_Config Per Se ....................................................................................................... 125 9.2. Usando Zend_Config con un Archivo de Configuracin PHP ............................................................ 126 9.3. Utilizando Zend_Config_Ini ........................................................................................................ 128 9.4. Usando Zend_Config_Xml ......................................................................................................... 129 9.5. Usando atributos de etiqueta en Zend_Config_Xml ......................................................................... 130 10.1. Using Zend_Config_Writer ....................................................................................................... 133 10.2. Modifying an existing config ..................................................................................................... 134 11.1. Using the Short Syntax ............................................................................................................ 136 11.2. Using the Long Syntax ............................................................................................................. 136 11.3. Catching Getopt Exceptions ...................................................................................................... 137 11.4. Using getOption() .................................................................................................................... 138 11.5. Using __get() and __isset() Magic Methods ................................................................................. 138 11.6. Using getRemainingArgs() ........................................................................................................ 138 11.7. Using addRules() ..................................................................................................................... 139 11.8. Using setHelp() ....................................................................................................................... 139 11.9. Using setAliases() .................................................................................................................... 140 11.10. Using addArguments() and setArguments() ................................................................................ 140 11.11. Using setOption() .................................................................................................................. 141 11.12. Using setOptions() ................................................................................................................. 141 12.1. Manejando Acciones No Existentes ............................................................................................ 185 12.2. Agregando una Tarea Usando Nombres de Accin, Controllador y Mdulo ........................................ 189 12.3. Agregando una Tarea al Objeto Solicitud (Request) ....................................................................... 190 12.4. AutoCompletion con Dojo Usando Zend MVC ............................................................................. 192 12.5. Permitiendo a las Acciones Responder a Requerimientos Ajax ......................................................... 201 12.6. Estableciendo Opciones ............................................................................................................ 205
xxxv
12.7. Usando Defaults ...................................................................................................................... 12.8. Usando la API _forward() de goto() ........................................................................................... 12.9. Usando Ruta de Ensamblaje con gotoRoute() ............................................................................... 12.10. Uso Bsico ........................................................................................................................... 12.11. Deshabilitando Autorender ...................................................................................................... 12.12. Eligiendo Un Script de Vista Diferente ...................................................................................... 12.13. Modificando la Vista Registrada ............................................................................................... 12.14. Cambiando las Especificaciones del Path ................................................................................... 12.15. Rendering Mltiples Scripts de Vista desde una Sola Accin ......................................................... 12.16. Standard Usage ..................................................................................................................... 12.17. Setting a Different Error Handler .............................................................................................. 12.18. Using Accessors .................................................................................................................... 13.1. Creating an Instance of Zend_Currency from the Locale ................................................................. 13.2. Other Ways to Create Instances of Zend_Currency ........................................................................ 13.3. Creating an Output String for a Currency .................................................................................... 13.4. Changing the displayed format of a currency ................................................................................ 13.5. Getting Information about Currencies .......................................................................................... 13.6. Setting a New Locale ............................................................................................................... 13.7. Caching currencies .................................................................................................................. 14.1. Configurando una Zona Horaria por Defecto ................................................................................ 14.2. Creating the Current Date ......................................................................................................... 14.3. get() - Output a Date ............................................................................................................... 14.4. set() - Set a Date ..................................................................................................................... 14.5. add() - Adding Dates ............................................................................................................... 14.6. compare() - Compare Dates ...................................................................................................... 14.7. equals() - Identify a Date or Date Part ........................................................................................ 14.8. User-Specified Input Date Format .............................................................................................. 14.9. Operating on Parts of Dates ...................................................................................................... 14.10. Date Creation by Instance ....................................................................................................... 14.11. Static Date Creation ............................................................................................................... 14.12. Quick Creation of Dates from Database Date Values .................................................................... 14.13. Convenient Creation of Dates from Database Date Values ............................................................. 14.14. Date Creation by Array .......................................................................................................... 14.15. Self-Defined ISO Formats ....................................................................................................... 14.16. Self-Defined Formats with PHP Specifier ................................................................................... 14.17. Checking Dates ..................................................................................................................... 14.18. Getting all Available Cities ..................................................................................................... 14.19. Getting the Location for a City ................................................................................................ 14.20. Calculating Sun Information .................................................................................................... 14.21. Working with Time Zones ...................................................................................................... 14.22. Multiple Time Zones .............................................................................................................. 15.1. Usando el Constructor de un Adaptador ...................................................................................... 15.2. Usando el Adaptador del mtodo factory ..................................................................................... 15.3. Usando el mtodo factory para una clase Adaptador personalizada ................................................... 15.4. Uso del mtodo factory del Adaptador con un objeto Zend_Config .................................................. 15.5. Passing the case-folding option to the factory .............................................................................. 15.6. Passing the auto-quoting option to the factory ............................................................................. 15.7. Passing PDO driver options to the factory .................................................................................... 15.8. Passing Serialization Options to the Factory ................................................................................. 15.9. Handling connection exceptions ................................................................................................. 15.10. Using fetchAll() .................................................................................................................... 15.11. Using setFetchMode() ............................................................................................................. 15.12. Using fetchAssoc() ................................................................................................................. 15.13. Using fetchCol() ....................................................................................................................
206 206 207 213 214 215 215 216 216 227 227 228 237 238 239 240 241 242 242 245 247 247 248 248 248 249 250 251 257 257 257 258 258 263 266 269 269 270 270 271 272 274 274 274 275 276 276 277 277 278 280 280 281 281
xxxvi
15.14. Using fetchPairs() .................................................................................................................. 15.15. Using fetchRow() .................................................................................................................. 15.16. Using fetchOne() ................................................................................................................... 15.17. Inserting in a Table ................................................................................................................ 15.18. Inserting Expressions in a Table ............................................................................................... 15.19. Using lastInsertId() for an Auto-Increment Key ........................................................................... 15.20. Using lastInsertId() for a Sequence ........................................................................................... 15.21. Using lastSequenceId() ........................................................................................................... 15.22. Updating Rows ...................................................................................................................... 15.23. Updating Rows Using an Array of Expressions ........................................................................... 15.24. Deleting Rows ...................................................................................................................... 15.25. Using quote() ........................................................................................................................ 15.26. Using quote() with a SQL Type ............................................................................................... 15.27. Using quoteInto() ................................................................................................................... 15.28. Using quoteInto() with a SQL Type .......................................................................................... 15.29. Using quoteIdentifier() ............................................................................................................ 15.30. Managing a Transaction to Ensure Consistency ........................................................................... 15.31. Closing a Database Connection ................................................................................................ 15.32. Running a Non-Prepared Statement in a PDO Adapter .................................................................. 15.33. Verifying server version before running a query .......................................................................... 15.34. Crear un objeto de declaracin SQL con query() ......................................................................... 15.35. Usando un constructor de declaracin SQL ................................................................................ 15.36. Ejecutar una declaracin con parmetros posicionales ................................................................... 15.37. Ejecutando una declaracin con parmetros nombrados ................................................................ 15.38. Usando fetch() en un bucle ...................................................................................................... 15.39. Usando fetchAll() .................................................................................................................. 15.40. Configurando un modo de extraccin ........................................................................................ 15.41. Usando fetchColumn() ............................................................................................................ 15.42. Usando fetchObject() .............................................................................................................. 15.43. Perfilando DB con Zend_Controller_Front ................................................................................. 15.44. Perfilar DB sin Zend_Controller_Front ........................................................................... 15.45. Ejemplo del mtodo select() del adaptador ................................................................................. 15.46. Ejemplo de creacin de un nuevo objeto Select ........................................................................... 15.47. Ejemplo de uso de mtodos que agregan clusulas ....................................................................... 15.48. Ejemplo de uso de la interfaz fluida. ......................................................................................... 15.49. Ejemplo del mtodo from() ..................................................................................................... 15.50. Ejemplo especificando una tabla con nombre de correlacin .......................................................... 15.51. Ejemplo especificando un nombre de esquema ............................................................................ 15.52. Ejemplos especificando columnas ............................................................................................. 15.53. Ejemplos especificando columnas que contienen expresiones ......................................................... 15.54. Ejemplo de entrecomillado de columnas en una expresin ............................................................. 15.55. Ejemplos agregando columnas con el mtodocolumns() ............................................................ 15.56. Ejemplo del mtodo join() ....................................................................................................... 15.57. Ejemplo especificando ninguna columna .................................................................................... 15.58. Ejemplo de mtodo joinUsing() ................................................................................................ 15.59. Ejemplo del mtodo where() .................................................................................................... 15.60. Ejemplo de parmetro en el mtodo where() ............................................................................... 15.61. Ejemplo de mtodos where() mltiples ...................................................................................... 15.62. Ejemplo del mtodo orWhere() ................................................................................................ 15.63. Ejemplos de Expresiones Booleanas con parntesis ...................................................................... 15.64. Ejemplo del mtodo group() .................................................................................................... 15.65. Ejemplo del mtodo having() ................................................................................................... 15.66. Ejemplo del mtodo order() ..................................................................................................... 15.67. Ejemplo del mtodo limit() ......................................................................................................
281 281 282 282 283 283 283 283 284 285 285 286 286 287 287 288 288 290 291 291 294 295 295 295 296 296 297 297 297 302 302 303 304 304 304 305 305 305 306 306 307 308 308 309 310 311 311 312 312 312 313 314 314 315
xxxvii
15.68. Ejemplo del mtodo limitPage() ............................................................................................... 15.69. Ejemplo del mtodo distinct() .................................................................................................. 15.70. Ejemplo of forUpdate() method ................................................................................................ 15.71. Ejemplo usando el mtodo adaptador query() del Adaptador de Base de datos ................................... 15.72. Ejempo usando el mtodo query() del objeto Select ..................................................................... 15.73. Ejemplo del mtodo __toString() .............................................................................................. 15.74. Ejemplo del mtodo getPart() .................................................................................................. 15.75. Ejemplo del mtodo reset() ...................................................................................................... 15.76. Declaring a table class with explicit table name ........................................................................... 15.77. Declaring a table class with implicit table name .......................................................................... 15.78. Declaring a table class with schema .......................................................................................... 15.79. Declaring table and schema names upon instantiation ................................................................... 15.80. Ejemplo of specifying the primary key ...................................................................................... 15.81. Ejemplo of overriding the _setupTableName() method .................................................................. 15.82. Ejemplo usage of init() method ................................................................................................ 15.83. Ejemplo of constructing a Table using an Adapter object .............................................................. 15.84. Ejemplo of constructing a Table using a the Default Adapter ......................................................... 15.85. Ejemplo of constructing a Table using a Registry key ................................................................... 15.86. Ejemplo of inserting to a Table ................................................................................................ 15.87. Ejemplo of inserting expressions to a Table ................................................................................ 15.88. Ejemplo of declaring a Table with auto-incrementing primary key .................................................. 15.89. Ejemplo of declaring a Table with a sequence ............................................................................. 15.90. Ejemplo of declaring a Table with a natural key .......................................................................... 15.91. Ejemplo of updating rows in a Table ......................................................................................... 15.92. Ejemplo of deleting rows from a Table ...................................................................................... 15.93. Ejemplo of finding rows by primary key values .......................................................................... 15.94. Ejemplo of finding rows by compound primary key values ............................................................ 15.95. Simple usage ........................................................................................................................ 15.96. Ejemplo of fluent interface ...................................................................................................... 15.97. Ejemplo of finding rows by an expression .................................................................................. 15.98. Ejemplo of finding rows by an expression .................................................................................. 15.99. Retrieving specific columns ..................................................................................................... 15.100. Retrieving expressions as columns .......................................................................................... 15.101. Using a lookup table to refine the results of fetchAll() ................................................................ 15.102. Removing the integrity check on Zend_Db_Table_Select to allow JOINed rows ............................... 15.103. Ejemplo of finding a single row by an expression ...................................................................... 15.104. Ejemplo of getting the table name ........................................................................................... 15.105. Using a Default Metadata Cache for all Table Objects ................................................................ 15.106. Using a Metadata Cache for a Specific Table Object .................................................................. 15.107. Ejemplo of specifying the Row and Rowset classes .................................................................... 15.108. Ejemplo of changing the Row and Rowset classes ...................................................................... 15.109. Custom logic to manage timestamps ........................................................................................ 15.110. Custom method to find bugs by status ..................................................................................... 15.111. Ejemplo of an abstract table class that implements inflection ........................................................ 15.112. Ejemplo of fetching a row ..................................................................................................... 15.113. Ejemplo of reading a row in a rowset ...................................................................................... 15.114. Ejemplo of reading a column in a row ..................................................................................... 15.115. Ejemplo of using the toArray() method .................................................................................... 15.116. Ejemplo of changing a column in a row ................................................................................... 15.117. Ejemplo of creating a new row for a table ................................................................................ 15.118. Ejemplo of populating a new row for a table ............................................................................. 15.119. Ejemplo of using setFromArray() to set values in a new Row ....................................................... 15.120. Ejemplo of deleting a row ..................................................................................................... 15.121. Ejemplo of serializing a row ..................................................................................................
315 316 316 316 317 317 318 318 319 319 320 320 321 321 322 322 323 323 323 324 324 325 325 325 326 326 327 328 328 329 329 329 330 330 330 331 331 332 333 334 335 335 336 337 337 338 338 338 339 339 340 340 341 341
xxxviii
15.122. Ejemplo of unserializing a serialized row ................................................................................. 15.123. Ejemplo of reactivating a row ................................................................................................ 15.124. Specifying a custom Row class .............................................................................................. 15.125. Ejemplo usage of init() method .............................................................................................. 15.126. Ejemplo of custom logic in a Row class ................................................................................... 15.127. Ejemplo of a Row class that logs insert data for multiple tables .................................................... 15.128. Ejemplo of defining an inflection transformation ........................................................................ 15.129. Ejemplo of fetching a rowset ................................................................................................. 15.130. Counting the Rows in a Rowset .............................................................................................. 15.131. Reading a Single Row from a Rowset ..................................................................................... 15.132. Iterating through a Rowset ..................................................................................................... 15.133. Seeking to a known position into a Rowset ............................................................................... 15.134. Using toArray() ................................................................................................................... 15.135. Serializing a Rowset ............................................................................................................. 15.136. Unserializing a Serialized Rowset ........................................................................................... 15.137. Reactivating a Rowset as Live Data ........................................................................................ 15.138. Specifying a custom Rowset class ........................................................................................... 15.139. Ejemplo of Rowset class with a new method ............................................................................. 15.140. Fetching a Dependent Rowset ................................................................................................ 15.141. Fetching a Dependent Rowset By a Specific Rule ...................................................................... 15.142. Fetching a Dependent Rowset using a Zend_Db_Table_Select ...................................................... 15.143. Fetching Dependent Rowsets using the Magic Method ................................................................ 15.144. Fetching the Parent Row ....................................................................................................... 15.145. Fetching a Parent Row By a Specific Rule ............................................................................... 15.146. Fetching the Parent Row using the Magic Method ...................................................................... 15.147. Fetching a Rowset with the Many-to-many Method .................................................................... 15.148. Fetching a Rowset with the Many-to-many Method By a Specific Rule .......................................... 15.149. Fetching Rowsets using the Magic Many-to-many Method .......................................................... 15.150. Ejemplo of a Cascading Delete ............................................................................................... 15.151. Ejemplo Declaration of Cascading Operations ........................................................................... 15.152. Describing the Definition of a Database Data Model .................................................................. 15.153. Interacting with the described definition ................................................................................... 15.154. Interacting A Mixed Use Zend_Db_Table Definition .................................................................. 16.1. Ejemplo del mtodo dump() ...................................................................................................... 17.1. Inicializacin de Zend_Dojo_Data via constructor ......................................................................... 17.2. Inicializacin de Zend_Dojo_Data via mutators ............................................................................ 17.3. Agregando datos a Zend_Dojo_Data ...................................................................................... 17.4. Especificando la etiqueta de un campo en Zend_Dojo_Data ........................................................ 17.5. Alimentando Zend_Dojo_Data desde JSON ............................................................................. 17.6. Usando los Ayudantes de Dojo View .......................................................................................... 17.7. dojo() Ejemplo de Uso del Ayudante de Vista .............................................................................. 17.8. Especificando el Uso Declarativo y Programtico de Dojo .............................................................. 17.9. Registrando el Prefijo del Path al Ayudante de Vista de Dojo .......................................................... 17.10. Ejemplo de esquema de BorderContainer dijit ............................................................................. 17.11. Usando CustomDijit para mostrar un dojox.layout.ContentPane ...................................................... 17.12. Habilitando Dojo en sus formularios existentes ........................................................................... 17.13. Uso del Decorador DijitElement ............................................................................................... 17.14. Uso del Decorador DijitContainer ............................................................................................. 17.15. Ejemplo de Uso del Elemento Button dijit .................................................................................. 17.16. Ejemplo de Uso de Elementos CheckBox dijit ............................................................................ 17.17. Elemento de ComboBox dijit Usado como select input ................................................................. 17.18. Elemento de ComboBox dijit Usado con datastore ....................................................................... 17.19. Ejemplo de Uso del Elemento CurrencyTextBox dijit ................................................................... 17.20. Ejemplo de Uso del Elemento DateTextBox dijit .........................................................................
341 342 342 343 343 344 345 346 346 346 346 347 348 348 348 349 349 350 353 353 353 354 355 355 355 356 357 357 358 359 360 361 361 363 366 366 366 366 366 369 370 371 375 377 386 387 388 389 390 391 392 392 393 394
xxxix
17.21. Ejemplo de Uso del Elemento Editor dijit .................................................................................. 17.22. Ejemplo de Uso del Elemento NumberSpinner dijit ...................................................................... 17.23. Ejemplo de Uso del Elemento NumberTextBox dijit .................................................................... 17.24. Ejemplo de Uso del Elemento PasswordTextBox dijit ................................................................... 17.25. Ejemplo de Uso del Elemento RadioButton dijit .......................................................................... 17.26. Ejemplo de Uso del Elemento SimpleTextarea dijit ...................................................................... 17.27. Ejemplo de Uso del Elemento SubmitButton dijit ........................................................................ 17.28. Ejemplo de Uso del Elemento TextBox dijit ............................................................................... 17.29. Ejemplo de Uso del Elemento Textarea dijit ............................................................................... 17.30. Ejemplo de Uso del Elemento TimeTextBox dijit ........................................................................ 17.31. Ejemplo de Uso del Elemento ValidationTextBox dijit ................................................................. 17.32. Ejemplo de Uso del Elemento VerticalSlider dijit ........................................................................ 17.33. Usando Zend_Dojo_Form .................................................................................................... 17.34. Modificando un form existente para utilizarlo con Dojo ................................................................ 19.1. Catching an Exception ............................................................................................................. 20.1. Putting Zend_Feed to Work on RSS Feed Data ............................................................................. 20.2. Basic Use of an Atom Feed ...................................................................................................... 20.3. Reading a Single-Entry Atom Feed ............................................................................................ 20.4. Using the Entry Object Directly for a Single-Entry Atom Feed ........................................................ 20.5. Modifying an Existing Feed Entry .............................................................................................. 20.6. Creating an Atom Entry with Elements of Custom Namespaces ....................................................... 20.7. Extending the Atom Entry Class with Custom Namespaces ............................................................. 21.1. Simple Form for Uploading Files ............................................................................................... 21.2. Checking Files ........................................................................................................................ 21.3. Getting the Filename ................................................................................................................ 21.4. Getting the size of a file ........................................................................................................... 21.5. Getting the hash of a file .......................................................................................................... 21.6. Getting the mimetype of a file ................................................................................................... 21.7. Using the progressbar adapter to retrieve the actual state ................................................................ 21.8. Manual usage of the file progress ............................................................................................... 21.9. Add Validators to a File Transfer Object ..................................................................................... 21.10. Limit Validators to Single Files ................................................................................................ 21.11. Add Multiple Validators ......................................................................................................... 21.12. Validate the Files ................................................................................................................... 21.13. Using the Count Validator ....................................................................................................... 21.14. Using the Crc32 Validator ....................................................................................................... 21.15. Using the ExcludeExtension Validator ....................................................................................... 21.16. Using the ExcludeMimeType Validator ..................................................................................... 21.17. Using the Exists Validator ....................................................................................................... 21.18. Using the Extension Validator .................................................................................................. 21.19. Using the FilesSize Validator ................................................................................................... 21.20. Using the ImageSize Validator ................................................................................................. 21.21. Using the IsCompressed Validator ............................................................................................ 21.22. Using the IsImage Validator .................................................................................................... 21.23. Using the Hash Validator ........................................................................................................ 21.24. Using the Md5 Validator ........................................................................................................ 21.25. Using the MimeType Validator ................................................................................................ 21.26. Using the NotExists Validator .................................................................................................. 21.27. Using the sha1 Validator ......................................................................................................... 21.28. Using the Size Validator ......................................................................................................... 21.29. Using the WordCount Validator ............................................................................................... 21.30. Add filters to a file transfer ..................................................................................................... 21.31. Limit filters to single files ....................................................................................................... 21.32. Add multiple filters ................................................................................................................
395 399 400 400 401 401 402 402 403 403 404 405 405 412 423 425 433 434 434 434 434 435 451 452 453 453 454 454 455 456 457 458 458 458 459 460 460 461 462 462 463 464 464 465 465 466 467 467 468 469 469 470 470 471
xl
21.33. Using the Decrypt filter with Mcrypt ......................................................................................... 21.34. Using the Decrypt filter with OpenSSL ..................................................................................... 21.35. Using the Encrypt filter with Mcrypt ......................................................................................... 21.36. Using the Encrypt filter with OpenSSL ...................................................................................... 21.37. Using the LowerCase filter ...................................................................................................... 21.38. Using the Rename filter .......................................................................................................... 21.39. Using the UpperCase filter ...................................................................................................... 22.1. Transforming MixedCase and camelCaseText to another format ....................................................... 22.2. Setting Multiple Rules at Once .................................................................................................. 22.3. Using Zend_Config with Zend_Filter_Inflector ............................................................................. 23.1. Etiqueta personalizada .............................................................................................................. 23.2. Determinando rutas de acceso de prefijos para todos los elementos ................................................... 23.3. Determinando Decoradores para todos los elementos ..................................................................... 23.4. Determinando decoradores para algunos elementos ........................................................................ 23.5. Determinando Filtros para todos los Elementos ............................................................................. 23.6. Fijando el Prefijo de Ruta del Decorador para todos los Grupos de Visualizacin ................................. 23.7. Fijando Decoradores para Todos los Grupos de Visualizacin .......................................................... 23.8. File form element usage ........................................................................................................... 23.9. Explicit file retrievement .......................................................................................................... 23.10. Checking if an optional file has been uploaded ........................................................................... 23.11. Configuracin de mltiples archivos .......................................................................................... 23.12. Ejemplo de formulario de registro ............................................................................................. 24.1. Passing a Developer Key and ClientID to Zend_Gdata_YouTube ..................................................... 24.2. Searching for videos ................................................................................................................ 24.3. Searching for videos in specific categories ................................................................................... 24.4. Retrieving a standard video feed ................................................................................................ 24.5. Using a Zend_Gdata_YouTube_VideoQuery to Retrieve Videos ...................................................... 24.6. Retrieving a video feed by URL ................................................................................................ 24.7. Retrieving videos uploaded by a specific user ............................................................................... 24.8. Retrieving a user's favorite videos .............................................................................................. 24.9. Retrieving a feed of video responses ........................................................................................... 24.10. Retrieving a feed of video comments from a video ID .................................................................. 24.11. Retrieving a Feed of Video Comments from a Zend_Gdata_YouTube_VideoEntry ............................. 24.12. Retrieving the playlists of a user .............................................................................................. 24.13. Retrieving a specific playlist .................................................................................................... 24.14. Retrieving all subscriptions for a user ........................................................................................ 24.15. Retrieving a user's profile ........................................................................................................ 24.16. Uploading a video ................................................................................................................. 24.17. Browser-based upload ............................................................................................................. 24.18. Browser-based upload: Creating the HTML form ........................................................................ 24.19. Checking video upload status ................................................................................................... 25.1. Instantiating a Zend_Http_Client Object ...................................................................................... 25.2. Performing a Simple GET Request ............................................................................................. 25.3. Using Request Methods Other Than GET .................................................................................... 25.4. Setting GET Parameters ........................................................................................................... 25.5. Setting POST Parameters .......................................................................................................... 25.6. Forcing RFC 2616 Strict Redirections on 301 and 302 Responses ..................................................... 25.7. Setting Cookies Using setCookie() ............................................................................................. 25.8. Enabling Cookie Stickiness ....................................................................................................... 25.9. Setting A Single Custom Request Header .................................................................................... 25.10. Setting Multiple Custom Request Headers .................................................................................. 25.11. Using setFileUpload to Upload Files ......................................................................................... 25.12. Sending Raw POST Data ........................................................................................................ 25.13. Setting HTTP Authentication User and Password ........................................................................
471 471 472 472 472 473 474 507 511 512 521 540 540 540 541 543 543 565 566 566 567 581 655 655 656 656 656 657 657 657 657 657 658 658 658 659 659 660 661 661 662 665 666 667 667 667 668 668 669 669 670 670 671 671
xli
25.14. Performing consecutive requests with one client .......................................................................... 25.15. Changing the HTTPS transport layer ......................................................................................... 25.16. Setting stream context options for the Socket adapter ................................................................... 25.17. Using Zend_Http_Client behind a proxy server ........................................................................... 25.18. Setting cURL options ............................................................................................................. 25.19. Transfering Files by Handle .................................................................................................... 25.20. Testing Against a Single HTTP Response Stub ........................................................................... 25.21. Testing Against Multiple HTTP Response Stubs .......................................................................... 25.22. Forcing the adapter to fail ....................................................................................................... 25.23. Creating your own connection adapter ....................................................................................... 25.24. Instantiating a Zend_Http_Cookie object .................................................................................... 25.25. Stringifying a Zend_Http_Cookie object .................................................................................... 25.26. Using getter methods with Zend_Http_Cookie ............................................................................ 25.27. Matching cookies ................................................................................................................... 25.28. Instantiating a Zend_Http_Response Object Using the Factory Method ............................................ 25.29. Using the isError() method to validate a response ........................................................................ 25.30. Using Zend_Http_Response Accessor Methods ........................................................................... 25.31. Accessing Response Headers ................................................................................................... 27.1. Uso de Zend_Json_Server ......................................................................................................... 28.1. Passing options to the constructor or startMvc() ............................................................................ 28.2. Using setOption() and setConfig() .............................................................................................. 28.3. Using Accessors ...................................................................................................................... 28.4. Using Zend_Layout accessors to modify the inflector ..................................................................... 28.5. Direct modification of Zend_Layout inflector ............................................................................... 28.6. Custom inflectors .................................................................................................................... 29.1. Getting an entry by its DN ........................................................................................................ 29.2. Check for the existence of a given DN ........................................................................................ 29.3. Count children of a given DN ................................................................................................... 29.4. Searching the LDAP tree .......................................................................................................... 29.5. Add a new entry to the LDAP ................................................................................................... 29.6. Delete an existing entry from the LDAP ...................................................................................... 29.7. Update an existing entry on the LDAP ........................................................................................ 29.8. Copy a LDAP entry recursively with all its descendants ................................................................. 29.9. Move a LDAP entry recursively with all its descendants to a different subtree .................................... 29.10. Create simple LDAP filters ..................................................................................................... 29.11. Create more complex LDAP filters ........................................................................................... 29.12. Traverse LDAP tree recursively ............................................................................................... 29.13. Getting hands on the RootDSE ................................................................................................ 29.14. Getting hands on the server schema .......................................................................................... 30.1. Ejemplo del Mtodo loadFile() .................................................................................................. 30.2. Ejemplo del mtodo loadClass() ................................................................................................. 30.3. Ejemplo del mtodo isReadable() ............................................................................................... 30.4. Ejemplo de registro del mtodo callback del autoloader .................................................................. 30.5. Ejemplo de registro del mtodo de callback autoload desde una clase extendida .................................. 30.6. Using the PluginLoader class file include cache ............................................................................ 31.1. Choosing a specific locale ........................................................................................................ 31.2. Automatically selecting a locale ................................................................................................. 31.3. Using automatic locales ............................................................................................................ 31.4. Handling locale exceptions ........................................................................................................ 31.5. Setting a default locale ............................................................................................................. 31.6. Dates default to correct locale of web users ................................................................................. 31.7. Overriding default locale selection .............................................................................................. 31.8. Performance optimization when using a default locale .................................................................... 31.9. Usage of an application wide locale ............................................................................................
672 674 674 676 677 677 678 678 679 680 682 682 683 684 687 688 688 689 701 715 715 715 717 717 718 746 746 746 747 747 747 747 748 748 748 748 749 750 750 755 755 756 756 756 767 770 771 772 772 772 773 773 773 773
xlii
31.10. Dates default to correct locale of web users ................................................................................ 31.11. Using STANDARD definitions for setOptions() .......................................................................... 31.12. clone ................................................................................................................................... 31.13. Check for equal locales .......................................................................................................... 31.14. Get default locales ................................................................................................................. 31.15. setLocale .............................................................................................................................. 31.16. getLanguage and getRegion ..................................................................................................... 31.17. getTranslationList .................................................................................................................. 31.18. getTranslationList .................................................................................................................. 31.19. Converting country name in one language to another .................................................................... 31.20. All Languages written in their native language ............................................................................ 31.21. getQuestion() ........................................................................................................................ 31.22. getLocaleList() ...................................................................................................................... 31.23. Simple locale detection ........................................................................................................... 31.24. Strict locale detection ............................................................................................................. 31.25. Implement locale aware behaviour ............................................................................................ 31.26. Locale aware behaviour as with Zend Framework 1.8 ................................................................... 31.27. Number normalization ............................................................................................................ 31.28. Number normalization with precision ........................................................................................ 31.29. Number localization ............................................................................................................... 31.30. Number localization with precision ........................................................................................... 31.31. Using a self defined number format .......................................................................................... 31.32. Number testing ...................................................................................................................... 31.33. Floating point value normalization ............................................................................................ 31.34. Floating point value localization ............................................................................................... 31.35. Floating point value testing ..................................................................................................... 31.36. Integer value normalization ..................................................................................................... 31.37. Integer value localization ........................................................................................................ 31.38. Integer value testing ............................................................................................................... 31.39. Converting numerals from Eastern Arabic scripts to European/Latin scripts ...................................... 31.40. Converting numerals from Latin script to Eastern Arabic script ...................................................... 31.41. Getting 4 letter CLDR script code using a native-language name of the script .................................... 31.42. Normalizing a date ................................................................................................................. 31.43. Normalizing a date by locale ................................................................................................... 31.44. Normalizing a date with time ................................................................................................... 31.45. Normalizing a userdefined date ................................................................................................ 31.46. Automatic correction of input dates ........................................................................................... 31.47. Date testing .......................................................................................................................... 31.48. Normalize an unknown time .................................................................................................... 31.49. Testing a time ....................................................................................................................... 32.1. Logging with Zend_Controller_Front .......................................................................................... 32.2. Logging without Zend_Controller_Front ...................................................................................... 33.1. Simple E-Mail with Zend_Mail .................................................................................................. 33.2. Passing additional parameters to the Zend_Mail_Transport_Sendmail transport ................................... 33.3. Sending E-Mail via SMTP ........................................................................................................ 33.4. Sending Multiple Mails per SMTP Connection ............................................................................. 33.5. Manually controlling the transport connection ............................................................................... 33.6. Using Different Transports ........................................................................................................ 33.7. Sending HTML E-Mail ............................................................................................................ 33.8. E-Mail Messages with Attachments ............................................................................................ 33.9. Changing the MIME Boundary .................................................................................................. 33.10. Adding E-Mail Message Headers .............................................................................................. 33.11. Enabling authentication within Zend_Mail_Transport_Smtp ........................................................... 33.12. Enabling a secure connection within Zend_Mail_Transport_Smtp ...................................................
774 774 775 775 776 776 776 777 788 788 789 789 790 790 791 791 792 792 793 793 793 794 794 795 795 795 796 796 796 797 797 797 799 800 800 800 801 801 802 802 819 819 829 830 830 831 831 832 832 832 834 834 835 835
xliii
34.1. Converting measurements ......................................................................................................... 34.2. The meter measurement ............................................................................................................ 34.3. Creation using integer and floating values .................................................................................... 34.4. Creation using strings ............................................................................................................... 34.5. Arbitrary text input containing measurements ............................................................................... 34.6. Localized string ...................................................................................................................... 34.7. Automatic output ..................................................................................................................... 34.8. Output a value ........................................................................................................................ 34.9. Outputting units ...................................................................................................................... 34.10. Convert ................................................................................................................................ 34.11. Adding units ......................................................................................................................... 34.12. Subtract ............................................................................................................................... 34.13. Different measurements .......................................................................................................... 34.14. Identical measurements ........................................................................................................... 34.15. Difference ............................................................................................................................ 34.16. Changing a value ................................................................................................................... 34.17. Changing the type .................................................................................................................. 35.1. Using Zend_Memory component ................................................................................................ 37.1. Custom page properties ............................................................................................................ 37.2. getHref() generates the page URI ............................................................................................... 37.3. isActive() determines if page is active ......................................................................................... 37.4. Using routes ........................................................................................................................... 37.5. The most simple custom page .................................................................................................... 37.6. A custom page with properties .................................................................................................. 37.7. Creating an MVC page using the page factory .............................................................................. 37.8. Creating a URI page using the page factory ................................................................................. 37.9. Creating a custom page type using the page factory ....................................................................... 37.10. Creating a container using an array ........................................................................................... 37.11. Creating a container using a config object .................................................................................. 37.12. Adding pages to a container .................................................................................................... 37.13. Removing pages from a container ............................................................................................. 37.14. Finding pages in a container .................................................................................................... 37.15. Iterating a container ............................................................................................................... 37.16. Converting a container to an array ............................................................................................ 38.1. The Simple OpenID Login form ................................................................................................ 38.2. The Authentication Request Handler ........................................................................................... 38.3. The Authentication Response Verifier ......................................................................................... 38.4. The Complete OpenID Login Script ........................................................................................... 38.5. Authentication Request for Specified Realm ................................................................................. 38.6. Immediate Check without Interaction .......................................................................................... 38.7. Database Storage ..................................................................................................................... 38.8. Sending Requests with a Simple Registration Extension ................................................................. 38.9. Verifying Responses with a Simple Registration Extension ............................................................. 38.10. Zend_Auth Adapter for OpenID ............................................................................................... 38.11. The Identity .......................................................................................................................... 38.12. Simple Identity Provider ......................................................................................................... 38.13. Simple Login Screen .............................................................................................................. 38.14. Simple Trust Screen ............................................................................................................... 38.15. Everything Together ............................................................................................................... 38.16. Identity with Profile ............................................................................................................... 38.17. Provider with SREG ............................................................................................................... 40.1. Crear un nuevo documento PDF o cargar uno ya esistente. .............................................................. 40.2. Requiriendo Revisiones Especficas de un documento PDF ............................................................. 40.3. Guardando Documentos PDF ....................................................................................................
847 847 848 848 848 849 849 850 850 851 851 852 852 852 853 853 853 857 872 873 873 874 875 876 877 877 878 878 882 885 886 887 889 890 895 895 895 896 897 897 898 902 902 903 905 905 906 907 908 909 910 921 922 922
xliv
40.4. Administracin de Pginas de un Documento PDF. ....................................................................... 923 40.5. Clonando una Pgina Existente. ................................................................................................. 924 40.6. Dibujar un string en la pgina ................................................................................................... 927 40.7. Dibujar un string codificado en UTF-8 en la pgina ....................................................................... 928 40.8. Crear un tipo de letra normal .................................................................................................... 928 40.9. Crear una fuente TrueType ....................................................................................................... 929 40.10. Crear una fuente TrueType, pero no incluirla en el documento PDF. ............................................... 929 40.11. No arrojar una excepcin para las fuentes que no puedan ser incorporadas. ....................................... 930 40.12. No comprimir una fuente incrustada. ......................................................................................... 930 40.13. La combinacin de opciones de la incrustacin de fuentes. ............................................................ 930 40.14. Combinacin de opciones de la incrustacin de fuentes. ................................................................ 931 40.15. Extraccin de las fuentes de un documento cargado. .................................................................... 931 40.16. Extraccin de la fuente de un documento cargado especificando el nombre de la fuente. ...................... 932 40.17. Dibujar una imagen ................................................................................................................ 933 40.18. Destinations usage example ..................................................................................................... 945 40.19. Demo de uso del mdulo Zend_Pdf .......................................................................................... 953 41.1. Basic example for the client-side stuff ......................................................................................... 961 43.1. Performing reflection on a file ................................................................................................... 973 43.2. Performing reflection on a class ................................................................................................. 973 43.3. Performing reflection on a method ............................................................................................. 974 43.4. Performing reflection on a docblock ........................................................................................... 974 44.1. Ejemplo of set() Method Usage ................................................................................................. 979 44.2. Ejemplo of get() Method Usage ................................................................................................. 979 44.3. Ejemplo of Iterating over the Registry ......................................................................................... 979 44.4. Ejemplo of Constructing a Registry ............................................................................................ 980 44.5. Ejemplo of Initializing the Singleton Registry ............................................................................... 980 44.6. Ejemplo of Array Access .......................................................................................................... 980 44.7. Ejemplo of Object Access ......................................................................................................... 980 44.8. Ejemplo of isRegistered() Method Usage ..................................................................................... 981 44.9. Ejemplo of isset() Method Usage ............................................................................................... 981 44.10. Ejemplo of Specifying the Singleton Registry's Class Name .......................................................... 982 44.11. Ejemplo of _unsetInstance() Method Usage ................................................................................ 982 45.1. A basic REST request .............................................................................................................. 983 45.2. Response Status ...................................................................................................................... 984 45.3. Using Technorati's Rest Service ................................................................................................. 984 45.4. Ejemplo Technorati Response .................................................................................................... 984 45.5. Setting Request Arguments ....................................................................................................... 985 45.6. Basic Zend_Rest_Server Usage - Classes ..................................................................................... 986 45.7. Basic Zend_Rest_Server Usage - Functions .................................................................................. 986 45.8. Returning Custom Status .......................................................................................................... 986 45.9. Return Custom XML ............................................................................................................... 987 46.1. Custom text Analyzer ............................................................................................................. 1021 48.1. isSpam() Usage ..................................................................................................................... 1040 48.2. submitSpam() Usage .............................................................................................................. 1041 48.3. submitHam() Usage ............................................................................................................... 1041 48.4. Search Amazon Using the Traditional API ................................................................................. 1043 48.5. Search Amazon Using the Query API ....................................................................................... 1043 48.6. Choosing an Amazon Web Service Country ............................................................................... 1043 48.7. Looking up a Specific Amazon Item by ASIN ............................................................................ 1044 48.8. Performing Amazon Item Searches ........................................................................................... 1044 48.9. Using the ResponseGroup Option ............................................................................................. 1044 48.10. Search Amazon Using the Alternative Query API ...................................................................... 1045 48.11. setKeys() Ejemplo ................................................................................................................ 1050 48.12. setRegion() Ejemplo ............................................................................................................. 1051
xlv
48.13. 48.14. 48.15. 48.16. 48.17. 48.18. 48.19. 48.20. 48.21. 48.22. 48.23. 48.24. 48.25. 48.26. 48.27. 48.28. 48.29. 48.30. 48.31. 48.32. 48.33. 48.34. 48.35. 48.36. 48.37. 48.38. 48.39. 48.40. 48.41. 48.42. 48.43. 48.44. 48.45. 48.46. 48.47. 48.48. 48.49. 48.50. 48.51. 48.52. 48.53. 48.54. 48.55. 48.56. 48.57. 48.58. 48.59. 48.60. 48.61. 48.62. 48.63. 48.64. 48.65. 48.66.
Starting New Ec2 Instances ................................................................................................... Rebooting an Ec2 Instances ................................................................................................... Terminating an Ec2 Instances ................................................................................................. Describing Instances ............................................................................................................. Describing Instances By Image Id ........................................................................................... Retreiving Console Output ..................................................................................................... Confirm Product Code on an Instance ...................................................................................... Turn on CloudWatch Monitoring on an Instance(s) .................................................................... Turn off CloudWatch Monitoring on an Instance(s) .................................................................... Bundles an Amazon EC2 instance running Windows .................................................................. Describes current bundling tasks ............................................................................................. Cancels an Amazon EC2 bundling operation ............................................................................. Describes Reserved Instances that you purchased ....................................................................... Describe current Reserved Instance Offerings available ............................................................... Turn off CloudWatch Monitoring on an Instance(s) .................................................................... Listing Aviable Metrics ......................................................................................................... Return Statistics for a given metric ......................................................................................... Register an AMI with EC2 .................................................................................................... Deregister an AMI with EC2 ................................................................................................. Describe an AMI ................................................................................................................. Modify Image Attributes ....................................................................................................... Reset an AMI Attribute ......................................................................................................... Describe AMI Attribute ......................................................................................................... Create a new EBS Volume .................................................................................................... Create an EBS Volume from a Snapshot .................................................................................. Create a Snapshot of an EBS Volume ...................................................................................... Describing an EBS Volume ................................................................................................... Describe Attached Volumes ................................................................................................... Describe an EBS Volume Snapshot ......................................................................................... Attaching an EBS Volume ..................................................................................................... Detaching an EBS Volume .................................................................................................... Deleting an EBS Volume ...................................................................................................... Deleting an EBS Volume Snapshot ......................................................................................... Allocating a new Elastic IP .................................................................................................... Describing Allocated Elastic IP Addresses ................................................................................ Releasing Elastic IP .............................................................................................................. Associates an Elastic IP to an Instance ..................................................................................... Disassociate an Elastic IP from an instance ............................................................................... Creating a new Amazon Keypair ............................................................................................ Deleting an Amazon Keypair ................................................................................................. Describe an Amazon Keypair ................................................................................................. Viewing the available regions ................................................................................................ Viewing the available zones ................................................................................................... Create a new Security Group ................................................................................................. Describe a Security Group ..................................................................................................... Delete a Security Group ........................................................................................................ Authorizing by IP ................................................................................................................ Authorize By Group ............................................................................................................. Revoke by IP ...................................................................................................................... Revoke By Group ................................................................................................................ Zend_Service_Amazon_S3 Usage Ejemplo ............................................................................... Zend_Service_Amazon_S3 Bucket Removal Ejemplo ................................................................. Zend_Service_Amazon_S3 Bucket Listing Ejemplo .................................................................... Zend_Service_Amazon_S3 Public Object Ejemplo .....................................................................
1052 1053 1053 1054 1054 1054 1055 1055 1055 1056 1057 1057 1058 1058 1058 1059 1059 1060 1060 1060 1061 1062 1062 1062 1063 1063 1063 1063 1064 1064 1064 1064 1065 1065 1065 1066 1066 1066 1066 1067 1067 1067 1068 1068 1069 1069 1069 1070 1070 1070 1071 1072 1072 1073
xlvi
48.67. Zend_Service_Amazon_S3 Object Listing Ejemplo .................................................................... 48.68. Zend_Service_Amazon_S3 Streams Ejemplo ............................................................................. 48.69. Zend_Service_Amazon_Sqs Usage Ejemplo .............................................................................. 48.70. Zend_Service_Amazon_Sqs Queue Removal Ejemplo ................................................................ 48.71. Zend_Service_Amazon_Sqs Queue Count Ejemplo .................................................................... 48.72. Zend_Service_Amazon_Sqs Queue Listing Ejemplo ................................................................... 48.73. Zend_Service_Amazon_Sqs Message Send Ejemplo ................................................................... 48.74. Zend_Service_Amazon_Sqs Message Receive Ejemplo ............................................................... 48.75. Zend_Service_Amazon_Sqs Message Delete Ejemplo ................................................................. 48.76. Retrieving User Profile Information ......................................................................................... 48.77. Retrieving a User's Weekly Artist Chart ................................................................................... 48.78. Retrieving Related Artists ...................................................................................................... 48.79. Get all posts ........................................................................................................................ 48.80. Accessing post lists .............................................................................................................. 48.81. Filtering a Post List with Specific Tags .................................................................................... 48.82. Filtering a Post List by URL .................................................................................................. 48.83. Post editing ......................................................................................................................... 48.84. Method call chaining ............................................................................................................ 48.85. Deleting posts ...................................................................................................................... 48.86. Adding a post ...................................................................................................................... 48.87. Tags .................................................................................................................................. 48.88. Bundles .............................................................................................................................. 48.89. Retrieving public data ........................................................................................................... 48.90. Changing the HTTP client of Zend_Rest_Client ........................................................................ 48.91. Configuring your HTTP client to keep connections alive ............................................................. 48.92. Simple Flickr Photo Search .................................................................................................... 48.93. Finding a Flickr User's Public Photos by E-Mail Address ............................................................ 48.94. Retrieving a Group's Pool Photos by Group ID .......................................................................... 48.95. Retrieving Flickr Image Details .............................................................................................. 48.96. Creating an instance of the reCAPTCHA service ....................................................................... 48.97. Displaying the reCAPTCHA .................................................................................................. 48.98. Verifying the form fields ....................................................................................................... 48.99. Validating the reCAPTCHA ................................................................................................... 48.100. Using the mail hide component ............................................................................................. 48.101. Generating many hidden email addresses ................................................................................ 48.102. Querying Links .................................................................................................................. 48.103. Modifying Links ................................................................................................................ 48.104. Working With Tags ............................................................................................................ 48.105. Working With Notes ........................................................................................................... 48.106. Retrieving Watchlists .......................................................................................................... 48.107. Sending your first query ...................................................................................................... 48.108. Refining your query ............................................................................................................ 48.109. Sending multiple queries with the same Zend_Service_Technorati instance .................................... 48.110. Consuming a result set object ............................................................................................... 48.111. Seeking a specific result set object ........................................................................................ 48.112. Consuming a standalone result object ..................................................................................... 48.113. Handling a Query Exception ................................................................................................ 48.114. Getting API key daily usage information ................................................................................ 48.115. Cosmos Query ................................................................................................................... 48.116. Search Query ..................................................................................................................... 48.117. Tag Query ......................................................................................................................... 48.118. DailyCounts Query ............................................................................................................. 48.119. TopTags Query .................................................................................................................. 48.120. BlogInfo Query ..................................................................................................................
1074 1074 1076 1076 1076 1077 1077 1077 1077 1079 1079 1080 1082 1083 1083 1083 1084 1084 1084 1085 1085 1085 1086 1087 1087 1087 1088 1088 1088 1095 1095 1095 1095 1095 1096 1097 1098 1099 1100 1100 1115 1115 1115 1116 1116 1116 1117 1117 1118 1118 1119 1119 1120 1120
xlvii
48.121. BlogPostTags Query ........................................................................................................... 48.122. GetInfo Query .................................................................................................................... 48.123. Iterating result objects from a resultset collection ..................................................................... 48.124. Creating the Twitter Class .................................................................................................... 48.125. Verifying credentials ........................................................................................................... 48.126. Sessions ending .................................................................................................................. 48.127. Rating limit status .............................................................................................................. 48.128. Retrieving public timeline .................................................................................................... 48.129. Retrieving friends timeline ................................................................................................... 48.130. Retrieving user timeline ....................................................................................................... 48.131. Showing user status ............................................................................................................ 48.132. Updating user status ............................................................................................................ 48.133. Showing user replies ........................................................................................................... 48.134. Deleting user status ............................................................................................................. 48.135. Retrieving user friends ........................................................................................................ 48.136. Retrieving user followers ..................................................................................................... 48.137. Showing user informations ................................................................................................... 48.138. Retrieving recent direct messages received .............................................................................. 48.139. Retrieving recent direct messages sent .................................................................................... 48.140. Sending direct message ....................................................................................................... 48.141. Deleting direct message ....................................................................................................... 48.142. Creating friend ................................................................................................................... 48.143. Deleting friend ................................................................................................................... 48.144. Checking friend existence .................................................................................................... 48.145. Retrieving favorites ............................................................................................................. 48.146. Creating favorites ............................................................................................................... 48.147. Deleting favorites ............................................................................................................... 48.148. Checking if block exists ...................................................................................................... 48.149. Blocking a user .................................................................................................................. 48.150. Removing a block .............................................................................................................. 48.151. Who are you blocking ......................................................................................................... 48.152. JSON Search Ejemplo ......................................................................................................... 48.153. ATOM Search Ejemplo ....................................................................................................... 48.154. Searching the Web with Yahoo! ............................................................................................ 48.155. Finding Images with Yahoo! ................................................................................................ 48.156. Finding videos with Yahoo! ................................................................................................. 48.157. Finding Local Businesses and Services with Yahoo! ................................................................. 48.158. Searching Yahoo! News ...................................................................................................... 48.159. Searching Yahoo! Site Explorer Inbound Links ........................................................................ 48.160. Searching Yahoo! Site Explorer's PageData ............................................................................. 49.1. Counting Page Views ............................................................................................................. 49.2. New Way: Namespaces Avoid Collisions ................................................................................... 49.3. Old Way: PHP Session Access ................................................................................................ 49.4. Session Iteration .................................................................................................................... 49.5. Accessing Session Data .......................................................................................................... 49.6. Starting the Global Session ...................................................................................................... 49.7. Locking Session Namespaces ................................................................................................... 49.8. Expiration Ejemplos ............................................................................................................... 49.9. Namespaced Sessions for Controllers with Automatic Expiration .................................................... 49.10. Limiting Session Namespace Access to a Single Instance ............................................................ 49.11. Modifying Array Data with a Session Namespace ...................................................................... 49.12. Building Arrays Prior to Session Storage .................................................................................. 49.13. Workaround: Reassign a Modified Array .................................................................................. 49.14. Workaround: store array containing reference ............................................................................
1120 1121 1122 1125 1126 1126 1126 1126 1126 1126 1127 1127 1127 1127 1128 1128 1128 1128 1129 1129 1129 1129 1129 1130 1130 1130 1130 1130 1131 1131 1131 1132 1132 1133 1133 1134 1134 1134 1134 1135 1144 1144 1144 1145 1145 1145 1147 1147 1147 1148 1149 1149 1149 1150
xlviii
49.15. PHPUnit Testing Code Dependent on Zend_Session ................................................................... 49.16. Using Zend_Config to Configure Zend_Session ......................................................................... 49.17. Session Fixation ................................................................................................................... 49.18. Basic Setup ......................................................................................................................... 49.19. Using a Multi-Column Primary Key ........................................................................................ 51.1. Using Zend_Tag .................................................................................................................... 51.2. Using Zend_Tag_Cloud .......................................................................................................... 52.1. Application Login TestCase example ........................................................................................ 52.2. Testing a UserController ......................................................................................................... 52.3. Database integration example ................................................................................................... 53.1. Using Zend_Text_Figlet .......................................................................................................... 53.2. Using Zend_Text_Table .......................................................................................................... 57.1. Ejemplo of single-language PHP code ....................................................................................... 57.2. Ejemplo of multi-lingual PHP code ........................................................................................... 57.3. Ejemplo TMX file ................................................................................................................. 57.4. Ejemplo CSV file .................................................................................................................. 57.5. Second CSV file example ....................................................................................................... 57.6. Ejemplo INI file .................................................................................................................... 57.7. Using translation options ......................................................................................................... 57.8. Handling languages with adapters ............................................................................................. 57.9. Automatically language detection ............................................................................................. 57.10. Scanning a directory structure for sources ................................................................................. 57.11. Directory scanning for languages ............................................................................................ 57.12. Filename scanning for languages ............................................................................................ 57.13. Checking if a text is translatable ............................................................................................. 57.14. Log translations ................................................................................................................... 57.15. Self defined log messages ...................................................................................................... 57.16. Handling languages with adapters ........................................................................................... 57.17. Ejemplo of traditional plural translations .................................................................................. 57.18. Ejemplo of modern plural translations ...................................................................................... 57.19. Ejemplo of modern plural translations using a different source language ......................................... 58.1. Creating a New URI with Zend_Uri::factory() ............................................................................ 58.2. Manipulating an Existing URI with Zend_Uri::factory() ................................................................ 58.3. URI Validation with Zend_Uri::check() ..................................................................................... 58.4. Allowing special characters in URIs .......................................................................................... 58.5. Getting the Scheme from a Zend_Uri_* Object ........................................................................... 58.6. Getting the Entire URI from a Zend_Uri_* Object ....................................................................... 58.7. Validating a Zend_Uri_* Object ............................................................................................... 59.1. Sitemap Lastmod Validator ..................................................................................................... 59.2. Sitemap Priority Validator ....................................................................................................... 59.3. Crear una Clase de Validacin sencilla ...................................................................................... 59.4. Escribiendo una Clase de Validacin habiendo Condiciones Dependientes ....................................... 59.5. Validacin con Condiciones Independientes, Mltiples Razones del Fracaso ..................................... 60.1. Ejemplo of the compareVersion() Method .................................................................................. 61.1. Basic Usage of Action View Helper .......................................................................................... 61.2. Cycle Helper Basic Usage ....................................................................................................... 61.3. Working with two or more cycles ............................................................................................. 61.4. Basic Usage of Partials ........................................................................................................... 61.5. Using PartialLoop to Render Iterable Models .............................................................................. 61.6. Rendering Partials in Other Modules ......................................................................................... 61.7. Basic Usage of Placeholders .................................................................................................... 61.8. Using Placeholders to Aggregate Content ................................................................................... 61.9. Using Placeholders to Capture Content ...................................................................................... 61.10. Doctype Helper Basic Usage ..................................................................................................
1150 1152 1155 1158 1159 1177 1178 1181 1188 1198 1201 1203 1227 1228 1232 1233 1233 1234 1234 1236 1237 1238 1239 1240 1241 1242 1242 1243 1244 1244 1244 1247 1247 1248 1248 1249 1249 1249 1263 1264 1266 1266 1268 1275 1293 1294 1294 1295 1296 1297 1297 1297 1298 1300
xlix
61.11. Retrieving the Doctype ......................................................................................................... 61.12. HeadLink Helper Basic Usage ................................................................................................ 61.13. HeadMeta Helper Basic Usage ............................................................................................... 61.14. Headscript With Conditional Comments ................................................................................... 61.15. HeadScript Helper Basic Usage .............................................................................................. 61.16. Capturing Scripts Using the HeadScript Helper .......................................................................... 61.17. Headstyle With Conditional Comments .................................................................................... 61.18. HeadStyle Helper Basic Usage ............................................................................................... 61.19. Capturing Style Declarations Using the HeadStyle Helper ............................................................ 61.20. HeadTitle Helper Basic Usage ................................................................................................ 61.21. Flash helper ........................................................................................................................ 61.22. Customizing the object by passing additional arguments .............................................................. 61.23. Proxying calls to the navigation container ................................................................................. 61.24. Rendering breadcrumbs ......................................................................................................... 61.25. Specifying indentation ........................................................................................................... 61.26. Customize breadcrumbs output ............................................................................................... 61.27. Rendering breadcrumbs using a partial view script ..................................................................... 61.28. Specify relations in pages ...................................................................................................... 61.29. Default rendering of links ...................................................................................................... 61.30. Specify which relations to render ............................................................................................ 61.31. Rendering a menu ................................................................................................................ 61.32. Calling renderMenu() directly ................................................................................................ 61.33. Rendering the deepest active menu .......................................................................................... 61.34. Rendering a menu with maximum depth .................................................................................. 61.35. Rendering a menu with minimum depth ................................................................................... 61.36. Rendering only the active branch of a menu ............................................................................. 61.37. Rendering only the active branch of a menu with minimum depth ................................................ 61.38. Rendering only the active branch of a menu with maximum depth ................................................ 61.39. Rendering only the active branch of a menu with maximum depth and no parents ............................ 61.40. Rendering a custom menu using a partial view script .................................................................. 61.41. Rendering an XML sitemap ................................................................................................... 61.42. Registered instance ............................................................................................................... 61.43. Within the view ................................................................................................................... 61.44. Direct usage ........................................................................................................................ 61.45. Single parameter .................................................................................................................. 61.46. List of parameters ................................................................................................................ 61.47. Array of parameters .............................................................................................................. 61.48. Change locale dynamically .................................................................................................... 61.49. Change locale statically ......................................................................................................... 61.50. Get the currently set locale .................................................................................................... 63.1. XML-RPC Method Call .......................................................................................................... 63.2. XML-RPC Method Call with Parameters ................................................................................... 63.3. Proxy the Default Namespace .................................................................................................. 63.4. Proxy Any Namespace ........................................................................................................... 63.5. Handling HTTP Errors ........................................................................................................... 63.6. Handling XML-RPC Faults ..................................................................................................... 63.7. Processing Request to Response ............................................................................................... B.1. Allow the usage of the HTTP fields ........................................................................................... B.2. Internal storage of uploaded file information ................................................................................ B.3. Disabling default caching ......................................................................................................... B.4. Changes for the rename filter from 1.6 to 1.7 ............................................................................... B.5. Changes for the count validator from 1.6 to 1.7 ............................................................................ B.6. Changes for the extension validator from 1.6 to 1.7 ....................................................................... B.7. Changes for the filessize validator from 1.6 to 1.7 ........................................................................
1300 1301 1302 1303 1304 1305 1305 1306 1306 1307 1308 1308 1311 1316 1317 1317 1317 1320 1321 1321 1323 1324 1325 1325 1326 1327 1328 1328 1329 1329 1331 1335 1336 1336 1336 1337 1337 1337 1337 1337 1343 1343 1345 1346 1346 1347 1347 1382 1382 1385 1386 1386 1387 1387
B.8. Changes for the hash validator from 1.6 to 1.7 ............................................................................. B.9. Changes for the imagesize validator from 1.6 to 1.7 ...................................................................... B.10. Changes for the size validator from 1.6 to 1.7 ............................................................................ B.11. How to change isLocale() from 1.6 to 1.7 .................................................................................. B.12. How to change getDefault() from 1.6 to 1.7 ............................................................................... B.13. Setting languages without getting notices ................................................................................... B.14. How to change your file validators from 1.6.1 to 1.6.2 ................................................................. F.1. Ejemplo: Optimized include_path ...............................................................................................
li
Instalacin
Zend Framework requiere por lo menos PHP 5.1.4 o superior, aunque Zend recomienda encarecidamente la versin 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 requisitos del sistema. para obtener ms informacin. La instalacin del Zend Framework es muy simple. Una vez que haya descargado y descomprimido el framework, deber aadir la carpeta /library de la distribucin al principio de su "include path". Tambin puede mover la carpeta "library" a cualquier otra posicin (compartida o no) de su sistema de archivos. Descargar la ltima versin estable. [http://framework.zend.com/download] Esta versin esta disponible en formatos.zip. .tar.gz, es una buena opcin para aquellos que comienzan o son nuevos en Zend Framework. Download the latest nightly snapshot. [http://framework.zend.com/download/snapshot] 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. Using a Subversion [http://subversion.tigris.org] (SVN) client. Zend Framework is open source software, and the Subversion repository used for its development is publicly available. Consider using SVN to get 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. Exporting [http://svnbook.red-bean.com/nightly/en/svn.ref.svn.c.export.html] is useful if you want to get a particular framework revision without the .svn directories as created in a working copy. Check out a working copy [http://svnbook.red-bean.com/nightly/en/svn.ref.svn.c.checkout.html] if you want contribute to Zend Framework, a working copy can be updated any time with svn update [http://svnbook.redbean.com/nightly/en/svn.ref.svn.c.update.html] and changes can be commited to our SVN repository with the svn commit [http://svnbook.red-bean.com/nightly/en/svn.ref.svn.c.commit.html] command. An externals definition [http://svnbook.red-bean.com/nightly/en/svn.advanced.externals.html] is quite convenient for developers already using SVN to manage their applications working copies. The URL for the trunk of Zend Frameworks SVN repository is: http://framework.zend.com/svn/framework/ standard/trunk [http://framework.zend.com/svn/framework/standard/trunk] Una vez que tenga disponible una copia de Zend Framework, su aplicacin necesita poder acceder a las clases del framework. Aunque hay diferentes maneras de lograr esto [http://www.php.net/manual/en/ configuration.changes.php], su include_path [http://www.php.net/manual/en/ini.core.php#ini.include-path] de PHP necesita contener una ruta a la librera de Zend Framework. Zend provides a QuickStart [http://framework.zend.com/docs/quickstart] 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. Ya que los componentes de Zend Framework estn dbilmente conectados, tiene la opcin de usar cualquier combinacin de ellos en sus aplicaciones. Los siguientes captulos presentan una referencia exhaustiva de Zend Framework, componente a componente.
Captulo 2. Zend_Acl
Introduccin
Zend_Acl provee la implementacin de un sistema simple y flexible de Listas de Control de Acceso (ACL, por sus siglas en ingls) para la administracin de privilegios. En general, una aplicacin puede utilizar las ACL para controlar el acceso a ciertos objetos protegidos, que son requeridos por otros objetos. Para los propsitos de esta documentacin: Un recurso es un objeto al cual el acceso esta controlado. Un rol es un objeto que puede solicitar acceso a un recurso. En trminos generales, Los roles solicitan acceso a los recursos . Por ejemplo, si una persona solicita acceso a un automvil, entonces la persona se convierte en el rol solicitante, y el automvil en el recurso, puesto que el acceso al automvil puede no estar disponible a cualquiera. A travs de la especificacin y uso de Listas de Control de Acceso (ACL), una aplicacin puede controlar cmo los objetos solicitantes (roles) han obtenido acceso a objetos protegidos (recursos).
Zend_Acl
Dado que la habilidad de herencia desde mltiples roles es muy til, mltiples herencias tambin introduce cierto grado de complejidad. El siguiente ejemplo ilustra la condicin de ambiguedad y como Zend_Acl soluciona esto.
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'; Ya que no hay reglas especficamente definidas para el rol "unUsuario" y "unRecurso", Zend_Acl debe buscar por reglas que puedan estar definidas para roles "unUsuario" hereda. Primero, el rol "admin" es visitado, y no hay regla de acceso definida para ste. Luego, el rol "miembro" es visitado, y Zend_Acl encuentra que aqu hay una regla especificando que "miembro" tiene permiso para acceder a "unRecurso". As, Zend_Acl va a seguir examinando las reglas definidas para otros roles padre, sin embargo, encontrara que "invitado" tiene el acceso denegado a "unRecurso". Este hecho introduce una ambigedad debido a que ahora "unUsuario" est tanto denegado como permitido para acceder a "unRecurso", por la razn de tener un conflicto de reglas heredadas de diferentes roles padre. Zend_Acl resuelve esta ambigedad completando la consulta cuando encuentra la primera regla que es directamente aplicable a la consulta. En este caso, dado que el rol "miembro" es examinado antes que el rol "invitado", el cdigo de ejemplo mostrara "permitido".
Nota
Cuando se especifican mltiples 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 autorizacin.
Zend_Acl
varias escalas de grupos sobre una amplia variedad de reas. Para crear un nuevo objeto ACL, iniciamos la ACL sin parmetros:
Nota
Hasta que un desarrollador especifique una regla"permitido", Zend_Acl deniega el acceso a cada privilegio sobre cada recurso para cada rol.
Registrando Roles
El Sistema de Administracin de Contenido (CMS) casi siempre necesita una jerarqua de permisos para determinar la capacidad de identificacin de sus usuarios. Puede haber un grupo de 'Invitados' para permitir acceso limitado para demostraciones, un grupo de 'Personal' para la mayora de usuarios del CMS quienes realizan la mayor parte de operaciones del da a da, un grupo 'Editores' para las responsabilidades de publicacin, revisin, archivo y eliminacin de contenido, y finalmente un grupo 'Administradores' cuyas tareas pueden incluir todas las de los otros grupos y tambin el mantenimiento de la informacin delicada, manejo de usuarios, configuracin de los datos bsicos y su respaldo/exportacin. 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 este ejemplo, se usa Zend_Acl_Role , pero cualquier objeto que implemente Zend_Acl_Role_Interface es admisible. Estos grupos pueden ser agregados al registro de roles de la siguiente manera:
require_once 'Zend/Acl.php'; $acl = new Zend_Acl(); // Agregar grupos al registro de roles usando <classname>Zend_Acl</classname>_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);
Zend_Acl
/* 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'));
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 tambin necesita privilegios adic $acl->allow('personal', null, array('editar', 'enviar', 'revisar')); // Editor hereda los privilegios de ver, editar, enviar, y revisar de personal, // pero tambin necesita privilegios adicionales $acl->allow('editor', null, array('publicar', 'archivar', 'eliminar')); // Administrador no hereda nada, pero tiene todos los privilegios permitidos $acl->allow('administrador'); El valor NULL en las llamadas de allow() es usado para indicar que las reglas de permiso se aplican a todos los recursos.
Zend_Acl
Consultando la ACL
Ahora tenemos una ACL flexible que puede ser usada para determinar qu solicitantes tienen permisos para realizar funciones a travs de la aplicacin web. Ejecutar consultas es la forma ms simple de usar el mtodo isAllowed() :
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
Zend_Acl
$acl->addRole(new Zend_Acl_Role('marketing'), 'staff'); A continuacin, la nota que por encima de los controles de acceso se refieren a recursos especficos (por ejemplo, "boletn informativo", "ltimas noticias", "anuncio de noticias"). Ahora aadimos estos recursos:
// Crear recursos para las reglas // newsletter $acl->addResource(new Zend_Acl_Resource('newsletter')); // news $acl->addResource(new Zend_Acl_Resource('news')); // ltimas Noticias $acl->addResource(new Zend_Acl_Resource('latest'), 'news'); // anuncio de noticias $acl->addResource(new Zend_Acl_Resource('announcement'), 'news'); Entonces es simplemente una cuestin de la definicin de estas normas ms especficas en mbitos de la ACL:
// 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'); Ahora podemos consultar el ACL con respecto a los ltimos cambios:
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
Zend_Acl
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
// Elimina la prohibicin 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 autorizacin 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
Los privilegios pueden ser modificados de manera incremental como se ha indicado anteriormente, pero un valor NULL para los privilegios anula tales cambios incrementales:
Zend_Acl
$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
Uso Avanzado
Almacenamiento Permanente de los Datos ACL
Zend_Acl fue diseado de tal manera que no requiere ninguna tecnologa particular como bases de datos o un servidor de cache para el almacenamiento de datos ACL. Al poseer una implementacin completamente construida en PHP, es posible construir herramientas de administracin 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 mtodos para configurar, y consultar, los controles de acceso de una aplicacin. El almacenamiento de los datos ACL es una tarea que se delega al desarrollador, puesto que la utilizacin variar extensamente en distintas situaciones. Dado que Zend_Acl es serializable, los objetos ACL pueden serializarse con la funcin serialize() [http://php.net/serialize] 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
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)
10
Zend_Acl
{ // ... } } Una vez la clase de asercin esta disponible, el desarrollador puede suministrar una instancia de la clase de asercin cuando asigna reglas condicionales. Una regla que es creada con una asercin slo se aplica cuando el mtodo de la asercin devuelve TRUE.
$acl = new Zend_Acl(); $acl->allow(null, null, null, new CleanIPAssertion()); El cdigo 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 peticin est en la "lista negra". Si una peticin 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" dara lugar a una negacin de acceso. ste es un caso especial, sin embargo, y debera ser entendido que en todos los otros casos (por ejemplo, cuando un rol especfico, recurso, o privilegio est especificado por la regla), una asercin fallida provoca que la regla no se aplique, y otras reglas deberan ser usadas para determinar si el acceso est permitido o denegado. El mtodo assert() de un objeto asercin es pasado a la ACL, regla, recurso, y privilegio para el cual una consulta de autorizacin (por ejemplo, isAllowed() ) se aplica, con el fin de proporcionar un contexto para que la clase de asercin determine sus condiciones cuando fuera necesario.
11
12
Captulo 3. Zend_Amf
Introduccin
Zend_Amf provee apoyo para el Formato de Mensajes de ActionScript Action Message Format [http:// en.wikipedia.org/wiki/Action_Message_Format] (AMF) de Adobe, que permite la comunicacin entre Adobe Flash Player [http://en.wikipedia.org/wiki/Adobe_Flash_Player] y PHP. Especficamente, proporciona una aplicacin para un servidor gateway que tramita las solicitudes enviadas desde Flash Player al servidor, mapeando estos requerimientos al objeto y a sus mtodos de clase, como as tambin a llamadas arbitrarias de comunicacin. Las especificaciones (en ingles) de AMF3 [http://download.macromedia.com/pub/labs/amf/amf3_spec_121207.pdf] son de libre disponibilidad y sirven como referencia para establecer qu tipos de mensajes pueden ser enviados entre Flash Player y el servidor.
Zend_Amf_Server
Zend_Amf_Server 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 fcil de recordar.
$servidor = new Zend_Amf_Server(); $servidor->setClass('Foo'); $respuesta = $servidor->handle(); echo $respuesta; Alternativamente, en su lugar puede elegir agregar una funcin simple como llamada de retorno:
$servidor = new Zend_Amf_Server(); $servidor->addFunction('myUberCoolFunction'); $respuesta = $servidor->handle(); echo $respuesta; Tambin 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 mtodos; puede hacerse simplemente pasando una segunda cadena de argumentos para cualquier addFunction() o setClass():
$servidor = new Zend_Amf_Server(); $servidor->addFunction('myUberCoolFunction', 'my') ->setClass('Foo', 'foo') ->setClass('Bar', 'bar'); $respuesta = $servidor->handle(); echo $respuesta;
13
Zend_Amf
El Zend_Amf_Server tambin permite cargar servicios dinmicamente, en funcin de una ruta de directorio ya suministrada. Puede aadir al servidor tantos directorios como desee. El orden en que se aadan los directorios al servidor ser el orden en que se realizarn las bsquedas LIFO en los directorios para coincidir con la clase. El mtodo addDirectory() realiza la accin de aadir directorios. $servidor->addDirectory(dirname(__FILE__) .'/../services/'); $servidor->addDirectory(dirname(__FILE__) .'/../package/'); Cuando se llama a servicios remotos, los nombres de los directorios que contengan las fuentes pueden tener los delimitadores guin bajo ("_") y el punto ("."). Cuando se utilize un guin bajo ("_") tanto en PEAR como en Zend Framework, se respetarn 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 com/Foo/Bar.php. Si se usa la notacin punto para su servicio remoto como com.Foo.Bar cada ruta incluida deber tener com/Foo/Bar.php agregado al final para autocargar Bar.php Todos las solicitudes AMF enviadas al script sern manejadas por el servidor, y este devolver una respuesta AMF.
Todos los mtodos y las funciones agregadas requieren bloques de documentacin (docblocks)
Como todos los dems componentes del servidor en Zend Framework, debe documentar los mtodos de su clase usando PHP docblocks. Como mnimo, necesita proporcionar anotaciones para cada argumento as como para el valor de retorno. Como ejemplos: // Funcin que agregar: /** * @param string $nombre * @param string $saludo * @return string */ function holaMundo($ombre, $saludo = 'Hola') { return $saludo . ', ' . $nombre; }
// Clase agregada class Mundo { /** * @param string $nombre * @param string $saludo * @return string */ public function hola($nombre, $saludo = 'Hola') { return $saludo . ', ' . $nombre; } } Pueden usarse otras anotaciones, pero sern ignoradas.
14
Zend_Amf
<?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"/>
15
Zend_Amf
</channel-definition> </channels> </services-config> 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 Zend_Amf_Server:
<channel-definition id="zend-endpoint" <endpoint uri="http://example.com/server.php" class="flex.messaging.endpoints.AMFEndpoint"/> </channel-definition> Advierta que a este canal le hemos dado un identificador, "zend-endpoint". El ejemplo crea un servicio cuyo destino hace referencia a este canal, asignndole tambin un ID, en este caso es "zend". Dentro de nuestros ficheros Flex MXML, necesitamos vincular un RemoteObject al servicio. En MXML, esto podra hacerse as:
<mx:RemoteObject id="myservice" fault="faultHandler(event)" showBusyCursor="true" destination="zend"> Aqu, hemos definido un nuevo objeto remoto identificado por "myservice" vinculado destino de servicio "zend" que hemos definido en el fichero services-config.xml. Entonces invocamos sus mtodos en nuestro ActionScript simplemente llamando a "myservice.<method>". . A modo de ejemplo:
myservice.world.hello("Wade"); Para ms informacin sobre como invocar a Flex RemoteObject visite el sitio de ayuda de Adobe Flex 3 en:http:// livedocs.adobe.com/flex/3/html/help.html?content=data_access_4.html.
Manejo de errores
Por defecto, todas las excepciones producidas en sus clases o funciones adjuntas sern 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 "produccin" (el estado por defecto). Cuando se est en modo de produccin, nicamente el cdigo de excepcin ser devuelto. Si desactiva el modo de produccin, algo que debe hacerse slo para probar -- sern devueltos ms detalles de la excepcin: el mensaje de excepcin (error), lnea y backtrace sern adjuntados. Para desactivar el modo de produccin, haga lo siguiente:
$server->setProduction(false);
16
Zend_Amf
$server->setProduction(true);
Respuestas de AMF
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 mtodo del servidor handle() que devuelve el objeto respuesta.
Objetos tipados
Similarmente a SOAP, AMF permite pasar objetos entre cliente y servidor. Esto le da una gran flexibilidad y coherencia a ambos entornos. Zend_Amf ofrece tres mtodos para mapear ActionScript y objetos PHP. Primero, usted puede crear uniones explcitas a nivel del servidor, utilizando el mtodo setClassMap(). El primer argumento es el nombre de la clase de ActionScript, el segundo es el nombre de la clase PHP que lo mapea:
// Mapea la clase ActionScript 'ContactVO' a la clase PHP 'Contact': $servidor->setClassMap('ContactVO', 'Contact'); Segundo, en su clase PHP puede ajustar la propiedad como pblica mediante $_explicitType, con el valor representativo de la clase ActionScript que mapear:
class Contact {
17
Zend_Amf
public $_explicitType = 'ContactVO'; } Tercero, en un sentido similar, puede definir como pblico el mtodo getASClassName() dentro de su clase. Este mtodo debe devolver la clase ActionScript apropiada:
class Contact { public function getASClassName() { return 'ContactVO'; } } Aunque hemos creado ContactVO en el servidor, ahora tenemos que hacer su clase correspondiente en AS3 para que el servidor pueda mapear el objeto. 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 cdigo en el fichero para terminar de crear la clase.
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 { } } } La clase es sintcticamente 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 ContactVO Es obligatorio que en esta etiqueta(tag), el valor que se estableci es la clase PHP sea estrictamente equivalente.
[Bindable] private var myContact:ContactVO; private function getContactHandler(event:ResultEvent):void { myContact = ContactVO(event.result); } El siguiente resultado del evento debido a la llamada de servicio, se incorpor instantneamente a ContactVO de Flex. Cualquier cosa que est ligada a myContact ser actualizada con los datos retornados por ContactVO.
18
Zend_Amf
Recursos
Zend_Amf provides tools for mapping resource types returned by service classes into data consumable by ActionScript. In order to handle specific resource type, the user needs to create a plugin class named after the resource name, with words capitalized and spaces removed (so, resource type "mysql result" becomes MysqlResult), with some prefix, e.g. My_MysqlResult. This class should implement one method, parse(), receiving one argument - the resource and returning the value that should be sent to ActionScript. The class should be located in the file named after the last component of the name, e.g. MysqlResult.php. The directory containing the resource handling plugins should be registered with Zend_Amf type loader:
Zend_Amf_Parse_TypeLoader::addResourceDirectory( "My", "application/library/resources/My" )); For detailed discussion of loading plugins, please see the plugin loader section. Default directory for Zend_Amf resources is registered automatically and currently contains handlers for "mysql result" and "stream" resources.
// Ejemplo class implementing handling resources of type mysql result class Zend_Amf_Parse_Resource_MysqlResult { /** * Parse resource into array * * @param resource $resource * @return array */ public function parse($resource) { $result = array(); while($row = mysql_fetch_assoc($resource)) { $result[] = $row; } return $result; } } Trying to return unknown resource type (i.e., one for which no handler plugin exists) will result in an exception.
19
Zend_Amf
Main.as. Abra ambos ficheros con su editor. Ahora vamos a conectar las dos ficheros a travs de la clase documento. Seleccione ZendEjemplo 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 enZendEjemplo.fla Cuando ejecute el fichero ZendEjemplo de Flash se ejecutar ahora la clase Main.as El paso siguiente ser aadir ActionScript para hacer una lamada AMF. Ahora vamos a hacer una clase Main(principal) para que podamos enviar los datos al servidor y mostrar el resultado. Copie el cdigo siguiente en su fichero Main.as y luego vamos a recorrer el cdigo para describir cul es el papel de cada elemento.
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)); } } } Primero tenemos que importar dos bibliotecas de ActionScript que realizan la mayor parte del trabajo. La primera es NetConnection que acta 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 estn relacionados con el xito o el fracaso de la llamada.
import flash.net.NetConnection; import flash.net.Responder; En la clase necesitaremos tres variables para representar a NetConnection, Responder, y la URL del gateway a nuestra instalacin Zend_Amf_Server.
20
Zend_Amf
private var gateway:String = "http://example.com/server.php"; private var connection:NetConnection; private var responder:Responder; En el constructor Main creamos un Responder(respondedor) y una nueva conexin al punto final de Zend_Amf_Server. El respondedor define dos diferentes mtodos para manejar la respuesta desde el servidor. Por simplicidad los hemos llamado onResult y onFault.
responder = new Responder(onResult, onFault); connection = new NetConnection; connection.connect(gateway); La funcin onComplete se ejecuta tan pronto como la construccin ha concluido, enviando los datos al servidor. Necesitamos aadir una lnea ms que hace una llamada a la funcin Zend_Amf_Server Mundo->hola.
connection.call("Mundo.hola", responder, params); Cuando creamos la variable responder hemos definido las funciones onResult y onFault para manejar la respuesta proveniente del servidor. Hemos aadido la funcin OnResult para el resultado exitoso desde el servidor. Cada vez que se ejecuta apropiadamente el manejo de conexin con el servidor, el manejador de eventos llama esta funcin.
private function onResult(result:Object):void { // Muestra los datos devueltos trace(String(result)); } La funcin 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 invlida, el servicio remoto o mtodo no existe o cualquier otra cuestin relacionada con la conexin.
private function onFault(fault:Object):void { trace(String(fault.description)); } La inclusin de ActionScript para realizar la conexin remota ha finalizado. Al ejecutar el fichero ZendEjemplo, se establece una conexin con Zend_Amf. En resumen, se han aadido las variables requeridas para abrir una conexin con el servidor remoto, se han definido qu mtodos se deben utilizar cuando su aplicacin recibe una respuesta desde el servidor, y finalmente se han mostrado los datos de salida devueltos a travs de trace().
Authentication
Zend_Amf_Server allows you to specify authentication and authorization hooks to control access to the services. It is using the infrastructure provided by Zend_Auth and Zend_Acl components. In order to define authentication, the user provides authentication adapter extening Zend_Amf_Auth_Abstract abstract class. The adapter should implement the authenticate() method just like regular authentication adapter. The adapter should use properties _username and _password from the parent Zend_Amf_Auth_Abstract class in order to authenticate. These values are set by the server using setCredentials() method before call to authenticate() if the credentials are received in the AMF request headers. The identity returned by the adapter should be an object containing property role for the ACL access control to work.
21
Zend_Amf
If the authentication result is not successful, the request is not proceseed further and failure message is returned with the reasons for failure taken from the result. The adapter is connected to the server using setAuth() method:
$server->setAuth(new My_Amf_Auth()); Access control is performed by using Zend_Acl object set by setAcl() method:
$acl = new Zend_Acl(); createPermissions($acl); // create permission structure $server->setAcl($acl); If the ACL object is set, and the class being called defines initAcl() method, this method will be called with the ACL object as an argument. The class then can create additional ACL rules and return TRUE, or return FALSE if no access control is required for this class. After ACL have been set up, the server will check if access is allowed with role set by the authentication, resource being the class name (or NULL for function calls) and privilege being the function name. If no authentication was provided, then if the anonymous role was defined, it will be used, otherwise the access will be denied.
if($this->_acl->isAllowed($role, $class, $function)) { return true; } else { require_once 'Zend/Amf/Server/Exception.php'; throw new Zend_Amf_Server_Exception("Access not allowed"); }
22
Captulo 4. Zend_Application
Introduccin
Zend_Application facilita la inicializacin de nuestras aplicaciones proporcionando recursos reutilizables, comunes y asociados con el mdulo de la clase de arranque y control de dependencias. Tambin se ocupa de establecer el entorno de PHP e introduce la autocarga (autoloading) por defecto.
Usando Zend_Tool
La forma ms rpida para comenzar a utilizar Zend_Application es usar Zend_Tool para generar su proyecto. Esto tambin crear su clase y archivo Bootstrap. Para crear un proyecto, ejecute el comando zf (en sistemas *nix):
C:> zf.bat create project newproject Ambos crearn una estructura del proyecto que se parece a lo siguiente:
newproject |-- application | |-- Bootstrap.php | |-- configs | | `-- application.ini | |-- controllers | | |-- ErrorController.php | | `-- IndexController.php | |-- models | `-- views | |-- helpers | `-- scripts | |-- error | | `-- error.phtml | `-- index | `-- index.phtml
23
Zend_Application
|-|-| `--
library public `-- index.php tests |-- application | `-- bootstrap.php |-- library | `-- bootstrap.php `-- phpunit.xml
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {} Tambin notar que se ha creado un archivo de configuracin, newproject/application/configs/ application.ini. Con el siguiente contenido:
[production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" [staging : production] [testing : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 Todos las opciones en este archivo de configuracin son para su uso con Zend_Application y su bootstrap. Otro archivo de inters es newproject/public/index.php, el cual invoca a Zend_Application y lo enva.
<?php // Define el path al directorio de la aplicacin defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application')); // Define el entorno de la aplicacin defined('APPLICATION_ENV')
24
Zend_Application
|| define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production')); /** Zend_Application */ require_once 'Zend/Application.php'; // Crea la application, el bootstrap, y lo ejecuta $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini' ); $application->bootstrap() ->run(); Para continuar con el inicio rpido, por favor vaya a la seccin de Recursos.
<?php class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { } Ahora, debe crear su configuracin. Para este tutorial, usaremos una configuracin de estilo INI; puede, por supuesto, usar un archivo de configuracin XML o PHP. Cree el archivo application/configs/application.ini, proporcionando el siguiente contenido.
[production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" [staging : production] [testing : production] phpSettings.display_startup_errors = 1
25
Zend_Application
phpSettings.display_errors = 1 [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 Ahora, modifiquemos su script de entrada (gateway), public/index.php. Si el archivo no existe, cree uno; de lo contrario, sustityalo por el siguiente contenido:
<?php // Define la ruta al directorio de la aplicacin defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application')); // Define el entorno de la aplicacin defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production')); // Typically, you will also want to add your library/ directory // to the include_path, particularly if it contains your ZF installed set_include_path(implode(PATH_SEPARATOR, array( dirname(dirname(__FILE__)) . '/library', get_include_path(), ))); /** Zend_Application */ require_once 'Zend/Application.php'; // Crea la aplicacin, el bootstrap, y lo ejecuta $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini' ); $application->bootstrap() ->run(); Se puede observar que el valor constante del entorno de la aplicacin busca una variable de entorno "APPLICATION_ENV". Recomendamos este ajuste en el entorno de su servidor web. En Apache, puede tambin configurarlo en la definicin de su vhost, o en su archivo .htaccess. Recomendamos el siguiente contenido para su archivo public/.htaccess:
SetEnv APPLICATION_ENV development RewriteEngine On RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L]
26
Zend_Application
[production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" ; ADD THE FOLLOWING LINES resources.layout.layout = "layout" resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts" [staging : production] [testing : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 Si hasta ahora no lo ha hecho, genere el directorio application/layouts/scripts/, y el archivo layout.phtml dentro de ese directorio. Un buen layout inicial es como sigue (y vincularlo con los recursos de la vista que cubriremos a continuacin):
27
Zend_Application
<head> <?php <?php <?php <?php </head> <body> <?php </body> </html>
En este punto, usted tendr un layout ya trabajando. Ahora, vamos aadir una vista de recurso personalizada. Cuando se inicializa la vista, queremos establecer el DocType HTML y un valor predeterminado del ttulo para utilizarlo en la cabecera de HTML. Esto puede llevarse a cabo editando su clase Bootstrap para agregar un mtodo.
<?php class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initView() { // Inicializar la vista $view = new Zend_View(); $view->doctype('XHTML1_STRICT'); $view->headTitle('My First Zend Framework Application'); // Aadir al ViewRenderer $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper( 'ViewRenderer' ); $viewRenderer->setView($view); // Retorno, de modo que pueda ser almacenada en el arranque (bootstrap) return $view; } } Este mtodo se ejecuta automticamente cuando arranca la aplicacin, y se asegurar que su vista sea inicializada segn las necesidades de su aplicacin.
Teora de Operacin
Obtener una aplicacin MVC configurada y lista para funcionar requiere de un porcentaje cada vez mayor de cdigo que disponga de ms caractersticas, tales como: Establecer la base de datos, configurar la vista y los ayudantes(helpers) de vistas, configurar los layouts, registro de plugins, registro de ayudantes de accin (action helpers), y mucho ms.
28
Zend_Application
Adems, a menudo desear reutilizar el mismo cdigo para arrancar sus pruebas, un cronjob, o un servicio en linea de comandos. Si bien es posible incluir simplemente su script bootstrap, a menudo hay inicializaciones que son especficas del entorno, puede que no necesite el MVC para un cronjob, o simplemente la capa de DB para un servicio script. Zend_Application pretende hacer esto ms fcil y promover la reutilizacin mediante el encapsulamiento del bootstraping en paradigmas de OOP. Zend_Application est dividida en tres reas: Zend_Application: carga el entono de PHP, incluyendo include_paths y autocarga, e instancia la clase requerida de bootstrap. Zend_Application_Bootstrap: suministra interfaces para las clases bootstrap. Zend_Application_Bootstrap_Bootstrap ofrece funcionalidad comn para la mayora de las necesidades de bootstrap, incluyendo algoritmos de comprobacin de dependencias y la capacidad de cargar recursos de bootstrap por demanda. Zend_Application_Resource provee una interfaz para recursos estandar de bootstrap que pueden ser cargados por demanda mediante una instancia bootstrap, as como implementaciones de varios recursos por defecto. Los desarrolladores crean una clase de arranque(bootstrap) para sus aplicaciones, extendiendo Zend_Application_Bootstrap_Bootstrap o implementando (mnimamente) Zend_Application_Bootstrap_Bootstrapper. El punto de entrada (por ejemplo, public/index.php) cargar Zend_Application, y la instanciar pasando por: El entorno actual Opciones para bootstrapping Las opciones de bootstrap incluyen la ruta hacia el archivo que contiene la clase bootstrap y opcionalmente: Cualquier include_paths extras a establecer Cualquier otro namespace de autocarga adicional a registrar Cualquier configuracin de php.ini a inicializar El nombre de clase para la clase bootstrap (si no es "Bootstrap") Pares de recursos prefijo de ruta a usar Cualquier recurso a usar (por nombre de clase o nombre corto) Ruta adicional al archivo de configuracin a cargar Opciones adicionales de configuracin Las opciones puden ser una array, un objeto Zend_Config, o la ruta a un archivo de configuracin.
Bootstrapping
La segunda rea de responsabilidad de Zend_Application es ejecutar la solicitud del bootstrap. Los bootstraps necesitan mnimamente implementar Zend_Application_Bootstrap_Bootstrapper, la que define la siguiente API:
interface Zend_Application_Bootstrap_Bootstrapper
29
Zend_Application
{ public public public public public public public public } Esta API permite aceptar al bootstrap en el entorno y la configuracin desde el objeto de la aplicacin, informa la responsabilidad de los recursos para los recursos bootstraping, luego hace el bootstrap y ejecuta la aplicacin. Puede implementar esta interfaz Zend_Application_Bootstrap_BootstrapAbstract, Zend_Application_Bootstrap_Bootstrap. usted mismo, o extendiendo usar function function function function function function function function __construct($application); setOptions(array $options); getApplication(); getEnvironment(); getClassResources(); getClassResourceNames(); bootstrap($resource = null); run();
Adems de esta funcionalidad, hay muchas otras reas de incumbencia con las cuales debe familiarizarse.
Mtodos Recursos
La implementacin de Zend_Application_Bootstrap_BootstrapAbstract proporciona una simple convencin para definir mtodos de recursos de clase. Cualquier mtodo protegido cuyo nombre comience con un prefijo _init ser considerado un mtodo de recurso. Para arrancar un nico mtodo de recurso, utilizar el mtodo bootstrap(), y pasarle el nombre del recurso. El nombre ser el nombre de mtodo menos el prefijo _init. Para arrancar varios mtodos de recursos, pasar un array de nombres. Para bootstrap de todos los mtodos de recursos, no pasar nada. Tome las siguientes clases bootstrap:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initFoo() { // ... } protected function _initBar() { // ... } protected function _initBaz() { // ... } } Para arrancar solo el mtodo _initFoo(), haga lo siguiente:
30
Zend_Application
$bootstrap->bootstrap(array('foo', 'bar)); Para arrancar todos los mtodos de recursos, llame a bootstrap() sin argumentos:
$bootstrap->bootstrap();
interface Zend_Application_Bootstrap_ResourceBootstrapper { public function registerPluginResource($resource, $options = null); public function unregisterPluginResource($resource); public function hasPluginResource($resource); public function getPluginResource($resource); public function getPluginResources(); public function getPluginResourceNames(); public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader); public function getPluginLoader(); } Bsicamente los recursos de plugins ofrecen la posibilidad de crear recursos incializadores que puede ser re-utilizados entre aplicaciones. Esto le permite mantener su actual bootstrap relativamente limpio, e introducir nuevos recursos sin necesidad de tocar su propio arranque (bootstrap). Zend_Application_Bootstrap_BootstrapAbstract (y Zend_Application_Bootstrap_Bootstrap por extensin) implementan esta interfaz, que le permite utilizar recursos de plugins. Para utilizar recursos de plugins, debe especificarlos en las opciones que pas al objeto aplicacin y/o bootstrap. Estas opciones pueden provenir de un archivo de configuracin, o ser pasadas manualmente. Las opciones debern ser pares de clave/opcin, representando con la clave el nombre del recurso. El nombre de recurso ser el segmento siguiente al prefijo de clase. Por ejemplo, los recursos que vienen con Zend Framework tienen el prefijo de clase "Zend_Application_Resource_"; cualquier cosa que le siga despus debe ser el nombre del recurso. Como por ejemplo,
31
Zend_Application
$application = new Zend_Application(APPLICATION_ENV, array( 'resources' => array( 'FrontController' => array( 'controllerDirectory' => APPLICATION_PATH . '/controllers', ), ), )); Esto indica que el recurso "Front Controller", debera ser utilizado, con las opciones especificadas. Si usted comienza a escribir su propio recurso de plugin, o utilizar recursos de plugin de terceras partes, necesitar decirle a su bootstrap donde encontrarlos. Internamente, el bootstrap utiliza Zend_Loader_PluginLoader, de manera tal que slo necesitar indicar el prefijo de la clase comn como pares de path. Supongamos por ejemplo, que usted tiene recursos de plugins personalizados en APPLICATION_PATH/ resources/ y que ellos comparten el prefijo de clase comn My_Resource. Entonces, debera pasar esa informacin al objeto aplicacin de la siguiente manera:
$application = new Zend_Application(APPLICATION_ENV, array( 'pluginPaths' => array( 'My_Resource' => APPLICATION_PATH . '/resources/', ), 'resources' => array( 'FrontController' => array( 'controllerDirectory' => APPLICATION_PATH . '/controllers', ), ), )); Ahora usted est habilitado para utilizar los recursos de ese directorio. Tal como los mtodos de recursos, utilice el mtodo bootstrap() para ejecutar recursos de plugins. Tambin tal como con los mtodos de recursos, puede especificar bien un nico recurso de plugin, mltiples plugins (va un array), o todos los plugins. Adems, los puede combinar para ejecutar mtodos de recursos.
// Ejecute uno: $bootstrap->bootstrap('FrontController'); // Ejecute varios: $bootstrap->bootstrap(array('FrontController', 'Foo')); // Ejecute todos los mtodos de recursos y plugins: $bootstrap->bootstrap();
Registro de Recursos
Muchos, si no todos, sus mtodos de recursos o plugins inicializarn objetos y, en muchos casos, estos objetos sern necesarios en otros lugares de su aplicacin. Cmo se puede acceder a ellos? Zend_Application_Bootstrap_BootstrapAbstract ofrece un registro local para estos objetos. Para almacenar sus objetos en ellos, simplemente debe devolverlos desde sus recursos.
32
Zend_Application
Para mxima flexibilidad, este registro es mencionado internamente como un "contenedor"; el nico requisito es que sea un objeto. Los recursos son luego registrados como propiedades nombrados despus del nombre del recurso. Por defecto, una instancia de Zend_Registry es utilizada, pero tambin puede especificar cualquier otro objeto que desee. Los mtodos setContainer() y getContainer() pueden ser utilizados para manipular el contenedor en si mismo. getResource($resource) puede ser utilizado para recuperar un recurso determinado del contenedor, y hasResource($resource) para verificar si el recurso ha sido efectivamente registrado. Como ejemplo, considere una visin bsica del recurso:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initView() { $view = new Zend_View(); // ms inicializacin... return $view; } } A continuacin, puede comprobarlos y/o traerlos as:
// Usando el par has/getResource(): if ($bootstrap->hasResource('view')) { $view = $bootstrap->getResource('view'); } // Via el contenedor: $container = $bootstrap->getContainer(); if (isset($container->view)) { $view = $container->view; } Tenga en cuenta que el registro y el contenedor no es global. Esto significa que usted necesita acceso al bootstrap a fin de recuperar recursos. Zend_Application_Bootstrap_Bootstrap proporciona cierta comodidad para ello: durante las ejecucin de run() se registra a s mismo como el "Front Controller" en el parmetro del "bootstrap", que permite buscarlo desde el router, despachador, plugins, y los contoladores de accin. Como ejemplo, si quiere tener acceso a los recursos de la vista desde dentro de su controlador de accin, podra hacer lo siguiente:
class FooController extends Zend_Controller_Action { public function init() { $bootstrap = $this->getInvokeArg('bootstrap'); $view = $bootstrap->getResource('view'); // ... }
33
Zend_Application
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initRequest() { // Asegurar que el front controller es inicializado $this->bootstrap('FrontController'); // Recuperar el front controller desde el registro de bootstrap $front = $this->getResource('FrontController'); $request = new Zend_Controller_Request_Http(); $request->setBaseUrl('/foo'); $front->setRequest($request); // Garantizar que la solicitud es almacenada en el registro de bootstrap return $request; } }
Plugins de Recursos
Como se seal anteriormente, una buena forma de crear recursos de bootstrap re-utilizables y a traspasar mucha de su codificacin a clases discretas es utilizar plugins de recursos. Si bien Zend Framework se entrega con una serie de plugins de recursos, la intencin es que los desarrolladores deberan escribir los suyos para encapsular sus propias necesidades de inicializacin. Los recursos plugins solo necesitan implemetar Zend_Application_Resource_Resource, o ms simple an, extenderse Zend_Application_Resource_ResourceAbstract. La interfaz bsica es simplemente esto:
34
Zend_Application
interface Zend_Application_Resource_Resource { public function __construct($options = null); public function setBootstrap( Zend_Application_Bootstrap_Bootstrapper $bootstrap ); public function getBootstrap(); public function setOptions(array $options); public function getOptions(); public function init(); } La interfaz define simplemente que un recurso plugin debe aceptar opciones para el constructor, tiene mecanismos de establecer y recuperar opciones, mecanismos de establecer y recuperar el objeto bootstrap, y un mtodo de inicializacin. Como ejemplo, supongamos que tiene una vista comn de inicializacin que utiliza en sus aplicaciones. Usted tiene un doctype comn, CSS y JavaScript, y quiere se capaz de pasar desde un documento base el ttulo via configuracin. Un recurso plugin tal podra ser como este:
class My_Resource_View extends Zend_Application_Resource_ResourceAbstract { protected $_view; public function init() { // Regresa la vista de manera que bootstrap la almacenar en el registro return $this->getView(); } public function getView() { if (null === $this->_view) { $options = $this->getOptions(); $title = ''; if (array_key_exists('title', $options)) { $title = $options['title']; unset($options['title']); } $view = new Zend_View($options); $view->doctype('XHTML1_STRICT'); $view->headTitle($title); $view->headLink()->appendStylesheet('/css/site.css'); $view->headScript()->appendfile('/js/analytics.js'); $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper( 'ViewRenderer' ); $viewRenderer->setView($view);
35
Zend_Application
$this->_view = $view; } return $this->_view; } } Minetrtas usted haya registrado el path del prefijo para este recurso de plugin, puede usarlo en su aplicacin. Mejor an, ya que usa el cargador de plugin, usted est pasando por encima del recurso de plugin de la "View" que viene con Zend Framework, se est asegurando as que usa el suyo en lugar del original.
Ejemplos
La propia clase Bootstrap suelen ser bastante mnima; a menudo, ser simplemente un taln vaco ampliando la clase base bootstrap:
; APPLICATION_PATH/configs/application.ini [production] bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" [testing : production] [development : production] Sin embargo, si debiera ser necesaria un inicializacin personalizada, usted tiene dos opciones. En primer lugar, usted puede escribir mtodos prefijados con _init para especificar cdigos distintos de arranque. Estos mtodos pueden ser llamados por bootstrap(), y tambin pueden ser llamados como si fueran mtodos pblicos: bootstrap<resource>(). Deben aceptar opcionalmente un array de opciones. Si su mtodo recurso devuelve un valor, ser almacenado en un contenedor en el bootstrap. Esto puede ser til cuando diferentes recursos necesitan interactuar (como un recurso inyectndose a s mismo en otro). Luego, el mtodo getResource() puede ser utilizado para recuperar esos valores. El siguiente ejemplo muestra un recurso de mtodo para inicializar el objeto solicitado. Hace uso del segimiento de la dependencia (que depende del recurso Front Controller), obteniendo un recurso desde el bootstrap y devolver el valor para almacenar en el bootstrap.
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initRequest(array $options = array()) { // Garantizar que la instancia de front controller est presente, y buscarla
36
Zend_Application
$this->bootstrap('FrontController'); $front = $this->getResource('FrontController'); // Inicializar el objeto requerido $request = new Zend_Controller_Request_Http(); $request->setBaseUrl('/foo'); // Agregarlo al front controller $front->setRequest($request); // Bootstrap guardar este valor en la clave 'request' de su contenedor return $request; } } Ntese en este ejemplo la llamada a bootstrap(); esto asegura que el front controller ha sido inicializado antes de llamar a este mtodo. Esa llamada puede desencadenar tanto un recurso u otro mtodo de la clase. La otra opcin es usar plugins de recursos, estos son objetos que realizan inicializaciones especficas, y pueden ser especificados: Cuando se instancia un onbeto de Zend_Application Durante la inicializacin del objeto bootstrap (arranque) Habilitndolos explcitamente a travs del mtodo de llamada al objeto bootstrap Los recursos de plugins implementan Zend_Application_Resource_ResourceAbstract, que define simplemente que permitirn la inyeccin del llamador y opciones, y que tienen un mtodo init() method. Como ejemplo, un recurso de una Vista (View) personalizada de bootstrap podra ser como lo siguiente:
class My_Bootstrap_Resource_View extends Zend_Application_Resource_ResourceAbstract { public function init() { $view = new Zend_View($this->getOptions()); Zend_Dojo::enableView($view); $view->doctype('XHTML1_STRICT'); $view->headTitle()->setSeparator(' - ')->append('My Site'); $view->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=utf-8'); $view->dojo()->setDjConfigOption('parseOnLoad', true) ->setLocalPath('/js/dojo/dojo.js') ->registerModulePath('../spindle', 'spindle') ->addStylesheetModule('spindle.themes.spindle') ->requireModule('spindle.main') ->disable(); $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper( 'ViewRenderer'
37
Zend_Application
); $viewRenderer->setView($view); return $view; } } Para decirle al bootstrap que utilice ste, se tendra que proporcionar ya sea el nombre de la clase del plugin del recurso, o una combinacin del del prefijo de la ruta de carga del plugin y el nombre corto del plugin del recurso (por ejemplo, "view"):
$application = new Zend_Application( APPLICATION_ENV, array( 'resources' => array( 'My_Bootstrap_Resource_View' => array(), // full class name; OR 'view' => array(), // short name 'FrontController' => array( 'controllerDirectory' => APPLICATION_PATH . '/controllers', ), ), // For short names, define plugin path: 'pluginPaths = array( 'My_Bootstrap_Resource' => 'My/Bootstrap/Resource', ) ) ); Los recursos que son plugins puede llamar a otros recursos e inicializadores accediendo al bootstrap padre:
class My_Bootstrap_Resource_Layout extends Zend_Application_Resource_ResourceAbstract { public function init() { // ensure view is initialized... $this->getBootstrap()->bootstrap('view'); // Get view object: $view = $this->getBootstrap()->getResource('view'); // ... } } En el uso normal, se podra instanciar la aplicacin, arrancarla, y ejecutarla:
38
Zend_Application
$application = new Zend_Application(...); $application->bootstrap() ->run(); Para un script personalizado, se podra necesitar simplemente inicializar recursos especficos:
$application = new Zend_Application(...); $application->getBootstrap()->bootstrap('db'); $service = new Zend_XmlRpc_Server(); $service->setClass('Foo'); // uses database... echo $service->handle(); En lugar de utilizar el mtodo bootstrap() para llamar a los mtodos internos o recursos, tambin puede usar sobrecarga:
Funcionalidad Bsica
Aqu encontrar documentacin del tipo API acerca de todos los componentes bsicos de Zend_Application.
Zend_Application
Zend_Application proporciona la funcionalidad bsica del componente, y el punto de entrada a su aplicacin Zend Framework. Su propsito es doble: para configurar el medio ambiente PHP (incluyendo autocarga), y ejecutar su aplicacin bootstrap.
Option names
Please note that option names are case insensitive. Tpicamente, pasar toda la configuracin al constructor Zend_Application, pero tambin puede configurar totalmente el objeto utilizando sus propios mtodos. En esta referencia se ilustran ambos casos de uso.
39
Zend_Application
getAutoloader()
Zend_Loader_Autoloader N/A
setOptions(array $options)
Zend_Application
$options: requerido. Todas las opciones se Un array de opciones de almacenan internamente, y aplicacin. llamando al mtodo varias veces las opciones se fusionarn. Las opciones concordantes con los diversos mtodos setter se
40
Zend_Application
Mtodo
Valor de Retorno
Parmetros
Descripcin pasarn a esos mtodos. Como ejemplo, la opcin "phpSettings" ser pasada a setPhpSettings(). (Los nombres de opciones son indiferentes a maysculas/ minsculas.) Recuperar todas las opciones usadas para inicializar el objeto; podra ser utilizada para guardar en cache a travs de Zend_Config las opciones para serializar un formato entre reqerimientos.
getOptions()
array
N/A
hasOption($key)
Boolean
$key: String opcional de Determinar si una opcin la clave de lookup con la clave ha sido registrada o no. Las claves son indiferentes a maysculas/ minsculas. $key: String opcional de Recuperar el valor de la la clave de lookup opcin de una clave dada. Retorna NULL si la clave no existe. $settings: requerido. Establece un conjunto de Array asociativo en los ajustaes en php.ini. settings de PHP INI. para run-time. Las configuraciones separadas $prefix: opcional. por punto pueden ser Prefijo de tipo string anidadas jerrquicamente para anteponer a (lo que puede ocurrir la opcin claves. con los archivos INI Usado internamente para Zend_Config) mediante permitir el mapping un array de de arrays, y an anidado de matrices resolver correctamente. separados por puntos en las claves de php.ini. En el uso normal, este argumento nunca debe ser pasado por un usuario. $namespaces: Registra los namespaces requerido. Array de con la instancia strings representando Zend_Loader_Autoloader. los namespaces a registrar con la instancia Zend_Loader_Autoloader. $path:: requerido. Puede ser tanto una instancia de Zend_Application_Bootstrap_Bootstrapper
getOption($key)
mixed
41
Zend_Application
Mtodo
Valor de Retorno
Parmetros Descripcin , un string del path a la clase bootstrap, un arrray asociativo de classname =>nombre_de_archivo, o un array asociativo con las claves 'class' y 'path'. $class: opcional. Si $path: es un string, entonces $class puede ser especificado, y debe ser el string nombre de clase de la clase contenida en el archivo representado por path.
getBootstrap() bootstrap()
null | N/A Recuperar la instancia del Zend_Application_Bootstrap_Bootstrapperbootstrap registrado. void N/A Llamar al mtodo bootstrap() para cargar la aplicacin. Llamar al mtodo run() del bootstrap para despachar la aplicacin.
run()
void
N/A
Zend_Application_Bootstrap_Bootstrapper
Zend_Application_Bootstrap_Bootstrapper es la interfaz base que deben implementar todas clases bootstrap. Las funcionalidades de base estn encaminadan a la configuracin, identificacin de los recursos, bootstraping (ya sea de los recursos individuales o de toda la aplicacin), y de despachar la aplicacin. Los siguientes mtodos conforman la definicin de la interfaz.
__construct($application) void
$application: Constructor. Acepta un requerido. Debe aceptar solo argumento, que un objeto debe ser un objeto Zend_Application Zend_Application, u o otro objero bootstrap. Zend_Application_Bootstrap_Bootstrapper como nico argumento.
setOptions(array $options)
Zend_Application_Bootstrap_Bootstrapper $options: requerido. Tpicamente, cualquier Array de opciones a opcin que tiene un setter establecer. concordante invocar ese setter; de lo contrario, la opcin ser simplemente almacenada para su recuperacin posterior.
42
Zend_Application
Mtodo getApplication()
Valor Retornado
Parmetros
Descripcin
Zend_Application | N/A Recuperar el objeto Zend_Application_Bootstrap_Bootstrapperaplicacin/bootstrap pasado via constructor. String N/A Recuperar el string del medio ambiente registrado con el objeto padre de la aplicacin o del bootstrap. Recuperar una lista de los recursos inicializadores de nombres disponibles con los que fueron definidos en la clase. Esto puede ser de implementacin especfica. Si $resource est vaco, ejecutar todos los recursos del bootstrap. Si es un string, ejecutar ese nico recurso; si es un array, ejecutar cada recurso del array. Define qu lgica de aplicacin ejecutar luego del bootstrap.
getEnvironment()
getClassResources() array
N/A
$resource: optional.
run()
void
N/A
Zend_Application_Bootstrap_ResourceBootstrapper
Zend_Application_Bootstrap_ResourceBootstrapper es una interfaz para usar cuando una clase de arranque cargar recursos externos -- por ejemplo, uno o ms recursos no se definirn directamente en la clase, sino ms bien via plugins. Debe ser utilizado en conjuncin con Zend_Application_Bootstrap_Bootstrapper; Zend_Application_Bootstrap_BootstrapAbstract que implementan esta funcionalidad. Los siguientes mtodos conforman la definicin de la interfaz.
registerPluginResource($resource, Zend_Application_Bootstrap_ResourceBootstrapper $resource: requerido. Registre un recurso con $options = null) Un nombre de la clase, proporcionando recurso o un objeto configuracin opcional para Zend_Application_Resource_Resource pasar al recurso. . $options: opcional. Un array o un objeto Zend_Config para pasar al recurso en instanciacin. unregisterPluginResource($resource) Zend_Application_Bootstrap_ResourceBootstrapper $resource: requerido. Eliminar un recurso de Nombre de un recurso plugin de la clase. para des-registrar desde la clase.
43
Zend_Application
Mtodo
Valor de Retorno
Parmetros
Descripcin
hasPluginResource($resource) Boolean
$resource: requerido. Determinar si un recurso Nombre del recurso. especfico se ha registrado en la clase.
getPluginResource($resource) Zend_Application_Resource_Resource $resource: requerido. Recuperar una instacia de Nombre de un recurso a un recurso de plugin por su recuperar (string). nombre. getPluginResourceNames() Array N/A Recuperar una lista de todos los nombres de recursos de plugin registrados.
setPluginLoader(Zend_Loader_PluginLoader_Interface Zend_Application_Bootstrap_ResourceBootstrapper $loader: requerido. Registre una instancia del $loader) Instancia del cargador cargador de plugin para de plugin para utilizar utilizar cuando se resuelven cuando se resuelven nombres de clases de plugin. nombres de plugin a las clases. getPluginLoader() Zend_Loader_PluginLoader_Interface N/A Recuperar el cargador de plugin registrado.
Zend_Application_Bootstrap_BootstrapAbstract
Zend_Application_Bootstrap_BootstrapAbstract es una clase abstracta que proporciona la base funcional de un arranque (bootstrap) comn. Implementa a ambos Zend_Application_Bootstrap_Bootstrapper y a Zend_Application_Bootstrap_ResourceBootstrapper.
setOptions(array $options)
Zend_Application_Bootstrap_Bootstrapper $options: requerido. Cualquier opcin que Array de opciones a tiene un setter concordante establecer. invocar ese setter; de lo contrario, la opcin ser simplemente almacenada para su recuperacin posterior. Como ejemplo, si su clase extendida defini un mtodo setFoo(), la opcin 'foo' pasara el valor a ese mtodo. Tambin pueden usarse dos opciones especiales clave. pluginPaths puede ser utilizada para especificar prefijos de paths para los
44
Zend_Application
Mtodo
Valor de Retorno
Parmetros
Descripcin recursos plugin; debera ser un array de la clase pares prefijo/path. resources puede ser utilizada para especificar los recursos plugin a utilizar, y debera estar constitudo por pares de opciones plugin recurso/ instanciacin. Devuelve todas opciones registradas setOptions(). las via
getOptions()
array
N/A
hasOption($key) getOption($key)
boolean mixed
$key: requerido. Clave Determinar si una opcin de opcin a probar. clave est presente. $key: requerido. Clave Recuperar el valor asociado de opcin para recuperar. con una opcin clave; retorna NULL si ninguna opcin est registrada con esa clave.
setApplication(Zend_Application Zend_Application_Bootstrap_BootstrapAbstract $application: Registrar al objeto padre | requerido. de la aplicacin o en el Zend_Application_Bootstrap_Bootstrapper bootstrap. $application) getApplication() Zend_Application | N/A Recuperar el objeto Zend_Application_Bootstrap_Bootstrapperaplicacin/bootstrap pasado via constructor. string N/A Recuperar el string del entorno registrado con el objeto padre de la aplicacin o del bootstrap. Recuperar una lista de los recursos inicializadores de nombres disponibles con los fueron definidos en la clase. Esto puede ser de implementacin especfica. Recupera el contenedor que almacena recursos. Si no hay un contenedor actualmente registrado, registra una instancia Zend_Registry antes de retornarlo.
getEnvironment()
getClassResources() array
N/A
getContainer()
object
N/A
setContainer($container) Zend_Application_Bootstrap_BootstrapAbstract $container, Proporciona un contenedor requerido. Un objeto en el en el que se almacenan cual almacenar recursos. recursos. Cuando un mtodo de recurso o plugin devuelve un valor, ser almacenado
45
Zend_Application
Mtodo
Valor de Retorno
Parmetros
hasResource($name) boolean
$name, requerido. Cuando un mtodo de Nombre del recurso a recurso o plugin devuelve comprobar. un valor, ser almacenado en el contenedor de recursos (ver getContainer() y setContainer(). Este mtodo indicar si se ha establecido o no un valor para ese recurso. $name, requerido. Cuando un mtodo de Nombre del recurso a recurso o plugin devuelve recuperar. un valor, ser almacenado en el contenedor de recursos (ver getContainer() y setContainer(). Este mtodo recuperar recursos del contenedor. $resource: opcional. Si $resource est vaco, ejecutar todos los recursos del bootstrap. Si es un string, ejecutar ese nico recurso; si es un array, ejecutar cada recurso del array. Este mtodo puede ser utilizado para ejecutar bootstraps individuales, ya hayan sido definidos en la propia clase o mediante clases de recursos de plugin. Un recurso definido en la clase ser ejecutado en preferencia por sobre un recurso de plugin en el caso de conflicto de nombres.
getResource($name) mixed
run()
void
N/A
__call($method, $args)
mixed
$method: requerido. El Ofrece comodidad para nombre del mtodo a bootstrapping de recursos llamar. individuales permitindole llamar $args: requerido. Array 'bootstrap<ResourceName>()' de argumentos para usar en vez de usar el mtodo en el mtodo de llamada. bootstrap().
46
Zend_Application
Zend_Application_Bootstrap_Bootstrap
Zend_Application_Bootstrap_Bootstrap es una implementacin concreta de Zend_Application_Bootstrap_BootstrapAbstract. Su principal caracterstica es que registra el recurso Front Controller, y que el mtodo run() primero comprueba est definido un mdulo por defecto y luego despacha el front controller. En muchos casos, usted quisiera extender esta clase por sus necesidades de bootstrapping, o simplemente utilizar esta clase y proporcionar una lista de los plugins de recursos a utilizar.
Zend_Application_Resource_Resource
Zend_Application_Resource_Resource es una interfaz para recursos de plugin utilizados con clases bootstrap implementando Zend_Application_Bootstrap_ResourceBootstrapper. Se espera que los recursos de plugins permitan la configuracin, estar enterados del bootstrap, y aplicar un patrn de estrategia para la inicializacin de recursos.
setBootstrap(Zend_Application_Bootstrap_Bootstrapper Zend_Application_Resource_Resource $bootstrap: Debera permitir registrar el $bootstrap) requerido. Padre del objeto padre del bootstrap. bootstrap inicializando este recurso. getBootstrap() setOptions(array $options) getOptions() init() Zend_Application_Bootstrap_Bootstrapper N/A Recuperar la instancia del bootstrap registrado. Zend_Application_Resource_Resource $options: requerido. Establecer el estado del Opciones con las cuales recurso. establecer el estado. Array Mixed N/A N/A Recuperar registradas. opciones
Zend_Application_Resource_ResourceAbstract
Zend_Application_Resource_ResourceAbstract es una clase abstracta implementando Zend_Application_Resource_Resource, y es un buen punto de partida para crear sus propios recursos de plugin personalizados. Nota: esta clase abstracta no implementa el mtodo init(); esto se deja para la definicin de extensiones concretas de la clase.
47
Zend_Application
Mtodo
Valor de Retorno
Parmetros Descripcin establecer el estado del las cuales inicializar el recurso. estado.
setBootstrap(Zend_Application_Bootstrap_Bootstrapper Zend_Application_Resource_ResourceAbstract $bootstrap: Debera permitir registrar el $bootstrap) requerido. Padre del objeto padre del bootstrap. bootstrap inicializando este recurso. getBootstrap() setOptions(array $options) getOptions() Zend_Application_Bootstrap_Bootstrapper N/A Recuperar la instancia registrada del bootstrap. Zend_Application_Resource_ResourceAbstract $options: requerido. Establecer el estado del Opciones con las cuales recurso. establecer el estado. Array N/A Recuperar registradas. opciones
Resource Names
When registering plugin resources, one issue that arises is how you should refer to them from the parent bootstrap class. There are three different mechanisms that may be used, depending on how you have configured the bootstrap and its plugin resources. First, if your plugins are defined within a defined prefix path, you may refer to them simply by their "short name" -- i.e., the portion of the class name following the class prefix. As an example, the class "Zend_Application_Resource_View" may be referenced as simply "View", as the prefix path "Zend_Application_Resource" is already registered. You may register them using the full class name or the short name:
$app = new Zend_Application(APPLICATION_ENV, array( 'pluginPaths' => array( 'My_Resource' => 'My/Resource/', ), 'resources' => array( // if the following class exists: 'My_Resource_View' => array(), // then this is equivalent: 'View' => array(), ), )); In each case, you can then bootstrap the resource and retrieve it later using the short name:
$bootstrap->bootstrap('view'); $view = $bootstrap->getResource('view'); Second, if no matching plugin path is defined, you may still pass a resource by the full class name. In this case, you can reference it using the resource's full class name:
48
Zend_Application
// This will load the standard 'View' resource: 'View' => array(), // While this loads a resource with a specific class name: 'My_Resource_View' => array(), ), )); Obviously, this makes referencing the resource much more verbose:
$bootstrap->bootstrap('My_Resource_View'); $view = $bootstrap->getResource('My_Resource_View'); This brings us to the third option. You can specify an explicit name that a given resource class will register as. This can be done by adding a public $_explicitType property to the resource plugin class, with a string value; that value will then be used whenever you wish to reference the plugin resource via the bootstrap. As an example, let's define our own view class:
class My_Resource_View extends Zend_Application_Resource_ResourceAbstract { public $_explicitType = 'My_View'; public function init() { // do some initialization... } } We can then bootstrap that resource or retrieve it by the name "My_View":
$bootstrap->bootstrap('My_View'); $view = $bootstrap->getResource('My_View'); Using these various naming approaches, you can override existing resources, add your own, mix multiple resources to achieve complex initialization, and more.
Zend_Application_Resource_Db
Zend_Application_Resource_Db inicializar un adaptador Zend_Db basado en las opciones que se le pasen. Por defecto, tambin establece el adaptador por defecto para usarlo con Zend_Db_Table. Se reconocen las siguientes configuraciones claves: adapter: tipo de adaptador Zend_Db. params: array asociativo de parmetros de configuracin para utilizar al recuperar la instancia del adaptador.
49
Zend_Application
isDefaultTableAdapter: Indica si establecer o no este adaptador como el adaptador de tablas por defecto.
[production] resources.db.adapter = "pdo_mysql" resources.db.params.host = "localhost" resources.db.params.username = "webuser" resources.db.params.password = "XXXXXXX" resources.db.params.dbname = "test" resources.db.isDefaultTableAdapter = true
$resource = $bootstrap->getPluginResource('db'); Una vez que tiene el recurso objeto, puede recuperar el adaptador de DB usando el mtodo getDbAdapter():
$db = $resource->getDbAdapter();
Zend_Application_Resource_Frontcontroller
Probablemente el recurso ms comn que se carga con Zend_Application ser el recurso Front Controller , que proporciona la habilidad para configurar Zend_Controller_Front. Este recurso ofrece la posibilidad de establecer parmetros arbitrarios del Front Controller, especificar plugins para inicializar, y mucho ms. Una vez inicializado, el recurso asigna la propiedad del $frontController del bootstrap a la instancia Zend_Controller_Front. Las claves de configuracin disponibles incluyen las siguientes, sin importar si son maysculas minsculas: controllerDirectory:: ya sea un valor de string especificando un nico directorio controlador, o un array de pares de directorio mdulo/controlador. moduleControllerDirectoryName: un valor de string indicando el subdirectorio bajo el cual un mdulo contiene controladores. moduleDirectory: directorio bajo el cual pueden encontrarse los mdulos. defaultControllerName: Nombre base del controlador por defecto (normalmente, "ndex").
50
Zend_Application
defaultAction: nombre base de la accin por defecto (normalmente, "ndex"). defaultModule: nombre base del mdulo por defecto (normalmente, "default"). baseUrl: base explcita a la URL de la aplicacin (normalmente auto-detect). plugins: array con los nombres de los plugins de las clases de los Front Controllers. El recurso instanciar a cada clase (sin argumentos al constructor) y luego registra la instancia con el Front Controller. params: array de pares clave/valor para registrarse con el front controller. Si se ingresa una clave no reconocida, sta ser registrada como un parmetro de Front Controller pasndolo a setParam().
[production] resources.frontController.controllerDirectory = APPLICATION_PATH . "/controllers" resources.frontController.moduleControllerDirectoryName = "actions" resources.frontController.moduleController = APPLICATION_PATH . "/modules" resources.frontController.defaultControllerName = "site" resources.frontController.defaultAction = "home" resources.frontController.defaultModule = "static" resources.frontController.baseUrl = "/subdir" resources.frontController.plugins.foo = "My_Plugin_Foo" resources.frontController.plugins.bar = "My_Plugin_Bar" resources.frontController.env = APPLICATION_ENV
Zend_Application_Resource_Layout
Zend_Application_Resource_Layout can be used to configure Zend_Layout. Configuration options are per the Zend_Layout options.
51
Zend_Application
Zend_Application_Resource_Modules
Zend_Application_Resource_Modules se utiliza para inicializar sus mdulos de aplicacin. Si su mdulo tiene un archivo Bootstrap.php en su raz, y contiene una clase llamada Module_Bootstrap (donde "Module" es el nombre del mdulo), entonces usar esa clase para arrancar el mdulo. Por defecto, se crear una instancia de Zend_Application_Module_Autoloader para el mdulo, utilizando el nombre del mdulo y del directorio para inicializarlo. Ya que los mdulos no reciben ningn parmetro por defecto, para poder activarlos via configuracin, ser necesario crearlo como un array vaco. Seguiendo el estilo de configuracin <acronim>INI</acronim> ser similar a: resources.modules[] = Siguiendo el estilo de configuracin XML ser similar a:
<resources> <modules> <!-- Placeholder to ensure an array is created --> <placeholder /> </modules> </resources> Utilizando un array PHP estandar, simplemente creelo como un array vaco:
52
Zend_Application
news.resources.db.params.host = "localhost" news.resources.db.params.username = "webuser" news.resources.db.params.password = "XXXXXXX" news.resources.db.params.dbname = "news" news.resources.layout.layout = "news"
<?xml version="1.0"?> <config> <production> <news> <resources> <db> <adapter>pdo_mysql</adapter> <params> <host>localhost</host> <username>webuser</username> <password>XXXXXXX</password> <dbname>news</dbname> </params> <isDefaultAdapter>true</isDefaultAdapter> </db> </resources> </news> </production> </config>
Zend_Application_Resource_Navigation
Zend_Application_Resource_Navigation can be used to configure a Zend_Navigation instance. Configuration options are per the Zend_Navigation options. Once done configuring the navigation instance, it assigns the instance to Zend_View_Helper_Navigation by default -- from which you may retrieve it later.
53
Zend_Application
resources.navigation.pages.page1.route = "Route that belongs to the first page" ; Page 2 is a subpage of page 1 resources.navigation.pages.page1.pages.page2.type = "Zend_Navigation_Page_Uri" resources.navigation.pages.page1.pages.page2.label = "Label of the second page" resources.navigation.pages.page1.pages.page2.uri = "/url/to/page/2"
Zend_Application_Resource_Router
Zend_Application_Resource_Router can be used to configure the router as it is registered with the Front Controller. Configuration options are per the Zend_Controller_Router_Route options.
resources.router.routes.route_id.route = "/login" resources.router.routes.route_id.defaults.module = "user" resources.router.routes.route_id.defaults.controller = "login" resources.router.routes.route_id.defaults.action = "index" ; Optionally you can also set a Chain Name Separator: resources.router.chainNameSeparator = "_" For more information on the Chain Name Separator, please see its section.
Zend_Application_Resource_Session
Zend_Application_Resource_Session le permite configurar Zend_Session y opcionalmente inicializar una sesin SaveHandler. Para establecer un manejador de sesiones, simplemente pasar al recurso la clave opcional saveHandler (case insensible). El valor de esta opcin puede ser uno de los siguientes: String: un string indicando una clase implementando Zend_Session_SaveHandler_Interface que debera ser instanciada. Array: un array con las claves "class" y, opcionalmente, "options", indicando la clase que implementa Zend_Session_SaveHandler_Interface que debera ser instanciada y una variedad de opciones para proporcionar a su constructor. Zend_Session_SaveHandler_Interface: un objeto implementando esta interfaz. Pasando cualquier otra opcin de claves ser pasado a Zend_Session::setOptions() para configurar Zend_Session.
54
Zend_Application
resources.session.save_path = APPLICATION_PATH "/../data/session" resources.session.use_only_cookies = true resources.session.remember_me_seconds = 864000 resources.session.saveHandler.class = "Zend_Session_SaveHandler_DbTable" resources.session.saveHandler.options.name = "session" resources.session.saveHandler.options.primary.session_id = "session_id" resources.session.saveHandler.options.primary.save_path = "save_path" resources.session.saveHandler.options.primary.name = "name" resources.session.saveHandler.options.primaryAssignment.sessionId = "sessionId" resources.session.saveHandler.options.primaryAssignment.sessionSavePath = "sessionSavePath" resources.session.saveHandler.options.primaryAssignment.sessionName = "sessionName" resources.session.saveHandler.options.modifiedColumn = "modified" resources.session.saveHandler.options.dataColumn = "session_data" resources.session.saveHandler.options.lifetimeColumn = "lifetime"
Zend_Application_Resource_View
Zend_Application_Resource_View puede ser utilizada para configurar una instancia Zend_View. Las opciones de configuracin son por las opciones de Zend_View. Una vez hecha la configuracin de la instancia de vista, crea una instancia de Zend_Controller_Action_Helper_ViewRenderer y registra el ViewRenderer con Zend_Controller_Action_HelperBroker -- desde la cual usted puede recuperarla posteriormente.
55
56
Captulo 5. Zend_Auth
Introduccin
Zend_Auth provee una API para autenticacin e incluye adaptadores concretos de autenticacin para escenarios de casos de uso comn. Zend_Auth es concerniente slo con autenticacin y no con autorizacin . Autenticacin es vagamente definido como: determinar si una entidad realmente es lo que pretende ser (o sea, identificacin), basandose en un grupo de credenciales. Autorizacin, el proceso de decidir si se permite a una entidad: acceso a, o el realizar operaciones en, otras entidades esta fuera del alcance de Zend_Auth . Para ms informacin sobre autorizacin y control de acceso con Zend Framework, por favor vea Zend_Acl .
Nota
La clase Zend_Auth implementa el patrn Singleton - slo una instancia de la clase est disponible - a travs de su mtodo esttico getInstance() . Esto significa que usar el operador new y la keyword clone no va a funcionar con la clase Zend_Auth : use Zend_Auth::getInstance() en su lugar.
Adaptadores
Un adaptador Zend_Auth es usado para autenticar en contra de un tipo particular de servicio de autenticacin, como LDAP, RDBMS, o almacenamiento basado en ficheros. Diferentes adaptadores pueden tener opciones y compotamientos muy diferentes, pero algunas cosas bsicas son comunes entre los adaptadores de autenticacin. Por ejemplo, aceptar credenciales de autenticacin (incluyendo una identidad supuesta), realizar consultas ante el servicio de autenticacin, y regresar resultados, son comunes para los adaptadores Zend_Auth . Cada clase adaptadora Zend_Auth implementa Zend_Auth_Adapter_Interface . Esta interface define un metodo, authenticate() , que la clase adaptadora debe implementar para realizar una peticion de autenticacin. Cada clase adaptadora debe ser preparada antes de llamar a authenticate() . Esta preparacin del adaptador incluye la creacin de credenciales (p.ej. nombre de usuario y contrasea) y la definicin de valores para opciones de configuracin especificos del adaptador, como valores de coneccion a base de datos para un adaptador de tabla de base de datos. El siguente ejemplo es un adaptador de autenticacin que requiere que un nombre de usuario y contrasea sean especificados para la autenticacin. Otros detalles, como la forma de realizar peticiones al servicio de autenticacin, han sido omitdos por brevedad: class MyAuthAdapter implements Zend_Auth_Adapter_Interface { /** * Establece nombre de usuario y contrasea para autenticacn * * @return void */ public function __construct($username, $password) { // ... } /** * Realiza un intento de autenticacin
57
Zend_Auth
* * @throws Zend_Auth_Adapter_Exception Si la autenticacin no puede * ser realizada * @return Zend_Auth_Result */ public function authenticate() { // ... } } Como se ha indicado en su docblock, authenticate() debe regresar una instancia de Zend_Auth_Result (o de una clase derivada de Zend_Auth_Result ). Si por alguna razn es imposible realizar una peticin de autenticacin, authenticate() debera arrojar una excepcin que se derive de Zend_Auth_Adapter_Exception .
Resultados
Los adaptadores Zend_Auth regresan una instancia de Zend_Auth_Result con authenticate() para representar el resultado de un intento de autenticacin. Los adaptadores llenan el objeto Zend_Auth_Result en cuanto se construye, as que los siguientes cuatro mtodos proveen un grupo bsico de operaciones "frente al usuario" que son comunes a los resultados de adaptadores Zend_Auth: isValid() - regresa true si y solo si el resultado representa un intento de autenticacin exitoso getCode() - regresa una constante identificadora Zend_Auth_Result para determinar el tipo de fallo en la autenticacin o si ha sido exitosa. Este puede ser usado en situaciones cuando el desarrollador desea distinguir entre varios tipos de resultados de autenticacin. Esto permite a los desarrolladores, por ejemplo, mantener estadsticas detalladas de los resultados de autenticacin. Otro uso de esta caracterstica es: proporcionar al usuario mensajes especficos detallados por razones de usabilidad, aunque los desarrolladores son exhortados a considerar el riesgo de proporcionar tales detalles a los usuarios, en vez de un mensaje general de fallo en la autenticacin. Para ms informacin, vea las siguientes notas: getIdentity() - regresa la identidad del intento de autenticacin getMessages() - regresa un arreglo de mensajes pertinentes a un fallido intento de autenticacin El desarrollador podra desear ramificar basado en el tipo de resultado de la autenticacin a fin de realizar operaciones mas especficas. Algunas operaciones que los desarrolladores podran encontrar tiles son: bloquear cuentas despues de varios intentos fallidos de ingresar una contrasea, marcar una direccin IP despues de que ha intentado muchas identidades no existentes, y porporcionar al usuario mensajes especificos resultados de la autenticacin. Los siguientes codigos de resultado estn disponibles: 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 El siguiente ejemplo ilustra como un desarrollador podra ramificar basado en el cdigo resultado: // debtri de AuthController / loginAction $result = $this->_auth->authenticate($adapter);
58
Zend_Auth
switch ($result->getCode()) { case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND: /** realiza algo para identidad inexistente **/ break; case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID: /** realiza algo para credencial invalida **/ break; case Zend_Auth_Result::SUCCESS: /** realiza algo para autenticacin exitosa **/ break; default: /** realiza algo para otras fallas **/ break; }
Persistencia de Identidad
Autenticar una peticin que incluye credenciales de autenticacin es util por s mismo, pero tambin es importante el soportar mantener la identidad autenticada sin tener que presentar las credenciales de autenticacin con cada peticin. HTTP es un protocolo sin estado, sin embargo, se han desarrollado tcnicas como las cookies y sesiones a fin de facilitar mantener el estado a travs de multiples peticiones en aplicaciones web del lado del servidor.
Nota
Si el automtico almacenamiento persistente de la identidad no es apropiado para un caso en particular, entonces los desarrolladores podran dejar de usar la clase Zend_Auth al mismo tiempo, utilizando en su lugar una clase adaptadora directamente.
59
Zend_Auth
// Usa 'unEspacionombre' en lugar de 'Zend_Auth' $auth->setStorage(new Zend_Auth_Storage_Session('unEspacionombre')); /** * @todo Set up the auth adapter, $authAdapter */ // Autenticar, almacenando el resultado, y persistiendo la identidad en // suceso $result = $auth->authenticate($authAdapter);
class MyStorage implements Zend_Auth_Storage_Interface { /** * Regresa true si y solo si el almacenamiento esta vacio * * @arroja Zend_Auth_Storage_Exception Si es imposible * determinar si el almacenamiento * esta vacio * @regresa boleano */ public function isEmpty() { /** * @por hacer implementacin */ } /** * Regresa el contenido del almacenamiento * * El comportamiento es indefinido cuando el almacenamiento esta vacio * * @arroja Zend_Auth_Storage_Exception Si leer contenido de * almacenamiento es imposible * @regresa mixto */ public function read() { /** * @por hacer implementacin
60
Zend_Auth
*/ } /** * Escribe $contents al almacenamiento * * @parametros mezclado $contents * @arroja Zend_Auth_Storage_Exception Si escribir $contents al * almacenamiento es imposible * @regresa boleano */ public function write($contents) { /** * @por hacer implementacin */ } /** * limpia contenidos del almacenamiento * * @arroja Zend_Auth_Storage_Exception Si limpiar contenidos del * almacenamiento es imposible * @regresa void */ public function clear() { /** * @por hacer implementacin */ } } A fin de poder usar esta clase de almacenamiento personalizada, Zend_Auth::setStorage() es invocada antes de intentar una peticin de autenticacin: // Instruye Zend_Auth para usar la clase de almacenamiento personalizada Zend_Auth::getInstance()->setStorage(new MyStorage()); /** * @por hacer Configurar el adaptador de autenticacin, $authAdapter */ // Autenticar, almacenando el resultado, y persistiendo la identidad // si hay exito $result = Zend_Auth::getInstance()->authenticate($authAdapter);
Uso
Hay dos formas provistas de usar adaptadores Zend_Auth: 1. indirectamente, a travs de Zend_Auth::authenticate() 2. directamente, a travs del metodo authenticate() del adaptador
61
Zend_Auth
El siguiente ejemplo ilustra como usar el adaptador :Zend_Auth : indirectamente, a travs del uso de la clase Zend_Auth : // Recibe una referencia a la instancia singleton de Zend_Auth $auth = Zend_Auth::getInstance(); // Configura el adaptador de autenticacin $authAdapter = new MyAuthAdapter($username, $password); // Intenta la autenticacin, almacenando el resultado $result = $auth->authenticate($authAdapter); if (!$result->isValid()) { // Fautenticacin fallida: imprime el por que foreach ($result->getMessages() as $message) { echo "$message\n"; } } else { // Autenticacin exitosa, la identidad ($username) es almacenada // en la sesin // $result->getIdentity() === $auth->getIdentity() // $result->getIdentity() === $username } Una vez que la autenticacin ha sido intentada en una peticin, como en el ejemplo anterior, es fcil verificar si existe una identidad autenticada exitosamente: $auth = Zend_Auth::getInstance(); if ($auth->hasIdentity()) { // Existe la identidad; obtenla $identity = $auth->getIdentity(); } Para remover una identidad del almacenamiento persistente, simplemente usa el metodo clearIdentity() method. Comunmente esto sera usado para implementar una operacin "cerrar sesin" en la aplicacin: Zend_Auth::getInstance()->clearIdentity(); Cuando el uso automtico de almacenamiento persistente es inapropiado para un caso en particular, el desarrollador podra simplemente omitir el uso de la clase Zend_Auth , usando una clase adaptadora directamente. El uso directo de una clase adaptadora implica configurar y preparar un objeto adaptador y despues llamar a su metodo authenticate() . Los detalles especficos del adaptador son discutidos en la documentacin de cada adaptador. El siguiente ejemplo utiliza directamente MyAuthAdapter : // Configura el adaptador de autenticacin $authAdapter = new MyAuthAdapter($username, $password); // Intenta la autenticacin, almacenando el resultado $result = $authAdapter->authenticate(); if (!$result->isValid()) { // Autenticacin fallida, imprime el porque
62
Zend_Auth
foreach ($result->getMessages() as $message) { echo "$message\n"; } } else { // Autenticacin exitosa // $result->getIdentity() === $username }
63
Zend_Auth
. '[username] VARCHAR(50) UNIQUE NOT NULL, ' . '[password] VARCHAR(32) NULL, ' . '[real_name] VARCHAR(150) NULL)'; // Crear las credenciales de autenticacin de la tabla $dbAdapter->query($sqlCreate);
// Construir una consulta para insertar una fila para que se pueda realizar la autenticaci $sqlInsert = "INSERT INTO users (username, password, real_name) " . "VALUES ('my_username', 'my_password', 'My Real Name')"; // Insertar los datos $dbAdapter->query($sqlInsert); Con la conexin de la base de datos y los datos de la tabla disponibles, podemos crear un instancia de Zend_Auth_Adapter_DbTable. Los valores de las opciones de configuracin pueden ser pasados al constructor o pasados como parmetros a los mtodos setter despus de ser instanciados.
// Configurar la instancia con los parmetros del constructor... $authAdapter = new Zend_Auth_Adapter_DbTable( $dbAdapter, 'users', 'username', 'password' ); // ...o configurar la instancia con los mtodos setter. $authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter); $authAdapter ->setTableName('users') ->setIdentityColumn('username') ->setCredentialColumn('password') ; En este punto, el adaptador de la instancia de autenticacin est listo para aceptar consultas de autenticacin. Con el fin de elaborar una consulta de autenticacin, los valores de entrada de la credencial son pasados por el adaptador ates de llamar al mtodo authenticate():
// Seleccionamos los valores de entrada de la credencial (e.g., de un formulario de acceso) $authAdapter ->setIdentity('my_username') ->setCredential('my_password') ; // Ejecutamos la consulta de autenticacin, salvando los resultados Adems de la disponibilidad del mtodo getIdentity() sobre el objeto resultante de la autenticacin, Zend_Auth_Adapter_DbTable tambin ayuda a recuperar la fila de al tabla sobre la autenticacin realizada.
64
Zend_Auth
// Imprimir la fila resultado print_r($authAdapter->getResultRowObject()); /* Salida: my_username Array ( [id] => 1 [username] => my_username [password] => my_password [real_name] => My Real Name ) Ya que la fila de la tabla contiene el valor de la credencial, es importante proteger los valores contra accesos no deseados.
// Autenticar con Zend_Auth_Adapter_DbTable $result = $this->_auth->authenticate($adapter); if ($result->isValid()) { // Almacena la identidad como un objedo dnde solo username y // real_name han sido devueltos $storage = $this->_auth->getStorage(); $storage->write($adapter->getResultRowObject(array( 'username', 'real_name', ))); // Almacena la identidad como un objeto dnde la columna contrasea ha // sido omitida $storage->write($adapter->getResultRowObject( null, 'password' )); /* ... */ } else { /* ... */ }
65
Zend_Auth
// El valor del campo status de una cuenta no es igual a "compromised" $adapter = new Zend_Auth_Adapter_DbTable( $db, 'users', 'username', 'password', 'MD5(?) AND status != "compromised"' ); // El valor del campo active de una cuenta es igual a "TRUE" $adapter = new Zend_Auth_Adapter_DbTable( $db, 'users', 'username', 'password', 'MD5(?) AND active = "TRUE"'
Otra idea puede ser la aplicacin de un mecanismo de "salting". "Salting" es un trmino que se refiere a una tcnica que puede mejorar altamente la seguridad de su aplicacin. Se basa en la idea de concatenar una cadena aleatoria a cada contrasea para evitar un ataque de fuerza bruta sobre la base de datos usando los valores hash de un diccionario pre-calculado. Por lo tanto, tenemos que modificar nuestra tabla para almacenar nuestra cadena mezclada:
$sqlAlter = "ALTER TABLE [users] " . "ADD COLUMN [password_salt] " . "AFTER [password]"; Aqu hay una forma sencilla de generar una cadena mezclada por cada usuario en el momento del registro:
for ($i = 0; $i < 50; $i++) { $dynamicSalt .= chr(rand(33, 126)); Y ahora vamos a construir el adaptador:
66
Zend_Auth
Nota
Puede mejorar an ms la seguridad mediante el uso de un valor 'salt' esttico fuertemente codificado en su aplicacin. En el caso de que su base de datos se vea comprometida (por ejemplo, por un ataque de inyeccin SQL), su servidor web est intacto y sus datos son inutilizable para el atacante. Otra alternativa es utilizar el mtodo getDbSelect() de Zend_Auth_Adapter_DbTable despus de que el adaptador se ha construido. Este mtodo devolver la instancia del objeto Zend_Db_Select que se va a utilizar para completar la rutina de authenticate(). Es importante sealar que este mtodo siempre devuelve el mismo objeto, independientemente de si authenticate() ha sido llamado o no. Este objeto no tendr ninguna de las credenciales de identidad o informacin de como estos valores son colocados dentro del objeto seleccionado en authenticate(). Un ejemplo de una situacin en la que uno podra querer utilizar el mtodo getDbSelect() sera comprobar el estado de un usuario, en otras palabras, ver si la cuenta del usuario est habilitada. // Continuando con el ejemplo de arriba $adapter = new Zend_Auth_Adapter_DbTable( $db, 'users', 'username', 'password', 'MD5(?)' ); // obtener el objeto select (por referencia) $select = $adapter->getDbSelect(); $select->where('active = "TRUE"'); // authenticate, esto asegura que users.active = TRUE $adapter->authenticate();
Autenticacin "Digest"
Introduccin
La Autenticacin "Digest" [http://en.wikipedia.org/wiki/Digest_access_authentication] es un mtodo de la autenticacin HTTP que mejora la Autenticacin Bsica [http://en.wikipedia.org/wiki/Basic_authentication_scheme] proporcionando una manera de autenticar sin tener que transmitir la contrasea de manera clara a travs de la red. Este adaptador permite la autentificacin contra archivos de texto que contengan lneas que tengan los elementos bsicos de la autenticacin "Digest": username, tal como "joe.user" realm, tal como "Administrative Area" Hash MD5 del username, realm y password, separados por dos puntos
67
Zend_Auth
Los elementos anteriores estn separados por dos puntos, como en el ejemplo siguiente (en el que la contrasea es "somePassword"): someUser:Some Realm:fde17b91c3a510ecbaf7dbd37f59d4f8
Detalles Especficos
El adaptador de autenticacin "Digest", Zend_Auth_Adapter_Digest, requiere varios parmetros de entrada: filename - Nombre del archivo contra el que se realiza la autenticacin de las consultas realm - Domino de la autenticacin "Digest" username - Usuario de la autenticacin "Digest" password - Contrasea para el usuario del dominio Estos parmetros deben ser establecidos antes de llamar a authenticate().
Identidad
El adaptador de autenticacin "Digest" devuelve un objeto Zend_Auth_Result, que ha sido rellenado con la identidad como un array que tenga claves realm y username. Los respectivos valores del array asociados con esas claves correspondes con los valores fijados andes de llamar a authenticate(). $adapter = new Zend_Auth_Adapter_Digest($filename, $realm, $username, $password); $result = $adapter->authenticate(); $identity = $result->getIdentity(); print_r($identity); /* Array ( [realm] => Some Realm [username] => someUser ) */
68
Zend_Auth
Caractersticas Principales: Soporta tanto Autenticacin "Digest" como Bsica. Establece retos en todos los proyectos soportados, por lo que el cliente puede responder con cualquier proyecto que soporte. Soporta autenticacin proxy. Incluye soporte para la autenticacin contra archivos de texto y proporciona una interfaz para autenticar contra otras fuentes, tales como bases de datos. Hay algunas caractersticas notables del RFC-2617 no implementadas todava: Seguimiento "nonce", que permitira un gran apoyo, y un aumento de la proteccin de repetidos ataques. Autenticacin con comprobacin de integridad, o "auth-int". Cabecera de informacin de la autenticacin HTTP.
Opciones de Configuracin
La clase Zend_Auth_Adapter_Http requiere un array configurado que pasar a su constructor. Hay varias opciones de configuracin disponibles, y algunas son obligatorias:
realm
Si
digest_domains
Si, cuando 'accept_schemes' Lista de URIs separadas por espacios contiene 'digest' para las cuales la misma informacin de autenticacin es vlida. No es necesario que todas las URIs apunten al mismo oservidor. Si, cuando 'accept_schemes' Establece el nmero de segundos para contiene 'digest' los cuales el "nonce" es vlido. Ver notas de abajo. No Deshabilitado por defecto. Permite llevar a cabo la autenticacin del
nonce_timeout
proxy_auth
69
Zend_Auth
Nombre de Opcin
Obligatoria
Nota
La implementacin actual del nonce_timeout tiene algunos efectos colaterales interesantes. Este ajuste es supuesto para determinar la vida util vlida para un determinado "nonce", o de manera efectiva el tiempo que una informacin de autenticacin del cliente es aceptada. Actualmente, si se establece en 3600 (por ejemplo), har que el adaptador indique al cliente las nuevas credenciales cada hora, a la hora en punto.
Resolvers
El trabajo del "Resolver" es tener un username y un realm, y devolver algn valor de tipo credencial. La autenticacin bsica espera recibir la versin codificada en Base64 de la contrasea del usuario. La autenticacin "Digest" espera recibir un hash del username del usuario, un realm, y su contrasea (separados por coma). Actualmente, slo se admite el algoritmo de hash MD5. Zend_Auth_Adapter_Http se basa en la implementacin de objetos Zend_Auth_Adapter_Http_Resolver_Interface. Un archivo de texto de la clase "Resolve" se incluye con este adaptador, pero cualquier otro tipo de "resolver" puede ser creado simplemente implementando la interfaz del "resolver".
Archivo Resolver
El archivo "resolver" es una clase muy simple. Tiene una nica propiedad que especifique un nombre de archivo, que tambin puede ser pasado al constructor. Su mtodo resolve() recorre el archivo de texto, buscando una linea con el correspondiente username y realm. El formato del archivo de texto es similar a los archivos htpasswd de Apache: <username>:<realm>:<credentials>\n Cada linea consta de tres campos -username, realm, y credenciales - cada uno separados por dos puntos. El campo credenciales es opaco al archivo "resolver"; simplemente devuelve el valor tal como s al llamador. Por lo tanto, este formato de archivo sirve tanto de autenticacin bsica como "Digest". En la autenticacin bsica, el campo credenciales debe ser escrito en texto claro. En la autenticacin "Digest", debera ser en hash MD5 descrito anteriormente. Hay dos formas igualmente fcil de crear un archivo de "resolver": $path = 'files/passwd.txt'; $resolver = new Zend_Auth_Adapter_Http_Resolver_File($path); o $path = 'files/passwd.txt'; $resolver = new Zend_Auth_Adapter_Http_Resolver_File(); $resolver->setFile($path); Si la ruta est vaca o no se puede leer, se lanza una excepcin.
Uso Bsico
En primer lugar, establecemos un array con los valores de configuracin obligatorios:
70
Zend_Auth
Este array har que el adaptador acepte la autenticacin bsica o "Digest", y requerir un acceso autenticado a todas las reas del sitio en /members_only y /my_account. El valor realm es normalmente mostrado por el navegador en el cuadro de dialogo contrasea. El nonce_timeout, por supuesto, se comporta como se ha descrito anteriormente. A continuacin, creamos el objeto Zend_Auth_Adapter_Http:
$adapter = new Zend_Auth_Adapter_Http($config); Ya que estamos soportando tanto la autenticacin bsica como la "Digest", necesitamos dos objetos diferentes resolver. Tenga en cuenta que esto podra ser facilmente dos clases diferentes:
$basicResolver = new Zend_Auth_Adapter_Http_Resolver_File(); $basicResolver->setFile('files/basicPasswd.txt'); $digestResolver = new Zend_Auth_Adapter_Http_Resolver_File(); $digestResolver->setFile('files/digestPasswd.txt'); $adapter->setBasicResolver($basicResolver); $adapter->setDigestResolver($digestResolver); Por ltimo, realizamos la autenticacin. El adaptador necesita una referencia a ambos objetos solicitud y respuesta para hacer su trabajo:
assert($request instanceof Zend_Controller_Request_Http); assert($response instanceof Zend_Controller_Response_Http); $adapter->setRequest($request); $adapter->setResponse($response); $result = $adapter->authenticate(); if (!$result->isValid()) { // Bad userame/password, or canceled password prompt }
LDAP Authentication
Introduction
Zend_Auth_Adapter_Ldap supports web application authentication with LDAP services. Its features include username and domain name canonicalization, multi-domain authentication, and failover capabilities. It has been tested to work with Microsoft Active Directory [http://www.microsoft.com/windowsserver2003/technologies/directory/ activedirectory/] and OpenLDAP [http://www.openldap.org/], but it should also work with other LDAP service providers.
71
Zend_Auth
This documentation includes a guide on using Zend_Auth_Adapter_Ldap, an exploration of its API, an outline of the various available options, diagnostic information for troubleshooting authentication problems, and example options for both Active Directory and OpenLDAP servers.
Usage
To incorporate Zend_Auth_Adapter_Ldap authentication into your application quickly, even if you're not using Zend_Controller, the meat of your code should look something like the following:
$username = $this->_request->getParam('username'); $password = $this->_request->getParam('password'); $auth = Zend_Auth::getInstance(); $config = new Zend_Config_Ini('../application/config/config.ini', 'production'); $log_path = $config->ldap->log_path; $options = $config->ldap->toArray(); unset($options['log_path']); $adapter = new Zend_Auth_Adapter_Ldap($options, $username, $password); $result = $auth->authenticate($adapter); if ($log_path) { $messages = $result->getMessages(); $logger = new Zend_Log(); $logger->addWriter(new Zend_Log_Writer_Stream($log_path)); $filter = new Zend_Log_Filter_Priority(Zend_Log::DEBUG); $logger->addFilter($filter); foreach ($messages as $i => $message) { if ($i-- > 1) { // $messages[2] and up are log messages $message = str_replace("\n", "\n ", $message); $logger->log("Ldap: $i: $message", Zend_Log::DEBUG); } } } Of course, the logging code is optional, but it is highly recommended that you use a logger. Zend_Auth_Adapter_Ldap will record just about every bit of information anyone could want in $messages (more below), which is a nice feature in itself for something that has a history of being notoriously difficult to debug. The Zend_Config_Ini code is used above to load the adapter options. It is also optional. A regular array would work equally well. The following is an example application/config/config.ini file that has options for two separate servers. With multiple sets of server options the adapter will try each, in order, until the credentials are successfully authenticated. The names of the servers (e.g., 'server1' and 'server2') are largely arbitrary. For details regarding the options array, see the Server Options section below. Note that Zend_Config_Ini requires that any values with "equals" characters (=) will need to be quoted (like the DNs shown below).
72
Zend_Auth
[production] ldap.log_path = /tmp/ldap.log ; Typical options for OpenLDAP ldap.server1.host = s0.foo.net ldap.server1.accountDomainName = foo.net ldap.server1.accountDomainNameShort = FOO ldap.server1.accountCanonicalForm = 3 ldap.server1.username = "CN=user1,DC=foo,DC=net" ldap.server1.password = pass1 ldap.server1.baseDn = "OU=Sales,DC=foo,DC=net" ldap.server1.bindRequiresDn = true ; Typical options for Active Directory ldap.server2.host = dc1.w.net ldap.server2.useStartTls = true ldap.server2.accountDomainName = w.net ldap.server2.accountDomainNameShort = W ldap.server2.accountCanonicalForm = 3 ldap.server2.baseDn = "CN=Users,DC=w,DC=net" The above configuration will instruct Zend_Auth_Adapter_Ldap to attempt to authenticate users with the OpenLDAP server s0.foo.net first. If the authentication fails for any reason, the AD server dc1.w.net will be tried. With servers in different domains, this configuration illustrates multi-domain authentication. You can also have multiple servers in the same domain to provide redundancy. Note that in this case, even though OpenLDAP has no need for the short NetBIOS style domain name used by Windows, we provide it here for name canonicalization purposes (described in the Username Canonicalization section below).
The API
The Zend_Auth_Adapter_Ldap constructor accepts three parameters. The $options parameter is required and must be an array containing one or more sets of options. Note that it is an array of arrays of Zend_Ldap options. Even if you will be using only one LDAP server, the options must still be within another array. Below is print_r() [http://php.net/print_r] output of an example options parameter containing two sets of server options for LDAP servers s0.foo.net and dc1.w.net (the same options as the above INI representation):
Array ( [server2] => Array ( [host] => dc1.w.net [useStartTls] => 1 [accountDomainName] => w.net [accountDomainNameShort] => W [accountCanonicalForm] => 3 [baseDn] => CN=Users,DC=w,DC=net
73
Zend_Auth
) [server1] => Array ( [host] => s0.foo.net [accountDomainName] => foo.net [accountDomainNameShort] => FOO [accountCanonicalForm] => 3 [username] => CN=user1,DC=foo,DC=net [password] => pass1 [baseDn] => OU=Sales,DC=foo,DC=net [bindRequiresDn] => 1 ) ) The information provided in each set of options above is different mainly because AD does not require a username be in DN form when binding (see the bindRequiresDn option in the Server Options section below), which means we can omit a number of options associated with retrieving the DN for a username being authenticated.
74
Zend_Auth
Server Options
Each set of server options in the context of Zend_Auth_Adapter_Ldap consists of the following options, which are passed, largely unmodified, to Zend_Ldap::setOptions():
useStartTls
useSsl
username
password
bindRequiresDn
75
Zend_Auth
Name
Description should be, as retrieving the DN requires an extra round trip to the server). Otherwise, this option must be set to TRUE (e.g. for OpenLDAP). This option also controls the default acountFilterFormat used when searching for accounts. See the accountFilterFormat option. The DN under which all accounts being authenticated are located. This option is required. if you are uncertain about the correct baseDn value, it should be sufficient to derive it from the user's DNS domain using DC= components. For example, if the user's principal name is alice@foo.net, a baseDn of DC=foo,DC=net should work. A more precise location (e.g., OU=Sales,DC=foo,DC=net) will be more efficient, however. A value of 2, 3 or 4 indicating the form to which account names should be canonicalized after successful authentication. Values are as follows: 2 for traditional username style names (e.g., alice), 3 for backslash-style names (e.g., FOO\alice) or 4 for principal style usernames (e.g., alice@foo.net). The default value is 4 (e.g., alice@foo.net). For example, with a value of 3, the identity returned by Zend_Auth_Result::getIdentity() (and Zend_Auth::getIdentity(), if Zend_Auth was used) will always be FOO\alice, regardless of what form Alice supplied, whether it be alice, alice@foo.net, FOO\alice, FoO \aLicE, foo.net\alice, etc. See the Account Name Canonicalization section in the Zend_Ldap documentation for details. Note that when using multiple sets of server options it is recommended, but not required, that the same accountCanonicalForm be used with all server options so that the resulting usernames are always canonicalized to the same form (e.g., if you canonicalize to EXAMPLE\username with an AD server but to username@example.com with an OpenLDAP server, that may be awkward for the application's high-level logic). The FQDN domain name for which the target LDAP server is an authority (e.g., example.com). This option is used to canonicalize names so that the username supplied by the user can be converted as necessary for binding. It is also used to determine if the server is an authority for the supplied username (e.g., if accountDomainName is foo.net and the user supplies bob@bar.net, the server will not be queried, and a failure will result). This option is not required, but if it is not supplied, usernames in principal name form (e.g., alice@foo.net) are not supported. It is strongly recommended that you supply this option, as there are
baseDn
accountCanonicalForm
accountDomainName
76
Zend_Auth
Name
Description many use-cases that require generating the principal name form. The 'short' domain for which the target LDAP server is an authority (e.g., FOO). Note that there is a 1:1 mapping between the accountDomainName and accountDomainNameShort. This option should be used to specify the NetBIOS domain name for Windows networks, but may also be used by non-AD servers (e.g., for consistency when multiple sets of server options with the backslash style accountCanonicalForm). This option is not required but if it is not supplied, usernames in backslash form (e.g., FOO\alice) are not supported. The LDAP search filter used to search for accounts. This string is a printf() [http://php.net/printf]style expression that must contain one '%s' to accomodate the username. The default value is '(&(objectClass=user)(sAMAccountName=%s))', unless bindRequiresDn is set to TRUE, in which case the default is '(&(objectClass=posixAccount)(uid=%s))'. For example, if for some reason you wanted to use bindRequiresDn = true with AD you would need to set accountFilterFormat = '(&(objectClass=user) (sAMAccountName=%s))'. If set to TRUE, this option indicates to the LDAP client that referrals should be followed. The default value is FALSE.
accountDomainNameShort
accountFilterFormat
optReferrals
Nota
If you enable useStartTls = TRUE or useSsl = TRUE you may find that the LDAP client generates an error claiming that it cannot validate the server's certificate. Assuming the PHP LDAP extension is ultimately linked to the OpenLDAP client libraries, to resolve this issue you can set "TLS_REQCERT never" in the OpenLDAP client ldap.conf (and restart the web server) to indicate to the OpenLDAP client library that you trust the server. Alternatively, if you are concerned that the server could be spoofed, you can export the LDAP server's root certificate and put it on the web server so that the OpenLDAP client can validate the server's identity.
Index 1
77
Zend_Auth
Description server operators. If the authentication is successful, this string is empty. All log messages in order starting at index 2.
In practice, index 0 should be displayed to the user (e.g., using the FlashMessenger helper), index 1 should be logged and, if debugging information is being collected, indexes 2 and higher could be logged as well (although the final message always includes the string from index 1).
accountCanonicalForm
accountDomainName accountDomainNameShort
Nota
Technically there should be no danger of accidental cross-domain authentication with the current Zend_Auth_Adapter_Ldap implementation, since server domains are explicitly checked, but this may not be true of a future implementation that discovers the domain at runtime, or if an alternative adapter is used (e.g., Kerberos). In general, account name ambiguity is known to be the source of security issues, so always try to use qualified account names.
78
Zend_Auth
password
bindRequiresDn baseDn
accountCanonicalForm
accountDomainName accountDomainNameShort
79
Zend_Auth
Nota
Zend_OpenId aprovecha las GMP extension [http://php.net/gmp], cuando estn disponibles. Considere la posibilidad de usar GMP extension para un mejor rendimiento cuando use Zend_Auth_Adapter_OpenId.
Caractersticas
Como es el caso de todos los adaptadores Zend_Auth, la clase Zend_Auth_Adapter_OpenId implementa Zend_Auth_Adapter_Interface, el cual define un metodo authenticate(). Este mtodo realiza la autenticacin en s, pero el objeto debe estar configurado antes de ser llamado. La configuracion del adaptador requiere la creacion de un OpenID y otras opciones de Zend_OpenId especficos. Sin embargo, a diferencia de otros adaptadores de Zend_Auth, Zend_Auth_Adapter_OpenId realiza la autenticacin en un servidor externo en dos peticiones HTTP separadas. As que el mtodo Zend_Auth_Adapter_OpenId::authenticate() debe ser llamado dos veces. En la primera invocacin del mtodo no regresar nada, sino que redirige al usuario a su servidor de OpenID. Luego, despus de que el usuario se autentica en el servidor remoto, este te regresar desde donde lo invocaste (a tu cdigo) y debers invocar a Zend_Auth_Adapter_OpenId::authenticate() de nuevo para verificar la firma que acompaa a la peticin de re-direccionamiento del servidor para completar el proceso de autenticacin . En esta segunda invocacin, el mtodo devolver el objeto Zend_Auth_Result como se esperaba. El siguiente ejemplo muestra el uso de Zend_Auth_Adapter_OpenId. Como se mencion anteriormente, Zend_Auth_Adapter_OpenId::autenticar() debe ser llamada dos veces. La primera vez es cuando el usuario enva el formulario HTML con el $_POST['openid_action'] en "Login" , y la segunda es posterior a la redireccin HTTP del servidor OpenID con $_GET['openid_mode'] o $_POST['openid_mode'] .
<?php $status = ""; $auth = Zend_Auth::getInstance(); if ((isset($_POST['openid_action']) && $_POST['openid_action'] == "login" && !empty($_POST['openid_identifier'])) || isset($_GET['openid_mode']) || isset($_POST['openid_mode'])) { $result = $auth->authenticate( new Zend_Auth_Adapter_OpenId(@$_POST['openid_identifier'])); if ($result->isValid()) { $status = "You are logged in as " . $auth->getIdentity() . "<br>\n"; } else { $auth->clearIdentity(); foreach ($result->getMessages() as $message) { $status .= "$message<br>\n"; } } } else if ($auth->hasIdentity()) { if (isset($_POST['openid_action']) && $_POST['openid_action'] == "logout") {
80
Zend_Auth
$auth->clearIdentity(); } else { $status = "You are logged in as " . $auth->getIdentity() . "<br>\n"; } } ?> <html><body> <?php echo htmlspecialchars($status);?> <form method="post"><fieldset> <legend>OpenID Login</legend> <input type="text" name="openid_identifier" value=""> <input type="submit" name="openid_action" value="login"> <input type="submit" name="openid_action" value="logout"> </fieldset></form></body></html>
Puede personalizar el proceso de autenticacin OpenID de varias formas. Por ejemplo, recibir la redireccin del servidor de OpenID en una pgina aparte, especificando la "raz" del sitio web y utilizar un Zend_OpenId_Consumer_Storage o un Zend_Controller_Response. Usted tambin puede utilizar el simple registro de extensiones para recuperar informacin sobre el usuario desde el servidor de OpenID. Todas estas posibilidades se describen con ms detalle en el captulo Zend_OpenId_Consume.
81
82
Captulo 6. Zend_Cache
Introduccin
Zend_Cache provee una forma genrica para cualquier cach de datos. El almacenamiento en cach en Zend Framework se opera por interfaces, mientras que los registros de cach son almacenados a travs de adapatadores del backend ( Archivo , Sqlite , Memcache ...) mediante un sistema flexible de documentos de identidad y etiquetas. Utilizando stas, es fcil en el futuro eliminar determinados tipos de registro. (Ejemplo: "eliminar todos los registros cach de determinada etiqueta"). El mdulo principal (Zend_Cache_Core) es genrico, flexible y configurable. Aun para sus necesidades especficas existen frontends de cach que extienden Zend_Cache_Core a conveniencia: Output , File , Function y Class .
83
Zend_Cache
// 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);
$backendOptions = array('cache_dir' => './tmp/'); $cache = Zend_Cache::factory('Output', 'File', $frontendOptions, $backendOptions); // Pasamos un identificador nico al mtodo 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().').'; Note que delineamos el resultado de time() dos veces; esto es algo dinmico para los propsitos de la demostracin. Trate de ejecutarlo y entonces regenrelo muchas veces; notar que el primer nmero no cambia mientras que el segundo cambia a medida que pasa el tiempo. Esto es porque el primer nmero esta delineado en la seccin cach
84
Zend_Cache
y esta guardado en medio de otras salidas. Despus de medio minuto (habremos establecido el tiempo de vida de 30 segundos) los nmeros deben acoplarse nuevamente porque el registro cach ha expirado -- slo para ser almacenado en cach nuevamente. Deber probarlo en su visualizador o consola.
Nota
Cuando usamos Zend_Cache, ponemos atencin a la importacin del identificador cach (pasado a save() y start() ). ste deber ser nico para cada recurso que se almacene en cach, de otra manera los registros almacenados en cach que no se vinculan podran borrarse unos a otros, o peor an, mostrarse uno en lugar del otro.
Nota
The conditional execution design of your generating code is not necessary in some frontends (Function, for an example) when the whole logic is implemented inside the frontend.
Nota
'Cache hit' is a term for a condition when a cache record is found, is valid and is 'fresh' (in other words hasn't expired yet). 'Cache miss' is everything else. When a cache miss happens, you must generate your data (as you would normally do) and have it cached. When you have a cache hit, on the other hand, the backend automatically fetches the record from cache transparently.
85
Zend_Cache
$frontendOptions, $backendOptions); In the following examples we will assume that the $cache variable holds a valid, instantiated frontend as shown and that you understand how to pass parameters to your chosen backends.
Nota
Always use Zend_Cache::factory() to get frontend instances. Instantiating frontends and backends yourself will not work as expected.
Tagging Records
Tags are a way to categorize cache records. When you save a cache with the save() method, you can set an array of tags to apply for this record. Then you will be able to clean all cache records tagged with a given tag (or tags): $cache->save($huge_data, 'myUniqueID', array('tagA', 'tagB', 'tagC'));
Nota
note than the save() method accepts an optional fourth argument: $specificLifetime (if != FALSE, it sets a specific lifetime for this particular cache record)
86
Zend_Cache
If you want to remove cache entries matching the tags 'tagA' or 'tagC': $cache->clean( Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, array('tagA', 'tagC') ); Available cleaning modes are: CLEANING_MODE_ALL, CLEANING_MODE_OLD, CLEANING_MODE_MATCHING_TAG, CLEANING_MODE_NOT_MATCHING_TAG and CLEANING_MODE_MATCHING_ANY_TAG. The latter are, as their names suggest, combined with an array of tags in cleaning operations.
Zend_Cache Frontends
Zend_Cache_Core
Introduction
Zend_Cache_Core is a special frontend because it is the core of the module. It is a generic cache frontend and is extended by other classes.
Nota
All frontends inherit from Zend_Cache_Core so that its methods and options (described below) would also be available in other frontends, therefore they won't be documented there.
Available options
These options are passed to the factory method as demonstrated in previous examples.
cache_id_prefix
String
NULL
lifetime
Integer
3600
87
Zend_Cache
Option logging
Description if set to TRUE, logging through Zend_Log is activated (but the system is slower) Enable / disable write control (the cache is read just after writing to detect corrupt entries), enabling write_control will lightly slow the cache writing but not the cache reading (it can detect some corrupt cache files but it's not a perfect control) Enable / disable automatic serialization, it can be used to save directly datas which aren't strings (but it's slower) Disable / Tune the automatic cleaning process (garbage collector): 0 means no automatic cache cleaning, 1 means systematic cache cleaning and x > 1 means automatic random cleaning 1 times in x write operations. if set to TRUE, the core will set the ignore_user_abort PHP flag inside the save() method to avoid cache corruptions in some cases
write_control
Boolean
TRUE
automatic_serialization
Boolean
FALSE
automatic_cleaning_factor Integer
10
ignore_user_abort
Boolean
FALSE
Ejemplos
An example is given in the manual at the very beginning. If you store only strings into cache (because with "automatic_serialization" option, it's possible to store some booleans), you can use a more compact construction like:
// we assume you already have $cache $id = 'myBigLoop'; // cache id of "what we want to cache" if (!($data = $cache->load($id))) { // cache miss $data = ''; for ($i = 0; $i < 10000; $i++) { $data = $data . $i;
88
Zend_Cache
} $cache->save($data); } // [...] do something with $data (echo it, pass it on etc.) If you want to cache multiple blocks or data instances, the idea is the same: // make sure you use unique identifiers: $id1 = 'foo'; $id2 = 'bar'; // block 1 if (!($data = $cache->load($id1))) { // cache missed $data = ''; for ($i=0;$i<10000;$i++) { $data = $data . $i; } $cache->save($data); } echo($data); // this isn't affected by caching echo('NEVER CACHED! '); // block 2 if (!($data = $cache->load($id2))) { // cache missed $data = ''; for ($i=0;$i<10000;$i++) { $data = $data . '!'; } $cache->save($data); } echo($data); If you want to cache special values (boolean with "automatic_serialization" option) or empty strings you can't use the compact construction given above. You have to test formally the cache record. // the compact construction // (not good if you cache empty strings and/or booleans) if (!($data = $cache->load($id))) { // cache missed
89
Zend_Cache
// [...] we make $data $cache->save($data); } // we do something with $data // [...] // the complete construction (works in any case) if (!($cache->test($id))) { // cache missed // [...] we make $data $cache->save($data); } else { // cache hit $data = $cache->load($id); } // we do something with $data
Zend_Cache_Frontend_Output
Introduction
Zend_Cache_Frontend_Output is an output-capturing frontend. It utilizes output buffering in PHP to capture everything between its start() and end() methods.
Available Options
This frontend doesn't have any specific options other than those of Zend_Cache_Core.
Ejemplos
An example is given in the manual at the very beginning. Here it is with minor changes: // if it is a cache miss, output buffering is triggered if (!($cache->start('mypage'))) { // output everything as usual echo 'Hello world! '; echo 'This is cached ('.time().') '; $cache->end(); // output buffering ends
90
Zend_Cache
} echo 'This is never cached ('.time().').'; Using this form it is fairly easy to set up output caching in your already working project with little or no code refactoring.
Zend_Cache_Frontend_Function
Introduction
Zend_Cache_Frontend_Function caches the results of function calls. It has a single main method named call() which takes a function name and parameters for the call in an array.
Available Options
Tabla 6.2. Function Frontend Options
Option cache_by_default cached_functions non_cached_functions Data Type Boolean Array Array Default Value TRUE Description if TRUE, function calls will be cached by default function names which will always be cached function names which must never be cached
Ejemplos
Using the call() function is the same as using call_user_func_array() in PHP: $cache->call('veryExpensiveFunc', $params); // // // // $params is an array For example to call veryExpensiveFunc(1, 'foo', 'bar') with caching, you can use $cache->call('veryExpensiveFunc', array(1, 'foo', 'bar'))
Zend_Cache_Frontend_Function is smart enough to cache both the return value of the function and its internal output.
Nota
You can pass any built in or user defined function with the exception of array(), echo(), empty(), eval(), exit(), isset(), list(), print() and unset().
Zend_Cache_Frontend_Class
Introduction
Zend_Cache_Frontend_Class is different from Zend_Cache_Frontend_Function because it allows caching of object and static method calls.
91
Zend_Cache
Available Options
Tabla 6.3. Class Frontend Options
Option cached_entity (required) Data Type Mixed Default Value Description if set to a class name, we will cache an abstract class and will use only static calls; if set to an object, we will cache this object methods TRUE if TRUE, calls will be cached by default method names which will always be cached method names which must never be cached
Ejemplos
For example, to cache static calls :
class Test { // Static method public static function foobar($param1, $param2) { echo "foobar_output($param1, $param2)"; return "foobar_return($param1, $param2)"; } } // [...] $frontendOptions = array( 'cached_entity' => 'Test' // The name of the class ); // [...] // The cached call $result = $cache->foobar('1', '2'); To cache classic method calls :
class Test { private $_string = 'hello !'; public function foobar2($param1, $param2) { echo($this->_string); echo "foobar2_output($param1, $param2)"; return "foobar2_return($param1, $param2)";
92
Zend_Cache
} } // [...] $frontendOptions = array( 'cached_entity' => new Test() // An instance of the class ); // [...] // The cached call $result = $cache->foobar2('1', '2');
Zend_Cache_Frontend_File
Introduction
Zend_Cache_Frontend_File is a frontend driven by the modification time of a "master file". It's really interesting for examples in configuration or templates issues. It's also possible to use multiple master files. For instance, you have an XML configuration file which is parsed by a function which returns a "config object" (like with Zend_Config). With Zend_Cache_Frontend_File, you can store the "config object" into cache (to avoid the parsing of the XML config file at each time) but with a sort of strong dependency on the "master file". So, if the XML config file is modified, the cache is immediately invalidated.
Available Options
Tabla 6.4. File Frontend Options
Option master_file (deprecated) master_files master_files_mode Data Type String Array String Default Value '' array() Description the complete path and name of the master file an array of complete path of master files
Zend_Cache_Frontend_File::MODE_OR Zend_Cache_Frontend_File::MODE_A or Zend_Cache_Frontend_File::MODE_O ; if MODE_AND, then all master files have to be touched to get a cache invalidation if MODE_OR, then a single touched master file is enough to get a cache invalidation FALSE if TRUE, missing master files are ignored silently (an exception is raised else)
ignore_missing_master_files Boolean
Ejemplos
Use of this frontend is the same than of Zend_Cache_Core. There is no need of a specific example - the only thing to do is to define the master_file when using the factory.
93
Zend_Cache
Zend_Cache_Frontend_Page
Introduction
Zend_Cache_Frontend_Page is like Zend_Cache_Frontend_Output but designed for a complete page. It's impossible to use Zend_Cache_Frontend_Page for caching only a single block. On the other hand, the "cache id" is calculated automatically with $_SERVER['REQUEST_URI'] and (depending on options) $_GET, $_POST, $_SESSION, $_COOKIE, $_FILES. More over, you have only one method to call (start()) because the end() call is fully automatic when the page is ended. For the moment, it's not implemented but we plan to add a HTTP conditional system to save bandwidth (the system will send a HTTP 304 Not Modified if the cache is hit and if the browser has already the good version).
Available Options
Tabla 6.5. Page Frontend Options
Option http_conditional Data Type Boolean Default Value FALSE Description use the http_conditional system (not implemented for the moment) if TRUE, a debug text is added before each cached pages an associative default options: array of
debug_header
Boolean
FALSE
default_options
Array
array(...see below...)
(boolean, TRUE by default) cache: cache is on if TRUE (boolean, FALSE by default) cache_with_get_variables: if TRUE, cache is still on even if there are some variables in $_GET array (boolean, FALSE by default) cache_with_post_variables: if TRUE, cache is still on even if there are some variables in $_POST array (boolean, FALSE by default) cache_with_session_variables: if TRUE, cache is still on even if there are some variables in $_SESSION array
94
Zend_Cache
Option
Data Type
Default Value
Description (boolean, FALSE by default) cache_with_files_variables: if TRUE, cache is still on even if there are some variables in $_FILES array (boolean, FALSE by default) cache_with_cookie_variables: if TRUE, cache is still on even if there are some variables in $_COOKIE array (boolean, TRUE by default) make_id_with_get_variables: if TRUE, the cache id will be dependent of the content of the $_GET array (boolean, TRUE by default) make_id_with_post_variables: if TRUE, the cache id will be dependent of the content of the $_POST array (boolean, TRUE by default) make_id_with_session_variables: if TRUE, the cache id will be dependent of the content of the $_SESSION array (boolean, TRUE by default) make_id_with_files_variables: if TRUE, the cache id will be dependent of the content of the $_FILES array (boolean, TRUE by default) make_id_with_cookie_variables: if TRUE, the cache id will be dependent
95
Zend_Cache
Option
Data Type
Default Value
Description of the content of the $_COOKIE array (int, FALSE by default) specific_lifetime: if not FALSE, the given lifetime will be used for the choosen regexp (array, array() by default) tags: tags for the cache record (int, NULL by default) priority: priority (if the backend supports it)
regexps
Array
array()
an associative array to set options only for some REQUEST_URI, keys are (PCRE) regexps, values are associative arrays with specific options to set if the regexp matchs on $_SERVER['REQUEST_URI'] (see default_options for the list of available options); if several regexps match the $_SERVER['REQUEST_URI'], only the last one will be used an array of strings corresponding to some HTTP headers name. Listed headers will be stored with cache datas and "replayed" when the cache is hit
memorize_headers
Array
array()
Ejemplos
Use of Zend_Cache_Frontend_Page is really trivial: // [...] // require, configuration and factory $cache->start(); // if the cache is hit, the result is sent to the browser // and the script stop here // rest of the page ... a more complex example which shows a way to get a centralized cache management in a bootstrap file (for using with Zend_Controller for example)
96
Zend_Cache
/* * You should avoid putting too many lines before the cache section. * For example, for optimal performances, "require_once" or * "Zend_Loader::loadClass" should be after the cache section. */ $frontendOptions = array( 'lifetime' => 7200, 'debug_header' => true, // for debugging 'regexps' => array( // cache the whole IndexController '^/$' => array('cache' => true), // cache the whole IndexController '^/index/' => array('cache' => true), // we don't cache the ArticleController... '^/article/' => array('cache' => false), // ... but we cache the "view" action of this ArticleController '^/article/view/' => array( 'cache' => true, // and we cache even there are some variables in $_POST 'cache_with_post_variables' => true, // but the cache will be dependent on the $_POST array 'make_id_with_post_variables' => true ) ) ); $backendOptions = array( 'cache_dir' => '/tmp/' ); // getting a Zend_Cache_Frontend_Page object $cache = Zend_Cache::factory('Page', 'File', $frontendOptions, $backendOptions); $cache->start(); // if the cache is hit, the result is sent to the browser and the // script stop here // [...] the end of the bootstrap file // these lines won't be executed if the cache is hit
97
Zend_Cache
// [...] // require, configuration and factory $cache->start(); // [...] if ($someTest) { $cache->cancel(); // [...] } // [...]
Zend_Cache Backends
There are two kinds of backends: standard ones and extended ones. Of course, extended backends offer more features.
Zend_Cache_Backend_File
This (extended) backends stores cache records into files (in a choosen directory). Available options are :
read_control
Boolean
TRUE
read_control_type
String
'crc32'
98
Zend_Cache
Option hashed_directory_level
Default Value 0
Description Hashed directory structure level : 0 means "no hashed directory structure", 1 means "one level of directory", 2 means "two levels"... This option can speed up the cache only when you have many thousands of cache files. Only specific benchs can help you to choose the perfect value for you. Maybe, 1 or 2 is a good start. Umask for the directory structure hashed
hashed_directory_umask file_name_prefix
Integer String
0700 'zend_cache'
prefix for cache files ; be really careful with this option because a too generic value in a system cache dir (like /tmp) can cause disasters when cleaning the cache umask for cache files internal max size for the metadatas array (don't change this value unless you know what you are doing)
cache_file_umask
Integer
0700 100
metatadatas_array_max_sizeInteger
Zend_Cache_Backend_Sqlite
This (extended) backends stores cache records into a SQLite database. Available options are :
Integer
10
99
Zend_Cache
Option
Data Type
Default Value
Description delete() or clean() methods are called) ; x (integer) > 1 => automatic vacuum randomly 1 times on x clean() or delete().
Zend_Cache_Backend_Memcached
This (extended) backends stores cache records into a memcached server. memcached [http://www.danga.com/ memcached/] is a high-performance, distributed memory object caching system. To use this backend, you need a memcached daemon and the memcache PECL extension [http://pecl.php.net/package/memcache]. Be careful : with this backend, "tags" are not supported for the moment as the "doNotTestCacheValidity=true" argument. Available options are :
compression compatibility
Boolean Boolean
FALSE FALSE
100
Zend_Cache
Zend_Cache_Backend_Apc
This (extended) backends stores cache records in shared memory through the APC [http://pecl.php.net/package/APC] (Alternative PHP Cache) extension (which is of course need for using this backend). Be careful : with this backend, "tags" are not supported for the moment as the "doNotTestCacheValidity=true" argument. There is no option for this backend.
Zend_Cache_Backend_Xcache
This backends stores cache records in shared memory through the XCache [http://xcache.lighttpd.net/] extension (which is of course need for using this backend). Be careful : with this backend, "tags" are not supported for the moment as the "doNotTestCacheValidity=true" argument. Available options are :
password
String
NULL
Zend_Cache_Backend_ZendPlatform
This backend uses content caching API of the Zend Platform [http://www.zend.com/en/products/platform/] product. Naturally, to use this backend you need to have Zend Platform installed. This backend supports tags, but does not support CLEANING_MODE_NOT_MATCHING_TAG cleaning mode. Specify this backend using a word separator -- '-', '.', ' ', or '_' -- between the words 'Zend' and 'Platform' when using the Zend_Cache::factory() method:
$cache = Zend_Cache::factory('Core', 'Zend Platform'); There are no options for this backend.
Zend_Cache_Backend_TwoLevels
This (extend) backend is an hybrid one. It stores cache records in two other backends : a fast one (but limited) like Apc, Memcache... and a "slow" one like File, Sqlite... This backend will use the priority parameter (given at the frontend level when storing a record) and the remaining space in the fast backend to optimize the usage of these two backends.
101
Zend_Cache
Specify this backend using a word separator -- '-', '.', ' ', or '_' -- between the words 'Two' and 'Levels' when using the Zend_Cache::factory() method:
slow_backend_custom_naming Boolean
fast_backend_custom_naming Boolean
FALSE
slow_backend_autoload
Boolean
FALSE
fast_backend_autoload
Boolean
FALSE
auto_refresh_fast_cache
Boolean
TRUE
stats_update_factor
Integer
10
102
Zend_Cache
$cache = Zend_Cache::factory('Core', 'Zend_Cache_Backend_ZendServer_Disk', $frontendOptions, $backendOptions, false, true); There is no option for this backend.
103
104
Captulo 7. Zend_Captcha
Introduccin
CAPTCHA [http://en.wikipedia.org/wiki/Captcha] es el acrnimo de "Completely Automated Public Turing test to tell Computers and Humans Apart" (Prueba de Turing pblica y automtica para diferenciar a mquinas y humanos). Es usado como un desafo-respuesta para asegurar que la informacin individual suministrada viene de un humano y no de un proceso automatizado. Tpicamente, un captcha es usado con envo de formularios donde no es necesario que el usuario se haya autenticado, pero se desea prevenir el envo de spam. Los Captchas pueden presentarse en multitud de formas, incluyendo preguntas lgicas, caracteres trastocados o presentar mltiples imgenes y preguntar cmo se relacionan. Zend_Form intenta proveer una amalgama de backends que pueden ser utilizados por separado o en conjuncin con Zend_Form .
Captcha Operation
All CAPTCHA adapter implement Zend_Captcha_Adapter, which looks like the following: interface Zend_Captcha_Adapter extends Zend_Validate_Interface { public function generate(); public function render(Zend_View $view, $element = null); public function setName($name); public function getName(); public function getDecorator(); // Additionally, to satisfy Zend_Validate_Interface: public function isValid($value); public function getMessages(); public function getErrors(); } The name setter and getter are used to specify and retrieve the CAPTCHA identifier. getDecorator() can be used to specify a Zend_Form decorator either by name or returning an actual decorator object. The most interesting methods are generate() and render(). generate() is used to create the CAPTCHA token. This process typically will store the token in the session so that you may compare against it in subsequent requests. render() is used to render the information that represents the CAPTCHA, be it an image, a figlet, a logic problem, or some other CAPTCHA. A typical use case might look like the following:
105
Zend_Captcha
// Originating request: $captcha = new Zend_Captcha_Figlet(array( 'name' => 'foo', 'wordLen' => 6, 'timeout' => 300, )); $id = $captcha->generate(); echo "<form method=\"post\" action=\"\">"; echo $captcha->render($view); echo "</form>"; // // // if } On subsequent request: Assume captcha setup as before, the value of $_POST['foo'] would be key/value array: id => captcha ID, input => captcha value ($captcha->isValid($_POST['foo'], $_POST)) { // Validated!
CAPTCHA Adapters
The following adapters are shipped with Zend Framework by default.
Zend_Captcha_Word
Zend_Captcha_Word is an abstract adapter that serves as the base class for most other CAPTCHA adapters. It provides mutators for specifying word length, session TTL, the session namespace object to use, and the session namespace class to use for persistence if you do not wish to use Zend_Session_Namespace. Zend_Captcha_Word encapsulates validation logic. By default, the word length is 8 characters, the session timeout is 5 minutes, and Zend_Session_Namespace is used for persistence (using the namespace "Zend_Form_Captcha_<captcha ID>"). In addition to the methods required by the Zend_Captcha_Adapter interface, Zend_Captcha_Word exposes the following methods: setWordLen($length) and getWordLen() allow you to specify the length of the generated "word" in characters, and to retrieve the current value. setTimeout($ttl) and getTimeout() allow you to specify the time-to-live of the session token, and to retrieve the current value. $ttl should be specified in seconds. setSessionClass($class) and getSessionClass() allow you to specify an alternate Zend_Session_Namespace implementation to use to persist the CAPTCHA token and to retrieve the current value. getId() allows you to retrieve the current token identifier. getWord() allows you to retrieve the generated word to use with the CAPTCHA. It will generate the word for you if none has been generated yet. setSession(Zend_Session_Namespace $session) allows you to specify a session object to use for persisting the CAPTCHA token. getSession() allows you to retrieve the current session object.
106
Zend_Captcha
All word CAPTCHAs allow you to pass an array of options to the constructor, or, alternately, pass them to setOptions(). You can also pass a Zend_Config object to setConfig(). By default, the wordLen, timeout, and sessionClass keys may all be used. Each concrete implementation may define additional keys or utilize the options in other ways.
Nota
Zend_Captcha_Word is an abstract class and may not be instantiated directly.
Zend_Captcha_Dumb
The Zend_Captch_Dumb adapter is mostly self-descriptive. It provides a random string that must be typed in reverse to validate. As such, it's not a good CAPTCHA solution and should only be used for testing. It extends Zend_Captcha_Word.
Zend_Captcha_Figlet
The Zend_Captcha_Figlet adapter utilizes Zend_Text_Figlet to present a figlet to the user. Options passed to the constructor will also be passed to the Zend_Text_Figlet object. See the Zend_Text_Figlet documentation for details on what configuration options are available.
Zend_Captcha_Image
The Zend_Captcha_Image adapter takes the generated word and renders it as an image, performing various skewing permutations to make it difficult to automatically decipher. It requires the GD extension [http://php.net/gd] compiled with TrueType or Freetype support. Currently, the Zend_Captcha_Image adapter can only generate PNG images. Zend_Captcha_Image extends Zend_Captcha_Word, and additionally exposes the following methods: setExpiration($expiration) and getExpiration() allow you to specify a maximum lifetime the CAPTCHA image may reside on the filesystem. This is typically a longer than the session lifetime. Garbage collection is run periodically each time the CAPTCHA object is invoked, deleting all images that have expired. Expiration values should be specified in seconds. setGcFreq($gcFreq) and getGcFreg() allow you to specify how frequently garbage collection should run. Garbage collection will run every 1/$gcFreq calls. The default is 100. setFont($font) and getFont() allow you to specify the font you will use. $font should be a fully qualified path to the font file. This value is required; the CAPTCHA will throw an exception during generation if the font file has not been specified. setFontSize($fsize) and getFontSize() allow you to specify the font size in pixels for generating the CAPTCHA. The default is 24px. setHeight($height) and getHeight() allow you to specify the height in pixels of the generated CAPTCHA image. The default is 50px. setWidth($width) and getWidth() allow you to specify the width in pixels of the generated CAPTCHA image. The default is 200px. setImgDir($imgDir) and getImgDir() allow you to specify the directory for storing CAPTCHA images. The default is "./images/captcha/", relative to the bootstrap script.
107
Zend_Captcha
setImgUrl($imgUrl) and getImgUrl() allow you to specify the relative path to a CAPTCHA image to use for HTML markup. The default is "/images/captcha/". setSuffix($suffix) and getSuffix() allow you to specify the filename suffix for the CAPTCHA image. The default is ".png". Note: changing this value will not change the type of the generated image. All of the above options may be passed to the constructor by simply removing the 'set' method prefix and casting the initial letter to lowercase: "suffix", "height", "imgUrl", etc.
Zend_Captcha_ReCaptcha
The Zend_Captcha_ReCaptcha adapter uses Zend_Service_ReCaptcha to generate and validate CAPTCHAs. It exposes the following methods: setPrivKey($key) and getPrivKey() allow you to specify the private key to use for the ReCaptcha service. This must be specified during construction, although it may be overridden at any point. setPubKey($key) and getPubKey() allow you to specify the public key to use with the ReCaptcha service. This must be specified during construction, although it may be overridden at any point. setService(Zend_Service_ReCaptcha $service) and getService() allow you to set and get the ReCaptcha service object.
108
Captulo 8. Zend_CodeGenerator
Introduccin
Zend_CodeGenerator ofrece facilidades para generar cdigo arbitrario usando una interfaz orientada a objetos, tanto para crear cdigo nuevo como para actualizar cdigo existente. Mientras que la implementacin actual se limita a generar cdigo PHP, usted fcilmente puede extender la clase base a fin de proveer generacin de cdigo para otras tareas como: JavaScript, archivos de configuracin, apache vhost, etc.
Teora de Operacin
En el caso de uso ms tpico, simplemente instanciar una clase de generacin de cdigo y podr pasarle tanto la configuracin adecuada o configurarla despus de la instanciacin. Para generar el cdigo, simplemente haga "echo" del objeto o llame a su mtodo generate().
// Pasando la configuracin al constructor: $file = new Zend_CodeGenerator_Php_File(array( 'classes' => array( new Zend_CodeGenerator_Php_Class(array( 'name' => 'World', 'methods' => array( new Zend_CodeGenerator_Php_Method(array( 'name' => 'hello', 'body' => 'echo \'Hello world!\';', )), ), )), ) )); // Configurando despus de la instanciacin $method = new Zend_CodeGenerator_Php_Method(); $method->setName('hello') ->setBody('echo \'Hello world!\';'); $class = new Zend_CodeGenerator_Php_Class(); $class->setName('World') ->setMethod($method); $file = new Zend_CodeGenerator_Php_File(); $file->setClass($class); // Mostrar el archivo generado echo $file; // o grabarlo a un archivo: file_put_contents('World.php', $file->generate()); Ambos ejemplos anteriores mostrarn el mismo resultado:
109
Zend_CodeGenerator
} Otro caso de uso comn es actualizar el cdigo actual -- por ejemplo, para aadir un mtodo a una clase. En ese caso, primero debe inspeccionar el cdigo actual utilizando reflexin, y entonces aadir su nuevo mtodo. Zend_CodeGenerator lo hace trivialmente simple, aprovechando Zend_Reflection. Como ejemplo, digamos que hemos grabado lo anterior al archivo "World.php", y que ya est includo. Podramos entonces hacer lo siguiente:
$class = Zend_CodeGenerator_Php_Class::fromReflection( new Zend_Reflection_Class('World') ); $method = new Zend_CodeGenerator_Php_Method(); $method->setName('mrMcFeeley') ->setBody('echo \'Hello, Mr. McFeeley!\';'); $class->setMethod($method); $file = new Zend_CodeGenerator_Php_File(); $file->setClass($class); // Mostrar el archivo generado echo $file; // O mejor an, volver a grabarlo al archivo original: file_put_contents('World.php', $file->generate()); El archivo de la clase resultante se vera as:
110
Zend_CodeGenerator
Ejemplos de Zend_CodeGenerator
Ejemplo 8.1. Generando clases PHP
El siguiente ejemplo genera una clase vaca con una clase de nivel DocBlock.
$foo = new Zend_CodeGenerator_Php_Class(); $docblock = new Zend_CodeGenerator_Php_Docblock(array( 'shortDescription' => 'Sample generated class', 'longDescription' => 'This is a class generated with Zend_CodeGenerator.', 'tags' => array( array( 'name' => 'version', 'description' => '$Rev:$', ), array( 'name' => 'license', 'description' => 'New BSD', ), ), )); $foo->setName('Foo') ->setDocblock($docblock); echo $foo->generate(); El cdigo anterior resultar en lo siguiente:
/** * Sample generated class * * This is a class generated with Zend_CodeGenerator. * * @version $Rev:$ * @license New BSD * */ class Foo {
111
Zend_CodeGenerator
$foo = new Zend_CodeGenerator_Php_Class(); $docblock = new Zend_CodeGenerator_Php_Docblock(array( 'shortDescription' => 'Sample generated class', 'longDescription' => 'This is a class generated with Zend_CodeGenerator.', 'tags' => array( array( 'name' => 'version', 'description' => '$Rev:$', ), array( 'name' => 'license', 'description' => 'New BSD', ), ), )); $foo->setName('Foo') ->setDocblock($docblock) ->setProperties(array( array( 'name' => '_bar', 'visibility' => 'protected', 'defaultValue' => 'baz', ), array( 'name' => 'baz', 'visibility' => 'public', 'defaultValue' => 'bat', ), array( 'name' => 'bat', 'const' => true, 'defaultValue' => 'foobarbazbat', ), )); echo $foo->generate(); Lo anterior resulta en la siguiente definicin de clase:
112
Zend_CodeGenerator
* @version $Rev:$ * @license New BSD * */ class Foo { protected $_bar = 'baz'; public $baz = 'bat'; const bat = 'foobarbazbat';
$foo = new Zend_CodeGenerator_Php_Class(); $docblock = new Zend_CodeGenerator_Php_Docblock(array( 'shortDescription' => 'Sample generated class', 'longDescription' => 'This is a class generated with Zend_CodeGenerator.', 'tags' => array( array( 'name' => 'version', 'description' => '$Rev:$', ), array( 'name' => 'license', 'description' => 'New BSD', ), ), )); $foo->setName('Foo') ->setDocblock($docblock) ->setProperties(array( array( 'name' => '_bar', 'visibility' => 'protected', 'defaultValue' => 'baz', ), array( 'name' => 'baz', 'visibility' => 'public', 'defaultValue' => 'bat', ), array( 'name' => 'bat',
113
Zend_CodeGenerator
'const' => true, 'defaultValue' => 'foobarbazbat', ), )) ->setMethods(array( // Mtodo pasado como array array( 'name' => 'setBar', 'parameters' => array( array('name' => 'bar'), ), 'body' => '$this->_bar = $bar;' . "\n" . 'return $this;', 'docblock' => new Zend_CodeGenerator_Php_Docblock(array( 'shortDescription' => 'Set the bar property', 'tags' => array( new Zend_CodeGenerator_Php_Docblock_Tag_Param(array( 'paramName' => 'bar', 'datatype' => 'string' )), new Zend_CodeGenerator_Php_Docblock_Tag_Return(array( 'datatype' => 'string', )), ), )), ), // Mtodo pasado como instancia concreta new Zend_CodeGenerator_Php_Method(array( 'name' => 'getBar', 'body' => 'return $this->_bar;', 'docblock' => new Zend_CodeGenerator_Php_Docblock(array( 'shortDescription' => 'Retrieve the bar property', 'tags' => array( new Zend_CodeGenerator_Php_Docblock_Tag_Return(array( 'datatype' => 'string|null', )), ), )), )), )); echo $foo->generate(); Lo anterior genera la siguiente salida:
/** * Sample generated class * * This is a class generated with Zend_CodeGenerator. * * @version $Rev:$ * @license New BSD */
114
Zend_CodeGenerator
class Foo { protected $_bar = 'baz'; public $baz = 'bat'; const bat = 'foobarbazbat'; /** * Set the bar property * * @param string bar * @return string */ public function setBar($bar) { $this->_bar = $bar; return $this; }
/** * Retrieve the bar property * * @return string|null */ public function getBar() { return $this->_bar; }
$file = new Zend_CodeGenerator_Php_File(array( 'classes' => array($foo); 'docblock' => new Zend_CodeGenerator_Php_Docblock(array( 'shortDescription' => 'Foo class file', 'tags' => array( array( 'name' => 'license', 'description' => 'New BSD',
115
Zend_CodeGenerator
), ), )), 'body' )); Llamando a generate() generar el cdigo -- pero no lo grabar en un archivo. Usted mismo deber capturar y grabar los contenidos en un archivo. Por ejemplo: => 'define(\'APPLICATION_ENV\', \'testing\');',
/** * Sample generated class * * This is a class generated with Zend_CodeGenerator. * * @version $Rev:$ * @license New BSD */ class Foo { protected $_bar = 'baz'; public $baz = 'bat'; const bat = 'foobarbazbat'; /** * Set the bar property * * @param string bar * @return string */ public function setBar($bar) { $this->_bar = $bar; return $this; }
116
Zend_CodeGenerator
/** * Retrieve the bar property * * @return string|null */ public function getBar() { return $this->_bar; }
define('APPLICATION_ENV', 'testing');
Ejemplo 8.5. Sembrando la generacin de cdigo para un archivo PHP via reflection
You can add PHP code to an existing PHP file using the code generator. To do so, you need to first do reflection on it. The static method fromReflectedFileName() allows you to do this.
$generator = Zend_CodeGenerator_Php_Class::fromReflection( new Zend_Reflection_Class($class) ); $generator->setMethod(array( 'name' => 'setBaz', 'parameters' => array( array('name' => 'baz'), ), 'body' => '$this->_baz = $baz;' . "\n" . 'return $this;', 'docblock' => new Zend_CodeGenerator_Php_Docblock(array( 'shortDescription' => 'Set the baz property', 'tags' => array( new Zend_CodeGenerator_Php_Docblock_Tag_Param(array( 'paramName' => 'baz', 'datatype' => 'string' )), new Zend_CodeGenerator_Php_Docblock_Tag_Return(array( 'datatype' => 'string', )),
117
Zend_CodeGenerator
Referencias de Zend_CodeGenerator
Clases Abstractas e Interfaces
Zend_CodeGenerator_Abstract
La clase base desde la cual heredan todos las clases CodeGenerator proporciona la funcionalidad mnima necesaria. Su API es la siguiente:
abstract class Zend_CodeGenerator_Abstract { final public function __construct(Array $options = array()) public function setOptions(Array $options) public function setSourceContent($sourceContent) public function getSourceContent() protected function _init() protected function _prepare() abstract public function generate(); final public function __toString() } El constructor primero llama a _init() (que se deja vaca para implementar extenciones a clases concretas), se pasa entonces el parmetro $options a setOptions(), y finalmente se llama a _prepare() (nuevamente, a ser implementada por extensin de una clase) Al igual que la mayora de las clases en Zend Framework, setOptions() compara una opcin clave con setters existentes en la clase, y pasa el valor de ese mtodo si lo encuentra. __toString() es marcado como final, y proxies a generate(). setSourceContent() y getSourceContent() estn destinados ya sea para fijar el valor por defecto del contenido para el cdigo a ser generado, o para sustituir dicho contenido una vez que se completen todas las tareas de generacin.
Zend_CodeGenerator_Php_Abstract
Zend_CodeGenerator_Php_Abstract extiende Zend_CodeGenerator_Abstract, y aade algunas propiedades para localizar su contenido si es que ha cambiado, as como el nivel de identacin que debe aparecer antes del contenido generado. Su API es la siguiente:
118
Zend_CodeGenerator
abstract class Zend_CodeGenerator_Php_Abstract extends Zend_CodeGenerator_Abstract { public function setSourceDirty($isSourceDirty = true) public function isSourceDirty() public function setIndentation($indentation) public function getIndentation() }
Zend_CodeGenerator_Php_Member_Abstract
Zend_CodeGenerator_Php_Member_Abstract es una clase base para generar los miembros de clase -propiedades y mtodos -- y brinda accesos y mutadores para establecer visibilidad; ya sea el miembro abstracto o no, esttico o definitivo; y el nombre del miembro. Su API es la siguiente:
abstract class Zend_CodeGenerator_Php_Member_Abstract extends Zend_CodeGenerator_Php_Abstract { public function setAbstract($isAbstract) public function isAbstract() public function setStatic($isStatic) public function isStatic() public function setVisibility($visibility) public function getVisibility() public function setName($name) public function getName() }
class Zend_CodeGenerator_Php_Body extends Zend_CodeGenerator_Php_Abstract { public function setContent($content) public function getContent() public function generate() }
Zend_CodeGenerator_Php_Class
Zend_CodeGenerator_Php_Class Est destinado a generar clases PHP. La funcionalidad bsica slo genera la clase PHP en si misma, as como opcionalmente el PHP DocBlock. Las clases pueden implementarse o heredarse de otras clases, y pueden ser marcadas como abstractas. Utilizando otras clases generadoras de cdigo, tambin puede agregar constantes de clase, propiedades y mtodos.
119
Zend_CodeGenerator
class Zend_CodeGenerator_Php_Class extends Zend_CodeGenerator_Php_Abstract { public static function fromReflection( Zend_Reflection_Class $reflectionClass ) public function setDocblock(Zend_CodeGenerator_Php_Docblock $docblock) public function getDocblock() public function setName($name) public function getName() public function setAbstract($isAbstract) public function isAbstract() public function setExtendedClass($extendedClass) public function getExtendedClass() public function setImplementedInterfaces(Array $implementedInterfaces) public function getImplementedInterfaces() public function setProperties(Array $properties) public function setProperty($property) public function getProperties() public function getProperty($propertyName) public function setMethods(Array $methods) public function setMethod($method) public function getMethods() public function getMethod($methodName) public function hasMethod($methodName) public function isSourceDirty() public function generate() } El mtodo setProperty() acepta un array de informacin que puede ser utilizada para generar una instancia Zend_CodeGenerator_Php_Property -- o simplemente una instancia de Zend_CodeGenerator_Php_Property. Anlogamente, setMethod() acepta o un array de informacin para generar una instancia de Zend_CodeGenerator_Php_Method o una instancia concreta de esa clase. Se debe observar que setDocBlock() espera una instancia de Zend_CodeGenerator_Php_DocBlock.
Zend_CodeGenerator_Php_Docblock
Zend_CodeGenerator_Php_Docblock puede ser utilizada para generar PHP docblocks arbitrarios, incluidas todas las caractersticas estndar de docblock: descripciones cortas y largas y adems los tags de anotaciones. Los tags de anotacin pueden establecerse utilizando los mtodos setTag() y setTags(); cada una de estas toman o un array describiendo el tag que puede ser pasado al constructor Zend_CodeGenerator_Php_Docblock_Tag, o una instancia de esa clase. La API de la clase es la siguiente:
class Zend_CodeGenerator_Php_Docblock extends Zend_CodeGenerator_Php_Abstract { public static function fromReflection( Zend_Reflection_Docblock $reflectionDocblock )
120
Zend_CodeGenerator
Zend_CodeGenerator_Php_Docblock_Tag
Zend_CodeGenerator_Php_Docblock_Tag est destinado a crear tags de anotaciones arbitrarias para su inclusin en PHP docblocks. Se espera que los tags (etiquetas) contengan un nombre (la porcin que sigue inmediatamente despus del smbolo '@') y una descripcin (todo lo que sigue despus del nombre del tag). La API de la clase es la siguiente:
class Zend_CodeGenerator_Php_Docblock_Tag extends Zend_CodeGenerator_Php_Abstract { public static function fromReflection( Zend_Reflection_Docblock_Tag $reflectionTag ) public function setName($name) public function getName() public function setDescription($description) public function getDescription() public function generate() }
Zend_CodeGenerator_Php_DocBlock_Tag_Param
Zend_CodeGenerator_Php_DocBlock_Tag_Param es una versin especializada de Zend_CodeGenerator_Php_DocBlock_Tag, y representa un parmetro del mtodo. El nombre del tag es por lo tanto ("param"), pero debido al formato de este tag de anotacin, es necesaria informacin adicional a fin de generarla: el nombre del parmetro y el tipo de datos que representa. La API de la clase es la siguiente:
class Zend_CodeGenerator_Php_Docblock_Tag_Param extends Zend_CodeGenerator_Php_Docblock_Tag { public static function fromReflection( Zend_Reflection_Docblock_Tag $reflectionTagParam ) public function setDatatype($datatype) public function getDatatype() public function setParamName($paramName) public function getParamName() public function generate() }
121
Zend_CodeGenerator
Zend_CodeGenerator_Php_DocBlock_Tag_Return
Al igual la variante del tag docblock, Zend_CodeGenerator_Php_Docblock_Tab_Return es una variante de un tag de anotacin para representar el valor de retorno del mtodo. En este caso, el nombre del tag de anotacin es conocido ("return"), pero requiere un tipo de retorno. La API de la clase es la siguiente:
class Zend_CodeGenerator_Php_Docblock_Tag_Param extends Zend_CodeGenerator_Php_Docblock_Tag { public static function fromReflection( Zend_Reflection_Docblock_Tag $reflectionTagReturn ) public function setDatatype($datatype) public function getDatatype() public function generate() }
Zend_CodeGenerator_Php_File
Zend_CodeGenerator_Php_File se utiliza para generar el contenido ntegro de un archivo que contiene cdigo PHP. El archivo puede contener clases o cdigo PHP arbitrario, as como un archivo de nivel docblock si as lo desea. Cuando se agregan clases al archivo, necesitar pasar o un array de informacin para pasar al constructor Zend_CodeGenerator_Php_Class, o una instancia de esa clase. De manera similar, con docblocks, usted tendr que pasar informacin para que lo consuma el constructor Zend_CodeGenerator_Php_Docblock o una instancia de la clase. La API de la clase es la siguiente:
class Zend_CodeGenerator_Php_File extends Zend_CodeGenerator_Php_Abstract { public static function fromReflectedFilePath( $filePath, $usePreviousCodeGeneratorIfItExists = true, $includeIfNotAlreadyIncluded = true) public static function fromReflection(Zend_Reflection_File $reflectionFile) public function setDocblock(Zend_CodeGenerator_Php_Docblock $docblock) public function getDocblock() public function setRequiredFiles($requiredFiles) public function getRequiredFiles() public function setClasses(Array $classes) public function getClass($name = null) public function setClass($class) public function setFilename($filename) public function getFilename() public function getClasses() public function setBody($body) public function getBody() public function isSourceDirty() public function generate()
122
Zend_CodeGenerator
Zend_CodeGenerator_Php_Member_Container
Zend_CodeGenerator_Php_Member_Container es usado internamente por Zend_CodeGenerator_Php_Class para seguir la pista de los los miembros de la clase -- a propiedades y mtodos por igual. Estos estn indexados por nombre, utilizando las instancias concretas de los miembros como valores. La API de la clase es la siguiente:
Zend_CodeGenerator_Php_Method
Zend_CodeGenerator_Php_Method describe un mtodo de clase, y puede generar tanto el cdigo y el docblock para el mtodo. La visibilidad y condicin esttica, abstracta, o se puede indicar como final, por su clase padre, Zend_CodeGenerator_Php_Member_Abstract. Finalmente, pueden especificarse los parmetros y valor de retorno para el mtodo. Pueden establecerse los parmetros usando setParameter() o setParameters(). En cada caso, un parmetro debe ser un array de informacin para pasar al constructor Zend_CodeGenerator_Php_Parameter o una instancia de esa clase. La API de la clase es la siguiente:
class Zend_CodeGenerator_Php_Method extends Zend_CodeGenerator_Php_Member_Abstract { public static function fromReflection( Zend_Reflection_Method $reflectionMethod ) public function setDocblock(Zend_CodeGenerator_Php_Docblock $docblock) public function getDocblock() public function setFinal($isFinal) public function setParameters(Array $parameters) public function setParameter($parameter) public function getParameters() public function setBody($body) public function getBody() public function generate() }
Zend_CodeGenerator_Php_Parameter
Zend_CodeGenerator_Php_Parameter puede ser utilizada para especificar parmetros del mtodo. Cada parmetro puede tener una posicin (si no estn especificados, se usarn en el orden que estn registrados en el mtodo), son oblogatorios un valor por defecto, un tipo de datos y un nombre de parmetro. La API de la clase es la siguiente:
123
Zend_CodeGenerator
class Zend_CodeGenerator_Php_Parameter extends Zend_CodeGenerator_Php_Abstract { public static function fromReflection( Zend_Reflection_Parameter $reflectionParameter ) public function setType($type) public function getType() public function setName($name) public function getName() public function setDefaultValue($defaultValue) public function getDefaultValue() public function setPosition($position) public function getPosition() public function generate() }
Zend_CodeGenerator_Php_Property
Zend_CodeGenerator_Php_Property describe una propiedad de clase, que puede ser tanto una constante o una variable. En cada caso, la propiedad puede tener un valor predeterminado asociado con ella. Adems, la visibilidad de las propiedades de la variable puede ser establecida por la clase padre, Zend_CodeGenerator_Php_Member_Abstract. La API de la clase es la siguiente:
class Zend_CodeGenerator_Php_Property extends Zend_CodeGenerator_Php_Member_Abstract { public static function fromReflection( Zend_Reflection_Property $reflectionProperty ) public function setConst($const) public function isConst() public function setDefaultValue($defaultValue) public function getDefaultValue() public function generate() }
124
Captulo 9. Zend_Config
Introduccin
Zend_Config est diseado para simplificar el acceso y el uso de datos de configuracin dentro de aplicaciones. Provee una interfaz de usuario basada en propiedades de objetos anidadas para acceder a datos de configuracin dentro del cdigo de la aplicacin. Los datos de configuracin pueden venir de multitud de medios que soporten almacenamiento de datos de forma jerrquica. Actualmente Zend_Config provee adaptadores para datos de configuracin que estn almacenados en archivos de texto con Zend_Config_Ini y Zend_Config_Xml .
// Dado un array de datos de configuracin $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 configuracin $config = new Zend_Config($configArray); // Muestra un dato de configuracin (resultado: 'www.example.com') echo $config->webhost; // Use los datos de configuracin 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 cmo interpretarlo. $db = Zend_Db::factory($config->database); Como se ilustra en el ejemplo de arriba, Zend_Config provee una sintxis de propiedades de objetos anidados para acceder a datos de configuracin pasados a su constructor. Junto al acceso a valores de datos orientado a objetos, Zend_Config tambin tiene el mtodo get() que devolver el valor por defecto suministrado si el elemento de datos no existe. Por ejemplo:
125
Zend_Config
// 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' ) ) );
// Lectura de la configuracin $config = new Zend_Config(require 'config.php'); // Muestra un dato de configuracin (resultado: 'www.example.com') echo $config->webhost;
Aspectos Tericos
Los datos de configuracin se hacen accesibles al constructor Zend_Config a travs de un array asociativo, que puede ser multidimensional, para permitir organizar los datos desde lo general a lo especfico. Las clases de adaptador concretas permiten construir una tabla asociativa para el constructor de Zend_Config a partir de un sistema de almacenamiento de datos de configuracin. 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. Cada valor del array de datos de configuracin se convierte en una propiedad del objeto Zend_Config. 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 Zend_Config, cargado con los datos del array. Esto ocurre recursivamente, de forma que una jerarqua de datos de configuracin puede ser creada con cualquier nmero de niveles. Zend_Config implementa las interfaces Countable e Iterator para facilitar el aceso sencillo a los datos de configuracin. As, uno puede usar la funcin count() [http://php.net/count] y constructores PHP como foreach [http://php.net/foreach] sobre objetos Zend_Config. Por defecto, los datos de configuracin permitidos a travs de Zend_Config son de slo lectura, y una asignacin (e.g., $config->database->host = 'example.com') provoca que se lance una excepcin. Este comportamiento por defecto puede ser sobrescrito a travs del constructor, sin embargo, para permitir la modificacin de valores de datos. Adems, cuando las modificaciones estn permitidas, Zend_Config soporta el borrado de elementos (unset) (i.e. unset($config->database->host);). El mtodo readOnly() puede ser usado para determinar si las modificaciones a un objeto Zend_Config estn permitidas y el mtodo setReadOnly() puede ser usado para evitar cualquier modificacin posterior a un objeto Zend_Config que fue creado con permiso de modificaciones.
126
Zend_Config
Nota
Es importante no confundir tales modificaciones en memoria con guardar los datos de configuracin a un medio de almacenamiento especfico. Las herramientas para crear y modificar datos de configuracin para distintos medios de almacenamiento estn fuera del alcance de Zend_Config. Existen soluciones thirdparty de cdigo abierto con el propsito de crear y modificar datos de configuracin de distintos medios de almacenamiento. Las clases del adaptador heredan de la clase Zend_Config debido a que utilizan su funcionalidad. La familia de clases Zend_Config permite organizar en secciones los datos de configuracin. Los objetos de adaptador Zend_Config pueden ser cargados con una sola seccin especificada, mltiples secciones especificadas, o todas las secciones (si no se especifica ninguna). Las clases del adaptador Zend_Config soportan un modelo de herencia nica que permite que los datos de configuracin hereden de una seccin de datos de configuracin a otra. Esto es provisto con el fin de reducir o eliminar la necesidad de duplicar datos de configuracin por distintos motivos. Una seccin heredada puede tambin sobrescribir los valores que hereda de su seccin padre. Al igual que la herencia de clases PHP, una seccin puede heredar de una seccin padre, la cual puede heredar de una seccin abuela, etc..., pero la herencia mltiple (i.e., la seccin C heredando directamente de las secciones padre A y B) no est permitida. Si tiene dos objetos Zend_Config, puede combinarlos en un nico objeto usando la funcin merge(). Por ejemplo, dados $config y $localConfig, puede fusionar datos de $localConfig a $config usando $config>merge($localConfig);. Los temes en $localConfig sobrescribirn cualquier item con el mismo nombre en $config.
Nota
El objeto Zend_Config que est ejecutando el merge debe haber sido construido para permitir modificaciones, pasando true como el segundo parmetro del constructor. El mtodo setReadOnly() puede entonces ser usado para evitar cualquier modificacin posterior despus de que el merge se haya completado.
Zend_Config_Ini
Zend_Config_Ini permite a los desarrolladores almacenar datos de configuracin en un formato de datos INI familiar, y leer de ellos en la aplicacin usando una sintxis de propiedades de objetos anidados. El formato INI se especializa en proveer tanto la habilidad de mantener una jerarqua de claves de datos (data keys) de configuracin como la de mantener una jerarqua entre secciones de datos de configuracin. Las jerarquas de datos de configuracin son provistas separando las claves mediante el carcter punto ( . ). Una seccin puede extender o heredar de otra seccin indicando el nombre de la seccin seguido de dos puntos ( : ) y el nombre de la seccin desde la cual se quieren heredar los datos.
parse_ini_file
Zend_Config_Ini utiliza la funcin parse_ini_file() [http://php.net/parse_ini_file] de PHP. Por favor, revise esta documentacin para observar sus comportamientos especficos, que se propagan a Zend_Config_Ini , tales como la forma en que los valores especiales: true , false , yes , no , y NULL son manejados.
Separador de clave
Por defecto, el carcter separador de clave es el punto ( . ). Puede ser reemplazado, no obstante,cambiando la clave de $options llamada 'nestSeparator' al construir el objeto Zend_Config_Ini . Por ejemplo:
127
Zend_Config
; Los datos de configuracin de la fase de pruebas heredan de la produccin ; y sobreescribren valores si es necesario [pruebas : produccion] database.params.host = dev.example.com database.params.username = devuser database.params.password = devsecret Ahora, asuma que el desarrollador de aplicaciones necesita los datos de configuracin de la etapa de pruebas del archivo INI. Resulta fcil cargar estos datos especificando el archivo INI en la seccin de la etapa de pruebas:
$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"
Nota
Tabla 9.1. Parmetros del constructor Zend_Config_Ini
Parmetros $filename $section Notas El archivo INI que se va a cargar. La [seccin] contenida en el archivo ini que se va a cargar. Fijar este parmetro a null cargar todas las secciones. Alternativamente, se puede introducir un array de nombres de seccin para cargar multiples secciones.
128
Zend_Config
Notas Array de opciones. Las siguientes claves estn aceptadas: allowModifications : Fijar a true para permitir modificaciones subsiguientes del archivo cargado. Por defecto es false nestSeparator : Carcter que utilizar como separador de anidamiento. Por defecto es "."
Zend_Config_Xml
Zend_Config_Xml permite a los desarrolladores almacenar datos de configuracin en un formato sencillo XML y leerlos a travs de una sintxis de propiedades de objetos anidados. El elemento raz del archivo XML es irrelevante y puede ser nombrado arbitrariamente. El primer nivel de elementos XML corresponde con las secciones de datos de configuracin. El formato XML admite organizacin jerrquica a travs del anidamiento de elementos XML bajo los elementos a nivel de seccin. El contenido de un elemento XML a nivel de hoja corresponde al valor de un dato de configuracin. La herencia de seccin est permitida por un atributo XML especial llamado extends, y el valor de este atributo se corresponde con la seccin de la cual los datos son heredados por la seccin extendida..
Tipo devuelto
Los datos de configuracin que se leen en Zend_Config_Xml son siempre devueltos como strings. La conversin de datos de string a otros tipos se deja en manos de los desarrolladores para que se ajuste a sus necesidades particulares.
<?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>
129
Zend_Config
<params> <host>dev.example.com</host> <username>devuser</username> <password>devsecret</password> </params> </database> </staging> </configdata> Ahora, asuma que el desarrollador de aplicaciones necesita los datos de configuracin de la fase de pruebas del archivo XML. Es una tarea sencilla cargar estos datos, especificando el archivo XML y la seccin de pruebas:
$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"
<?xml version="1.0"?> <configdata> <production webhost="www.example.com"> <database adapter="pdo_mysql"> <params host="db.example.com" username="dbuser" password="secret" dbname="dbnam </database> </production> <staging extends="production"> <database> <params host="dev.example.com" username="devuser" password="devsecret"/> </database> </staging> </configdata> La otra forma no reduce la configuracin, sino que permite mantenerla de forma ms fcil dado que no es necesario escribir el nombre de la etiqueta dos veces. Simplemente, cree una etiqueta vaca con el valor en el atributo value:
<?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"/>
130
Zend_Config
</params> </database> </production> <staging extends="production"> <database> <params> <host value="dev.example.com"/> <username value="devuser"/> <password value="devsecret"/> </params> </database> </staging> </configdata>
XML strings
Zend_Config_Xml is able to load an XML string directly, such as that retrieved from a database. The string is passed as the first parameter to the constructor and must start with the characters '<?xml':
$string = <<<EOT <?xml version="1.0"?> <config> <production> <db> <adapter value="pdo_mysql"/> <params> <host value="db.example.com"/> </params> </db> </production> <staging extends="production"> <db> <params> <host value="dev.example.com"/> </params> </db> </staging> </config> EOT; $config = new Zend_Config_Xml($string, 'staging');
131
132
// Create the config object $config = new Zend_Config(array(), true); $config->production = array(); $config->staging = array(); $config->setExtend('staging', 'production'); $config->production->db = array(); $config->production->db->hostname = 'localhost'; $config->production->db->username = 'production'; $config->staging->db = array(); $config->staging->db->username = 'staging'; // Write the config file in one of the following ways: // a) $writer = new Zend_Config_Writer_Xml(array('config' => $config, 'filename' => 'config.xml')); $writer->write(); // b) $writer = new Zend_Config_Writer_Xml();
133
Zend_Config_Writer
$writer->setConfig($config) ->setFilename('config.xml') ->write(); // c) $writer = new Zend_Config_Writer_Xml(); $writer->write('config.xml', $config); This will create an XML config file with the sections production and staging, where staging extends production.
// Load all sections from an existing config file, while skipping the extends. $config = new Zend_Config_Ini('config.ini', null, array('skipExtends' => true, 'allowModifications' => true)); // Modify a value $config->production->hostname = 'foobar'; // Write the config file $writer = new Zend_Config_Writer_Ini(array('config' => $config, 'filename' => 'config.ini')); $writer->write();
134
135
Zend_Console_Getopt
136
Zend_Console_Getopt
'apple|a' => 'apple option, with no parameter', 'banana|b=i' => 'banana option, with required integer parameter', 'pear|p-s' => 'pear option, with optional string parameter' ) ); In the example declaration above, there are three options. --apple and -a are aliases for each other, and the option takes no parameter. --banana and -b are aliases for each other, and the option takes a mandatory integer parameter. Finally, --pear and -p are aliases for each other, and the option may take an optional string parameter.
137
Zend_Console_Getopt
Reporting Options
There are several methods to report the full set of options given by the user on the current command-line. As a string: use the toString() method. The options are returned as a space-separated string of flag=value pairs. The value of an option that does not have a parameter is the literal string "TRUE". As an array: use the toArray() method. The options are returned in a simple integer-indexed array of strings, the flag strings followed by parameter strings, if any. As a string containing JSON data: use the toJson() method. As a string containing XML data: use the toXml() method. In all of the above dumping methods, the flag string is the first string in the corresponding list of aliases. For example, if the option aliases were declared like verbose|v, then the first string, verbose, is used as the canonical name of the option. The name of the option flag does not include any preceding dashes.
138
Zend_Console_Getopt
Configuring Zend_Console_Getopt
Adding Option Rules
You can add more option rules in addition to those you specified in the Zend_Console_Getopt constructor, using the addRules() method. The argument to addRules() is the same as the first argument to the class constructor. It is either a string in the format of the short syntax options specification, or else an associative array in the format of a long syntax options specification. See Declaring Getopt Rules for details on the syntax for specifying options.
139
Zend_Console_Getopt
Adding Configuration
The third parameter to the Zend_Console_Getopt constructor is an array of configuration options that affect the behavior of the object instance returned. You can also specify configuration options using the setOptions() method, or you can set an individual option using the setOption() method.
140
Zend_Console_Getopt
Zend_Console_Getopt::CONFIG_DASHDASH ("dashDash"), if TRUE, enables the special flag -- to signify the end of flags. Command-line arguments following the double-dash signifier are not interpreted as options, even if the arguments start with a dash. This configuration option is TRUE by default. Zend_Console_Getopt::CONFIG_IGNORECASE ("ignoreCase"), if TRUE, makes flags aliases of each other if they differ only in their case. That is, -a and -A will be considered to be synonymous flags. This configuration option is FALSE by default. Zend_Console_Getopt::CONFIG_RULEMODE ("ruleMode") may have values Zend_Console_Getopt::MODE_ZEND ("zend") and Zend_Console_Getopt::MODE_GNU ("gnu"). It should not be necessary to use this option unless you extend the class with additional syntax forms. The two modes supported in the base Zend_Console_Getopt class are unambiguous. If the specifier is a string, the class assumes MODE_GNU, otherwise it assumes MODE_ZEND. But if you extend the class and add more syntax forms, you may need to specify the mode using this option. More configuration options may be added as future enhancements of this class. The two arguments to the setOption() method are a configuration option name and an option value.
141
142
Quick Start
Si necesita informacin ms detallada, mire las secciones siguientes. Si solamente quiere inicializar y ejecutar una aplicacin rpidamente, siga leyendo.
application/ controllers/ IndexController.php models/ views/ scripts/ index/ index.phtml helpers/ filters/ html/ .htaccess index.php
143
Zend_Controller
RewriteEngine On RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L] RewriteRule ^.*$ index.php [NC,L] La regla de arriba redirigir las peticiones a recuros existentes (enlaces simblicos existentes, archivos no vacos, o directorios no vacos) en consecuencia, y todas las otras peticiones al front controller.
Nota
Las reglas de arriba pertenecen a Apache. Para ejemplos de reglas de rewrite para otros servidores web, mire la documentacin de router .
Zend_Controller_Front::run('/path/to/app/controllers'); Esto instanciar y har un dispatch del front controller, que redigir las peticiones a los action controllers.
144
Zend_Controller
{ } } Por defecto, el action helper ViewRenderer est activado. Esto significa que simplemente definiendo un action method y un view script correspondiente, tendr su contenido generado inmediatamente. Por defecto, Zend_View es usado como la capa Vista en el patrn MVC. El ViewRenderer hace algo de magia, y usa el nombre de controlador (e.g., index ) y el nombre de accin actual (e.g., index ) para determinar qu plantilla traer. Por defecto, las plantillas terminan con la extensin .phtml , lo que significa que en el ejemplo de arriba, la plantilla index/index.phtml ser generada. Adicionalmente, el ViewRenderer asume automticamente que la carpeta views al mismo nivel que la carpeta controller ser la carpeta raz de la vista, y que el script de vista actual estar en la subcarpeta views/ scripts/. De esta forma, la plantilla generada ser encontrada en application/views/scripts/index/ index.phtml .
<!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 aplicacin Zend Framework</title> </head> <body> <h1>>Hola, Mundo!</h1> </body> </html>
class ErrorController extends Zend_Controller_Action { public function errorAction() { } } Asumiendo el sistema de carpetas discutido anteriormente, este archivo ir en application/controllers/ ErrorController.php . Tambin necesitar crear un view script en application/views/scripts/ error/error.phtml ; el contenido de ejemplo ser parecido a:
145
Zend_Controller
"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, intntelo de nuevo ms tarde.</p> </body> </html>
Vea el sitio!
Con su primer controlador y vista, ya puede arrancar su navegador y acceder a su sitio. Asumiendo que example.com es su dominio, cualquiera de las siguientes URLs le llevar a la pgina que acaba de crear: http://example.com/ http://example.com/index http://example.com/index/index Ya est listo para empezar a crear ms mtodos de controladores y acciones. Felicidades!
146
Zend_Controller
El flujo de procesos de Zend_Controller est implementado por varios componentes. Si bien no es necesario entender los cimientos de todos estos componentes para utilizar el sistema, tener un conocimiento prctico del proceso es de mucha utilidad. Zend_Controller_Front organiza todo el flujo de trabajo del sistema Zend_Controller. Es una interpretacin del patrn FrontController. Zend_Controller_Front procesa todas las solicitudes recibidas
147
Zend_Controller
por el servidor y es responsable en ltima instancia de la delegacin de las solicitudes a los ActionControllers (Zend_Controller_Action). Zend_Controller_Request_Abstract (a menudo denominado Request Object) representa el entorno de la solicitud y ofrece mtodos para establecer y recuperar el controlador, los nombres de las acciones y cualquier parmetro de solicitud. Adems realiza un seguimiento de si la accin que contiene ha sido enviada o no por Zend_Controller_Dispatcher. Se pueden usar extensiones del objeto abstracto para encapsular toda el entorno de la solicitud, permitiendo a los routers traer informacin del mbito de la solicitud a fin de establecer el controlador y los nombres de accin. Por defecto, se usa Zend_Controller_Request_Http, el cual proporciona acceso a todo el mbito de la peticin HTTP. Zend_Controller_Router_Interface se usa para definir routers. El ruteo es el proceso de examinar el mbito de la solicitud para determinar qu controlador, y qu accin del controlador debe recibir la solicitud. Este controlador, la accin, y los parmetros opcionales son luego establecidos en el objeto de la solicitud para ser procesados por Zend_Controller_Dispatcher_Standard. El ruteo (routing) ocurre slo una vez: cuando la solicitud se recibe inicialmente y antes de enviar el primer controlador. El router por defecto, Zend_Controller_Router_Rewrite, toma el punto final de una URI como se especific en Zend_Controller_Request_Http y la descompone en un controlador, una accin y parmetros, basndose en la informacin de la ruta del url. Como ejemplo, la URL http://localhost/foo/ bar/key/value se decodificar para usar el controlador foo, la accin bar y especificar un parmetro key con el valor de value. Zend_Controller_Router_Rewrite tambin puede ser utilizado para igualar las rutas arbitrarios; para ms informacin, ver documentacin del router. Zend_Controller_Dispatcher_Interface se usa para definir dispatchers. Dispatching (Despachar) es el proceso de sacar el controlador y la accin del objeto que solicita y mapearlo a un controlador archivo/clase y al mtodo accin en la clase del controlador. Si el controlador o accin no existen, har un manejo para determinar los controladores por defecto y las acciones a enviar. El proceso actual de dispatching(despacho) consta de instanciar la clase del controlador y llamar al mtodo accin en esa clase. A diferencia del routing, que ocurre slo una vez, el dispatching(despacho) ocurre en un bucle. Si el estado del objeto que que enva la solicita es reseteado en cualquier punto, el bucle se repetir, llamando a cualquier accin que est actualmente establecida en la solicitud del objeto. La primera vez el bucle termina con la solicitud del objeto, el estado de lo enviado se establece a (booleano true), que terminar el procesamiento. El dispatcher por defecto es Zend_Controller_Dispatcher_Standard. Se definen como controladores MixedCasedClasses cuando terminan en la palabra Controller, y los mtodos de accin como camelCasedMethods cuando terminan en la palabra Action: FooController::barAction(). En este caso, el controlador ser referido como foo y a la accin como bar.
148
Zend_Controller
Como ejemplo, si se va a la accin en FooBarController::bazBatAction(), se referir a ella en la URL como /foo-bar/baz-bat o /foo.bar/baz.bat. Zend_Controller_Action es el componente base del controlador de accin. Cada controlador es una sola clase que extiende la clase Zend_Controller_Action y debe contener uno o ms mtodos de accin. Zend_Controller_Response_Abstract define una clase base de respuesta utilizada para recoger y retornar respuestas de los controladores de accin. Recoge tanto a las cabeceras como al contenido del cuerpo. La clase de respuesta (response) por defecto es Zend_Controller_Response_Http, la cual es adecuada para usarla en un entorno HTTP. El flujo de procesos de Zend_Controller es relativamente sencillo. Una solicitud es recibida por Zend_Controller_Front, la que a su vez llama a Zend_Controller_Router_Rewrite para determinar qu controlador (y la accin en ese controlador) despachar. Zend_Controller_Router_Rewrite descompone la URI a fin de establecer el controlador y el nombre de accin en la solicitud. Zend_Controller_Front entonces entra al bucle del dispatch. Llama a Zend_Controller_Dispatcher_Standard, el que pasa la solicitud para enviar al controlador y a la accin especificada en la solicitud (o el usado por defecto). Despus de que el controlador ha terminado, el control vuelve a Zend_Controller_Front. Si el controlador ha indicado que debe enviarse otro controlador mediante el reinicio del estado de la condicin de la solicitud, el bucle contina y se ejecuta otro envio. En caso contrario el proceso termina.
El Front Controller
Introduccin
Zend_Controller_Front implementa un Front Controller pattern [http://www.martinfowler.com/eaaCatalog/ frontController.html] usado en aplicaciones Model-View-Controller (MVC) [http://en.wikipedia.org/wiki/Modelview-controller]. Su propsito es inicializar el entorno de la solicitud, rutear la solicitud entrante, y luego hacer un envo de cualquier de las acciones descubiertas; le agrega las respuestas y las regresa cuando se completa el proceso. Zend_Controller_Front tambin implementa el Singleton pattern [http://en.wikipedia.org/wiki/ Singleton_pattern], significando que solo una nica instancia de l puede estar disponible en cualquier momento dado. Esto le permite actuar tambin como un registro en el que los dems objetos pueden extraer del proceso dispatch. Zend_Controller_Front registra un plugin broker consigo mismo, permitiendo que diversos eventos que dispara sean observados por plugins. En muchos casos, esto da el desarrollador la oportunidad de adaptar el proceso de dispatch al sitio sin la necesidad de ampliar el Front Controller para aadir funcionalidad. Como mnimo, el front controller necesita una o ms paths a directorios que contengan action controllers a fin de hacer su trabajo. Una variedad de mtodos tambin pueden ser invocados para seguir adaptando el medio ambiente del front controller y ese a sus helper classes.
149
Zend_Controller
Para deshabilitar el ViewRenderer, haga lo siguiente antes de llamar a dispatch(): // Deshabilitar el ViewRenderer helper: $front->setParam('noViewRenderer', true);
Mtodos Bsicos
El front controller tiene varios accessors para establecer su medio ambiente. Sin embargo, hay tres mtodos bsicos clave para la funcionalidad del front controller:
getInstance()
getInstance() se utiliza para recuperar una instancia del front controller. Como el front controller implementa un patrn Singleton, este tambin es el nico medio posible para instanciar un objeto front controller. $front = Zend_Controller_Front::getInstance();
setControllerDirectory() y addControllerDirectory
setControllerDirectory() se usa para decirle a el dispatcher dnde buscar para los archivos de clase action controller. Acepta bien un nico path o un array asociativo de pares mdulo/path. Como algunos ejemplos: // Establer el directorio de controladores por defecto: $front->setControllerDirectory('../application/controllers'); // Establecer varios directorios mdulos a la vez: $front->setControllerDirectory(array( 'default' => '../application/controllers', 'blog' => '../modules/blog/controllers', 'news' => '../modules/news/controllers', )); // Agregar un directorio de mdulos 'foo': $front->addControllerDirectory('../modules/foo/controllers', 'foo');
Nota
Si usa addControllerDirectory() sin un nombre de mdulo, este establecer el directorio default para el mdulo -- sobreescribindolo si ya existe. Puede conseguir la configuracin actual para el directorio del getControllerDirectory(); este devolver un array de pares mdulo/directorio. controlador utilizando
addModuleDirectory() y getModuleDirectory()
Uno de los aspectos del front controller es que puede definir una estructura modular de directorio para crear componentes standalone; estos son llamados "mdulos". Cada mdulo debe estar en su propio directorio y ser un espejo de la estructura del directorio del mdulo por defecto -- es decir, que debera tener como mnimo un subdirectorio de "controladores", y tpicamente un subdirectorio de "views" y otros subdirectorios de aplicaciones.
150
Zend_Controller
addModuleDirectory() permite pasar el nombre de un directorio que contiene uno o ms directorios de mdulos. A continuacin lo analiza y los aade como directorios de controladores al front controller. Despus, si quiere determinar el path a un determinado mdulo o al mdulo actual, puede llamar a getModuleDirectory(), opcionalmente puede pasar un nombre de mdulo para conseguir el directorio de ese mdulo especfico.
dispatch()
dispatch(Zend_Controller_Request_Abstract $request = null, Zend_Controller_Response_Abstract $response = null) hace el trabajo pesado del front controller. Puede opcionalmente tomar un request object y/o un response object, permitiendo al desarrollador pasar objetos peronalizados para cada uno. Si no se pasa ningun objeto solicitud o respuesta, dispatch() comprobar por objetos previamente registrados y utilizar esos o instanciar versiones por defecto a utilizar en su proceso (en ambos casos, el sabor de HTTP ser utilizado por defecto). Similarmente, dispatch() comprueba los objetos registrados router y dispatcher , instanciando las versiones por defecto de cada uno si ninguno de ellos se encuentra. El proceso de dispatch tiene tres eventos distintos: Routing Dispatching Response El routing se lleva a cabo exactamente una vez, utilizando los valores del objeto solicitud cuando se llama a dispatch(). El dispatching se lleva a cabo en un bucle; una solicitud puede indicar, bien mltiples acciones de dispatch, o el controlador o un plugin pueden restablecer el objeto solicitud para forzar medidas adicionales para dispatch. Cuando todo est hecho, el front controller devuelve una respuesta.
run()
Zend_Controller_Front::run($path) es un mtodo esttico que toma simplemente un path a un directorio que contiene controladores. Obtiene una instancia del front controller (via getInstance(), registra el path provisto via setControllerDirectory(), y finalmente dispatches. Bsicamente, run() es un mtodo conveniente que pueden utilizarse para setups de sitios que no requieran la personalizacin del medio ambiente del front controller.
// Instanciar el front controller, establecer el directorio de controladores, // y hacer el dispatch fcilmente en en un solo paso: Zend_Controller_Front::run('../application/controllers');
151
Zend_Controller
(set|get)DefaultControllerName() permite especificar un nombre diferente para usar en el controlador por defecto (en caso coontrario, se usa 'index') y recuperar el valor actual. Delegan a el dispatcher. (set|get)DefaultAction() le deja especificar un nombre diferente a utilizar para la accin predeterminada (en caso coontrario, se usa 'index') y recuperar el valor actual. Delegan a el dispatcher. (set|get)Request() le permite especificar la clase u objeto el request a usar durante el proceso de dispatch y recuperar el objeto actual. Al setear el objeto solicitud, puede pasarlo en un nombre de clase de solicitud, en cuyo caso el mtodo va a cargar el archivo clase y lo instanciar. (set|get)Router() le permite especificar la clase u objeto el router a usar durante el proceso de dispatch y recuperar el objeto actual. Al setear el objeto router, puede pasarlo en un nombre de clase de router, en cuyo caso el mtodo va a cargar el archivo clase y lo instanciar. Al recuperar el objeto router, en primer lugar comprueba para ver si hay alguno presente, y si no, instancia al router por defecto(reescribe el router). (set|get)BaseUrl() le permite especificar la URL base de la cual tirar cuando se rutean peticiones y recuperar el valor actual. El valor se provee al objeto solicitud justo antes de rutear. (set|get)Dispatcher() le permite especificar la clase u objeto el dispatcher a usar durante el proceso de dispatch y recuperar el objeto actual. Al setear el objeto dispatch, puede pasarlo en un nombre de clase de dispatcher, en cuyo caso el mtodo va a cargar el archivo clase y lo instanciar. Al recuperar el objeto dispatch, en primer lugar comprueba para ver si hay alguno presente, y si no, instancia al dispatcher por defecto. (set|get)Response() le permite especificar la clase u objeto response a usar durante el proceso de dispatch y recuperar el objeto actual. Al setear el objeto response, puede pasarlo en un nombre de clase de response, en cuyo caso el mtodo va a cargar el archivo clase y lo instanciar. registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null) le permite registrar plugin objects. Opcionalmente, setting $stackIndex, puede controlar el orden en que se ejecutarn los plugins. unregisterPlugin($plugin) le permite desregistrar plugin objects. $plugin puede ser tanto un objeto plugin o un string que denota la clase de plugin a desregistrar. throwExceptions($flag) se utiliza para activar/desactivar la capacidad de arrojar excepciones durante el proceso de dispatch. Por defecto, las excepciones son capturadas y colocadas en el objeto response ; activando throwExceptions() se anular este comportamiento. Para ms informacin, lea the section called Excepciones MVC. returnResponse($flag) se usa para decirle al front controller cuando regresar la respuesta (true) desde dispatch(), o si la respuesta debe ser emitida automticamente (false). Por defecto, la respuesta es automticamente emitida (llamando a Zend_Controller_Response_Abstract::sendResponse()); activando returnResponse()) se anular este comportamiento. Las razones para regresar la respuesta incluyen un deseo de comprobar las excepciones antes de emitir la respuesta, necesidad de hacer un log de diversos aspectos de la respuesta (tales como cabeceras), etc.
152
Zend_Controller
-- objetos y variables -- con el front controller, a ser devueltos en cualquier momento en la cadena de dispatch. Estos valores se transmiten al router, al dispatcher, y a los action controllers. Los mtodos incluyen: setParam($name, $value) permite establecer un nico parmetro de $name con el valor $value. setParams(array $params) permite configurar varios parmetros a la vez usando un array asociativo. getParam($name) permite recuperar un nico parmetro a la vez, utilizando como identificador a $name. getParams() permite recuperar toda la lista de parmetros a la vez. clearParams() permite borrar un nico parmetro (pasando un string identificador), parmetros con mltiples nombres (pasando un array de strings identificadores), o el stack de parmetros completo (pasando nada). Hay varios parmetros pre-definidos que puede ser seteados para tener usos especficos en la cadena de dispatch: useDefaultControllerAlways se usa para indicar a el dispatcher que utilice el controlador por defecto en el mdulo por defecto de cualquier solicitud que no sea dispatchable (es decir, el mdulo, el controlador y/o la accin no existen). Por defecto, est en off. Ver the section called Excepciones MVC que Usted Pueda Encontrar para informacin ms detallada sobre el uso de este setting. disableOutputBuffering se usa para indicarle a el dispatcher que no debe utilizar output buffering para capturar la salida generada por los controladores de accin. Por defecto, el dispatcher captura cualquier salida y la aade al contenido del cuerpo del objeto respuesta. noViewRenderer se usa para deshabilitar el ViewRenderer. Poniendo este parmetro a true, lo deshabilita. noErrorHandler se usa para deshabilitar el Error Handler plugin. Poniendo este parmetro a true, lo deshabilita.
153
Zend_Controller
Solicitud HTTP
Solicitud de acceso a datos
Zend_Controller_Request_Http encapsula el acceso a relevantes valores tal como el nombre de la llave y el valor para el controlador y variables de aacin enrutamiento y todos los parmetros adicionales analizados desde el URI. Adiccionalmente permite el acceso a valores contenidos en las superglobales como miembros pblicos y administra la actual base URL y la solicitud URI. los valores Superglobales no pueden ser determinados en una solicitud objeto, en vez usar los mtodos setParam/getParam para determinar o recuperar los parmetros del usuario.
Datos Superglobales
Cuando se accede a datos Superglobales a travs Zend_Controller_Request_Http como propiedades de miembros pblicos, es necesario mantener en mente que el nombre de la propiedad (supergloabl array key) corresponda a una supergloabl en un especfico orden de precedencia:1. GET, 2. POST, 3. COOKIE, 4. SERVER, 5. ENV. Las supergloables especficas pueden ser accedidas usando un mtodo pblico como una alternativa. Por ejemplo, el valor original de $_POST['user'] puede ser accedido llamando a getPost('user') en la solicitud objeto. Esto incluye getQuery() para recuperar elementos $_GET, y getHeader() para recuperar la solicitud de los encabezadores (headers).
154
Zend_Controller
Apache Quirks
Si est usando Apache 404 handler para pasar If you are using Apache's 404 handler to pass incoming requests to the front controller, or using a PT flag with rewrite rules, $_SERVER['REDIRECT_URL'] contains the URI you need, not $_SERVER['REQUEST_URI']. If you are using such a setup and getting invalid routing, you should use the Zend_Controller_Request_Apache404 class instead of the default Http class for your request object:
$request = new Zend_Controller_Request_Apache404(); $front->setRequest($request); This class extends the Zend_Controller_Request_Http class and simply modifies the autodiscovery of the request URI. It can be used as a drop-in replacement.
155
Zend_Controller
/** * Dispatch Request with custom base URL with Zend_Controller_Front. */ $router = new Zend_Controller_Router_Rewrite(); $controller = Zend_Controller_Front::getInstance(); $controller->setControllerDirectory('./application/controllers') ->setRouter($router) ->setBaseUrl('/projects/myapp'); // set the base url! $response = $controller->dispatch();
156
Zend_Controller
Most AJAX libraries allow you to send custom HTTP request headers; if your library does not send this header, simply add it as a request header to ensure the isXmlHttpRequest() method works for you.
157
Zend_Controller
/** * @param string $key * @return mixed */ public function getParam($key); /** * @param string $key * @param mixed $value * @return self */ public function setParam($key, $value); /** * @return array */ public function getParams(); /** * @param array $array * @return self */ public function setParams(array $array); /** * @param boolean $flag * @return self */ public function setDispatched($flag = true); /** * @return boolean */ public function isDispatched(); } La solicitud objeto es un contenedor para entorno de la solicitud. La cadena del controlador slo necesita saber cmo establecer y recuperar el controlador, la accin, los parmetros opcionales, y el estado del despachador. Por defecto, la solicitud buscar sus propios parmetros mediante el controlador o las llaves de la accin con el fin de determinar el controlador y la accin. Para ampliar esta clase, o uno de sus derivados, cuando se necesita la clase solicitud que interactue con un entorno especfico con el fin de recuperar los datos para su uso en las tareas antes descritas. Los ejemplos incluyen el entorno HTTP , un entorno CLI, o un entorno de PHP-GTK.
El Router Standard
Introduccin
Zend_Controller_Router_Rewrite Es el router standard del Framework. Routing es el proceso de tomar la parte final de una URI (la parte de la URI que viene despus de la URL base) y la descomposicin en parmetros para determinar qu mdulo, qu controlador y accin de ese controlador debe recibir la solicitud. Estos valores del mdulo,
158
Zend_Controller
controlador, accin y otros parmetros estn enpaquetados en un objeto Zend_Controller_Request_Http el cual es procesado luego por Zend_Controller_Dispatcher_Standard. El routing ocurre slo una vez: cuando se recibi inicialmente la solicitud y antes del dispatch del primer controlador. Zend_Controller_Router_Rewrite est diseado para permitir que una funcionalidad tipo mod_rewrite se pueda usar en estructuras PHP puras. Se basa muy vagamente en el routing de Ruby on Rails (RoR) y no requiere ningn conocimiento previo de reescritura de la URL del webserver. Est diseado para trabajar con solo una regla mod_rewrite de Apache (one of):
RewriteEngine On RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L] RewriteRule ^.*$ index.php [NC,L] El router rewrite tambin puede utilizarse con el IIS webserver (versions <= 7.0) si Isapi_Rewrite [http:// www.isapirewrite.com] se ha instalado como una extensin Isapi con la siguiente regla de reescribir:
IIS Isapi_Rewrite
Cuando se usa IIS, $_SERVER['REQUEST_URI'] puede no existir, o establecerlo como un string vaco. En este caso, Zend_Controller_Request_Http intentar usar el valor de $_SERVER['HTTP_X_REWRITE_URL'] establecido por la extensin Isapi_Rewrite. IIS 7.0 introduce un mdulo nativo de reescribir la URL, y puede ser configurado como sigue:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <rewrite> <rules> <rule name="Imported Rule 1" stopProcessing="true"> <match url="^.*$" /> <conditions logicalGrouping="MatchAny"> <add input="{REQUEST_FILENAME}" matchType="IsFile" pattern="" ignoreCase="false" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" pattern="" ignoreCase="false" /> </conditions> <action type="None" /> </rule>
159
Zend_Controller
<rule name="Imported Rule 2" stopProcessing="true"> <match url="^.*$" /> <action type="Rewrite" url="index.php" /> </rule> </rules> </rewrite> </system.webServer> </configuration>]></programlisting> <para> Si est usando Lighttpd, la siguiente regla de reescritura es vlida: </para> <programlisting language="lighttpd"><![CDATA[ url.rewrite-once = ( ".*\?(.*)$" => "/index.php?$1", ".*\.(js|ico|gif|jpg|png|css|html)$" => "$0", "" => "/index.php" )
Usando un Router
Para utilizar adecuadamente el router de reescritura debe instanciarlo, agregar algunas rutas definidas por el usuario y luego inyectarlo en el controlador. El siguiente cdigo ilustra el procedimiento: // Crear un router $router = $ctrl->getRouter(); // returns a rewrite router by default $router->addRoute( 'user', new Zend_Controller_Router_Route('user/:username', array('controller' => 'user', 'action' => 'info')) );
160
Zend_Controller
the section called Zend_Controller_Router_Route_Chain the section called Routes por Defecto * Las rutas pueden ser utilizadas numerosas veces para crear una cadena o un esquema de aplicacin de ruteo definido por el usuario. Puede usar cualquier nmero de rutas en cualquier configuracin, con la excepcin de la ruta del Mdulo, la cual debe ser utilizada una vez y probablemente como la ruta ms genrica (es decir, por defecto). Cada ruta se describe en mayor detalle ms adelante. El primer parmetro a addRoute es el nombre de la ruta. Se utiliza como un manejador para sacar las rutas del router (por ejemplo, con fines de generacin de URL). El segundo parmetro es la ruta misma.
Nota
El uso ms comn del nombre de ruta es por medio del ayudante de url Zend_View: <a href= "<?php echo $this->url(array('username' => 'martel'), 'user') ?>">Martel</a> Que resultara en la href: user/martel. El routing es un simple proceso de iteracin a travs de todas las rutas provistas y la equiparacin de sus definiciones con la peticin actual de URI. Cuando se encuentra una concordancia, se devuelven valores de variables desde la instancia Route y se inyecta en el objeto Zend_Controller_Request para su posterior utilizacin en el dispatcher as tambin como en los controladores creados por el usuario. En caso de no encontrar ninguna concordancia, se comprobar la siguiente ruta en la cadena. Si necesita determinar en qu ruta se encontr una concordancia, puede usar el mtodo getCurrentRouteName(), que devolver el identificador usado cuando registr la ruta con el router. Si quiere el objeto de la ruta actual, puede usar getCurrentRoute().
Matching Inverso
Las rutas estn equiparadas en orden inverso para asegurarse que las rutas ms genricas se definan primero.
Valores Retornados
Los valores retornados del routing provienen de parmetros URL o de rutas definidas por defecto por el usuario. Estas variables son accesibles posteriormente a travs de los mtodos Zend_Controller_Request::getParam() o Zend_Controller_Action::_getParam(). Hay tres variables que pueden utilizarse en las rutas - 'module', 'controller' y 'action'. Estas variables especiales son utilizados por Zend_Controller_Dispatcher para encontrar un controlador y una accin para hacer el dispatch.
Variables Especiales
Los nombres de estas variables especiales pueden ser diferentes si elige alterar los valores por defecto en Zend_Controller_Request_Http mediante los mtodos setControllerKey y setActionKey.
161
Zend_Controller
elemento del path, permitiendo URIs de la forma module/controller/action. Por ltimo, tambin coincidr con cualquier parmetro adicional agregado a la URI por defecto - controller/action/var1/value1/ var2/value2. Algunos ejemplos de cmo estn equiparadas las rutas:
// Asumiendo lo siguiente: $ctrl->setControllerDirectory( array( 'default' => '/path/to/default/controllers', 'news' => '/path/to/news/controllers', 'blog' => '/path/to/blog/controllers' ) ); Mdulo nicamente: http://example/news module == news Modulo invlido mapea al nombre del controlador: http://example/foo controller == foo Mdulo + controlador: http://example/blog/archive module == blog controller == archive Mdulo + controlador + acccin: http://example/blog/archive/list module == blog controller == archive action == list Mdulo + controlador + acccin + parmetros: http://example/blog/archive/list/sort/alpha/date/desc module == blog controller == archive action == list sort == alpha date == desc La ruta por defecto es simplemente un objeto Zend_Controller_Router_Route_Module almacenado bajo el nombre de (index) por 'default' en RewriteRouter. Est generado ms o menos as:
$compat = new Zend_Controller_Router_Route_Module(array(), $dispatcher, $request); $this->addRoute('default', $compat); Si no quiere esta ruta en particular en su esquema por defecto de routing, podr anularla creando su propia ruta por 'defecto' (es decir, almacenar bajo el nombre de 'default') o eliminarla por completo usando removeDefaultRoutes():
162
Zend_Controller
$request->setBaseUrl('/~user/application-root/');
Parmetros Globales
Puede establecer los parmetros globales en un router que se proporcionan automticamente a una ruta cuando se ensamblasn mediante setGlobalParam. Si se establece un parmetro global pero tambin se lo entrega directamente al mtodo de ensamblaje, el parmetro del usuario sobreescribe al parmetro global. Puede establecer un parmetro global esta forma:
$router->setGlobalParam('lang', 'en');
Tipos de Route
Zend_Controller_Router_Route
Zend_Controller_Router_Route es la ruta standard del framework. Combina la facilidad de uso con la flexibilidad para la definicin de rutas. Cada ruta consiste fundamentalmente en el mapeo de la URL (de partes estticas y dinmicas (variables)) y puede ser iniciada con valores predeterminados as como con requisitos variables. Imaginemos que nuestra aplicacin ficticia necesitar algunas pginas informativas sobre los autores del contenido. Queremos ser capaces de apuntar nuestro navegador web a http://domain.com/author/martel para ver la informacin sobre este muchacho "martel". La ruta para esa funcionalidad podra parecerse a:
$route = new Zend_Controller_Router_Route( 'author/:username', array( 'controller' => 'profile', 'action' => 'userinfo' ) ); $router->addRoute('user', $route); El primer parmetro en el constructor Zend_Controller_Router_Route es una definicin de ruta que ser acompaada de una URL. Las definiciones de ruta consisten en partes estticas y dinmicas separadas por el caracter barra ('/'). Las partes estticas son simples textos: author. Las partes dinmicas, llamadas variables, se marcan anteponiendo dos puntos (:) al nombre de la variable :username.
163
Zend_Controller
Uso de Caracteres
La implementacin actual le permite utilizar cualquier carcter (salvo una barra) como un identificador de variable, pero se recomienda encarecidamente que se utilicen slo caracteres que sean vlidos para identificadores de variables PHP. En implementaciones futuras se podra alterar este comportamiento, resultando en probables fallos escondidos en su cdigo. Este ejemplo de ruta debera ser coincidente cuando apunta su navegador a http://domain.com/author/ martel, en cuyo caso todas sus variables se inyectan al objeto Zend_Controller_Request y quedando accesibles en ProfileController. Las variables devueltas por este ejemplo pueden ser representadas como el siguiente array de pares clave/valor:
$values = array( 'username' => 'martel', 'controller' => 'profile', 'action' => 'userinfo' ); Despus, Zend_Controller_Dispatcher_Standard debe invocar al mtodo userinfoAction() de su clase ProfileController (en el mdulo por defecto) basado en estos valores. All se podrn acceder a todas las variables mediante los mtodos Zend_Controller_Action::_getParam() o Zend_Controller_Request::getParam():
public function userinfoAction() { $request = $this->getRequest(); $username = $request->getParam('username'); $username = $this->_getParam('username'); } La definicin de ruta puede contener uno o ms caracteres especiales - un comodn - representado por el smbolo '*'. Se utiliza para reunir parmetros al igual que el valor de ruta por defecto del Mdulo (var => pares de valores definidos en la URI). La siguiente ruta imita ms o menos el comportamiento de la ruta del Mdulo:
164
Zend_Controller
$router->addRoute('archive', $route); La ruta de arriba comparar URLs como http://domain.com/archive/2005 y http://example.com/ archive. En este ltimo caso la variable year(ao) tendr un valor inicial predeterminado de 2006. Este ejemplo resultar en inyectar una variable ao al objeto solicitud. Ya que no hay informacin de enrutamiento presente (no se define ningn controlador ni parmetros de accin), la solicitud ser enviada al controlador y al mtodo de accin por defecto (que a la vez ambos estn definidos en Zend_Controller_Dispatcher_Abstract). Para hacerlos ms utilizables, tiene que proporcionar un controlador vlido y una accin vlida como la ruta por defecto:
$route = new Zend_Controller_Router_Route( 'archive/:year', array( 'year' => 2006, 'controller' => 'archive', 'action' => 'show' ) ); $router->addRoute('archive', $route); Entonces, esta ruta resultar en el dispatch al mtodo showAction() de la clase ArchiveController.
$route = new Zend_Controller_Router_Route( 'archive/:year', array( 'year' => 2006, 'controller' => 'archive', 'action' => 'show' ), array('year' => '\d+') ); $router->addRoute('archive', $route); Con una ruta definida como la de arriba, el router comparar solo cuando la variable ao contenga datos numricos, eg. http://domain.com/archive/2345. Una URL como http://example.com/archive/test no se comparar y en su lugar el control se pasar a la prxima ruta en la cadena.
Segmentos Traducidos
El standard de ruta brinda apoyo a la traduccin de segmentos. Para utilizar esta caracterstica, tiene que definir por lo menos un traductor (una instancia de Zend_Translate) mediante una de las siguientes formas: Ponerlo en el registro con la clave Zend_Translate. Setearlo mediante el mtodo Zend_Controller_Router_Route::setDefaultTranslator(). Pasarlo como cuarto parmetro al constructor. esttico
165
Zend_Controller
Por defecto, se utilizar el "locale" especificado en la instancia Zend_Translate. Para anularlo, debe setearlo (como una instancia de Zend_Locale o un string local) de una de las siguientes maneras: Ponerlo en el registro con la clave Zend_Locale. Setearlo mediante el mtodo esttico Zend_Controller_Router_Route::setDefaultLocale(). Pasarlo como cuarto parmetro al constructor. Pasarlo como parmetro @locale al mtodo de ensamblaje. Los segmentos traducidos se dividen en dos partes. Los segmentos fijos estn precedidos por un nico signo @, y sern traducidos al "locale" actual para el ensamblaje y se revierten al ID del mensaje cuando se acepte nuevamente. Los segmentos dinmicos tienen el prefijo :@. Para el ensamblaje, el parmetro dado ser traducido y se insertar en la posicin del parmetro. Cuando se acepte, el parmetro traducido de la URL volver al ID del mensaje nuevamente.
// Prepare el traductor $translator = new Zend_Translate('array', array(), 'en'); $translator->addTranslation(array('archive' => 'archiv', 'year' => 'jahr', 'month' => 'monat', 'index' => 'uebersicht'), 'de'); // Establecer el "locale" actual para el traductor $translator->setLocale('en'); // Establecerlo como traductor por defecto para las rutas Zend_Controller_Router_Route::setDefaultTranslator($translator); Este ejemplo demuestra el uso de segmentos estticos:
// Crear la ruta $route = new Zend_Controller_Router_Route( '@archive', array( 'controller' => 'archive', 'action' => 'index' ) ); $router->addRoute('archive', $route); // Ensamblar la URL en el locale actual por defecto: archive $route->assemble(array());
166
Zend_Controller
// Ensamblar la URL en alemn: archiv $route->assemble(array()); Puede usar segmentos dinmicos para crear veriones traducidas como del tipo mdulo-ruta:
// Crear la ruta $route = new Zend_Controller_Router_Route( ':@controller/:@action/*', array( 'controller' => 'index', 'action' => 'index' ) ); $router->addRoute('archive', $route); // Ensamblar la URL en el "locale" por defecto: archive/index/foo/bar $route->assemble(array('controller' => 'archive', 'foo' => 'bar')); // Ensamblar la URL en alemn: archiv/uebersicht/foo/bar $route->assemble(array('controller' => 'archive', 'foo' => 'bar')); Tambin puede mezclar segmentos estticos y dinmicos:
// Crear la ruta $route = new Zend_Controller_Router_Route( '@archive/:@mode/:value', array( 'mode' => 'year' 'value' => 2005, 'controller' => 'archive', 'action' => 'show' ), array('mode' => '(month|year)' 'value' => '\d+') ); $router->addRoute('archive', $route); // Ensamblar la URL en el "locale" por defecto: archive/month/5 $route->assemble(array('mode' => 'month', 'value' => '5')); // Ensamblar la URL en alemn: archiv/monat/5 $route->assemble(array('mode' => 'month', 'value' => '5', '@locale' => 'de'));
Zend_Controller_Router_Route_Static
Los ejemplos sobre todo usan rutas dinmicas -- rutas que contienen patrones contra los cuales comparar. A veces, sin embargo, una ruta en particular pareciera estar seteada en piedra, y ejecutar el motor de expresiones regulares sera excesivo. La respuesta a esta situacin es utilizar rutas estticas:
$route = new Zend_Controller_Router_Route_Static( 'login', array('controller' => 'auth', 'action' => 'login')
167
Zend_Controller
); $router->addRoute('login', $route); La ruta anterior se comparar con una URL de http://domain.com/login, y har un dispatch a AuthController::loginAction().
$front->setParam('useDefaultControllerAlways', true); Sin embargo, esto es considerado un rodeo; siempre es mejor definir explcitamente valores correctos o sanos por defecto.
Zend_Controller_Router_Route_Regex
Adems de los tipos de ruta estticos y por defecto, tambin est disponible el tipo de ruta Expresin Regular. Esta ruta ofrece ms potencia y flexibilidad que los otros, pero a costa de un ligero aumento en la complejidad. Al mismo tiempo, debera ser ms rpido que la standard Route. Al igual que la standard Route, esta ruta tiene que ser inicializada con una definicin de ruta y algunos valores predeterminados. Vamos a crear un archivo ruta como un ejemplo, similar al previamente definido, slo que esta vez usaremos la ruta Regex:
$route = new Zend_Controller_Router_Route_Regex( 'archive/(\d+)', array( 'controller' => 'archive', 'action' => 'show' ) ); $router->addRoute('archive', $route); Cada sub-patrn regex definido ser inyectado al objeto solicitud. Con nuestro ejemplo anterior, despus de un matching exitoso http://domain.com/archive/2006, el valor resultante del array puede verse como:
$values = array(
168
Zend_Controller
Nota
Las barras de comienzo y final estn recortadas de la URL en el Router antes de una concordancia. Como resultado, coincidendo con la URL http://domain.com/foo/bar/, involucrara al regex de foo/ bar, y no a /foo/bar.
Nota
Las anclas de comienzo y fin de lnea ('^' y '$', respectivamente) son automticamente antepuestas y pospuestas a todas las expresiones. As, no debe usar stas en sus expresiones regulares, y debe coincidir con el string completo.
Nota
Esta clase de ruta usa el carcter # como un delimitador. Esto significa que necesitar caracteres hash ('#') para escapar pero no barras ('/') en sus definiciones de ruta. Dado que el carcter '#' (llamado ancla) es raramente pasado al webserver, ser muy rara la necesidad de utilizar ese carcter en su regex. Puede obtener el contenido de los sub-patrones definidos por la forma habitual:
Nota
Tenga en cuenta que la clave es un entero (1) en lugar de un string ('1'). Sin embargo, esta ruta no funciona exactamente igual que su contraparte standard route dado que el valor por defecto para 'year' todava no se ha establecido. Y lo que puede ser no tan evidente es que tendremos un problema con una barra final incluso si declaramos por defecto el ao y hacemos opcional al sub-patrn. La solucin es hacer que toda la parte del ao sea opcional junto con la barra pero capturar solo la parte numrica:
$route = new Zend_Controller_Router_Route_Regex( 'archive(?:/(\d+))?', array( 1 => '2006', 'controller' => 'archive', 'action' => 'show' ) ); $router->addRoute('archive', $route); Ahora, ocupemsnos del problema que probablemente haya notado. Utilizar claves basadas en enteros para los parmetros no es una solucin fcilmente manejable y puede ser potencialmente problemtica a largo plazo. Y aqu es
169
Zend_Controller
donde entra el tercer parmetro. Este parmetro es un array asociativo que representa un mapa de sub-patrones regex a nombres de clave de parmetros. Trabajemos en nuestro ejemplo ms fcil: $route = new Zend_Controller_Router_Route_Regex( 'archive/(\d+)', array( 'controller' => 'archive', 'action' => 'show' ), array( 1 => 'year' ) ); $router->addRoute('archive', $route); Esto resultara en los siguientes valores inyectados a la solicitud: $values = array( 'year' => '2006', 'controller' => 'archive', 'action' => 'show' ); El mapa puede ser definido en cualquier direccin para hacer que funcione en cualquier ambiente. Las claves pueden contener nombres de variables o ndices de sub-patrones: $route = new Zend_Controller_Router_Route_Regex( 'archive/(\d+)', array( ... ), array(1 => 'year') ); // O $route = new Zend_Controller_Router_Route_Regex( 'archive/(\d+)', array( ... ), array('year' => 1) );
Nota
Las claves de los sub-patrones deben respresentarse por enteros. Observe que el ndice numrico en los valores del Request ahora han desaparecido y en su lugar se muestra una variable nombrada. Por supuesto que puede mezclar variables nombradas y numricas si lo desea: $route = new Zend_Controller_Router_Route_Regex( 'archive/(\d+)/page/(\d+)', array( ... ), array('year' => 1) );
170
Zend_Controller
Lo que resultar en una mezcla de valores disponibles en la solicitud. Como ejemplo, la URL http:// domain.com/archive/2006/page/10 resultar con los siguientes valores:
Dado que los patrones regex no pueden invertirse fcilmente, tendr que preparar una URL inversa si desea usar un ayudante de URL o incluso un mtodo de ensamble de esta clase. Este path inverso est representado por un string parseable por sprintf() y se define como el cuarto parmetro del constructor:
$route = new Zend_Controller_Router_Route_Regex( 'archive/(\d+)', array( ... ), array('year' => 1), 'archive/%s' ); Todo esto es algo que ya fue posible de hacer por medio de un objeto de ruta estandard, por lo tanto podra preguntarese: cul es la ventaja de utilizar la ruta Regex?. Principalmente, le permite describir cualquier tipo de URL sin restriccin alguna. Imagnese que tiene un blog y desea crear URLs como: http://domain.com/blog/ archive/01-Using_the_Regex_Router.html, y que tiene que descomponer el ltimo elemento del path 01-Using_the_Regex_Router.html, en un ID de artculo y en el ttulo/descripcin del artculo; esto no es posible con el standard route. Con la ruta Regex, puede hacer algo como la siguiente solucin:
$route = new Zend_Controller_Router_Route_Regex( 'blog/archive/(\d+)-(.+)\.html', array( 'controller' => 'blog', 'action' => 'view' ), array( 1 => 'id', 2 => 'description' ), 'blog/archive/%d-%s.html' ); $router->addRoute('blogArchive', $route); Como puede ver, esto aade una enorme cantidad de flexibilidad por encima del standard route.
Zend_Controller_Router_Route_Hostname
Zend_Controller_Router_Route_Hostname es la ruta del framework en el servidor. Funciona similarmente a la standard route, pero funciona con el nombre del host de la URL llamada, en lugar del path. Vamos a usar el ejemplo de la standard route y ver cmo se vera con un nombre basado en host. En lugar de llamar al usuario mediante un path, quisiramos que un usuario pueda llamar a http://martel.users.example.com para ver la informacin acerca del usuario "martel".
171
Zend_Controller
$hostnameRoute = new Zend_Controller_Router_Route_Hostname( ':username.users.example.com', array( 'controller' => 'profile', 'action' => 'userinfo' ) ); $plainPathRoute = new Zend_Controller_Router_Route_Static(''); $router->addRoute('user', $hostnameRoute->chain($plainPathRoute); El primer parmetro del constructor en Zend_Controller_Router_Route_Hostname es una definicin de ruta que ser comparada con el nombre del host. Las definiciones de ruta consisten en partes estticas y dinmicas separadas por el carcter punto ('.'). Las partes dinmicas, llamadas variables, se marcan anteponiendo dos puntos (':') al nombre de la variable: :username. Las partes estticas son simplemente texto: user. Las rutas del nombre del host pueden, pero nunca deben ser utilizadas as. La razn detrs de esto es que la ruta del nombre del host solamente, concordara con cualquier path. Entonces, lo que tiene que hacer es encadenar una ruta del path a la ruta del nombre del host. Esto se hace como en el ejemplo llamando a $hostnameRoute>chain($pathRoute);. Haciendo esto, $hostnameRoute no se modifica, pero devuelve una nueva ruta (Zend_Controller_Router_Route_Chain), que luego puede ser entregada al router.
Zend_Controller_Router_Route_Chain
Zend_Controller_Router_Route_Chain es una ruta que permite encadenar juntas a mltiples rutas. Esto le permite encadenar hostname/rutas y rutas de paths, o mltiples paths de rutas por ejemplo. El encadenamiento puede hacerse programticamente o dentro de un archivo de configuracin.
Prioridad de Parmetros
Cuando se encadenan en conjunto varias rutas, los parmetros de la ruta exterior tienen mayor prioridad que los parmetros de la ruta interior. As, si define un controlador en el exterior y otro en la ruta interior, ser seleccionado el controlador de la ruta exterior. Cuando el encadenamiento se realiza progrmaticamente, hay dos maneras de archivarlo. La primera consiste en crear una nueva instancia Zend_Controller_Router_Route_Chain y entones llamar al mtodo chain varias veces con todas las rutas que deberan encadenarse juntas. La otra forma es tomar la primera ruta, por ejemplo, la ruta del nombre del host, y llamar al mtodo chain con la ruta que debera ser anexada a ella. Esto no modificar la ruta del nombre del host, pero devolver una nueva instancia de Zend_Controller_Router_Route_Chain, teniendo entonces a ambas rutas encadenadas juntas: // Crear dos rutas $hostnameRoute = new Zend_Controller_Router_Route_Hostname(...); $pathRoute = new Zend_Controller_Router_Route(...); // Primera manera, encadenarlas con chain route $chainedRoute = new Zend_Controller_Router_Route_Chain(); $chainedRoute->chain($hostnameRoute) ->chain($pathRoute); // Segunda manera, encadenarlas directamente $chainedRoute = $hostnameRoute->chain($pathRoute);
172
Zend_Controller
Cuando las rutas se encadenan juntas, su separador por defecto es una barra ('/'). Pueden haber casos cuando quiera tener un separador diferente: // Crear dos rutas $firstRoute = new Zend_Controller_Router_Route('foo'); $secondRoute = new Zend_Controller_Router_Route('bar'); // Encadenarlas juntas con un separador diferente $chainedRoute = $firstRoute->chain($secondRoute, '-'); // Ensamblar la ruta: "foo-bar" echo $chainedRoute->assemble();
173
Zend_Controller
</routes> Esto se traducir en las tres rutas www-language-index, www-language-imprint y users-languageprofile que slo concordarn basados en el nombre y la ruta misc, que se comparar con cualquier nombre de host. La manera alternativa de crear una ruta encadenada es a travs del parmetro chain, que slo puede utilizarse directamente con el tipo cadena-ruta, y tambin trabaja en el nivel raz: <routes> <www type="Zend_Controller_Router_Route_Chain"> <route>www.example.com</route> </www> <language type="Zend_Controller_Router_Route"> <route>:language</route> <reqs language="[a-z]{2}"> </language> <index type="Zend_Controller_Router_Route_Static"> <route></route> <defaults module="default" controller="index" action="index" /> </index> <imprint type="Zend_Controller_Router_Route_Static"> <route>imprint</route> <defaults module="default" controller="index" action="index" /> </imprint> <www-index type="Zend_Controller_Router_Route_Chain"> <chain>www, language, index</chain> </www-index> <www-imprint type="Zend_Controller_Router_Route_Chain"> <chain>www, language, imprint</chain> </www-imprint> </routes> Tambin puede darle el parmetro a chain como un array en vez de separ las rutas con comas: <routes> <www-index type="Zend_Controller_Router_Route_Chain"> <chain>www</chain> <chain>language</chain> <chain>index</chain> </www-index> <www-imprint type="Zend_Controller_Router_Route_Chain"> <chain>www</chain> <chain>language</chain> <chain>imprint</chain> </www-imprint> </routes>
174
Zend_Controller
Como ejemplo, considere el siguiente archivo INI: [production] routes.archive.route = "archive/:year/*" routes.archive.defaults.controller = archive routes.archive.defaults.action = show routes.archive.defaults.year = 2000 routes.archive.reqs.year = "\d+" routes.news.type = "Zend_Controller_Router_Route_Static" routes.news.route = "news" routes.news.defaults.controller = "news" routes.news.defaults.action = "list" routes.archive.type = "Zend_Controller_Router_Route_Regex" routes.archive.route = "archive/(\d+)" routes.archive.defaults.controller = "archive" routes.archive.defaults.action = "show" routes.archive.map.1 = "year" ; O: routes.archive.map.year = 1 Entonces el archivo INI puede ser ledo por un objeto Zend_Config como sigue: $config = new Zend_Config_Ini('/path/to/config.ini', 'production'); $router = new Zend_Controller_Router_Rewrite(); $router->addConfig($config, 'routes'); En el ejemplo de arriba, le decimos el router que utilice la seccin 'routes' del archivo INI para utilizarlo en sus rutas. Cada clave de primer nivel en esa seccin ser utilizada para definir un nombre de ruta; el ejemplo anterior define las rutas 'archive' y 'news'. Entonces cada ruta requiere, como mnimo, una entrada a la 'ruta' y una o ms entradas por 'default'; opcionalmente puede proporcionarse una o ms 'reqs' (abreviacin de 'required'). Dicho todo esto, estos corresponden a los tres argumentos que se le suministran al objeto Zend_Controller_Router_Route_Interface. Puede utilizarse una clave opcional 'type' para especificar el tipo de clase de ruta a utilizar en esa ruta en particular; por defecto, usa Zend_Controller_Router_Route. En el ejemplo de arriba, la ruta 'news' est definida para usar Zend_Controller_Router_Route_Static.
175
Zend_Controller
public function route(Zend_Controller_Request_Abstract $request); } El routing slo ocurre una vez: cuando la peticin es recibida por primera vez en el sistema. El propsito del router es determinar el controlador, la accin, y los parmetros opcionales sobre la base del medio ambiente de la solicitud, y luego ajustarlos en la solicitud. El objeto solicitud se pasa entonces al dispatcher. Si no es posible trazar una ruta hacia un dispatch token, el router no debe hacer nada con el objeto solicitud.
El Despachador
Introduccin
Despachar es el proceso de tomar el objeto solicitud, Zend_Controller_Request_Abstract, extraer el nombre del mdulo, el nombre del controlador, el nombre de la accin, y los parmetros opcionales contenido en l, y luego instanciar un controlador y llamar una accin de ese controlador. Si no se encuentra algn mdulo, controlador o accin, se usarn los valores por defecto para ellos. Zend_Controller_Dispatcher_Standard especifica index para cada uno de los controladores y acciones por defecto y default para el valor por defecto del mdulo, pero permite al desarrollador cambiar los valores por defecto para cada uno usando los mtodos setDefaultController(), setDefaultAction(), y setDefaultModule() respectivamente.
// En su front controller: $front->setParam('prefixDefaultModule', true); // En su despachador: $dispatcher->setParam('prefixDefaultModule', true); Esto le permite re-determinar un mdulo existente para ser el mdulo por defecto para una solicitud. El proceso de despachar tiene lugar en un bucle en el front controller. Antes de llevarse a cabo el despacho, el front controller rutea la solicitud para encontrar valores especificados por el usuario para el mdulo, controlador, accin, y los parmetros opcionales. A continuacin entra en un loop de despacho, despachando la solicitud. Al comienzo de cada iteracin, establece un flag en el objeto solicitud indicando que la accin se ha despachado. Si una accin o un plugin pre/postDispatch resetea ese flag, el loop de despacho continuar e intentar despachar la nueva solicitud. Cambiando el controlador y/o la accin en la solicitud y reseteando el flag despachado, el desarrollador puede definir una cadena de peticiones a realizar. El mtodo del controlador de accin que controla ese despacho es _forward(); llamar a este mtodo para cualquiera de los pre/postDispatch() o mtodos de accin, proporcionando un controlador de accines, mdulo y, opcionalmente cualquier parmetro adicional que desee enviar a la nueva accin:
public function fooAction() { // adelantar a otra accin en el controlador y mdulo actuales: $this->_forward('bar', null, null, array('baz' => 'bogus'));
176
Zend_Controller
} public function barAction() { // adelantar a una accin en otro controlador: // FooController::bazAction(), // en el mdulo actual: $this->_forward('baz', 'foo', null, array('baz' => 'bogus')); } public function bazAction() { // adelantar a una accin en otro controlador en otro mdulo, // Foo_BarController::bazAction(): $this->_forward('baz', 'bar', 'foo', array('baz' => 'bogus')); }
Subclaseando el Despachador
Zend_Controller_Front llamar en primer lugar al router para determinar la primera accin en la solicitud. A continuacin se entra en un loop de despacho, el cual llama al despachador para despachar la accin. El despachador necesita de una variedad de datos a fin de hacer su trabajo - necesita saber cmo formatear los nombres del controlador y de la accin, dnde mirar para los archivos de clase del controlador, cundo el nombre de un controlador provisto es vlido o no, y una API para determinar si una determinada solicitud es incluso despachable basado en la otra informacin disponible. Zend_Controller_Dispatcher_Interface define los siguientes mtodos como necesarios para cualquier implementacin de un despachador:
interface Zend_Controller_Dispatcher_Interface { /** * Formatea un string dentro del nombre de clase del controlador. * * @param string $unformatted * @return string */ public function formatControllerName($unformatted); /** * Formatea un string dentro de un nombre de mtodo de accin. * * @param string $unformatted * @return string */ public function formatActionName($unformatted); /** * Determina si la solicitud es despachable * * @param Zend_Controller_Request_Abstract $request * @return boolean
177
Zend_Controller
*/ public function isDispatchable( Zend_Controller_Request_Abstract $request ); /** * Establece un parmetro de usuario (via front controller, o para uso local) * * @param string $name * @param mixed $value * @return Zend_Controller_Dispatcher_Interface */ public function setParam($name, $value); /** * Establece un array de parmetros de usuario * * @param array $params * @return Zend_Controller_Dispatcher_Interface */ public function setParams(array $params); /** * Recupera un nico parmetro de usuario * * @param string $name * @return mixed */ public function getParam($name); /** * Recupera todos los parmetros de usuario * * @return array */ public function getParams(); /** * Limpia el stack de parmetros de usuario, o un nico parmetro de usuario * * @param null|string|array single key or array of keys for * params to clear * @return Zend_Controller_Dispatcher_Interface */ public function clearParams($name = null); /** * Establece el objeto respuesta a usar, si hubiera alguno * * @param Zend_Controller_Response_Abstract|null $response * @return void */ public function setResponse( Zend_Controller_Response_Abstract $response = null
178
Zend_Controller
); /** * Recupera el objeto respuesta, si hubiera alguno * * @return Zend_Controller_Response_Abstract|null */ public function getResponse(); /** * Agrega un directorio de controladoes al stack de directorios de controladores * * @param string $path * @param string $args * @return Zend_Controller_Dispatcher_Interface */ public function addControllerDirectory($path, $args = null); /** * Establece el directorio (o directorios) donde se almacenan los archivos * de controladoes * * @param string|array $dir * @return Zend_Controller_Dispatcher_Interface */ public function setControllerDirectory($path); /** * Regresa el directorio(s) actualmente establecido para el lookup de los * archivos de controladores * * @return array */ public function getControllerDirectory(); /** * Despacha una solicitud a una accin de (mdulo/)controlador. * * @param Zend_Controller_Request_Abstract $request * @param Zend_Controller_Response_Abstract $response * @return Zend_Controller_Request_Abstract|boolean */ public function dispatch( Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response ); /** * Si un mdulo dado es vlido o no * * @param string $module * @return boolean */ public function isValidModule($module);
179
Zend_Controller
/** * Recuperar el nombre por defecto del mdulo * * @return string */ public function getDefaultModule(); /** * Recuperar el nombre por defecto del controlador * * @return string */ public function getDefaultControllerName(); /** * Recuperar la accin por defecto * * @return string */ public function getDefaultAction(); } En muchos casos, sin embargo, simplemente debe extender la clase abstracta Zend_Controller_Dispatcher_Abstract, en el que cada uno de estas ya han sido definidas, o Zend_Controller_Dispatcher_Standard para modificar la funcionalidad del despachador estndar. Las posibles razones para subclasear al despachador incluye un deseo de utilizar un esquema diferente para nombrar las clases o mtodos en sus controladores de accin, o el deseo de utilizar otro paradigma de despacho como ser despachar los archivos de accin bajo directorios de controladores (en lugar de despacharlos a los mtodos de clase).
Controladores de Accin
Introduccin
Zend_Controller_Action es una clase abstracta que puede utilizar para implementar controladores de accin (Action Controllers) para usar con el Front Controller al crear un un sitio basado en el patrn Modelo-Vista-Controlador (MVC). Para usar Zend_Controller_Action, necesitar hacerla una subclase en sus clases actuales de controladores de accin (o hacerla una subclase para crear su propia clase base de accin de controladores). La operacin ms elemental es hacerla una subclase, y crear mtodos de accin que corresponden a las diversas acciones que desee que el contralor maneje para su sitio. El manejo del ruteo y envo de Zend_Controller descubrir por s mismo cualquier mtodo que termine en 'Action' en su clase, como posibles acciones del controlador. Por ejemplo, digamos que su clase se define como sigue:
180
Zend_Controller
} public function bazAction() { // hacer algo } } La clase de arriba FooController (el controlador foo) define dos acciones, bar y baz. Se pueden lograr muchas cosas ms, tales como personalizar la inicializacin de acciones, las acciones a llamar por defecto no deberan especificar ninguna accin (o una accin invlida), ganchos de pre y post despacho, y una variedad de mtodos ayudantes. Este captulo sirve como panorama de la funcionalidad del controlador de acciones.
class FooController extends Zend_Controller_Action { public function init() { // Local a este controlador nicamente; afecta a todas las acciones // al cargarse en init: $this->_helper->viewRenderer->setNoRender(true); // Globalmente: $this->_helper->removeHelper('viewRenderer'); // Tambin globalmente, pero tendra que ser en conjuncin con la // versin local con el fin de propagarlo para este controlador: Zend_Controller_Front::getInstance() ->setParam('noViewRenderer', true); } } initView(), getViewScript(), render(), y renderScript() cada proxy al ViewRenderer a menos que el ayudante no est como ayudante intermediario o no se haya establecido el flag de noViewRenderer. Tambin puede simplemente desactivarse para una prestacin individual ajustando el flag noRender de ViewRenderer:
class FooController extends Zend_Controller_Action { public function barAction() { // deshabilitar el autorendering para esta accin solamente: $this->_helper->viewRenderer->setNoRender(); } }
181
Zend_Controller
Las principales razones para desactivar ViewRenderer son si usted simplemente no necesita una objeto "view" o si no est mostrndolos via view scripts (por ejemplo, cuando se utiliza un controlador de accin para alimentar a los protocolos de un servicio web como SOAP, XML-RPC, o REST). En muchos casos, nunca necesitar desactivar a ViewRenderer globalmente, slo selectivamente dentro de los distintos controladores o acciones.
Inicializacin de Objectos
Si bien siempre puede anular el contolador de accin del constructor, no lo recomendamos. Zend_Controller_Action::__construct() realiza algunas tareas importantes, tales como registrar los objetos de solicitud y respuesta, as como los argumentos de cualquier invocacin personalizada pasados desde el front controller. Si debe anular el constructor, asegrese de llamar a parent::__construct($request, $response, $invokeArgs). La manera ms apropiada de personalizar la instanciacin es utilizar el mtodo init(), el cual es llamado como la ltima tarea de __construct(). Por ejemplo, si se quiere conectar a una base de datos en la instanciacin: class FooController extends Zend_Controller_Action { public function init() { $this->db = Zend_Db::factory('Pdo_Mysql', array( 'host' => 'myhost', 'username' => 'user', 'password' => 'XXXXXXX', 'dbname' => 'website' )); } }
Accessors (Accededores)
Con el objeto, se registran una serie de objetos y variables, y cada uno tiene mtodos de acceso. Objecto Requerimiento: getRequest() puede ser utilizado para recuperar el objeto solicitud utilizado para llamar a la accin. Objecto Respuesta: getResponse() puede ser utilizado para recuperar el objeto respuesta agregando la respuesta final. Algunas llamadas tpicas podran ser: $this->getResponse()->setHeader('Content-Type', 'text/xml'); $this->getResponse()->appendBody($content); Argumentos de Invocacin: el front controller puede empujar parmetros al router, al despachador, y al controlador de accin. Para recuperarlos, use getInvokeArg($key); por otra parte, se puede traer toda la lista utilizando getInvokeArgs().
182
Zend_Controller
Parmetros de Requerimientos: La objeto solicitud agrega parmetros de solicitud, como cualquiera de los parmetros _GET o _POST, o parmetros del usuario especificados en la informacin del path de la URL. Para recuperarlos, use _getParam($key) o _getAllParams(). Tambin se pueden establecer parmetros de solicitud usando _setParam(); lo que es til cuando se reenvan a acciones adicionales. Para probar si un parmetro existe o no (muy til para bifurcaciones lgicas), use _hasParam($key).
Nota
_getParam() puede tomar opcionalmente un segundo argumento que contiene un valor por defecto a utilizar si el parmetro no est establecido o est vaco. Usndolo elimina la necesidad de llamar previamente a _hasParam() para recuperar un valor:
// Usar por defecto el valor 1 si el id no est establecido $id = $this->_getParam('id', 1); // En lugar de: if ($this->_hasParam('id') { $id = $this->_getParam('id'); } else { $id = 1; }
Integracin de Vistas
Integracin de la Vista por Defecto via ViewRenderer
El contenido de esta seccin slo es vlida cuando usted tiene explcitamente deshabilitado a ViewRenderer. De lo contrario, puede saltarse esta seccin. Zend_Controller_Action proporciona un mecanismo rudimentario y flexible para ver la integracin. Hay dos mtodos para lograrlo, initView() y render(); el anterior mtodo $view carga la propiedad pblica, y este ltimo muestra una vista en base a la accin requerida actual, utilizando la jerarqua del directorio para determinar el path del script.
Inicializacin de la Vista
initView() inicializa el objeto vista. render() llama a initView() con el fin de recuperar el objeto vista, pero puede ser iniciada en cualquier momento; por defecto introduce informacin a la propiedad de $view con un objeto Zend_View, pero se puede usar cualquier clase que implemente Zend_View_Interface. Si $view ya ha sido inicializada, simplemente devuelve esa propiedad. La implementacin por defecto hace la siguiente hiptesis de la estructura del directorio:
183
Zend_Controller
filters/ En otras palabras, los scripts de vista se supone estn en el subdirectorio views/scripts/, y en el subdirectorio views se supone que contiene funcionalidades hermanas (ayudantes, filtros). Al determinar el nombre y el path del script, el directorio views/scripts/ ser utilizado como el path base, con directorios nombrados despus que los controladores individuales proporcionen una jerarqua a los scripts de vista.
string render(string $action = null, string $name = null, bool $noController = false); render() suministra un script de vista. Si no se pasan argumentos, se supone que el script requerido es [controller]/[action].phtml (donde .phtml es el valor de la propiedad $viewSuffix). Pasndole un valor a $action suministrar esa plantilla en al subdirectorio [controller]. Para anular el subdirectorio [controller] ponga un valor verdadero en $noController. Por ltimo, las plantillas son suministradas en el objeto respuesta; si desea suministrar a un determinado named segment en el objeto respuesta, pase un valor a $name.
Nota
Dado que el controlador y los nombres de accin pueden contener caracteres delimitadores como '_', '.', y '-', render() los normaliza a '-' para determinar el nombre del script. Internamente, utiliza los delimitadores de palabra y de path del despachador para hacer esta normalizacin. As, una solicitud a /foo.bar/baz-bat suministrar el script foo-bar/baz-bat.phtml. Si su mtodo de accin contiene camelCasing, recuerde que esto se traducir en palabras separadas por '-' al determinar el nombre del archivo del script de vista. Algunos ejemplos:
class MyController extends Zend_Controller_Action { public function fooAction() { // Suministra my/foo.phtml $this->render(); // Suministra my/bar.phtml $this->render('bar'); // Suministra baz.phtml $this->render('baz', null, true); // Suministra my/login.phtml al segmento 'form' del // objeto respuesta $this->render('login', 'form'); // Suministra site.phtml al segmento 'page' del objeto // respuesta; no usa el subdirectorio 'my/' $this->render('site', 'page', true); }
184
Zend_Controller
Mtodos Utilitarios
Adems de los accesadores y de los mtodos de integracin de vistas, Zend_Controller_Action tiene varios mtodos utilitarios para realizar tareas comunes dentro de sus mtodos de accin (o de pre-/post-despacho). _forward($action, $controller = null, $module = null, array $params = null): realiza otra accin. Si es llamado en preDispatch(), la accin actualmente requerida se saltar en favor de la nueva. De lo contrario, despus de procesar la accin actual, se ejecutar la accin solicitada en _forward(). _redirect($url, array $options = array()): redireccionar a otro lugar. Este mtodo toma una URL y un conjunto de opciones. Por defecto, realiza una redireccin HTTP 302. Las opciones pueden incluir uno o ms de los siguientes: exit: ya sea para salir inmediatamente o no. Si as lo solicita, limpiamente cerrar cualquier sesin abierta y realizar la redireccin. Puede configurar esta opcin globalmente en el controlador utilizando el accesador setRedirectExit(). prependBase: ya sea anteponiendo o no la base URL registrada con el objeto solicitud a la URL provista. Puede configurar esta opcin setRedirectPrependBase(). globalmente en el controlador utilizando el accesador
code: qu cdigo HTTP utilizar en la redireccin. Por defecto, se utiliza un HTTP 302; se puede utilizar cualquier cdigo entre 301 y 306. Puede configurar esta opcin globalmente en el controlador utilizando el accesador setRedirectCode().
185
Zend_Controller
Usted debe anular esta funcionalidad si desea realizar otras operaciones. Por ejemplo, si desea mostrar un mensaje de error, usted podra escribir algo como esto:
class MyController extends Zend_Controller_Action { public function __call($method, $args) { if ('Action' == substr($method, -6)) { // Si no se encontr el mtodo de la accin, suministrar la // plantilla de error return $this->render('error'); } // todos los otros mtodos lanzan una excepcin throw new Exception('Se ha llamado al mtodo "' . $method . '" que es invlido', 500); } } Otra posibilidad es que puede querer avanzar a un controlador de pgina por defecto:
class MyController extends Zend_Controller_Action { public function indexAction() { $this->render(); } public function __call($method, $args) { if ('Action' == substr($method, -6)) { // Si no se encontr el mtodo de accin, avance a la // accin index return $this->_forward('index'); } // todos los otros mtodos lanzan una excepcin throw new Exception('Se ha llamado al mtodo "' . $method . '" que es invlido', 500); } } Adems de sobrecargar __call(), cada uno de los mtodos gancho de inicializacin, utilidad, accesador, vista, y despacho mencionados anteriormente en este captulo pueden ser anulados a fin de personalizar sus controladores. Como ejemplo, si est almacenando su objeto vista en un registro, quizs desee modificar su mtodo initView() con cdigo parecido al siguiente:
186
Zend_Controller
{ public function initView() { if (null === $this->view) { if (Zend_Registry::isRegistered('view')) { $this->view = Zend_Registry::get('view'); } else { $this->view = new Zend_View(); $this->view->setBasePath(dirname(__FILE__) . '/../views'); } } return $this->view; } } Es de esperar, que de la informacin en este captulo, usted puede ver la flexibilidad de este componente en particular y cmo puede darle forma a su aplicaciones o a las necesidades de su sitio web.
Action Helpers
Introduction
Action Helpers allow developers to inject runtime and/or on-demand functionality into any Action Controllers that extend Zend_Controller_Action. Action Helpers aim to minimize the necessity to extend the abstract Action Controller in order to inject common Action Controller functionality. There are a number of ways to use Action Helpers. Action Helpers employ the use of a brokerage system, similar to the types of brokerage you see in Zend_View_Helper, and that of Zend_Controller_Plugin. Action Helpers (like Zend_View_Helper) may be loaded and called on demand, or they may be instantiated at request time (bootstrap) or action controller creation time (init()). To understand this more fully, please see the usage section below.
Helper Initialization
A helper can be initialized in several different ways, based on your needs as well as the functionality of that helper. The helper broker is stored as the $_helper member of Zend_Controller_Action; use the broker to retrieve or call on helpers. Some methods for doing so include: Explicitly using getHelper(). Simply pass it a name, and a helper object is returned: $flashMessenger = $this->_helper->getHelper('FlashMessenger'); $flashMessenger->addMessage('We did something in the last request'); Use the helper broker's __get() functionality and retrieve the helper as if it were a member property of the broker: $flashMessenger = $this->_helper->FlashMessenger; $flashMessenger->addMessage('We did something in the last request'); Finally, most action helpers implement the method direct() which will call a specific, default method in the helper. In the example of the FlashMessenger, it calls addMessage():
187
Zend_Controller
Nota
All of the above examples are functionally equivalent. You may also instantiate helpers explicitly. You may wish to do this if using the helper outside of an action controller, or if you wish to pass a helper to the helper broker for use by any action. Instantiation is as per any other PHP class.
Zend_Controller_Action_HelperBroker::addHelper($helper); Of course, instantiating and passing helpers to the broker is a bit time and resource intensive, so two methods exists to automate things slightly: addPrefix() and addPath(). addPrefix() takes a class prefix and uses it to determine a path where helper classes have been defined. It assumes the prefix follows Zend Framework class naming conventions.
// Add helpers prefixed with My_Action_Helpers in My/Action/Helpers/ Zend_Controller_Action_HelperBroker::addPrefix('My_Action_Helpers'); addPath() takes a directory as its first argument and a class prefix as the second argument (defaulting to 'Zend_Controller_Action_Helper'). This allows you to map your own class prefixes to specific directories.
// Add helpers prefixed with Helper in Plugins/Helpers/ Zend_Controller_Action_HelperBroker::addPath('./Plugins/Helpers', 'Helper'); Since these methods are static, they may be called at any point in the controller chain in order to dynamically add helpers as needed. Internally, the helper broker uses a PluginLoader instance to maintain paths. You can retrieve the PluginLoader using the static method getPluginLoader(), or, alternately, inject a custom PluginLoader instance using setPluginLoader(). To determine if a helper exists in the helper broker, use hasHelper($name), where $name is the short name of the helper (minus the prefix):
// Check if 'redirector' helper is registered with the broker: if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) { echo 'Redirector helper registered'; } There are also two static methods for retrieving helpers from the helper broker: getExistingHelper() and getStaticHelper(). getExistingHelper() will retrieve a helper only if it has previously been invoked
188
Zend_Controller
by or explicitly registered with the helper broker; it will throw an exception if not. getStaticHelper() does the same as getExistingHelper(), but will attempt to instantiate the helper if has not yet been registered with the helper stack. getStaticHelper() is a good choice for retrieving helpers which you wish to configure. Both methods take a single argument, $name, which is the short name of the helper (minus the prefix).
// Check if 'redirector' helper is registered with the broker, and fetch: if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) { $redirector = Zend_Controller_Action_HelperBroker::getExistingHelper('redirector'); } // Or, simply retrieve it, not worrying about whether or not it was // previously registered: $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector'); } Finally, to delete a registered helper from the broker, use removeHelper($name), where $name is the short name of the helper (minus the prefix):
// Conditionally remove the 'redirector' helper from the broker: if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) { Zend_Controller_Action_HelperBroker::removeHelper('redirector') }
ActionStack
El ayudante ActionStack le permite empujar requerimientos al ActionStack plugin del front controller, el cual le ayuda efectivamente a crear una cola de acciones a ejecutar durante la solicitud. El ayudante le permite aadir acciones ya sea especificando nuevos objetos solicitud o conjuntos accin/controlador/mdulo.
Ejemplo 12.2. Agregando una Tarea Usando Nombres de Accin, Controllador y Mdulo
A menudo, es ms sencillo simplemente especificar la accin, el controlador y el mdulo (y parmetros opcionales de requerimientos), tal como cuando llama a Zend_Controller_Action::_forward():
189
Zend_Controller
{ public function barAction() { // Agregar dos acciones a la pila (stack) // Y llamar a /foo/baz/bar/baz // (FooController::bazAction() con el requrimiento var bar == baz) $this->_helper->actionStack('baz', 'foo', 'default', array('bar' => 'baz')); // Agregar la llamada a /bar/bat // (BarController::batAction()) $this->_helper->actionStack('bat', 'bar'); } }
class FooController extends Zend_Controller_Action { public function barAction() { // Agregar dos acciones al stack // Agregar la llamada a /foo/baz/bar/baz // (FooController::bazAction() with request var bar == baz) $request = clone $this->getRequest(); // No establezca controlador o mdulo; use los valores actuales $request->setActionName('baz') ->setParams(array('bar' => 'baz')); $this->_helper->actionStack($request); // Agregar la llamada a /bar/bat // (BarController::batAction()) $request = clone $this->getRequest(); // no establezca mdulo; use el valor actual $request->setActionName('bat') ->setControllerName('bar'); $this->_helper->actionStack($request); } }
AutoComplete
Muchas bibliotecas de Javascript con AJAX ofrecen funcionalidad para proporcionar autocompletado segn la cual un selectlist de resultados potencialmente concordantes se visualiza a medida que el usuario tipea. El ayudante AutoComplete pretende simplificar el retorno de respuestas aceptables a esos mtodos. Dado que no todas la bibliotecas JS implementan el autocompletado de la misma manera, el ayudante AutoComplete ofrece algunas funcionalidades abstractas de base necesarias para muchas bibliotecas, e implementaciones concretas
190
Zend_Controller
para distintas bibliotecas. Los tipos de datos de retorno son generalmente o bien arrays de strings JSON, array de arrays JSON (donde cada miembro del array est en un array asociativo de metadatos utilizado para crear la selectlist), o HTML. El uso bsico para cada aplicacin es el mismo: class FooController extends Zend_Controller_Action { public function barAction() { // Ejecutar alguna lgica... // Codificar y enviar la respuesta; $this->_helper->autoCompleteDojo($data); // O explicitamente: $response = $this->_helper->autoCompleteDojo ->sendAutoCompletion($data); // O prepare simplemente la respuesta de autocompletado: $response = $this->_helper->autoCompleteDojo ->prepareAutoCompletion($data); } } Por defecto, el autocompletado hace lo siguiente: Desactiva esquemas y a ViewRenderer. Establece las cabeceras apropiadas para la respuesta. Establece el cuerpo de la respuesta con datos codificados/formateados para autocompletar. Enva la respuesta. Los mtodos disponibles para el ayudante incluyen: disableLayouts() puede ser utilizada para desactivar esquemas y a ViewRenderer. Tpicamente, esto se llama dentro de prepareAutoCompletion(). encodeJson($data, $keepLayouts = false) codificar datos a JSON, y opcionalmente habilitando o deshabilitando esquemas. Tpicamente, esto se llama dentro de prepareAutoCompletion(). prepareAutoCompletion($data, $keepLayouts = false) se utiliza para preparar datos en el formato necesario de la respuesta para la aplicacin concreta, opcionalmente los esquemas pueden habilitarse o deshabilitarse. El valor de retorno variar dependiendo de la implementacin. sendAutoCompletion($data, $keepLayouts = false) se utiliza para preparar datos en el formato necesario de la respuesta para la aplicacin concreta. Esta llama a prepareAutoCompletion(), y entonces enva la respuesta. direct($data, $sendNow = true, $keepLayouts = false) se utiliza cuando se llama al ayudante como un mtodo del ayudante intermediario. El flag $sendNow se utiliza para determinar si se debe llamar a sendAutoCompletion() o a prepareAutoCompletion(), respectivamente. Actualmente, AutoComplete soporta las bibliotecas AJAX de Dojo y Scriptaculous.
191
Zend_Controller
192
Zend_Controller
=> array('StringTrim'), => array('dijit.form.ComboBox'), => 'testStore', => 'false', => 'true', input:',
)), 'go' => array('type' => 'submit', 'options' => array('label' => 'Go!')) )); } return $this->_form; } } Aqu, estamos simplemente creando un formulario con los mtodos 'test' y 'go'. El mtodo 'test' agrega varios atributos especiales especficos de Dojo: dojoType, store, autoComplete y hasDownArrow. El dojoType es utilizado para indicar que estamos creando un ComboBox, y que vamos a vincularlo a un almacn de datos (clave 'store') de 'testStore' -veremos ms de esto ms adelante. Especificando 'autoComplete' como falso se le dice a Dojo que no seleccione automticamente el primer acierto, sino mostrar una lista de aciertos. Por ltimo, 'hasDownArrow' crea una flecha abajo similar a un select box para que podamos mostrar y ocultar los aciertos o concordancias. Vamos a aadir un mtodo para mostrar la forma, as como un punto final para el procesamiento de AutoCompletion: class TestController extends Zend_Controller_Action { // ... /** * Pgina final */ public function indexAction() { $this->view->form = $this->getForm(); } public function autocompleteAction() { if ('ajax' != $this->_getParam('format', false)) { return $this->_helper->redirector('index'); } if ($this->getRequest()->isPost()) { return $this->_helper->redirector('index'); } $match = trim($this->getRequest()->getQuery('test', '')); $matches = array(); foreach ($this->getData() as $datum) { if (0 === strpos($datum, $match)) { $matches[] = $datum; } } $this->_helper->autoCompleteDojo($matches);
193
Zend_Controller
} } En nuestro autocompleteAction() hacemos una serie de cosas. En primer lugar, esperamos a asegurarnos de que tengamos una peticin post, y que existe un parmetro 'form' establecido al valor 'ajax'; esto es simplemente para ayudar a reducir preguntas espreas a la accin. A continuacin, vamos a comprobar el parmetro 'test', y compararlo contra nuestros datos. (Yo deliberadamente dej de lado la implementacin de getData() aqu -- podra ser cualquier tipo de fuente de datos). Por ltimo, enviamos nuestros aciertos a nuestro ayudante AutoCompletion. Ahora que tenemos todas las piezas en el backend, veamos lo que necesitamos para entregar en nuestro script de vista para la pgina final. En primer lugar, necesitamos configurar nuestro data store, luego hacer nuestro formulario, y finalmente garantizar que las biblotecas Dojo apropiadas -- incluyendo que nuestro data store personalizado -- estn cargadas. Veamos el script de vista, el cual comenta los pasos:
<?php // establecemos nuestro data store: ?> <div dojoType="custom.TestNameReadStore" jsId="testStore" url="<?php echo $this->baseUrl() ?>/unit-test/autocomplete/format/ajax" requestMethod="get"></div> <?php // mostramos nuestro form: ?> <?php echo $this->form ?> <?php // establecemos CSS relacionado con Dojo a cargar en HTML head: ?> <?php $this->headStyle()->captureStart() ?> @import "<?php echo $this->baseUrl() ?>/javascript/dijit/themes/tundra/tundra.css"; @import "<?php echo $this->baseUrl() ?>/javascript/dojo/resources/dojo.css"; <?php $this->headStyle()->captureEnd() ?> <?php // setup de javascript para cargar en HTML head, incluyendo todas las // bibliotecas Dojo requeridas: ?> <?php $this->headScript() ->setAllowArbitraryAttributes(true) ->appendFile($this->baseUrl() . '/javascript/dojo/dojo.js', 'text/javascript', array('djConfig' => 'parseOnLoad: true')) ->captureStart() ?> djConfig.usePlainJson=true; dojo.registerModulePath("custom","../custom"); dojo.require("dojo.parser"); dojo.require("dojox.data.QueryReadStore"); dojo.require("dijit.form.ComboBox"); dojo.require("custom.TestNameReadStore"); <?php $this->headScript()->captureEnd() Note que las llamadas a los ayudantes de vista como headStyle y headScript; son ubicadores, que podemos suministrar a la seccin 'head' del HTML de nuestro script de vista. Ahora tenemos todas las piezas para que el AutoCompletion de Dojo pueda trabajar.
194
Zend_Controller
El ayudante para utilizar con esta biblioteca es 'AutoCompleteScriptaculous'. Simplemente proporcionarle un array de datos, y el ayudante crear una respuesta HTML compatible con Ajax.Autocompleter.
195
Zend_Controller
$contextSwitch = $this->_helper->getHelper('contextSwitch'); $contextSwitch->addActionContext('list', 'xml') ->initContext(); } // ... } Esto es lo que har: Establecer la cabecera de respuesta 'Content-Type' a 'text/xml'. Cambiar el sufijo de vista de 'xml.phtml' (o, si usa un sufifo de vista alternativo, 'xml.[su sufijo]'). Ahora, necesitar crear un nuevo script de vista, 'news/list.xml.phtml', que crear y mostrar a XML. Para determinar si una solicitud debe iniciar un cambio de contexto, el ayudante comprueba si hay un token en el objeto solicitud. Por defecto, busca el parmetro 'format', aunque esto puede ser configurado. Esto significa que, en muchos casos, para provocar un cambio de contexto, puede agregar un parmetro 'format' a su solicitud: Via parmetro URL: /news/list/format/xml (recordar que el valor por defecto del esquema de ruteo permite pares arbitrarios de clave/valor tras la accin). Via parmetro GET: /news/list?format=xml ContextSwitch le permite especificar contextos arbitrarios, incluso qu sufijo cambiar (si hay alguno), cualquier cabecera de respuesta que deba ser enviada, y callbacks arbitrarios para la inicializacin y posterior procesamiento.
196
Zend_Controller
callbacks: un array que contiene una o ms de las claves 'init' o 'post', apuntando a callbacks PHP vlidos que pueden utilizarse para inicializar el contexto y posterior procesamiento. La inicializacin de callbacks ocurre cuando el contexto es detectado por ContextSwitch. Usted puede usarlo para ejecutar una lgica arbitraria. Por ejemplo, el contexto JSON utiliza un callback para desactivar a ViewRenderer cuando est activada la serializacin auto-JSON. El post procesamiento ocurre durante la rutina de la accin postDispatch(), y puede ser utilizada para ejecutar una lgica arbitraria. Como ejemplo, el contexto JSON utiliza un callback para determinar si la serializacin autoJSON est activada; si as fuera, serializa las variables de la vista a JSON y enva la respuesta, pero si no, re-habilita a ViewRenderer. Hay una variedad de mtodos para interactuar con contextos: addContext($context, array $spec): agrega un nuevo contexto. Lanza una excepcin si el contexto ya existe. setContext($context, array $spec): aade un nuevo contexto o sobrescribir un contexto existente. Usa la misma especificacin que addContext(). addContexts(array $contexts): aade muchos contextos de una vez. El array $contexts debera ser un array de pares contexto/especificacin. Si alguno de los contextos ya existe, arrojar una excepcin. setContexts(array $contexts): aade nuevos contextos y sobreescribe los existentes. Usa la misma especificacin que addContexts(). hasContext($context): devuelve true si el contexto existe, false de lo contrario. getContext($context): recupera un nico contexto por su nombre. Devuelve un array siguiendo la especificacin usada en addContext(). getContexts(): recupera todos los contextos. Devuelve un array de pares contexto/especificacin. removeContext($context): elimina un nico contexto por su nombre. Devuelve true si tiene xito, false si el contexto no fue encontrado. clearContexts(): elimina todos los contextos.
class FooController extends Zend_Controller_Action { public function listAction() { } public function viewAction() { }
197
Zend_Controller
public function commentsAction() { } public function updateAction() { } } Supongamos que queremos aadir un contexto XML a la accin 'list', y contextos XML y JSON a la accin 'comments'. Podramos hacerlo en el mtodo init():
class FooController extends Zend_Controller_Action { public function init() { $this->_helper->contextSwitch() ->addActionContext('list', 'xml') ->addActionContext('comments', array('xml', 'json')) ->initContext(); } } Alternativamente, puede simplemente definir la propiedad del array $contexts:
class FooController extends Zend_Controller_Action { public $contexts = array( 'list' => array('xml'), 'comments' => array('xml', 'json') ); public function init() { $this->_helper->contextSwitch()->initContext(); } } El anterior es el menos sobrecargado, pero tambin est expuesto a posibles errores. Los siguientes mtodos pueden ser utilizados para construir los mapeos del contexto: addActionContext($action, $context): marca uno o ms contextos como disponibles para una accin. Si ya existen los mapeos, simplemente se aade a esos mapeos. $context puede ser un nico contexto, o un array de contextos. Un valor de true para el contexto marcar todos los contextos como disponibles para la accin. Un valor vaco de $contexto desactivar todos los contextos para la accin determinada. setActionContext($action, $context): marca uno o ms contextos como disponibles para una accin. Si el mapeo ya existe, se reemplaza con los especificados. $context puede ser un nico contexto, o un array de contextos.
198
Zend_Controller
addActionContexts(array $contexts): agrega varios pares accin/contexto de una vez. $contexts debe ser un array asociativo de pares accin/contexto. Le pasa la peticin a addActionContext(), lo que significa que si los emparejamientos ya existen, se aade a ellos. setActionContexts(array $contexts): acta como addActionContexts(), pero sobreescribe pares de accin/contexto existentes. hasActionContext($action, determinado. $context): determina si una accin particular tiene un contexto
getActionContexts($action = null): devuelve o todos los contextos para una accin determinada, o todos los pares de accin/contexto. removeActionContext($action, $context): elimina uno o ms contextos de una accin determinada. $context puede ser un nico contexto o un array de contextos. clearActionContexts($action = null): elimina todos los contextos de una accin determinada, o de todas las acciones con contextos.
class NewsController extends Zend_Controller_Action { public function init() { $this->_helper->contextSwitch()->initContext(); } } En algunos casos, puede querer forzar el contexto utilizado; por ejemplo, puede que slo quiera permitir el contexto XML si la conmutacin de contexto est activada. Puede hacerlo pasando el contexto a initContext():
$contextSwitch->initContext('xml');
Funcionalidad Adicional
Se pueden utilizar una variedad de mtodos para alterar el comportamiento del ayudante ContextSwitch. Estos incluyen: setAutoJsonSerialization($flag): Por defecto, los contextos JSON serializarn cualquier variable de vista a notacin JSON y lo devolvern como una respuesta. Si usted desea crear su propia respuesta, debe deshabilitar esta opcin; esto debe hacerse antes de llamar a initContext().
$contextSwitch->setAutoJsonSerialization(false); $contextSwitch->initContext(); Puede recuperar el valor del flag con getAutoJsonSerialization(). setSuffix($context, $suffix, $prependViewRendererSuffix): Con este mtodo, puede especificar un sufijo diferente para utilizarlo en un contexto determinado. El tercer argumento es utilizado para indicar si anteponer o no el actual sufijo de ViewRenderer con el nuevo sufijo; este flag est activado por defecto.
199
Zend_Controller
Pasando un valor vaco para el sufijo har que slo el sufijo ViewRenderer ser utilizado. addHeader($context, $header, $content): Aadir una cabecera de respuesta para un determinado contexto. $header es el nombre de la cabecera, y $content es el valor a pasar por esa cabecera. Cada contexto pueden tener mltiples cabeceras; addHeader() agrega cabeceras adicionales al stack de cabecera del contexto. Si el $header especificado ya existe para el contexto, arrojar una excepcin. setHeader($context, $header, $content): setHeader() acta igual que addHeader(), excepto que le permite sobreescribir cabeceras del contexto actual. addHeaders($context, array $headers): Aade varias cabeceras de una vez a un determinado contexto. Delega a addHeader(), as que si la cabecera ya existe, arrojar una excepcin. $headers es un array de pares cabecera/contexto. setHeaders($context, array $headers.): como addHeaders(), excepto que lo delegua a setHeader(), permitindole sobreescribir las cabeceras existentes. getHeader($context, $header): recuperar el valor de una cabecera para un determinado contexto. Retorna null si no existe. removeHeader($context, $header): eliminar una nica cabecera para un determinado contexto. clearHeaders($context, $header): eliminar todas las cabeceras para un determinado contexto. setCallback($context, $trigger, $callback): establecer un callback en un determinado disparador para poner en marcha un determinado contexto. Los disparadores pueden ser 'init' o 'post' (indicando que se llamar a un callback para cada contexto de inicializacin o postDispatch). $callback debe ser un callback vlido de PHP. setCallbacks($context, array $callbacks): establece varios callbacks para un determinado contexto. $callbacks deben ser pares de diparadores/callbacks. En realidad, la mayor cantidad de callbacks que pueden ser registrados son dos, uno para la inicializacin y otro para el procesamiento posterior. getCallback($context, $trigger): recuperar un callback para un determinado disparador en un contexto dado. getCallbacks($context): recupera todos los callbacks para un determinado contexto. Devuelve un array de pares disparor/callback. removeCallback($context, $trigger): elimina un callback para un determinado disparador y contexto. clearCallbacks($context): elimina todos los callbacks para un determinado contexto. setContextParam($name): establece el parmetro de peticin para comprobar si un conmutador de contexto ha sido solicitado. El valor por defecto es 'format', pero este accededor puede ser utilizado para establecer un valor alternativo. getContextParam() puede ser utilizado para recuperar el valor actual. setAutoDisableLayout($flag): Por defecto, los esquemas estn deshabilitados cuando sucede una conmutacin de contexto; esto es porque normalmente los esquemas slo sern utilizados para devolver respuestas normales, y no tienen sentido en otros contextos. Sin embargo, si desea usar esquemas (tal vez puede tener un diseo para el nuevo contexto), puede cambiar este comportamiento pasando un valor falso a setAutoDisableLayout(). Usted debera hacer esto antes de llamar a initContext().
200
Zend_Controller
Para conseguir el valor de este flag, utilice el accededor getAutoDisableLayout(). getCurrentContext() Puede ser utilizado para determinar qu contexto fue detectado, si hay alguno. Este retorna null si no hubo conmutacin de contexto, o si initContext() fue llamado antes de ser invocado.
Funcionalidad de AjaxContext
El ayudante AjaxContext extiende ContextSwitch, as que toda de la funcionalidad listada para ContextSwitch est disponible. Hay algunas diferencias fundamentales, sin embargo. En primer lugar, el controlador de accin utiliza una propiedad diferente para determinar contextos, $ajaxable. Esto es, que puede tener diferentes contextos utilizados para AJAX versus peticiones normales HTTP. Los diversos mtodos *ActionContext*() de AjaxContext le escribirn a esta propiedad. En segundo lugar, slo se disparar si se produjo un XmlHttpRequest, segn lo determinado por la solicitud del mtodo del objeto isXmlHttpRequest(). As, si se pasa el parmetro de contexto ('format') en la solicitud, pero la solicitud no fue hecha como un XmlHttpRequest, no se disparar ninguna conmutacin de contexto. En tercer lugar, AjaxContext agrega un contexto adicional, HTML. En este contexto, se establece el sufijo a 'ajax.phtml' para diferenciar el contexto de una solicitud normal. No se devuelven cabeceras adicionales.
class CommentController extends Zend_Controller_Action { public function init() { $ajaxContext = $this->_helper->getHelper('AjaxContext'); $ajaxContext->addActionContext('view', 'html') ->addActionContext('form', 'html') ->addActionContext('process', 'json') ->initContext(); } public { // // // } public { // // // } function viewAction() Tirar para ver un nico comentario. Cuando se detecta AjaxContext, utiliza el script de vista comment/view.ajax.phtml.
function formAction() Mostrar el form "add new comment". Cuando se detecta AjaxContext, utiliza el script de vista comment/form.ajax.phtml.
201
Zend_Controller
{ // Procesar un nuevo comentario // Devolver los resultados como JSON; simplemente asignar los // resultados como variables de la vista, y se devolvern como JSON. } } En el lado del cliente, su biblioteca AJAX simplemente pedir los parmetros finales '/comment/view', '/comment/ form', y '/comment/process', y pasar el parmetro 'format': '/comment/view/format/html', '/comment/form/format/html', '/comment/process/format/json'. (O puede pasar el parmetro via string de consulta: e.g., "?format=json"). Asumiendo que su biblioteca pasa la cabecera 'X-Requested-With:XmlHttpRequest' entonces estas acciones devolvern la respuesta en el formato apropiado.
FlashMessenger
Introduccin
El ayudante FlashMessenger le permite pasar mensajes que el usuario puede querer ver en la prxima solicitud. Para lograrlo, FlashMessenger usa Zend_Session_Namespace para almacenar los mensajes para las futuras o prxima solicitud de recuperacin. Es una buena idea si planea utilizar Zend_Session o Zend_Session_Namespace, que inicializa con Zend_Session::start() en su archivo bootstrap. (Para ms detalles de su uso vea la documentacin en Zend_Session).
202
Zend_Controller
JSON
Las respuestas JSON se estn convirtiendo en la respuesta de eleccin cuando se trata de requerimientos AJAX que esperan recibir respuestas datasets; en el lado del cliente, JSON puede ser inmediatamente parseado y ejecutado rpidamente. El ayudante de accin de JSON hace varias cosas: Deshabilita los layouts si estuvieran habilitados. Opcionalmente, un array de opciones que pasar como segundo argumento a Zend_Json::encode(). Este array de opciones permite habilitar layouts y codificacin utilizando Zend_Json_Expr. $this->_helper->json($data, array('enableJsonExprFinder' => true)); Desactiva la ViewRenderer si est actualmente habilitada. Establece la cabecera de respuesta 'Content-Type' a 'application/json'. Por defecto, devuelve inmediatamente la respuesta, sin esperar a la accin para finalizar la ejecucin. El uso es simple: o bien llamarlo como un mtodo del ayudante, o llamar a uno de los mtodos encodeJson() o sendJson(): class FooController extends Zend_Controller_Action { public function barAction() { // hacer algn procesamiento... // Enviar la respuesta JSON: $this->_helper->json($data); // o... $this->_helper->json->sendJson($data); // o recuperar json: $json = $this->_helper->json->encodeJson($data); } }
203
Zend_Controller
$this->_helper->json($data, true); Opcionalmente, puede pasar un array como el segundo parmetro. Este array puede contener una variedad de opciones, incluida la opcin keepLayouts:
$this->_helper->json($data, array('enableJsonExprFinder' => true); Si desea hacer esto, debe pasar un array como segundo argumento. Esto tambin le permite combinar otras opciones, como la opcin keepLayouts. Todas esas opciones se pasan luego a Zend_Json::encode().
Redirector
Introduccin
El ayudante Redirector le permite utilizar un objeto de redireccionamiento para cumplir con necesidades de su aplicacin para redireccionar a una nueva URL. Ofrece numerosas ventajas sobre el mtodo _redirect(), tales como poder preconfigurar un comportamiento para todo el sitio en el objeto redirector o usando el construido en gotoSimple($action, $controller, $module, $params), interfaz similar a la de Zend_Controller_Action::_forward(). El Redirector tiene un nmero de mtodos que pueden utilizarse para afectar el comportamiento al redireccionar: setCode() puede ser utilizado para establecer el cdigo de respuesta HTTP que utilizar durante la redireccin. setExit() puede usarse para forzar un exit() tras una redireccin. Por defecto es verdadero (true). setGotoSimple() puede ser utilizada para establecer la URL que usar por defecto si no se ha pasado ninguna a gotoSimple(). Utiliza la API de Zend_Controller_Action::_forward(): setGotoSimple($action, $controller = null, $module = null, array $params = array()); setGotoRoute() puede ser utilizada para establecer una URL basada en una ruta. Pasarla en un array de pares clave/valor y un nombre de ruta, y que ensamblarn la URL segn la definicin y el tipo de ruta. setGotoUrl() puede ser utilizada para establecer una URL por defecto si no se pasa ninguna a gotoUrl(). Acepta un solo string URL. setPrependBase() puede ser utilizada para anteponer la URL base del objeto solicitud a una URL especificada con setGotoUrl(), gotoUrl(), o gotoUrlAndExit().
204
Zend_Controller
setUseAbsoluteUri() puede ser utilizada para forzar al Redirector a usar URIs absolutas cuando est redireccionando. Cuando se establece esta opcin, se utiliza el valor de $_SERVER['HTTP_HOST'], $_SERVER['SERVER_PORT'], y $_SERVER['HTTPS'] para formar una URI completa a la URL especificada por uno de los mtodos de redireccin. Esta opcin est desactivada por defecto, pero podr ser activada por defecto en versiones posteriores. Adems, hay una variedad de mtodos en el redireccionamiento para realizar las redirecciones actuales: gotoSimple() usa setGotoSimple() (_forward()-tipo API) para construir una URL y realizar un redireccionamiento. gotoRoute() usa setGotoRoute() (route-assembly) para construir una URL y realizar un redireccionamiento. gotoUrl() usa setGotoUrl() (URL string) para construir una URL y realizar un redireccionamiento. Por ltimo, usted puede determinar la redireccin actual de la URL en cualquier momento usando getRedirectUrl().
class SomeController extends Zend_Controller_Action { /** * Redirector - definido para completar el cdigo * * @var Zend_Controller_Action_Helper_Redirector */ protected $_redirector = null; public function init() { $this->_redirector = $this->_helper->getHelper('Redirector'); // Establece las opciones por defecto del redirector // Dado que el objeto es registrado en el ayudante, stos pasan a // ser relevantes para todas las acciones desde este punto en adelante $this->_redirector->setCode(303) ->setExit(false) ->setGotoSimple("this-action", "some-controller"); } public function myAction() { /* hacer algunas cosas */
205
Zend_Controller
// Redireccionar a una URL previamente registrada, // y forzar una salida cuando est hecho: $this->_redirector->redirectAndExit(); return; // nunca alcanzado } }
// EJEMPLO ALTERNATIVO class AlternativeController extends Zend_Controller_Action { /** * Redirector - definido para completar el cdigo * * @var Zend_Controller_Action_Helper_Redirector */ protected $_redirector = null; public function init() { $this->_redirector = $this->_helper->getHelper('Redirector'); } public function myAction() { /* hacer algunas cosas */ $this->_redirector ->gotoUrl('/my-controller/my-action/param1/test/param2/test2'); return; // nunca alcanzado dado que por defecto es ir a URL y salir } }
class ForwardController extends Zend_Controller_Action { /** * Redirector - definido para completar el cdigo * * @var Zend_Controller_Action_Helper_Redirector */ protected $_redirector = null;
206
Zend_Controller
public function init() { $this->_redirector = $this->_helper->getHelper('Redirector'); } public function myAction() { /* hacer algunas cosas */ // Redireccionar a 'my-action' de 'my-controller' en el mdulo // actual, usando los parmetros param1 => test y param2 => test2 $this->_redirector->gotoSimple('my-action', 'my-controller', null, array('param1' => 'test', 'param2' => 'test2' ) ); } }
$route = new Zend_Controller_Router_Route( 'blog/:year/:month/:day/:id', array('controller' => 'archive', 'module' => 'blog', 'action' => 'view') ); $router->addRoute('blogArchive', $route); Dado un array con el ao fijado a 2006, mes a 4, da a 24, e id a 42, entonces construye la siguiente URL / blog/2006/4/24/42.
class BlogAdminController extends Zend_Controller_Action { /** * Redirector - definido para completar el cdigo * * @var Zend_Controller_Action_Helper_Redirector */ protected $_redirector = null; public function init() { $this->_redirector = $this->_helper->getHelper('Redirector'); }
207
Zend_Controller
public function returnAction() { /* hacer algunas cosas */ // Redireccionar al archivo blog. Construir la siguiente URL: // /blog/2006/4/24/42 $this->_redirector->gotoRoute( array('year' => 2006, 'month' => 4, 'day' => 24, 'id' => 42), 'blogArchive' ); } }
ViewRenderer
Introduccin
El ayudante ViewRenderer est diseado para satisfacer los siguientes objetivos: Eliminar la necesidad de instanciar objetos de vista dentro de los controladores; los objetos de vista quedarn registrados automticamente con el contralor. Establece automticamente el script de vista, el ayudante, y los paths de los filtros basados en el mdulo actual. Asocia automticamente el nombre del mdulo actual como un prefijo de clase para las clases ayudante y filtro. Crea un objeto de vista, disponible globalmente para todos los controladores y acciones despachados. Permite al desarrollador establecer por defecto las opciones de renderizado para todos los controladores. Agrega la capacidad para renderizar automticamente los scripts de vista sin ninguna intervencin. Permite al desarrollador crear sus propias especificaciones para el path base de vistas y para el path de los scripts de vista.
Nota
Si realiza un _forward(), redirecciona, o render manualmente, el autorendering no se llevar a cabo, como est realizando cualquiera de estas acciones le est diciendo al ViewRenderer que usted est determinando su propia salida.
Nota
El ViewRenderer est habilitado por defecto. Puede desactivarlo va parmetro del front controller noViewRenderer ($front->setParam('noViewRenderer', true)) o eliminando al ayudante del stack de ayudantes (Zend_Controller_Action_HelperBroker::removeHelper('viewRenderer')). Si desea modificar los settings del ViewRenderer antes de despachar el front controller, puede hacerlo en una de las dos maneras: Instanciar y registrar su propio objeto ViewRenderer y pasarlo al ayudante:
208
Zend_Controller
$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer(); $viewRenderer->setView($view) ->setViewSuffix('php'); Zend_Controller_Action_HelperBroker::addHelper($viewRenderer); Inicializar y/o recuperar un objeto ViewRenderer por demanda via el ayudante:
API
En su uso ms bsico, simplemente instancie a ViewRenderer y pselo al ayudante de acciones. La forma ms fcil para instanciar y registrar de una sola vez es utilizando el mtodo del ayudante getStaticHelper():
Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); La primera vez que se instancia un controlador de accin, se disparar ViewRenderer para instanciar al objeto vista. Cada vez que el controlador es instanciado, se llama al mtodo init() de ViewRenderer, que lo llevar a establecer la propiedad del controlador de accin, y llama a addScriptPath() con un path relativo al mdulo actual; este ser llamado con un prefijo de clase nombrada despus del mdulo actual, haciendo efectivamente el namespacing de todas las clases de ayudantes y filtros que define para el mdulo. Cad vez que llama a postDispatch(), este llamar a render() para la accin actual. Como ejemplo, considere la siguiente clase:
// Una clase controlador, mdulo foo: class Foo_BarController extends Zend_Controller_Action { // Render bar/index.phtml por defecto; no se requiere accin public function indexAction() { } // Render bar/populate.phtml con la variable 'foo' establecida a 'bar'. // Dado que el objeto vista est definido en preDispatch(), // ya est disponible. public function populateAction() { $this->view->foo = 'bar'; } } ... // en uno de sus scripts de vista: $this->foo(); // llama a Foo_View_Helper_Foo::foo()
209
Zend_Controller
El ViewRenderer tambin define una serie de accededores para permitir establecer y recuperar opciones de vista: setView($view) le permite establecer el objeto vista para ViewRenderer. Se vuelve como una propiedad de clase pblica $view. setNeverRender($flag = true) puede ser utilizado para activar o desactivar globalmente el autorendering, es decir, para todos los controladores. Si es verdadero, postDispatch() no llamar automticamente a render() en el controlador actual. getNeverRender() recupera el valor actual. setNoRender($flag = true) puede ser utilizado para activar o desactivar el autorendering. Si es verdadero, postDispatch() no llamar automticamente a render() en el controlador actual. Este ajuste se resetear cada vez que se llame a preDispatch() (es decir, usted necesita establecer este flag para cada controlador para el cual no quiera que el autorenderering se ejecute). getNoRender() recupera el valor actual. setNoController($flag = true) pude ser usado para decirle a render() que no busque el script de accin en un subdirectorio nombrado despus de que el controlador (que es el comportamiento por defecto) getNoController() recupere el valor actual. setNeverController($flag = true) es anlogo a setNoController(), pero trabaja a un nivel global -- es decir, que no se resetear por cada accin ejecutada. getNeverController() recupera el valor actual. setScriptAction($name) puede ser utilizado para especificar el script de accin a renderizar. $name debe ser el nombre del script menos el sufijo del archivo (y sin el subdirectorio del controlador, a menos que noController se haya activado). Si no se ha especificado, busca un script de vista nombrado despus de la accin en el objeto solicitud. getScriptAction() recupera el valor actual. setResponseSegment($name) puede ser utilizado para especificar qu segmento del objeto respuesta nombrado renderizar. Si no se especifica, se hace en el segmento por defecto. getResponseSegment() recupera el valor actual. initView($path, $prefix, $options) puede ser llamado para especificar el path base de las vistas, prefijos de clase para scripts de ayudantes y filtros, y las opciones de ViewRenderer. Puede pasar cualquiera de los siguientes flags: neverRender, noRender, noController, scriptAction, y responseSegment. setRender($action = null, $name = null, $noController = false) le permite establecer cualquier scriptAction, responseSegment, y noController en un pase. direct() es un alias a este mtodo, permitindole llamar a este mtodo fcilmente dede su controlador:
// Render 'foo' en lugar del script de accin actual $this->_helper->viewRenderer('foo'); // render form.phtml al segmento de respuesta de 'html', sin usar un // subdirectorio de scripts de controladores de accin: $this->_helper->viewRenderer('form', 'html', true);
Nota
setRender() y direct() realmente no renderiza el script de vista, sino que establece indicaciones que postDispatch() y render() utlizarn para renderizar la vista. El constructor le permite opcionalmente pasar el objeto vista y las opciones de ViewRenderer; acepta los mismos flags que initView():
210
Zend_Controller
$view = new Zend_View(array('encoding' => 'UTF-8')); $options = array('noController' => true, 'neverRender' => true); $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view, $options); Hay varios mtodos adicionales para personalizar especificaciones del path, usados para determinar el path base del script de vista para aadir al objeto vista, y el path del script de vista a usar cuando est autodeterminando el script de vista a renderizar. Cada uno de estos mtodos toma uno o ms de los siguientes localizadores: :moduleDir hace referencia a la actual directorio base del mdulo(por convencin, el directorio padre del directorio del mdulo controlador). :module hace referencia al nombre del mdulo actual. :controller hace referencia al nombre del controlador actual. :action hace referencia al nombre de la accin actual. :suffix hace referencia al sufijo del script de vista (que puede ser definido via setViewSuffix()). Los mtodos para controlar las especificaciones del path son: setViewBasePathSpec($spec) le permite cambiar la especificacin del path utilizada para determinar el path base para aadir al objeto vista. La especificacin por defecto es :moduleDir/views. Puede recuperar la especificacin actual en cualquier momento usando getViewBasePathSpec(). setViewScriptPathSpec($spec) le permite cambiar el path de la especificacin utilizada para determinar el path a un script de vista individual (menos el path de la base del script de vista). La especificacin por defecto es :controller/:action.:suffix. Puede recuperar la especificacin actual en cualquier momento usando getViewScriptPathSpec(). setViewScriptPathNoControllerSpec($spec) le permite cambiar el path de la especificacin utilizado para determinar el path a un script de vista individual cuando noController est activado (menos el path base del script de vista). La especificacin por defecto es :action.:suffix. Puede recuperar la especificacin actual en cualquier momento usando getViewScriptPathNoControllerSpec(). Para un control ms refinado sobre el path de especificaciones, puede usar Zend_Filter_Inflector. Bajo el cap, ViewRenderer ya usa un inflector para realizar mapeos del path. Para interactuar con el inflector -- ya sea para establecerlo para uso propio, o para modificar el inflector por defecto, se pueden utilizar los siguientes mtodos: getInflector() recupera el inflector. Si no existe todava en ViewRenderer, se crea uno utilizando las reglas predeterminadas. Por defecto, utiliza reglas de referencias estticas para el sufijo y directorio de mdulos, as como una meta esttica; esto permite que diversas propiedades de ViewRenderer tengan la capacidad de modificar dinmicamente al inflector. setInflector($inflector, $reference) permite establecer un inflector personalizado para usar con ViewRenderer. Si $reference es verdadero, establecer el sufijo y directorio de mdulos como referencias estticas a las propiedades de ViewRenderer, as como al objetivo.
211
Zend_Controller
:module: MixedCase y camelCasedWords estn separados por guiones, y el string completo se convierte a minsculas. Por ejemplo: "FooBarBaz" pasa a ser "foo-bar-baz". Internamente, el inflector utiliza los filtros Zend_Filter_Word_CamelCaseToDash y Zend_Filter_StringToLower. :controller: MixedCase y camelCasedWords estn separados por guiones; los subrayados se convierten en separadores de directorio , y el string emitido a minsculas. Ejemplos: "FooBar" pasa a ser "foo-bar"; "FooBar_Admin" pasa a ser "foo-bar/admin". Internamente, el inflector utiliza los filtros Zend_Filter_Word_CamelCaseToDash, Zend_Filter_Word_UnderscoreToSeparator, y Zend_Filter_StringToLower. :action: MixedCase y camelCasedWords estn separados por guiones; los caracteres no alfanumricos son traducidos a guiones, y el string emitido a minsculas. Ejemplos: "fooBar" pasa a ser "foo-bar"; "foobarBaz" pasa a ser "foo-bar-baz". Internamente, el inflector utiliza los filtros Zend_Filter_Word_CamelCaseToDash, Zend_Filter_PregReplace, y Zend_Filter_StringToLower. Los ltimos temas en la API de ViewRenderer son los mtodos para determinar realmente los paths de los scripts de vista y el rendering de las vistas. Estos incluyen: renderScript($script, $name) permite renderizar un script con una ruta que especifique, opcionalmente a un segmento nombrado del path. Cuando se utiliza este mtodo, ViewRenderer no autodetermina el nombre del script, en cambio pasa directamente a $script el argumento directamente al mtodo del objeto vista render().
Nota
Una vez que la vista ha sido renderizada al objeto respuesta, se establece noRender para evitar accidentalmente renderizar el mismo script de vista varias veces.
Nota
Por defecto, Zend_Controller_Action::renderScript() le delega a ViewRenderer el mtodo renderScript(). getViewScript($action, $vars) crea el path a un script de vista basado en la accin pasada y/o cualquier variables pasadas en $vars. Las claves para este array pueden incluir cualquiera de las claves de especificacin de paths ('moduleDir', 'module', 'controller', 'action', y 'suffix'). Se utilizarn cualquiera de la variables pasadas; de lo contrario, se utilizarn valores basados en la peticin actual. getViewScript() utilizar tanto a viewScriptPathSpec o viewScriptPathNoControllerSpec sobre la base establecida del flag noController. Los delimitadores de palabras encontrados en un mdulo, controlador o nombres de accin sern reemplazados por guiones ('-'). As pues, si tiene el nombre de controlador 'foo.bar' y la accin 'baz:bat', utilizando la especificacin por defecto del path se traducir en un path al script de vista 'foo-bar/baz-bat.phtml'.
Nota
Por defecto, Zend_Controller_Action::getViewScript() getViewScript() de ViewRenderer. delega el mtodo
render($action, $name, $noController) comprueba primero para ver si bien $name o $noController se han pasado, y si es as, establece los flags apropiados (responseSegment y noController,
212
Zend_Controller
respectivamente) en ViewRenderer. A continuacin, pasa el argumento $action, si hay alguno, a getViewScript(). Por ltimo, pasa el path calculado del script de vista a renderScript().
Nota
Hay que ser conscientes de los efectos secundarios al usar render(): los valores que usted pasa para el nombre del segmento respuesta y para el flag noController persistirn en el objeto. Adems, noRender ser establecido despus de completar la renderizacin.
Nota
Por defecto, Zend_Controller_Action::render() delega a ViewRenderer el mtodo render(). renderBySpec($action, $vars, $name) permite pasar variables de especificacin del path a fin de determinar el path para la creacin del script de vista. Este pasa $action y $vars a getScriptPath(), y luego pasa el path del script resultante y $name a renderScript().
// En su bootstrap: Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); ... // 'foo' mdulo, 'bar' controlador: class Foo_BarController extends Zend_Controller_Action { // Render bar/index.phtml por defecto; no se requieren acciones public function indexAction() { } // Render bar/populate.phtml la variable 'foo' establecida a 'bar'. // Dado que el objeto fue definido en preDispatch(), est disponible. public function populateAction() { $this->view->foo = 'bar'; } // No hace rendering, ya que salta a otra accin; la nueva accin // realizar cualquier rendering public function bazAction() { $this->_forward('index'); } // No hace rendering, ya que redirecciona a otra ubicacin
213
Zend_Controller
// Baz clase del controlador, bar mdulo: class Bar_BazController extends Zend_Controller_Action { public function fooAction() { // No auto renderize esta accin $this->_helper->viewRenderer->setNoRender(); } } // Bat clase del controlador, bar mdulo: class Bar_BatController extends Zend_Controller_Action { public function preDispatch() { // Nunca auto renderizar las acciones de este controlador $this->_helper->viewRenderer->setNoRender(); } }
Nota
En muchos casos, no tiene sentido desactivar el autorendering globalmente (ala setNeverRender()), y la nica cosa que puede ganar de ViewRenderer es el autosetup del objeto de vista.
214
Zend_Controller
// Bar clase controlador, foo mdulo: class Foo_BarController extends Zend_Controller_Action { public function addAction() { // Render 'bar/form.phtml' en lugar de 'bar/add.phtml' $this->_helper->viewRenderer('form'); } public function editAction() { // Render 'bar/form.phtml' en lugar de 'bar/edit.phtml' $this->_helper->viewRenderer->setScriptAction('form'); } public function processAction() { // hacer alguna validacin... if (!$valid) { // Render 'bar/form.phtml' en lugar de 'bar/process.phtml' $this->_helper->viewRenderer->setRender('form'); return; } // de otra manera, continuar procesando... } }
// Bar clase controlador, foo mdulo: class Foo_BarController extends Zend_Controller_Action { public function preDispatch() { // cambiar la codificavin de la vista $this->view->setEncoding('UTF-8'); } public function bazAction()
215
Zend_Controller
{ // Obtener el objeto vista y establecer // el callback de escape a 'htmlspecialchars' $view = $this->_helper->viewRenderer->view; $view->setEscape('htmlspecialchars'); } }
Ejemplos de Uso Avanzado Ejemplo 12.14. Cambiando las Especificaciones del Path
En algunas circunstancias, puede decidir que las especificaciones del path por defecto no se adaptan a su sitio. Por ejemplo, usted puede querer tener un rbol nico de plantillas al que puede dar acceso a sus diseadores (esto es muy tpico cuando se utiliza Smarty [http://smarty.php.net/], por ejemplo). En ese caso, puede querer embeber los datos de la especificacin del path base de la vista, y crear una especificacin alternativa para el script de vista del path ellos mismos. Para los fines de este ejemplo, supongamos que el path base de las vistas debera ser '/opt/vendor/templates', y que desea para que los scripts de vista sean referenciados por ':moduleDir/:controller/:action.:suffix'; si el flag noController ha sido establecido, quiere renderizar fuera del nivel superior en lugar de en un subdirectorio (':action.:suffix'). Por ltimo, que quiere utilizar 'tpl' como el sufijo del nombre de archivo del script de vista.
/** * En su bootstrap: */ // Implementacin de una vista diferente $view = new ZF_Smarty(); $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view); $viewRenderer->setViewBasePathSpec('/opt/vendor/templates') ->setViewScriptPathSpec(':module/:controller/:action.:suffix') ->setViewScriptPathNoControllerSpec(':action.:suffix') ->setViewSuffix('tpl'); Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
Ejemplo 12.15. Rendering Mltiples Scripts de Vista desde una Sola Accin
A veces, puede que necesite renderizar mltiples scripts de vista desde una sola accin. Esto es muy sencillo -simplemente hacer mltiples llamadas a render():
class SearchController extends Zend_Controller_Action { public function resultsAction() { // Suponga que $this->model es el modelo actual $this->view->results = $this->model->find($this->_getParam('query', ''); // render() por defecto lo delega al ViewRenderer // Render primero al from de bsqueda y luego los resultados
216
Zend_Controller
$this->render('form'); $this->render('results'); } public function formAction() { // No hacer nada; ViewRenderer hace autorender del script de vista } }
217
Zend_Controller
$response->sendResponse();
Nota
By default, the front controller calls sendResponse() when it has finished dispatching the request; typically you will never need to call it. However, if you wish to manipulate the response or use it in testing, you can override this behaviour by setting the returnResponse flag with Zend_Controller_Front::returnResponse(true):
$front->returnResponse(true); $response = $front->dispatch(); // do some more processing, such as logging... // and then send the output: $response->sendResponse(); Developers should make use of the response object in their action controllers. Instead of directly rendering output and sending headers, push them to the response object:
// Within an action controller action: // Set a header $this->getResponse() ->setHeader('Content-Type', 'text/html') ->appendBody($content); By doing this, all headers get sent at once, just prior to displaying the content.
Nota
If using the action controller view integration, you do not need to set the rendered view script content in the response object, as Zend_Controller_Action::render() does this by default. Should an exception occur in an application, check the response object's isException() flag, and retrieve the exception using getException(). Additionally, one may create custom response objects that redirect to error pages, log exception messages, do pretty formatting of exception messages (for development environments), etc. You may retrieve the response object following the front controller dispatch(), or request the front controller to return the response object instead of rendering output.
218
Zend_Controller
// Or, have the front controller dispatch() process return it $front->returnResponse(true); $response = $front->dispatch(); // do some processing... // finally, echo the response $response->sendResponse(); By default, exception messages are not displayed. This behaviour may be overridden by calling renderExceptions(), or enabling the front controller to throwExceptions(), as shown above:
$response->renderExceptions(true); $front->dispatch($request, $response); // or: $front->returnResponse(true); $response = $front->dispatch(); $response->renderExceptions(); $response->sendResponse(); // or: $front->throwExceptions(true); $front->dispatch();
Manipulating Headers
As stated previously, one aspect of the response object's duties is to collect and emit HTTP response headers. A variety of methods exist for this: canSendHeaders() is used to determine if headers have already been sent. It takes an optional flag indicating whether or not to throw an exception if headers have already been sent. This can be overridden by setting the property headersSentThrowsException to FALSE. setHeader($name, $value, $replace = false) is used to set an individual header. By default, it does not replace existing headers of the same name in the object; however, setting $replace to TRUE will force it to do so. Before setting the header, it checks with canSendHeaders() to see if this operation is allowed at this point, and requests that an exception be thrown. setRedirect($url, $code = 302) sets an HTTP Location header for a redirect. If an HTTP status code has been provided, it will use that status code. Internally, it calls setHeader() with the $replace flag on to ensure only one such header is ever sent. getHeaders() returns an array of all headers. Each array element is an array with the keys 'name' and 'value'. clearHeaders() clears all registered headers. setRawHeader() can be used to set headers that are not key and value pairs, such as an HTTP status header. getRawHeaders() returns any registered raw headers. clearRawHeaders() clears any registered raw headers.
219
Zend_Controller
clearAllHeaders() clears both regular key and value headers as well as raw headers. In addition to the above methods, there are accessors for setting and retrieving the HTTP response code for the current request, setHttpResponseCode() and getHttpResponseCode().
Named Segments
The response object has support for "named segments". This allows you to segregate body content into different segments and order those segments so output is returned in a specific order. Internally, body content is saved as an array, and the various accessor methods can be used to indicate placement and names within that array. As an example, you could use a preDispatch() hook to add a header to the response object, then have the action controller add body content, and a postDispatch() hook add a footer:
// Assume that this plugin class is registered with the front controller class MyPlugin extends Zend_Controller_Plugin_Abstract { public function preDispatch(Zend_Controller_Request_Abstract $request) { $response = $this->getResponse(); $view = new Zend_View(); $view->setBasePath('../views/scripts'); $response->prepend('header', $view->render('header.phtml')); } public function postDispatch(Zend_Controller_Request_Abstract $request) { $response = $this->getResponse(); $view = new Zend_View(); $view->setBasePath('../views/scripts'); $response->append('footer', $view->render('footer.phtml')); } } // a sample action controller class MyController extends Zend_Controller_Action { public function fooAction() { $this->render(); } } In the above example, a call to /my/foo will cause the final body content of the response object to have the following structure:
array( 'header' => ..., // header content 'default' => ..., // body content from MyController::fooAction() 'footer' => ... // footer content
220
Zend_Controller
); When this is rendered, it will render in the order in which elements are arranged in the array. A variety of methods can be used to manipulate the named segments: setBody() and appendBody() both allow you to pass a second value, $name, indicating a named segment. In each case, if you provide this, it will overwrite that specific named segment or create it if it does not exist (appending to the array by default). If no named segment is passed to setBody(), it resets the entire body content array. If no named segment is passed to appendBody(), the content is appended to the value in the 'default' name segment. prepend($name, $content) will create a segment named $name and place it at the beginning of the array. If the segment exists already, it will be removed prior to the operation (i.e., overwritten and replaced). append($name, $content) will create a segment named $name and place it at the end of the array. If the segment exists already, it will be removed prior to the operation (i.e., overwritten and replaced). insert($name, $content, $parent = null, $before = false) will create a segment named $name. If provided with a $parent segment, the new segment will be placed either before or after that segment (based on the value of $before) in the array. If the segment exists already, it will be removed prior to the operation (i.e., overwritten and replaced). clearBody($name = null) will remove a single named segment if a $name is provided (and the entire array otherwise). getBody($spec = false) can be used to retrieve a single array segment if $spec is the name of a named segment. If $spec is FALSE, it returns a string formed by concatenating all named segments in order. If $spec is TRUE, it returns the body content array.
221
Zend_Controller
renderExceptions($flag) allows you to set a flag indicating whether or not exceptions should be emitted when the response is sent.
Plugins
Introduction
The controller architecture includes a plugin system that allows user code to be called when certain events occur in the controller process lifetime. The front controller uses a plugin broker as a registry for user plugins, and the plugin broker ensures that event methods are called on each plugin registered with the front controller. The event methods are defined in the abstract class Zend_Controller_Plugin_Abstract, from which user plugin classes inherit: routeStartup() is called before Zend_Controller_Front calls on the router to evaluate the request against the registered routes. routeShutdown() is called after the router finishes routing the request. dispatchLoopStartup() is called before Zend_Controller_Front enters its dispatch loop. preDispatch() is called before an action is dispatched by the dispatcher. This callback allows for proxy or filter behavior. By altering the request and resetting its dispatched flag (via Zend_Controller_Request_Abstract::setDispatched(false)), the current action may be skipped and/or replaced. postDispatch() is called after an action is dispatched by the dispatcher. This callback allows for proxy or filter behavior. By altering the request and resetting its dispatched flag (via Zend_Controller_Request_Abstract::setDispatched(false)), a new action may be specified for dispatching. dispatchLoopShutdown() is called after Zend_Controller_Front exits its dispatch loop.
Writing Plugins
In order to write a plugin class, Zend_Controller_Plugin_Abstract: simply include and extend the abstract class
222
Zend_Controller
// ... } None of the methods of Zend_Controller_Plugin_Abstract are abstract, and this means that plugin classes are not forced to implement any of the available event methods listed above. Plugin writers may implement only those methods required by their particular needs. Zend_Controller_Plugin_Abstract also makes the request and response objects available to controller plugins via the getRequest() and getResponse() methods, respectively.
Using Plugins
Plugin classes are registered with Zend_Controller_Front::registerPlugin(), and may be registered at any time. The following snippet illustrates how a plugin may be used in the controller chain:
class MyPlugin extends Zend_Controller_Plugin_Abstract { public function routeStartup(Zend_Controller_Request_Abstract $request) { $this->getResponse() ->appendBody("<p>routeStartup() called</p>\n"); } public function routeShutdown(Zend_Controller_Request_Abstract $request) { $this->getResponse() ->appendBody("<p>routeShutdown() called</p>\n"); } public function dispatchLoopStartup( Zend_Controller_Request_Abstract $request) { $this->getResponse() ->appendBody("<p>dispatchLoopStartup() called</p>\n"); } public function preDispatch(Zend_Controller_Request_Abstract $request) { $this->getResponse() ->appendBody("<p>preDispatch() called</p>\n"); } public function postDispatch(Zend_Controller_Request_Abstract $request) { $this->getResponse() ->appendBody("<p>postDispatch() called</p>\n"); } public function dispatchLoopShutdown() { $this->getResponse() ->appendBody("<p>dispatchLoopShutdown() called</p>\n"); }
223
Zend_Controller
} $front = Zend_Controller_Front::getInstance(); $front->setControllerDirectory('/path/to/controllers') ->setRouter(new Zend_Controller_Router_Rewrite()) ->registerPlugin(new MyPlugin()); $front->dispatch(); Assuming that no actions called emit any output, and only one action is called, the functionality of the above plugin would still create the following output: <p>routeStartup() called</p> <p>routeShutdown() called</p> <p>dispatchLoopStartup() called</p> <p>preDispatch() called</p> <p>postDispatch() called</p> <p>dispatchLoopShutdown() called</p>
Nota
Plugins may be registered at any time during the front controller execution. However, if an event has passed for which the plugin has a registered event method, that method will not be triggered.
ActionStack
The ActionStack plugin allows you to manage a stack of requests, and operates as a postDispatch plugin. If a forward (i.e., a call to another action) is already detected in the current request object, it does nothing. However, if not, it checks its stack and pulls the topmost item off it and forwards to the action specified in that request. The stack is processed in LIFO order. You can retrieve the plugin from the front controller at any time using Zend_Controller_Front::getPlugin('Zend_Controller_Plugin_ActionStack'). Once you have the plugin object, there are a variety of mechanisms you can use to manipulate it. getRegistry() and setRegistry(). Internally, ActionStack uses a Zend_Registry instance to store the stack. You can substitute a different registry instance or retrieve it with these accessors.
224
Zend_Controller
getRegistryKey() and setRegistryKey(). These can be used to indicate which registry key to use when pulling the stack. Default value is 'Zend_Controller_Plugin_ActionStack'. getStack() allows you to retrieve the stack of actions in its entirety. pushStack() and popStack() allow you to add to and pull from the stack, respectively. pushStack() accepts a request object. An additional method, forward(), expects a request object, and sets the state of the current request object in the front controller to the state of the provided request object, and markes it as undispatched (forcing another iteration of the dispatch loop).
Zend_Controller_Plugin_ErrorHandler
Zend_Controller_Plugin_ErrorHandler provides a drop-in plugin for handling exceptions thrown by your application, including those resulting from missing controllers or actions; it is an alternative to the methods listed in the MVC Exceptions section. The primary targets of the plugin are: Intercept exceptions raised due to missing controllers or action methods Intercept exceptions raised within action controllers In other words, the ErrorHandler plugin is designed to handle HTTP 404-type errors (page missing) and 500-type errors (internal error). It is not intended to catch exceptions raised in other plugins or routing. By default, Zend_Controller_Plugin_ErrorHandler will forward to ErrorController::errorAction() in the default module. You may set alternate values for these by using the various accessors available to the plugin: setErrorHandlerModule() sets the controller module to use. setErrorHandlerController() sets the controller to use. setErrorHandlerAction() sets the controller action to use. setErrorHandler() takes an associative array, which may contain any of the keys 'module', 'controller', or 'action', with which it will set the appropriate values. Additionally, you may pass an optional associative array to the constructor, which will then proxy to setErrorHandler(). Zend_Controller_Plugin_ErrorHandler registers a postDispatch() hook and checks for exceptions registered in the response object. If any are found, it attempts to forward to the registered error handler action. If an exception occurs dispatching the error handler, the plugin will tell the front controller to throw exceptions, and rethrow the last exception registered with the response object.
225
Zend_Controller
class ErrorController extends Zend_Controller_Action { public function errorAction() { $errors = $this->_getParam('error_handler'); } } Once you have the error object, you can get the type via $errors->type;. It will be one of the following: Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER, controller was not found. indicating the
Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION, indicating the requested action was not found. Zend_Controller_Plugin_ErrorHandler::EXCEPTION_OTHER, indicating other exceptions. You can then test for either of the first two types, and, if so, indicate a 404 page:
class ErrorController extends Zend_Controller_Action { public function errorAction() { $errors = $this->_getParam('error_handler'); switch ($errors->type) { case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER: case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION: // 404 error -- controller or action not found $this->getResponse() ->setRawHeader('HTTP/1.1 404 Not Found'); // ... get some output to display... break; default: // application error; display error page, but don't // change status code break; } } } Finally, you can retrieve the exception that triggered the error handler by grabbing the exception property of the error_handler object:
226
Zend_Controller
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION: // 404 error -- controller or action not found $this->getResponse() ->setRawHeader('HTTP/1.1 404 Not Found'); // ... get some output to display... break; default: // application error; display error page, but don't change // status code // ... // Log the exception: $exception = $errors->exception; $log = new Zend_Log( new Zend_Log_Writer_Stream( '/tmp/applicationException.log' ) ); $log->debug($exception->getMessage() . "\n" . $exception->getTraceAsString()); break; } }
227
Zend_Controller
class ErrorController extends Zend_Controller_Action { public function errorAction() { $errors = $this->_getParam('error_handler'); switch ($errors->type) { case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER: case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION: // 404 error -- controller or action not found $this->getResponse()->setRawHeader('HTTP/1.1 404 Not Found'); $content =<<<EOH <h1>Error!</h1> <p>The page you requested was not found.</p> EOH; break; default: // application error $content =<<<EOH <h1>Error!</h1> <p>An unexpected error occurred. Please try again later.</p> EOH; break; } // Clear previous content $this->getResponse()->clearBody(); $this->view->content = $content; } }
Zend_Controller_Plugin_PutHandler
Zend_Controller_Plugin_PutHandler provides a drop-in plugin for marshalling PUT request bodies into request parameters, just like POST request bodies. It will inspect the request and, if PUT, will use parse_str to parse the raw PUT body into an array of params which is then set on the request. E.g.,
228
Zend_Controller
PUT /notes/5.xml HTTP/1.1 title=Hello&body=World To receive the 'title' and 'body' params as regular request params, register the plugin: $front = Zend_Controller_Front::getInstance(); $front->registerPlugin(new Zend_Controller_Plugin_PutHandler()); Then you can access the PUT body params by name from the request inside your controller: ... public function putAction() { $title = $this->getRequest()->getParam('title'); // $title = "Hello" $body = $this->getRequest()->getParam('body'); // $body = "World" } ...
229
Zend_Controller
filters/ news/ controllers/ IndexController.php ListController.php models/ views/ scripts/ index/ list/ helpers/ filters/ In this paradigm, the module name serves as a prefix to the controllers it contains. The above example contains three module controllers, 'Blog_IndexController', 'News_IndexController', and 'News_ListController'. Two global controllers, 'IndexController' and 'FooController' are also defined; neither of these will be namespaced. This directory structure will be used for examples in this chapter.
230
Zend_Controller
* Assuming the following directory structure: * application/ * modules/ * default/ * controllers/ * foo/ * controllers/ * bar/ * controllers/ */ $front->addModuleDirectory('/path/to/application/modules'); The above example will define the default, foo, and bar modules, each pointing to the controllers/ subdirectory of their respective module. You may customize the controller subdirectory setModuleControllerDirectoryName(): to use within your modules by using
/** * Change the controllers subdirectory to be 'con' * application/ * modules/ * default/ * con/ * foo/ * con/ * bar/ * con/ */ $front->setModuleControllerDirectoryName('con'); $front->addModuleDirectory('/path/to/application/modules');
Nota
You can indicate that no controller subdirectory be used for your modules by passing an empty value to setModuleControllerDirectoryName().
Routing to Modules
The default route in Zend_Controller_Router_Rewrite is an object of type Zend_Controller_Router_Route_Module. This route expects one of the following routing schemas: :module/:controller/:action/* :controller/:action/* In other words, it will match a controller and action by themselves or with a preceding module. The rules for matching specify that a module will only be matched if a key of the same name exists in the controller directory array passed to the front controller and dispatcher.
231
Zend_Controller
first looks for this default controller in the module path, and then falls back on the default controller found in the 'default', global, namespace. If you wish to always default to the global namespace, set the $useDefaultControllerAlways parameter in the front controller:
$front->setParam('useDefaultControllerAlways', true);
Excepciones MVC
Introduccin
Los componentes MVC en Zend Framework utilizan un Front Controller, lo que significa que todas las solicitudes de un determinado sitio pasarn por un solo punto de entrada. Como resultado, todas las excepciones burbujearn eventualmente hacia arriba hasta el Front Controller, permitiendo al desarrollador manejarlos en un solo lugar. Sin embargo, los mensajes de excepcin y la informacin de backtrace contienen a menudo informacin sensible del sistema, como declaraciones SQL, ubicaciones de archivos y otras cosas ms. Para ayudar a proteger su sitio, por defecto Zend_Controller_Front captura todas las excepciones y las registra con el objeto respuesta; a su vez, y por defecto, el objeto respuesta no muestra mensajes de excepcin.
$front->throwExceptions(true); try { $front->dispatch(); } catch (Exception $e) { // usted mismo maneja las excepciones } Este mtodo es probablemente la forma ms fcil de aadir un manejo de excepciones personalizado que abarque toda la gama de posibles excepciones a su aplicacin de front controller.
232
Zend_Controller
Zend_Controller_Response_Abstract::renderExceptions() Al pasar a este mtodo un valor booleano verdadero, le esta diciendo al objeto respuesta que debe emitir un mensaje de excepcin y backtrace cuando se renderiza a s mismo. En este escenario, se mostrar cualquier excepcin planteada por su aplicacin. Esto no es recomendable para entornos de produccin, pero s en desarrollo. Zend_Controller_Front::returnResponse() Zend_Controller_Response_Abstract::isException(). y
Pasando un valor booleano verdadero a Zend_Controller_Front::returnResponse(), Zend_Controller_Front::dispatch() no renderizar la respuesta, sino que la devolver. Una vez que tiene la respuesta, entonces puede probar ver si todas las excepciones fueron atrapadas usando su mtodo isException(), y recuperando las excepciones a travs del mtodo getException(). Como ejemplo:
$front->returnResponse(true); $response = $front->dispatch(); if ($response->isException()) { $exceptions = $response->getException(); // maneje las excepciones ... } else { $response->sendHeaders(); $response->outputBody(); } La principal ventaja que este mtodo ofrece por sobre Zend_Controller_Front::throwExceptions() es que le permite renderizar condicionalmente la respuesta despus de manejar la excepcin. Esta capturar cualquier excepcin en la cadena de controladores, a diferencia del plugin de manejo de errores.
$front->setParam('useDefaultControllerAlways', true); // o $dispatcher->setParam('useDefaultControllerAlways', true); Cuando este flag est establecido, el despachador utilizar el controlador y la accin por defecto en lugar de lanzar una excepcin. La desventaja de este mtodo es que cualquier error ortogrfico que un usuario haga cuando acceda a su sitio lo resolver y mostrar su pgina de inicio, y que puede causar estragos con la optimizacin para los motores de bsqueda.
233
Zend_Controller
La excepcin arrojada por dispatch() es una Zend_Controller_Dispatcher_Exception conteniendo el texto 'Invalid controller specified'. Use uno de los mtodos descriptos de la seccin anterior para atrapar la excepcin, y luego redireccionar a una pgina genrica de error o a la pgina de inicio. Zend_Controller_Action::__call() arrojar una Zend_Controller_Action_Exception si no puede despachar una accin inexistente a un mtodo. Es probable que desee utilizar alguna accin por defecto en el controlador en casos como este. Formas de lograr esto incluyen: Subclasear Zend_Controller_Action y anular el mtodo __call(). Como ejemplo:
class My_Controller_Action extends Zend_Controller_Action { public function __call($method, $args) { if ('Action' == substr($method, -6)) { $controller = $this->getRequest()->getControllerName(); $url = '/' . $controller . '/index'; return $this->_redirect($url); } throw new Exception('Invalid method'); } } El ejemplo anterior intercepta cualquier llamada a un mtodo de accin indefinido y redirecciona a la accin predeterminada en el controlador. Subclasea a Zend_Controller_Dispatcher y anula el mtodo getAction() para verificar si la accin existe. Como ejemplo:
class My_Controller_Dispatcher extends Zend_Controller_Dispatcher { public function getAction($request) { $action = $request->getActionName(); if (empty($action)) { $action = $this->getDefaultAction(); $request->setActionName($action); $action = $this->formatActionName($action); } else { $controller = $this->getController(); $action = $this->formatActionName($action); if (!method_exists($controller, $action)) { $action = $this->getDefaultAction(); $request->setActionName($action); $action = $this->formatActionName($action); } } return $action; } }
234
Zend_Controller
El cdigo anterior comprueba para ver que las acciones solicitadas existan en la clase del controlador; si no, se restablece la accin a la accin por defecto. Este mtodo es agradable porque puede alterar transparentemente la accin antes del ltimo despacho. Sin embargo, tambin significa que errores ortogrficos en la URL todava pueden despacharse correctamente, lo que no es muy bueno para la optimizacin en un motor de bsqueda. Use Zend_Controller_Action::preDispatch() Zend_Controller_Plugin_Abstract::preDispatch() para identificar acciones invlidas. o
Subclaseando Zend_Controller_Action y modificando preDispatch(), puede modificar todos sus controladores que transmitan a otra accin o redireccionar antes de despachar la accin. El cdigo para hacer esto se ver parecido al cdigo de sustitucin de arriba __call(). Alternativamente, puede verificar esta informacin en un plugin global. Esto tiene la ventaja de ser independiente del controlador de accin; si su aplicacin consiste en una variedad de controladores de accin, y no todos ellos heredan de la misma clase, este mtodo puede aadir coherencia a su manejo de clases diferentes. Como ejemplo:
class My_Controller_PreDispatchPlugin extends Zend_Controller_Plugin_Abstract { public function preDispatch(Zend_Controller_Request_Abstract $request) { $front = Zend_Controller_Front::getInstance(); $dispatcher = $front->getDispatcher(); $class = $dispatcher->getControllerClass($request); if (!$controller) { $class = $dispatcher->getDefaultControllerClass($request); } $r = new ReflectionClass($class); $action = $dispatcher->getActionMethod($request); if (!$r->hasMethod($action)) { $defaultAction = $dispatcher->getDefaultAction(); $controllerName = $request->getControllerName(); $response = $front->getResponse(); $response->setRedirect('/' . $controllerName . '/' . $defaultAction); $response->sendHeaders(); exit; } } } En este ejemplo, vamos a consultar para ver si la accin solicitada est disponible en el controlador. Si no, redireccionamos a la accin predeterminada en el controlador, y salimos inmediatamente de la ejecucin del script.
235
236
$currency = new Zend_Currency(); Zend_Currency also supports the usage of an application-wide locale. You can set a Zend_Locale instance in the registry as shown below. With this notation you can avoid setting the locale manually for each instance when you want to use the same locale throughout the application.
237
Zend_Currency
// in your bootstrap file $locale = new Zend_Locale('de_AT'); Zend_Registry::set('Zend_Locale', $locale); // somewhere in your application $currency = new Zend_Currency();
Nota
If your system has no default locale, or if the locale of your system can not be detected automatically, Zend_Currency will throw an exception. If see this exception, you should consider setting the locale manually. Depending on your needs, several parameters can be speicified at instantiation. Each of these parameters is optional and can be omitted. Even the order of the parameters can be switched. The meaning of each parameter is described in this list: currency: A locale can include several currencies. Therefore the first parameter 'currency' can define which currency should be used by giving the short name or full name of that currency. If that currency in not recognized in any locale an exception will be thrown. Currency short names are always made up of 3 letters, written in uppercase. Well known currency shortnames include USD or EUR. locale: The 'locale' parameter defines which locale should be used for formatting the currency. The specified locale will also be used to get the script and symbol for this currency if these parameters are not given.
Nota
Note that Zend_Currency only accepts locales which include a region. This means that all locales that only include a language will result in an exception. For example the locale en will cause an exception to be thrown whereas the locale en_US will return USD as currency.
238
Zend_Currency
Nota
For many countries there are several known currencies. Typically, one currency will currently be in use, with one or more ancient currencies. If the 'currency' parameter is suppressed the contemporary currency will be used. The region 'de' for example knows the currencies 'EUR' and 'DEM'... 'EUR' is the contemporary currency and will be used if the currency parameter is omitted.
239
Zend_Currency
Number formatting: The amount of currency (formally known as value of money) is formatted by the usage of formatting rules within the locale. For example is in English the ',' sign used as separator for thousands, and in German the '.' sign. So if you need to change the format, you should the setFormat() method. It takes an array which should include every option you want to change. The $options array supports the following settings: position: Defines the position at which the currency description should be displayed. The supported positions can be found in this table. script: Defined which script should be used for displaying digits. The default script for most locales is 'Latn', which includes the digits 0 to 9. Other scripts such as 'Arab' (Arabian) can be used. format: Defines the format which should be used for displaying numbers. This number-format includes for example the thousand separator. You can eighter use a default format by giving a locale identifier, or define the numberformat manually. If no format is set the locale from the Zend_Currency object will be used. display: Defines which part of the currency should be used for displaying the currency representation. There are 4 representations which can be used and which are all described in this table. precision: Defines the precision which should be used for the currency representation. The default value is 2. name: Defines the full currency name which should be displayed. This option overwrites any currency name which is set through the creation of Zend_Currency. currency: Defines the international abbreviation which should be displayed. This option overwrites any abbreviation which is set through the creation of Zend_Currency. symbol: Defines the currency symbol which should be displayed. This option overwrites any symbol which is set through the creation of Zend_Currency.
Tabla 13.2. Constants for the selecting the position of the currency description
constant STANDARD RIGHT LEFT description Set the standard position as defined within the locale Display the currency representation at the right side of the value Display the currency representation at the left side of the value
240
Zend_Currency
$currency = new Zend_Currency('en_US'); // prints 'US$ 1,000.00' echo $currency->toCurrency(1000); $currency->setFormat(array('display' => Zend_Currency::USE_NAME, 'position' => Zend_Currency::RIGHT)); // prints '1.000,00 US Dollar' echo $currency->toCurrency(1000); $currency->setFormat(array('name' => 'American Dollar')); // prints '1.000,00 American Dollar' echo $currency->toCurrency(1000); $currency->setFormat(array('format' => '##0.00')); // prints '1000,00 American Dollar' echo $currency->toCurrency(1000);
241
Zend_Currency
// creates an instance with 'en_US' using 'USD', 'Latin' and 'en_US' // as these are the default values from 'en_US' $currency = new Zend_Currency('en_US'); // prints '$' echo $currency->getSymbol(); // prints 'EUR' echo $currency->getShortName('EUR'); // prints 'sterreichische Schilling' echo $currency->getName('ATS', 'de_AT'); // returns an array with all regions where USD is used print_r($currency->getRegionList(); // returns an array with all currencies which were ever used in this // region print_r($currency->getCurrencyList('de_AT');
242
Zend_Currency
Zend_Currency::setCache($cache);
243
244
245
Zend_Date
Zend_Date aporta una API muy sencilla, que combina lo mejor de la funcionalidad fecha/hora de cuatro lenguajes de programacin. Es posible, por ejemplo, aadir o comparar dos horas dentro de una misma columna. Completamente internacionalizado Todos los nombres de meses y das de la semana completos y abreviados estn incluidos para ms de 130 idiomas. Los mtodos admiten tanto entrada como salida de fechas usando los nombres localizados de meses y das de la semana. Timestamps ilimitados A pesar de que la documentacin 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," Zend_Date admite un rango casi ilimitado, con la ayuda de la extensin BCMath. Si BCMath no est disponible, Zend_Date tendr una funcionalidad de timestamps reducida al rango del tipo float soportado por su servidor. El tamao de un float es dependiente de la plataforma, aunque un mximo de ~1.8e308 con una precisin de cerca de 14 dgitos decimales es un valor habitual (formato 64 bit IEEE)." [ http://www.php.net/float ]. Adicionalmente, las limitaciones heredadas de los tipos de dato float, y errores de redondeo de nmeros flotantes pueden introducir errores en los clculos. Para evitar estos problemas, los componentes ZF I18n usan la extensin BCMath, si est disponible. Soporte para especificaciones de fecha ISO_8601 Las especificaciones de fecha ISO_8601 estn aceptadas. Incluso las especificaciones de fecha ISO_8601 parcialmente autorizadas sern identificadas. Estos formatos de fecha son particularmente tiles al trabajar con bases de datos. Por ejemplo, aunque MsSQL y MySQL [http://dev.mysql.com/doc/refman/5.0/en/date-and-timefunctions.html] difieren ligeramente uno de otro, ambos tienen soporte por parte de Zend_Date usando la constante de especificacin de formato Zend_Date::ISO_8601. Cuando las cadenas de fecha sean del tipo "Y/m/d" o "Ym-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. Calcular amanecer y puesta de sol Las horas de amanecer y puesta de sol pueden mostrarse para cualquier lugar y da, para que no pierda ni un segundo de luz diurna para trabajar en su proyecto PHP favorito :)
Theory of Operation
Why is there only one class Zend_Date for handling dates and times in Zend Framework? Many languages split the handling of times and calendar dates into two classes. However, Zend Framework strives for extreme simplicity, and forcing the developer to manage different objects with different methods for times and dates becomes a burden in many situations. Since Zend_Date methods support working with ambiguous dates that might not include all parts (era, year, month, day, hour, minute, second, timezone), developers enjoy the flexibility and ease of using the same class and the same methods to perform the same manipulations (e.g. addition, subtraction, comparison, merging of date parts, etc.). Splitting the handling of these date fragments into multiple classes would create complications when smooth interoperation is desired with a small learning curve. A single class reduces code duplication for similar operations, without the need for a complex inheritance hierarchy.
Internals
UNIX Timestamp All dates and times, even ambiguous ones (e.g. no year), are represented internally as absolute moments in time, represented as a UNIX timestamp expressing the difference between the desired time and January 1st, 1970 00:00:00 GMT. This was only possible, because Zend_Date is not limited to UNIX timestamps nor integer values. The
246
Zend_Date
BCMath extension is required to support extremely large dates outside of the range Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT. Additional, tiny math errors may arise due to the inherent limitations of float data types and rounding, unless using the BCMath extension. Date parts as timestamp offsets Thus, an instance object representing three hours would be expressed as three hours after January 1st, 1970 00:00:00 GMT -i.e. 0 + 3 * 60 * 60 = 10800. PHP functions Where possible, Zend_Date usually uses PHP functions to improve performance.
Basic Methods
The following sections show basic usage of Zend_Date primarily by example. For this manual, "dates" always imply a calendar date with a time, even when not explicitly mentioned, and vice-versa. The part not specified defaults to an internal representation of "zero". Thus, adding a date having no calendar date and a time value of 12 hours to another date consisting only of a calendar date would result in a date having that calendar date and a time of "noon". Setting only a specific date, with no time part, implies a time set to 00:00:00. Conversely, setting only a specific time implies a date internally set to 01.01.1970 plus the number of seconds equal to the elapsed hours, minutes, and seconds identified by the time. Normally, people measure things from a starting point, such as the year 0 A.D. However, many software systems use the first second of the year 1970 as the starting point, and denote times as a timestamp offset counting the number of seconds elapsed from this starting point.
Current Date
Without any arguments, constructing an instance returns an object in the default locale with the current, local date using PHP's time() function to obtain the UNIX timestamp [http://en.wikipedia.org/wiki/Unix_Time] for the object. Make sure your PHP environment has the correct default timezone .
Zend_Date by Ejemplo
Reviewing basic methods of Zend_Date is a good place to start for those unfamiliar with date objects in other languages or frameworks. A small example will be provided for each method below.
Output a Date
The date in a Zend_Date object may be obtained as a localized integer or string using the get() method. There are many available options, which will be explained in later sections.
247
Zend_Date
Setting a Date
The set() method alters the date stored in the object, and returns the final date value as a timestamp (not an object). Again, there are many options which will be explored in later sections.
Comparison of Dates
All basic Zend_Date methods can operate on entire dates contained in the objects, or can operate on date parts, such as comparing the minutes value in a date to an absolute value. For example, the current minutes in the current time may be compared with a specific number of minutes using compare(), as in the example below.
248
Zend_Date
Opciones Zend_Date
Selecting the Date Format Type
Several methods use date format strings, in a way similar to PHP's date(). If you are more comfortable with PHP's date format specifier than with ISO format specifiers, then you can use Zend_Date::setOptions(array('format_type' => 'php')). Afterward, use PHP's date format specifiers for all functions which accept a $format parameter. Use Zend_Date::setOptions(array('format_type' => 'iso')) to switch back to the default mode of supporting only ISO date format tokens. For a list of supported format codes, see the section called Self-Defined OUTPUT Formats Using PHP's date() Format Specifiers
Month Calculations
When adding or substracting months from an existing date, the resulting value for the day of the month might be unexpected, if the original date fell on a day close to the end of the month. For example, when adding one month to January 31st, people familiar with SQL will expect February 28th as the result. On the other side, people familiar with
249
Zend_Date
Excel and OpenOffice will expect March 3rd as the result. The problem only occurs, if the resulting month does not have the day, which is set in the original date. For Zend Framework developers, the desired behavior is selectable using the extend_month option to choose either the SQL behaviour, if set to FALSE, or the spreadsheet behaviour when set to TRUE. The default behaviour for extend_month is FALSE, providing behavior compatible to SQL. By default, Zend_Date computes month calculations by truncating dates to the end of the month (if necessary), without wrapping into the next month when the original date designates a day of the month exceeding the number of days in the resulting month. Use Zend_Date::setOptions(array('extend_month' => true)); to make month calculations work like popular spreadsheet programs.
250
Zend_Date
$date3 = new Zend_Date('Feb 31, 2007', 'MM.dd.yyyy'); echo $date3, "\n"; // outputs "Mar 3, 2007 12:00:00 AM" If the optional $locale parameter is provided, then the $locale disambiguates the $date operand by replacing month and weekday names for string $date operands, and even parsing date strings expressed according to the conventions of that locale (see Zend_Locale_Format::getDate() ). The automatic normalization of localized $date operands of a string type occurs when $part is one of the Zend_Date::DATE* or Zend_Date::TIME* constants. The locale identifies which language should be used to parse month names and weekday names, if the $date is a string containing a date. If there is no $date input parameter, then the $locale parameter specifies the locale to use for localizing output (e.g. the date format for a string representation). Note that the $date input parameter might actually have a type name instead (e.g. $hour for addHour()), although that does not prevent the use of Zend_Date objects as arguments for that parameter. If no $locale was specified, then the locale of the current object is used to interpret $date, or select the localized format for output. Since Zend Framework 1.7.0 Zend_Date does also support the usage of an application wide locale. You can simply set a Zend_Locale instance to the registry like shown below. With this notation you can forget about setting the locale manually with each instance when you want to use the same locale multiple times. // in your bootstrap file $locale = new Zend_Locale('de_AT'); Zend_Registry::set('Zend_Locale', $locale); // somewhere in your application $date = new Zend_Date('31.Feb.2007');
251
Zend_Date
method. Thus, the names of these methods (e.g. "Year" or "Minute") identify the units of the $date operand, when $date is a string or integer.
Month [http://en.wikipedia.org/wiki/ Gregorian calendar month (1-12, localized names Month#Julian_and_Gregorian_calendars] supported) 24 hour hour_clock] clock [http://en.wikipedia.org/wiki/24- Hours of the day (0-23) denote the hours elapsed, since the start of the day. Minutes of the hour (0-59) denote minutes elapsed, since the start of the hour. Seconds of the minute (0-59) denote the elapsed seconds, since the start of the minute. Milliseconds denote thousandths of a second (0-999). Zend_Date supports two additional methods for working with time units smaller than seconds. By default, Zend_Date instances use a precision defaulting to milliseconds, as seen using getFractionalPrecision(). To change the precision use setFractionalPrecision($precision). However, precision is limited practically to microseconds, since Zend_Date uses microtime() [http:// php.net/microtime]. Zend_Date::DAY_SHORT is extracted from $date if the $date operand is an instance of Zend_Date or a numeric string. Otherwise, an attempt is made to extract the day according to the conventions documented for these constants: Zend_Date::WEEKDAY_NARROW, Zend_Date::WEEKDAY_NAME, Zend_Date::WEEKDAY_SHORT, Zend_Date::WEEKDAY (Gregorian calendar assumed) Zend_Date::WEEK is extracted from $date if the $date operand is an instance of Zend_Date or a numeric string. Otherwise an exception is raised. (Gregorian calendar assumed) Zend_Date::DAY_MEDIUM is extracted from $date if the $date operand is an instance of Zend_Date. Otherwise, an attempt is made to normalize the $date string into a Zend_Date::DATE_MEDIUM formatted date. The format of Zend_Date::DAY_MEDIUM depends on the object's locale. Weekdays are (for Sunday) represented numerically as 0 through 6 (for Saturday).
Day [http://en.wikipedia.org/wiki/Day]
Week [http://en.wikipedia.org/wiki/Week]
Date
Weekday
252
Zend_Date
Date Part
Explanation Zend_Date::WEEKDAY_DIGIT is extracted from $date, if the $date operand is an instance of Zend_Date or a numeric string. Otherwise, an attempt is made to extract the day according to the conventions documented for these constants: Zend_Date::WEEKDAY_NARROW, Zend_Date::WEEKDAY_NAME, Zend_Date::WEEKDAY_SHORT, Zend_Date::WEEKDAY (Gregorian calendar assumed) In Zend_Date, the day of the year represents the number of calendar days elapsed since the start of the year (0-365). As with other units above, fractions are rounded down to the nearest whole number. (Gregorian calendar assumed) Arpa dates (i.e. RFC 822 formatted dates) are supported. Output uses either a "GMT" or "Local differential hours +min" format (see section 5 of RFC 822). Before PHP 5.2.2, using the DATE_RFC822 constant with PHP date functions sometimes produces incorrect results [http:// bugs.php.net/bug.php?id=40308]. Zend_Date's results are correct. Ejemplo: Mon, 31 Dec 06 23:59:59 GMT Only complete ISO 8601 dates are supported for output. Ejemplo: 2009-02-14T00:31:30+01:00
DayOfYear
Arpa [http://www.faqs.org/rfcs/rfc822.html]
Iso [http://en.wikipedia.org/wiki/ISO_8601]
253
Zend_Date
Explanation sub($date, $part = null, $locale = null) Subtracts the $part of $date having a locale $locale from the current object's date.
copyPart()
copyPart($part, $locale = null) Returns a cloned object, with only $part of the object's date copied to the clone, with the clone have its locale arbitrarily set to $locale (if specified).
compare()
compare($date, $part = null, $locale = null) compares $part of $date to this object's timestamp, returning 0 if they are equal, 1 if this object's part was more recent than $date's part, otherwise -1.
Comparing Dates
The following basic operations do not have corresponding convenience methods for the date parts listed in the section called Zend_Date API Overview .
254
Zend_Date
Method
Explanation Use isLeapYear() to determine if the current object is a leap year, or use Zend_Date::checkLeapYear($year) to check $year, which can be a string, integer, or instance of Zend_Date. Is the year a leap year? isDate($date, $format = null, $locale = null) This method checks if a given date is a real date and returns TRUE if all checks are ok. It works like PHP's checkdate() function but can also check for localized month names and for dates extending the range of checkdate()
isDate()
255
Zend_Date
Method
Explanation Number of weekday 'weekday' (Zend_Date::WEEKDAY_DIGIT) Day of year 'dayofyear' (Zend_Date::DAY_OF_YEAR) Week as 'week' (Zend_Date::WEEK) Delay of timezone to GMT 'gmtsecs' (Zend_Date::GMT_SECS)
as
as
as
toValue()
toValue($part = null) Returns an integer representation of the selected date $part according to the conventions of the object's locale. Returns FALSE when $part selects a non-numeric value, such as Zend_Date::MONTH_NAME_SHORT. NOTE: This method calls get() and casts the result to a PHP integer, which will give unpredictable results, if get() returns a numeric string containing a number too large for a PHP integer on your system. Use get() instead.
get()
get($part = null, $locale = null) This method returns the $part of object's date localized to $locale as a formatted string or integer. See the section called List of Date Operations for more information.
now()
now($locale = null) This convenience function is equivalent to new Zend_Date(). It returns the current date as a Zend_Date object, having $locale
Sunrise / Sunset
Three methods provide access to geographically localized information about the Sun, including the time of sunrise and sunset.
256
Zend_Date
Creation of Dates
Zend_Date provides several different ways to create a new instance of itself. As there are different needs the most convenient ways will be shown in this chapter.
257
Zend_Date
$datearray = array('year' => 2006, 'month' => 4, 'day' => 18, 'hour' => 12, 'minute' => 3, 'second' => 10); $date = new Zend_Date($datearray);
$datearray = array('year' => 2006, 'month' => 4, 'day' => 18); $date = new Zend_Date($datearray);
258
Zend_Date
Using Constants
For example, the constant Zend_Date::HOUR can be used in the ways shown below. When working with days of the week, calendar dates, hours, minutes, seconds, and any other date parts that are expressed differently when in different parts of the world, the object's timezone will automatically be used to compute the correct value, even though the internal timestamp is the same for the same moment in time, regardless of the user's physical location in the world. Regardless of the units involved, output must be expressed either as GMT or UTC or localized to a locale. The example output below reflects localization to Europe/GMT+1 hour (e.g. Germany, Austria, France).
Compare hour, returns 0, 1 2009-02-13T14:53:27+01:001 (if object > argument) or -1 2009-02-13T14:53:27+01:001970-01-01T14:00:00+01:00 Compares the hour, returns 2009-02-13T14:53:27+01:00TRUE TRUE or FALSE Compares the hour, returns 2009-02-13T14:53:27+01:00TRUE TRUE or FALSE Compares the hour, returns 2009-02-13T14:53:27+01:00FALSE TRUE or FALSE
copy(Zend_Date::HOUR) Copies only the hour part equals(14, Zend_Date::HOUR) isEarlier(12, Zend_Date::HOUR) isLater(12, Zend_Date::HOUR)
Zend_Date::DAY_SHORT Day (as a number, one or 2009-02-06T14:53:27+01:006 two digit) Zend_Date::WEEKDAY Weekday (Name of the day, 2009-02-13T14:53:27+01:00Friday localized, complete) Zend_Date::WEEKDAY_SHORT Weekday (Name of the day, 2009-02-13T14:53:27+01:00Fri for Friday localized, abbreviated, the first three digits) Zend_Date::WEEKDAY_NAME Weekday (Name of the day, 2009-02-13T14:53:27+01:00Fr for Friday localized, abbreviated, the first two digits)
259
Zend_Date
Constant
Description
Date
Result
Zend_Date::WEEKDAY_NARROW Weekday (Name of the day, 2009-02-13T14:53:27+01:00F for Friday localized, abbreviated, only the first digit) Zend_Date::WEEKDAY_DIGIT Weekday (0 = Sunday, 6 = 2009-02-13T14:53:27+01:005 for Friday Saturday) Zend_Date::WEEKDAY_8601 Weekday according to ISO 2009-02-13T14:53:27+01:005 for Friday 8601 (1 = Monday, 7 = Sunday) Zend_Date::DAY_OF_YEAR Day (as a number, one or 2009-02-13T14:53:27+01:0043 two digit) Zend_Date::DAY_SUFFIX English addendum for the 2009-02-13T14:53:27+01:00th day (st, nd, rd, th)
2009-02-13T14:53:27+01:008
Zend_Date::MONTH_NAME Month (Name of the month, 2009-02-13T14:53:27+01:00February localized, complete) Zend_Date::MONTH_NAME_SHORT Month (Name of the month, 2009-02-13T14:53:27+01:00Feb localized, abbreviated, three digit) Zend_Date::MONTH_NAME_NARROW Month (Name of the month, 2009-02-13T14:53:27+01:00F localized, abbreviated, one digit) Zend_Date::MONTH Month (Number of the 2009-02-13T14:53:27+01:0002 month, two digit)
Zend_Date::MONTH_SHORT Month (Number of the 2009-02-13T14:53:27+01:002 month, one or two digit) Zend_Date::MONTH_DAYS Number of days for this 2009-02-13T14:53:27+01:0028 month (number)
2009-02-13T14:53:27+01:002009
Zend_Date::YEAR_8601 Year according to ISO 8601 2009-02-13T14:53:27+01:002009 (number) Zend_Date::YEAR_SHORT Year (number, two digit) 2009-02-13T14:53:27+01:0009 Zend_Date::YEAR_SHORT_8601 Year according to ISO 8601 2009-02-13T14:53:27+01:0009 (number, two digit)
260
Zend_Date
Constant
Description
Date
Result
Zend_Date::HOUR_SHORT Hour (0-23, one or two digit) 2009-02-13T14:53:27+01:0014 Zend_Date::HOUR_SHORT_AM Hour (1-12, one or two digit) 2009-02-13T14:53:27+01:002 Zend_Date::HOUR_AM Hour (01-12, two digit) Zend_Date::MINUTE Minute (00-59, two digit) 2009-02-13T14:53:27+01:0002 2009-02-13T14:53:27+01:0053
Zend_Date::MINUTE_SHORT Minute (0-59, one or two 2009-02-13T14:03:27+01:003 digit) Zend_Date::SECOND Second (00-59, two digit) 2009-02-13T14:53:27+01:0027 Zend_Date::SECOND_SHORT Second (0-59, one or two 2009-02-13T14:53:07+01:007 digit) Zend_Date::MILLISECOND Millisecond infinite) (theoretically 2009-02-06T14:53:27.2054620546
Zend_Date::MERIDIEM Time of day (forenoon or 2009-02-13T14:53:27+01:00afternoon afternoon) Zend_Date::SWATCH Swatch Internet Time 2009-02-13T14:53:27+01:00620
Zend_Date::GMT_DIFF_SEP Difference to GMT in 2009-02-13T14:53:27+01:00+01:00 seconds (string, separated) Zend_Date::DAYLIGHT Summer time or Winter 2009-02-13T14:53:27+01:00FALSE time? (TRUE or FALSE)
261
Zend_Date
Constant
Description
Date
Result
Zend_Date::TIMESTAMP Unix time [http:// 2009-02-13T14:53:27+01:001234533207 en.wikipedia.org/wiki/ Unix_Time] (seconds since 1.1.1970, mixed) Zend_Date::ATOM Zend_Date::COOKIE Date according to ATOM 2009-02-13T14:53:27+01:002009-02-13T14:53:27+01:00 (string) Date for Cookies (string, for 2009-02-13T14:53:27+01:00Friday, 13-Feb-09 Cookies) 14:53:27 Europe/Paris
Zend_Date::RFC_822 Date according to RFC 822 2009-02-13T14:53:27+01:00Fri, 13 Feb 09 14:53:27 (string) +0100 Zend_Date::RFC_850 Date according to RFC 850 2009-02-13T14:53:27+01:00Friday, 13-Feb-09 (string) 14:53:27 Europe/Paris Zend_Date::RFC_1036 Date according to RFC 1036 2009-02-13T14:53:27+01:00Fri, 13 Feb 09 14:53:27 (string) +0100 Zend_Date::RFC_1123 Date according to RFC 1123 2009-02-13T14:53:27+01:00Fri, 13 Feb 2009 14:53:27 (string) +0100 Zend_Date::RSS Zend_Date::W3C Date for RSS Feeds (string) 2009-02-13T14:53:27+01:00Fri, 13 Feb 2009 14:53:27 +0100 Date for HTML or HTTP 2009-02-13T14:53:27+01:002009-02-13T14:53:27+01:00 according to W3C (string)
Especially note Zend_Date::DATES, since this format specifier has a unique property within Zend_Date as an input format specifier. When used as an input format for $part, this constant provides the most flexible acceptance of a variety of similar date formats. Heuristics are used to automatically extract dates from an input string and then "fix" simple errors in dates (if any), such as swapping of years, months, and days, when possible.
Zend_Date::ERA_NAME Epoch (string, localized, 2009-02-13T14:53:27+01:00anno domini (anno Domini) complete) Zend_Date::DATES Standard date (string, 2009-02-13T14:53:27+01:0013.02.2009 localized, default value).
Zend_Date::DATE_FULL Complete date (string, 2009-02-13T14:53:27+01:00Friday, 13. February 2009 localized, complete) Zend_Date::DATE_LONG Long date (string, localized, 2009-02-13T14:53:27+01:0013. February 2009 long) Zend_Date::DATE_MEDIUM Normal date localized, normal) (string, 2009-02-13T14:53:27+01:0013.02.2009
Zend_Date::DATE_SHORT Abbreviated Date (string, 2009-02-13T14:53:27+01:0013.02.09 localized, abbreviated) Zend_Date::TIMES Standard time (string, 2009-02-13T14:53:27+01:0014:53:27 localized, default value)
262
Zend_Date
Constant
Description
Date
Result
Zend_Date::TIME_FULL Complete time (string, 2009-02-13T14:53:27+01:0014:53 Uhr CET localized, complete) Zend_Date::TIME_LONG Long time (string, localized, 2009-02-13T14:53:27+01:0014:53:27 CET Long) Zend_Date::TIME_MEDIUM Normal time localized, normal) (string, 2009-02-13T14:53:27+01:0014:53:27
Zend_Date::TIME_SHORT Abbreviated time (string, 2009-02-13T14:53:27+01:0014:53 localized, abbreviated) Zend_Date::DATETIME Standard date with time 2009-02-13T14:53:27+01:0013.02.2009 14:53:27 (string, localized, default value). Zend_Date::DATETIME_FULL Complete date with time 2009-02-13T14:53:27+01:00Friday, 13. February 2009 (string, localized, complete) 14:53 Uhr CET Zend_Date::DATETIME_LONG Long date with time (string, 2009-02-13T14:53:27+01:0013. February localized, long) 14:53:27 CET Zend_Date::DATETIME_MEDIUM Normal date with time 2009-02-13T14:53:27+01:0013.02.2009 14:53:27 (string, localized, normal) Zend_Date::DATETIME_SHORT Abbreviated date with 2009-02-13T14:53:27+01:0013.02.09 14:53 time (string, localized, abbreviated) 2009
263
Zend_Date
Constant GGG GGGG GGGGG y yy yyy yyyy yyyyy Y YY YYY YYYY YYYYY M MM MMM MMMM MMMMM w ww d dd D DD DDD E EE
Result AD
Epoch, localized, complete Zend_Date::ERA_NAME anno domini localized, Zend_Date::ERA Zend_Date::YEAR a 9 2009 2009 02009
Year, at least one digit Year, at least two digit Year, at least three digit Year, at least four digit Year, at least five digit
Year according to ISO 8601, Zend_Date::YEAR_8601 9 at least one digit Year according to ISO 8601, Zend_Date::YEAR_SHORT_8601 09 at least two digit Year according to ISO 8601, Zend_Date::YEAR_8601 2009 at least three digit Year according to ISO 8601, Zend_Date::YEAR_8601 2009 at least four digit Year according to ISO 8601, Zend_Date::YEAR_8601 02009 at least five digit Month, one or two digit Month, two digit Month, abbreviated Zend_Date::MONTH_SHORT 2 Zend_Date::MONTH 02
Month, localized, complete Zend_Date::MONTH_NAME February Month, localized, Zend_Date::MONTH_NAME_NARROW F abbreviated, one digit Week, one or two digit Week, two digit Zend_Date::WEEK Zend_Date::WEEK 5 05
Day of the month, one or Zend_Date::DAY_SHORT 9 two digit Day of the month, two digit Zend_Date::DAY 09 Day of the year, one, two or Zend_Date::DAY_OF_YEAR 7 three digit Day of the year, two or three Zend_Date::DAY_OF_YEAR 07 digit Day of the year, three digit Zend_Date::DAY_OF_YEAR 007 Day of the week, localized, Zend_Date::WEEKDAY_NARROW M abbreviated, one char Day of the week, localized, Zend_Date::WEEKDAY_NAME Mo abbreviated, two or more chars
264
Zend_Date
Description
Corresponds best to
Result
Day of the week, localized, Zend_Date::WEEKDAY_SHORT Mon abbreviated, three chars Day of the week, localized, Zend_Date::WEEKDAY Monday complete Day of the week, localized, Zend_Date::WEEKDAY_NARROW M abbreviated, one digit Number of the day, one digit Zend_Date::WEEKDAY_DIGIT 4 Number of the day, two digit Zend_Date::WEEKDAY_NARROW 04 Time of day, localized Zend_Date::MERIDIEM vorm. Hour, (1-12), one or two Zend_Date::HOUR_SHORT_AM 2 digit Hour, (01-12), two digit Zend_Date::HOUR_AM 02 Hour, (0-23), one or two Zend_Date::HOUR_SHORT 2 digit Hour, (00-23), two digit Zend_Date::HOUR 02 Minute, (0-59), one or two Zend_Date::MINUTE_SHORT 2 digit Minute, (00-59), two digit Zend_Date::MINUTE 02 Second, (0-59), one or two Zend_Date::SECOND_SHORT 2 digit Second, (00-59), two digit Millisecond Time zone, abbreviated Time zone, abbreviated Time zone, abbreviated Time zone, complete Zend_Date::SECOND 02 Zend_Date::MILLISECOND 20536 localized, Zend_Date::TIMEZONE CET localized, Zend_Date::TIMEZONE CET localized, Zend_Date::TIMEZONE CET localized, Zend_Date::TIMEZONE_NAME Europe/Paris Zend_Date::GMT_DIFF +0100 Zend_Date::GMT_DIFF +0100 Zend_Date::GMT_DIFF +0100
Nota
Note that the default ISO format differs from PHP's format which can be irritating if you have not used in previous. Especially the format specifiers for Year and Minute are often not used in the intended way. For year there are two specifiers available which are often mistaken. The Y specifier for the ISO year and the y specifier for the real year. The difference is small but significant. Y calculates the ISO year, which is
265
Zend_Date
often used for calendar formats. See for example the 31. December 2007. The real year is 2007, but it is the first day of the first week in the week 1 of the year 2008. So, if you are using 'dd.MM.yyyy' you will get '31.December.2007' but if you use 'dd.MM.YYYY' you will get '31.December.2008'. As you see this is no bug but a expected behaviour depending on the used specifiers. For minute the difference is not so big. ISO uses the specifier m for the minute, unlike PHP which uses i. So if you are getting no minute in your format check if you have used the right specifier.
Day of the month, two Zend_Date::DAY dd digit Day week, of the Zend_Date::WEEKDAY_SHORT EEE localized,
266
Zend_Date
Constant
CLDR Result
j l (lowercase L) N S
Day of the month, one Zend_Date::DAY_SHORT d or two digit Day of the week, Zend_Date::WEEKDAY EEEE localized, complete Number of the Zend_Date::WEEKDAY_8601 e weekday, one digit English suffixes for no equivalent day of month, two chars no equivalent
9 Monday 4 st
Number of the Zend_Date::WEEKDAY_DIGIT no equivalent weekday, 0=sunday, 6=saturday Day of the year, one, Zend_Date::DAY_OF_YEAR D two or three digit Week, one or two digit Zend_Date::WEEK w Month, complete localized, Zend_Date::MONTH_NAME MMMM Zend_Date::MONTH MM
z W F m M n t
7 5 February 02 Feb 2 30
Month, localized, Zend_Date::MONTH_NAME_SHORT MMM abbreviated Month, one or two Zend_Date::MONTH_SHORT M digit Number of days per Zend_Date::MONTH_DAYS no equivalent month, one or two digits Leapyear, boolean Zend_Date::LEAPYEAR no equivalent Year according to ISO Zend_Date::YEAR_8601 YYYY 8601, at least four digit Year, at least four Zend_Date::YEAR yyyy digit Year, at least two digit Zend_Date::YEAR_SHORT yy
L o
true 2009
Y y a A
2009 09
Time of day, localized Zend_Date::MERIDIEM a (sort of, but likely to vorm. be uppercase) Time of day, localized Zend_Date::MERIDIEM a (sort of, but no VORM. guarantee that the format is uppercase) Swatch internet time Zend_Date::SWATCH no equivalent 1463 2 Hour, (1-12), one or Zend_Date::HOUR_SHORT_AM h two digit
B g
267
Zend_Date
Constant G h H i s e I O P T Z c r U
Description
CLDR Result 2 02 02 02 02 Europe/Paris 1 +0100 +01:00 CET 3600 2004-02-13T15:19:21+00:00 Thu, 21 Dec 2000 16:01:07 +0200 15275422364
Hour, (0-23), one or Zend_Date::HOUR_SHORT H two digit Hour, (01-12), two Zend_Date::HOUR_AM hh digit Hour, (00-23), two Zend_Date::HOUR HH digit Minute, (00-59), two Zend_Date::MINUTE mm digit Second, (00-59), two Zend_Date::SECOND ss digit Time zone, localized, Zend_Date::TIMEZONE_NAME zzzz complete Daylight Difference zone of Zend_Date::DAYLIGHT no equivalent time Zend_Date::GMT_DIFF Z or ZZ or ZZZ
Difference of time Zend_Date::GMT_DIFF_SEP ZZZZ zone, separated Time zone, localized, Zend_Date::TIMEZONE z or zz or zzz abbreviated Time zone offset in Zend_Date::TIMEZONE_SECS no equivalent seconds Standard Iso format Zend_Date::ISO_8601 no equivalent output Standard Rfc 2822 Zend_Date::RFC_2822 no equivalent format output Unix timestamp Zend_Date::TIMESTAMP no equivalent
Working Ejemplos
Within this chapter, we will describe several additional functions which are also available through Zend_Date. Of course all described functions have additional examples to show the expected working and the simple API for the proper using of them.
Checking Dates
Probably most dates you will get as input are strings. But the problem with strings is that you can not be sure if the string is a real date. Therefor Zend_Date has spent an own static function to check date strings. Zend_Locale has an own function getDate($date, $locale) which parses a date and returns the proper and normalized date parts. A monthname for example will be recognised and returned just a month number. But as Zend_Locale does not know anything about dates because it is a normalizing and localizing class we have integrated an own function isDate($date) which checks this. isDate($date, $format, $locale) can take up to 3 parameters and needs minimum one parameter. So what we need to verify a date is, of course, the date itself as string. The second parameter can be the format which the date is expected to have. If no format is given the standard date format from your locale is used. For details about how formats should look like see the chapter about self defined formats.
268
Zend_Date
The third parameter is also optional as the second parameter and can be used to give a locale. We need the locale to normalize monthnames and daynames. So with the third parameter we are able to recognise dates like '01.Jnner.2000' or '01.January.2000' depending on the given locale. isDate() of course checks if a date does exist. Zend_Date itself does not check a date. So it is possible to create a date like '31.February.2000' with Zend_Date because Zend_Date will automatically correct the date and return the proper date. In our case '03.March.2000'. isDate() on the other side does this check and will return FALSE on '31.February.2000' because it knows that this date is impossible.
269
Zend_Date
The location itself can be received with the Zend_Date_Cities::city() function. It accepts the name of the city as returned by the Zend_Date_Cities::getCityList() function and optional as second parameter the horizon to set. There are 4 defined horizons which can be used with locations to receive the exact time of sunset and sunrise. The '$horizon' parameter is always optional in all functions. If it is not set, the 'effective' horizon is used.
Of course also a self-defined location can be given and calculated with. Therefor a 'latitude' and a 'longitude' has to be given and optional the 'horizon'.
270
Zend_Date
Time Zones
Time zones are as important as dates themselves. There are several time zones depending on where in the world a user lives. So working with dates also means to set the proper timezone. This may sound complicated but it's easier as expected. As already mentioned in the first chapter of Zend_Date the default timezone has to be set. Either by php.ini or by definition within the bootstrap file. A Zend_Date object of course also stores the actual timezone. Even if the timezone is changed after the creation of the object it remembers the original timezone and works with it. It is also not necessary to change the timezone within the code with PHP functions. Zend_Date has two built-in functions which makes it possible to handle this. getTimezone() returns the actual set timezone of within the Zend_Date object. Remember that Zend_Date is not coupled with PHP internals. So the returned timezone is not the timezone of the PHP script but the timezone of the object. setTimezone($zone) is the second function and makes it possible to set new timezone for Zend_Date. A given timezone is always checked. If it does not exist an exception will be thrown. Additionally the actual scripts or systems timezone can be set to the date object by calling setTimezone() without the zone parameter. This is also done automatically when the date object is created.
271
Zend_Date
Having the timezone coupled within Zend_Date has another positive effect. It is possible to have several dates with different timezones.
272
Nota
Cada Zend_Db_Adaptador utiliza una extensin PHP. Se debe de tener habilitada la respectiva extensin 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 extensin PDO como el driver PDO del tipo de base de datos que se utiliza.
273
Zend_Db
Ejemplo 15.3. Usando el mtodo factory para una clase Adaptador personalizada
// No tenemos que cargar el archivo de clase Adaptador // porque ser cargado para nosotros por el mtodo factory de Zend_Db. // Automticamente 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',
274
Zend_Db
'password' => 'xxxxxxxx', 'dbname' => 'test', 'adapterNamespace' => 'MyProject_Db_Adapter' ));
Ejemplo 15.4. Uso del mtodo factory del Adaptador con un objeto Zend_Config
En el siguiente ejemplo, un objeto Zend_Config es creado usando un array. Tambin puedes cargar los datos de un archivo externo, por ejemplo con Zend_Config_Ini o Zend_Config_Xml . $config = new Zend_Config( array( 'database' => array( 'adapter' => 'Mysqli', 'params' => array( 'dbname' => 'test', 'username' => 'webuser', 'password' => 'secret', ) ) ) ); $db = Zend_Db::factory($config->database); El segundo argumento del mtodo factory() puede ser un array asociativo con entradas correspondientes a los parmetros 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.
275
Zend_Db
options : este parmetro es un array asociativo de opciones que son genricas a todas las clases Zend_Db_Adapter. driver_options : este parmetro es un array asociativo de opciones adicionales para una extensin de base de datos dada. un uso tpico de este parmetro es establecer atributos de un driver PDO. adapterNamespace : 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 mtodo factory() para cargar un adaptador de clase de base de datos que no sea de Zend.
$options = array( Zend_Db::CASE_FOLDING => Zend_Db::CASE_UPPER ); $params = array( 'host' 'username' 'password' 'dbname' 'options' );
$options = array( Zend_Db::AUTO_QUOTE_IDENTIFIERS => false ); $params = array( 'host' 'username' 'password' 'dbname' 'options' );
276
Zend_Db
277
Zend_Db
Additionally, an adapter can get serialized to store it, for example, in a session variable. This can be very useful not only for the adapter itself, but for other objects that aggregate it, like a Zend_Db_Select object. By default, adapters are allowed to be serialized, if you don't want it, you should consider passing the Zend_Db::ALLOW_SERIALIZATION=false option, see the example above. To respect lazy connections principle, the adapter won't reconnect itself after being unserialized. You must then call getConnection() yourself. You can make the adapter auto-reconnect by passing the Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE=true as an adapter option.
278
Zend_Db
); CREATE TABLE bugs_products ( bug_id INTEGER NOT NULL REFERENCES bugs, product_id INTEGER NOT NULL REFERENCES products, PRIMARY KEY (bug_id, product_id) ); Also notice that the bugs table contains multiple foreign key references to the accounts table. Each of these foreign keys may reference a different row in the accounts table for a given bug. The diagram below illustrates the physical data model of the example database.
279
Zend_Db
280
Zend_Db
281
Zend_Db
$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;
Inserting Data
You can add new rows to a table in your database using the insert() 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.
282
Zend_Db
283
Zend_Db
// return the last value generated by sequence 'bugs_id_gen'. $id = $db->lastSequenceId('bugs_id_gen'); 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 NULL.
Updating Data
You can update rows in a database table using the update() 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. The values in the data array are treated as string literals. See the section called Inserting Data for information on using SQL expressions in the data array. 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 the section called Quoting Values and Identifiers for methods to help you do this. The return value is the number of rows affected by the update operation.
284
Zend_Db
$n = $db->update('bugs', $data, 'bug_id = 2'); If you omit the third argument, then all rows in the database table are updated with the values specified in the data array. If you provide an array of strings as the third argument, these strings are joined together as terms in an expression separated by AND operators.
$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')
Deleting Data
You can delete rows from a database table using the delete() method. This method takes two arguments: the first is a string naming the table. 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 the section called Quoting Values and Identifiers for methods to help you do this. The return value is the number of rows affected by the delete operation.
285
Zend_Db
$name = "O'Reilly"; $sql = "SELECT * FROM bugs WHERE reported_by = '$name'"; echo $sql; // SELECT * FROM bugs WHERE reported_by = 'O'Reilly' 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 http://en.wikipedia.org/wiki/SQL_Injection). 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.
Using quote()
The quote() 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 (').
SELECT * FROM atable WHERE intColumn = '123' You can use the optional second argument to the quote() method to apply quoting selectively for the SQL datatype you specify.
286
Zend_Db
$sql = 'SELECT * FROM atable WHERE intColumn = ' . $db->quote($value, 'INTEGER'); 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 Zend_Db::INT_TYPE, Zend_Db::BIGINT_TYPE, and Zend_Db::FLOAT_TYPE to write code in a more RDBMS-independent way. Zend_Db_Table specifies SQL types to quote() automatically when generating SQL queries that reference a table's key columns.
Using quoteInto()
The most typical usage of quoting is to interpolate a PHP variable into a SQL expression or statement. You can use the quoteInto() method to do this in one step. This method takes two arguments: the first argument is a string containing a placeholder symbol (?), and the second argument is a value or PHP variable that should be substituted for that placeholder. The placeholder symbol is the same symbol used by many RDBMS brands for positional parameters, but the quoteInto() 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.
Using quoteIdentifier()
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. However, SQL has a feature called delimited identifiers, 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.
287
Zend_Db
The quoteIdentifier() method works like quote(), 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 (") for identifier delimiters, and most RDBMS brands use that symbol. MySQL uses back-quotes (`) by default. The quoteIdentifier() method also escapes special characters within the string argument.
288
Zend_Db
$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(); }
289
Zend_Db
Description True if an integer-based type is reported as UNSIGNED. True if the column is part of the primary key of this table. Ordinal position (1-based) of the column in the primary key. True if the column uses an autogenerated value.
Closing a Connection
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. 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 closeConnection() method to explicitly close the underlying database connection. Since release 1.7.2, you could check you are currently connected to the RDBMS server with the method isConnected(). This means that a connection resource has been initiated and wasn't closed. This function is not currently able to test for example a server side closing of the connection. This is internally use to close the connection. It allow you to close the connection multiple times without errors. It was already the case before 1.7.2 for PDO adapters but not for the others.
290
Zend_Db
Database connections have state. That is, some objects in the RDBMS server exist in session scope. Ejemplos 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.
291
Zend_Db
IBM DB2
Specify this Adapter to the factory() method with the name 'Db2'. This Adapter uses the PHP extension ibm_db2. IBM DB2 supports both sequences and auto-incrementing keys. Therefore the arguments to lastInsertId() 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 'table_column_seq'.
MySQLi
Specify this Adapter to the factory() method with the name 'Mysqli'. This Adapter utilizes the PHP extension mysqli. MySQL does not support sequences, so lastInsertId() ignores its arguments and always returns the last value generated for an auto-increment key. The lastSequenceId() method returns NULL.
Oracle
Specify this Adapter to the factory() method with the name 'Oracle'. This Adapter uses the PHP extension oci8. Oracle does not support auto-incrementing keys, so you should specify the name of a sequence to lastInsertId() or lastSequenceId(). The Oracle extension does not support positional parameters. You must use named parameters. Currently the Zend_Db::CASE_FOLDING option is not supported by the Oracle adapter. To use this option with Oracle, you must use the PDO OCI adapter. By default, LOB fields are returned as OCI-Lob objects. You could retrieve them as string for all requests by using driver options 'lob_as_string' or for particular request by using setLobAsString(boolean) on adapter or on statement.
292
Zend_Db
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 Microsoft's Knowledge Base [http://support.microsoft.com/kb/232580] for more information. Zend_Db_Adapter_Pdo_Mssql sets QUOTED_IDENTIFIER ON immediately after connecting to a SQL Server database. This makes the driver use the standard SQL identifier delimiter symbol (") instead of the proprietary square-brackets syntax SQL Server uses for delimiting identifiers. You can specify pdoType 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 FreeTDS [http://www.freetds.org/] set of libraries. See also http://www.php.net/manual/en/ref.pdo-dblib.connection.php [http://www.php.net/manual/en/ ref.pdo-dblib.connection.php] for more information on the DSN prefixes used in this driver.
PDO MySQL
Specify this Adapter to the factory() method with the name 'Pdo_Mysql'. This Adapter uses the PHP extensions pdo and pdo_mysql. MySQL does not support sequences, so lastInsertId() ignores its arguments and always returns the last value generated for an auto-increment key. The lastSequenceId() method returns NULL.
PDO Oracle
Specify this Adapter to the factory() method with the name 'Pdo_Oci'. This Adapter uses the PHP extensions pdo and pdo_oci. Oracle does not support auto-incrementing keys, so you should specify the name of a sequence to lastInsertId() or lastSequenceId().
PDO PostgreSQL
Specify this Adapter to the factory() method with the name 'Pdo_Pgsql'. This Adapter uses the PHP extensions pdo and pdo_pgsql. PostgreSQL supports both sequences and auto-incrementing keys. Therefore the arguments to lastInsertId() 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 'table_column_seq'.
PDO SQLite
Specify this Adapter to the factory() method with the name 'Pdo_Sqlite'. This Adapter uses the PHP extensions pdo and pdo_sqlite. SQLite does not support sequences, so lastInsertId() ignores its arguments and always returns the last value generated for an auto-increment key. The lastSequenceId() method returns NULL. To connect to an SQLite2 database, specify 'sqlite2'=>true in the array of parameters when creating an instance of the Pdo_Sqlite Adapter.
293
Zend_Db
To connect to an in-memory SQLite database, specify 'dbname'=>':memory:' in the array of parameters when creating an instance of the Pdo_Sqlite Adapter. 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.
Firebird/Interbase
This Adapter uses the PHP extension php_interbase. Firebird/interbase does not support auto-incrementing keys, so you should specify the name of a sequence to lastInsertId() or lastSequenceId(). Currently the Zend_Db::CASE_FOLDING option is not supported by the Firebird/interbase adapter. Unquoted identifiers are automatically returned in upper case. Adapter name is ZendX_Db_Adapter_Firebird. Remember to use the param adapterNamespace with value ZendX_Db_Adapter. We recommend to update the gds32.dll (or linux equivalent) bundled with php, to the same version of the server. For Firebird the equivalent gds32.dll is fbclient.dll. By default all identifiers (tables names, fields) are returned in upper case.
Zend_Db_Statement
Adems de algunos mtodos convenientes tales como fetchAll() e insert() documentados en the section called Zend_Db_Adapter, puede usarse un objeto de declaracin para obtener ms opciones al ejecutar consultas y devolver conjuntos de resultados. Esta seccin describe cmo obtener una instancia de un objeto de declaracin y cmo usar sus mtodos. Zend_Db_Statement est basado en el objeto PDOStatement en la extensin PHP Data Objects [http:// www.php.net/pdo].
294
Zend_Db
Puede crear una declaracin con su constructor, pero ste es un uso menos tpico. No hay un mtodo factory para crear el objeto, as que es necesario cargar una clase de declaracin especfica y llamar a su constructor. Pase el objeto Adaptador como el primer parmetro, y un string conteniendo la declaracin SQL como el segundo parmetro. La declaracin es preparada pero no ejecutada.
Ejecutando la declaracin
Necesita ejecutar un objeto de declaracin si lo crea con el constructor, o si desea ejecutar la misma declaracin varias veces. Use el mtodo execute() del mismo objeto de declaracin. El nico parmetro es un array de valores a vincular a posiciones de parmetros en la declaracin. Si usa parmetros posicionales, o los que estn marcados por un signo de interrogacin (?), pase los valores de vinculacin en un array plano.
295
Zend_Db
resultados. Puede ejecutar las ltimas declaraciones de SQL usando Zend_Db_Statement, pero no puede llamar a los mtodos que extraen filas de resultados desde ste.
296
Zend_Db
para establecer el modo de extraccin. Especifique el modo de extraccin usando las constantes de la clase Zend_Db: FETCH_ASSOC, FETCH_NUM, FETCH_BOTH, FETCH_COLUMN, and FETCH_OBJ. Vea the section called Changing the Fetch Mode para ms informacin de estos modos. Llamadas subsiguientes a los mtodos de la declaracin fetch() o fetchAll() usan el modo de extraccin especificado.
297
Zend_Db
Zend_Db_Profiler
Introduccin
Zend_Db_Profiler puede ser habilitado para Perfilar las consultas. Los Perfiles incluyen la consulta procesada por el adaptador como el tiempo as transcurrido en la ejecucin de las consultas, permitiendo inspeccionar las consultas realizadas win necesidad de agregar informacin de depuracin extra en el cdigo de las clases. El uso avanzado tambin permite que el desarrollador filtre las consultas que desea perfilar. Habilite el perfilador pasando una directiva al al constructor del adaptador, o pidiendole al adaptador permitirlo ms adelante.
$params = array( 'host' => 'username' => 'password' => 'dbname' => 'profiler' => );
'127.0.0.1', 'webuser', 'xxxxxxxx', 'test' true // enciende el perfilador // establezca false para deshabilitar (est deshabilitado por defec
$db = Zend_Db::factory('PDO_MYSQL', $params); // apagar el perfilador: $db->getProfiler()->setEnabled(false); // encender el perfilador: $db->getProfiler()->setEnabled(true); El valor de la opcin 'profiler' es flexible. Es interpretada de distintas formas dependiendo del tipo. Normalmente, debera usar un valor booleano simple, pero otros tipos le permiten personalizar el comportamiento del perfilador. Un argumento booleano establece el perfilador como habilitado si el valor es true, o deshabilitado si es false. La clase del perfilador es el la clase de perfilador por defecto del adaptador, Zend_Db_Profiler.
$params['profiler'] = true; $db = Zend_Db::factory('PDO_MYSQL', $params); Una instancia del objeto perfilador hace que el adaptador use ese objeto. El tipo del objeto debe ser Zend_Db_Profiler o una subclase de este. Habilitar el perfilador se hace por separado.
$profiler = MyProject_Db_Profiler(); $profiler->setEnabled(true); $params['profiler'] = $profiler; $db = Zend_Db::factory('PDO_MYSQL', $params); El argumento puede ser un array asociativo conteniendo algunas o todas las claves 'enabled', 'instance', y 'class'. Las claves 'enabled' e 'instance' corresponden a los tipos booleano y la instancia documentada previamente. La clave 'class' es usada para nombrar la clase que usar el perfilador personalizado. La clase debe ser Zend_Db_Profiler o una subclase. La clase es instanciada sin argumentos de constructor. La opcin 'class' es ignorada cuando la opcin 'instance' est dada.
298
Zend_Db
$params['profiler'] = array( 'enabled' => true, 'class' => 'MyProject_Db_Profiler' ); $db = Zend_Db::factory('PDO_MYSQL', $params); Finalmente, el argumento puede ser un objeto de tipo Zend_Config conteniendo las propiedades, que son tratadas como las claves de array descritas recin. Por ejemplo, un archivo "config.ini" puede contener los siguientes datos: [main] db.profiler.class = "MyProject_Db_Profiler" db.profiler.enabled = true Esta configuracin puede ser aplicada con el siguiente cdigo PHP: $config = new Zend_Config_Ini('config.ini', 'main'); $params['profiler'] = $config->db->profiler; $db = Zend_Db::factory('PDO_MYSQL', $params); La propiedad 'instance' debe ser usada como el siguiente ejemplo: $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);
Usando el Perfilador
En este punto, obtenemos el perfilador usando el mtodo getProfiler() del adaptador: $profiler = $db->getProfiler(); Este retorna una instancia del objeto Zend_Db_Profiler. Con esta instancia, el desarrollador puede examinar las consultar usando una variedad de mtodos: getTotalNumQueries() retorna el nmero total de consultas que han sido perfiladas. getTotalElapsedSecs() retorna el nmero total de segundos transcurridos en todas las consultas perfiladas. getQueryProfiles() retorna un array con todos los perfiles de consultas. getLastQueryProfile() retorna el ltimo perfil (ms reciente) de consulta, independientemente de si la consulta ha terminado o no (si no lo ha hecho, la hora de finalizacin ser nula). clear() limpia los perfiles de consulta de la pila. El valor de retorno de getLastQueryProfile() y elementos individuales de getQueryProfiles() son Zend_Db_Profiler_Query objetos, que proporcionan la capacidad para inspeccionar cada una de las consultas:
299
Zend_Db
getQuery() retorna el texto SQL de la consulta. El texto SQL de una declaracin preparada con parmetros es el texto al tiempo en que la consulta fu preparada, por lo que contiene marcadores de posicin, no los valores utilizados cuando la declaracin se ejecuta. getQueryParams() retorna un array de los valores de los parmetros usados cuando se ejecuta una consulta preparada. Este incluye ambos parmetros y argumentos vinculados al mtodo execute() de la declaracin. Las claves del array son las posiciones (basado en 1) o indices de parmetros nombrados (string). getElapsedSecs() returna el nmero de segundos que tuvo la consulta al correr. La informacin que Zend_Db_Profiler 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 ejecucin:
$query = $profiler->getLastQueryProfile(); echo $query->getQuery(); Tal vez una pgina se genera lentamente; use el perfilador para determinar primero el nmero total de segundos de todas las consultas, y luego recorrer paso a paso a travs de las consultas para encontrar la ms lenta:
= = = =
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 ms lenta: ' . $longestTime . "\n"; echo "Consulta ms lenta: \n" . $longestQuery . "\n";
300
Zend_Db
// 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);
301
Zend_Db
$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);
Perfiladores Especializados
Un Perfilador Especializado es un objeto que hereda de Zend_Db_Profiler. Los Perfiladores Especializados tratan la informacin de perfilado de maneras ms especificas.
302
Zend_Db
$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();
Zend_Db_Select
Descripcin del Objeto Select
El objeto Zend_Db_Select object representa una declaracin de consulta SELECT de SQL. La clase tiene mtodos para agregar partes individuales a la consulta. Se pueden especificar algunas partes de la consulta usando los mtodos en PHP y sus estructuras de datos, y la clase forma la sintaxis SLQ correcta. Despus de construir la consulta, puede ejecutarla como si se hubiera escrito como un string. Las posibilidades de Zend_Db_Select incluyen: Mtodos Orientados a objetos para especificar consultas SQL pieza-a-pieza; Abstraccin de partes de las consultas SQL, independiente de la Base de datos; Entrecomillado automtico de identificadores de metadatos en la mayora de los casos, soportanto identificadores que contienen palabras reservadas de SQL y caracteres especiales; Entrecomillado de identificadores y valores, para ayudar a reducir el riesgo de ataque por inyeccin SQL. El uso de Zend_Db_Select no es obligatorio. Para consultas SELECT muy simples, es usualmente ms simple especificar la consulta completa como un string y ejecutarla usando un mtodo del Adapter como query() o fetchAll(). Usar Zend_Db_Select es til si se necesita ensamblar una consulta SELECT proceduralmente, o basada en condiciones lgicas en la aplicacin.
303
Zend_Db
$db = Zend_Db::factory( ...options... ); $select = $db->select(); Otra manera de crear el objeto Zend_Db_Select es con su constructor, especificando el adaptador de base de datos como un argumento.
304
Zend_Db
Agregando Columnas
En el segundo argumento del mtodo from(), puede especificar las columnas que seleccionar desde la tabla respectiva. Si no especifica columnas, por defecto ser "*", el comodn SQL para "todas las columnas". Puede 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 necesita especificar un alias de columna, puede listarla solo con un string en lugar de un array.
305
Zend_Db
Si se entrega un array vaco como el argumento de las tablas, no se incluirn columnas en el resultado. Vea un cdigo de ejemplo en la seccin del mtodo join(). Puedes especificar el nombre de columna como "nombreCorrelacionado.nombreDeColumna". Zend_Db_Select entrecomillar cada parte individualmente. Si no especifica un nombre de correlacin para una columna, se usar el nombre de correlacin para la tabla nombrada en el mtodo actual from().
Nota
El Uso de Zend_Db_Expr para nombres de columnas no es necesario si la expresin de la columna contiene parntesis; Zend_Db_Select reconoce y trata el string como expresin, saltndose el entrecomillado y la correlacin de nombres.
306
Zend_Db
// Construya 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)')); // Construya 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)') ); // Construya esta consulta usando Zend_Db_Expr explcitamente: // 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')) ); En los casos anteriores, Zend_Db_Select no altera el string para aplicar correlacin de nombres o entrecomillado de identificadores. Si estos cambios son necesarios para resolver ambigedades, deberas realizar cambios manualmente en el string. Si el nombre de su columna es alguna palabra reservada de SQL o contiene caracteres especiales, debera usar el mtodo quoteIdentifier() del Adapdator e interpolar el resultado en un string. El mtodo quoteIdentifier() 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. Su cdigo es ms independiente de la base de datos si se usa el mtodo quoteIdentifier() en vez de las excribir literalmente las comillas en la cadena, debido a que algunos RDBMS no usan simbolos estndar para entrecomillar identificadores. El mtodo quoteIdentifier() est diseado para usar los smbolos apropiados para entrecomillar basado en el tipo del adaptador. El mtodo quoteIdentifier() tambin escapa cual caracter de comilla que aparezca en el nombre del identificador mismo.
307
Zend_Db
$select = $db->select() ->from(array('p' => 'products'), array('origin' => '(p.' . $db->quoteIdentifier('from') . ' + 10)') );
308
Zend_Db
El segundo argumento join() es un string que es usado como condicin de unin. Esta es una expresin que declara un criterio por el cual las filas en una tabla concuerdan con las filas de la otra tabla. Puedes especificar correlacin de nombres en esta expresin.
Nota
No se aplica entrecomillado en la expresin especificada para la condicin de unin; si tienes problemas con nombres que necesitan ser entrecomillados, debers usar quoteIdentifier() para formar el string de condicin de unin. El tercer argumento join() es un array de nombres de columnas, como al usar el mtodo from(). Este es por defecto "*", soporta correlacin de nombres, expresiones, y Zend_Db_Expr de la misma manera que el array de nombres de columnas en el mtodo from(). Para no seleccionar columnas de una tabla, use un array vaco para la lista de columnas. El uso de esto trabaja con el mtodo from() tambin, 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.
309
Zend_Db
Unin exterior por la derecha es el complementario de la unin exterior por la izquierda. Todas las filas de la tabla a la derecha del operando son incluidas, pareando las filas de la tabla a la izquierda del operando incluidas, y las columnas de la tabla a la izquierda del operando son rellenadas con NULLs si no existen filas que coincidan con la tabla de la derecha. Algunos RDBMS no soportan este tipo de join, pero en general, cualquier unin por la derecha puede representarse por una unin por la izquierda invirtiendo el orden de las tablas. FULL JOIN con el mtodo joinFull(table, condition, [columns]). Una unin externa total es como una combinacin de una unin exterior por la izquierda y una unin exterior por la derecha. Todas las filas de ambas tablas son incluidas, vinculadas entre s en la misma fila si satisfacen la condicin de unin, y en otro caso, se vinculan con valores nulos en lugar de columnas de la otra tabla. Algunos RDBMS no soportan este tipo de unin. CROSS JOIN con el mtodo joinCross(table, [columns]). Una unin cruzada es un Producto Cartesiano. Cada fila en la primera tabla es pareada con cada una en la segunda tabla. Por lo tanto, el nmero de filas en el resultado es igual al producto del nmero de filas en cada tabla. Puede filtrar el conjunto de resultados con el uso de condiciones en un clusula WHERE; de esta forma una unin cruzada es similar a la antigua sintaxis de unin en SQL-89. El mtodo joinCross() no tiene parmetros para especificar una condicin de unin. Algunos RDBMS no soportan este tipo de unin. NATURAL JOIN con el mtodo joinNatural(table, [columns]). Una unin natural compara cualquier columa(s) que aparezca con el nombre en ambas tablas. La comparacin es el equivalente de todas las columna(s); comparando las columnas usando desigualdad no es una unin natural. Solo la unin interna natural es soportada por este API, aun cuando SQL permita una unin externa natural. El mtodo joinNatural() no tiene parmetros para especificar una condicin. Adems de los mtodos de unin, puede simplificar las consultas usando mtodos JoinUsing. En vez de proveer una condicin completa a la unin, simplemente pase el nombre de columna en la que se har la unin y el objeto Zend_Db_Select completa la condicin.
310
Zend_Db
joinUsing(table, join, [columns]) y joinInnerUsing(table, join, [columns]) joinLeftUsing(table, join, [columns]) joinRightUsing(table, join, [columns]) joinFullUsing(table, join, [columns])
Nota
No se aplica entrecomillado en una expresin dada en el mtodo where() u orWhere(). Si tiene nombres de columnas que necesitan ser entrecomillados, debe usar el mtodo quoteIdentifier() para formar el string de la condicin. El segundo argumento del mtodo where() es opcional. Es un valor para sustituir en la expresin. Zend_Db_Select entrecomilla el valor y lo sustituye por un signo de interrogacin ("?") en la expresin. Este mtodo acepta solo un parmetro. Si tiene una expresin en la cual necesita sustituir mltiples variables, deber formar el string manualmente, interpolando variables y realizando entrecomillado manualmente.
311
Zend_Db
312
Zend_Db
$prod = 'Apple'; $select = $db->select() ->from('products', array('product_id', 'product_name', 'price')) ->where("price < $minimumPrice OR price > $maximumPrice") ->where('product_name = ?', $prod); En el ejemplo anterior, los resultados deberan ser diferentes sin parntesis, porque AND tiene precedencia ms alta respecto a OR. Zend_Db_Select aplica el parentesis con un efecto tal que la expresin en sucesivas llamadas al mtodo where() vincula de forma ms fuerte el AND que combina las expresiones.
313
Zend_Db
Nota
No se aplica entrecomillado a expresiones dadas al mtodo having() u orHaving(). Si tiene nombres de columnas que deban ser entrecomillados, deber usar quoteIdentifier() para formar el string de la condicin.
314
Zend_Db
Nota
La sintaxis de LIMIT no est soportada por todos los RDBMS brands. Algunos RDBMS requieren diferente sintaxis para soportar una funcionalidad similar Cada clase Zend_Db_Adapter_Abstract incluye un mtodo para producir el SQL apropiado para cada RDBMS. Use el mtodo limitPage() como un modo alternativo de especificar la cantidad de filas y el offset. Este mtodo permite limitar el conjunto resultado a una serie de subconjuntos de tamao fijo de filas del total del resultado de la consulta. En otras palabras, puede especificar el tamao de una "pgina" de resultados, y el nmero ordinal de la pgina simple donde se espera que devuelva la consulta. El nmero de pgina es el primer argumento del mtodo limitPage(), y la longitud de la pgina es el segundo argumento. Ambos son argumentos requeridos; no tienen valores por omisin.
315
Zend_Db
->limitPage(2, 10);
Ejemplo 15.71. Ejemplo usando el mtodo adaptador query() del Adaptador de Base de datos
$select = $db->select() ->from('products'); $stmt = $db->query($select); $result = $stmt->fetchAll();
316
Zend_Db
Otros Mtodos
Esta seccin describe otros mtodos de Zend_Db_Select que no han sido cubiertos antes: getPart() y reset().
317
Zend_Db
318
Zend_Db
$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();
Zend_Db_Table
Introduction
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. The Zend_Db_Table solution is an implementation of the Tabla Data Gateway [http://www.martinfowler.com/ eaaCatalog/tableDataGateway.html] pattern. The solution also includes a class that implements the Row Data Gateway [http://www.martinfowler.com/eaaCatalog/rowDataGateway.html] pattern.
319
Zend_Db
class bugs extends Zend_Db_Table_Abstract { // table name matches class name } You can also declare the schema for the table, either with the protected variable $_schema, or with the schema prepended to the table name in the $_name property. Any schema specified with the $_name property takes precedence over a schema specified with the $_schema property. In some RDBMS brands, the term for schema is "database" or "tablespace," but it is used similarly.
320
Zend_Db
// 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')); If you don't specify the schema name, it defaults to the schema to which your database adapter instance is connected.
Nota
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 describeTable(), then the table cannot be used with Zend_Db_Table.
321
Zend_Db
_setupTableName() 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. _setupMetadata() sets the schema if the table name contains the pattern "schema.table"; calls describeTable() to get metadata information; defaults the $_cols array to the columns reported by describeTable(). By overriding this method, you can specify the columns. _setupPrimaryKey() defaults the primary key columns to those reported by describeTable(); checks that the primary key columns are included in the $_cols array. By overriding this method, you can specify the primary key columns.
Tabla initialization
If application-specific logic needs to be initialized when a Table class is constructed, you can select to move your tasks to the init() method, which is called after all Table metadata has been processed. This is recommended over the __construct method if you do not need to alter the metadata in any programmatic way.
322
Zend_Db
application. You can do this with the static method Zend_Db_Table_Abstract::setDefaultAdapter(). The argument is an object of type Zend_Db_Adapter_Abstract.
323
Zend_Db
$table->insert($data); 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.
324
Zend_Db
If you define $_sequence 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 INSERT operation.
Nota
All RDBMS brands support tables with natural keys. Ejemplos 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.
325
Zend_Db
$where = $table->getAdapter()->quoteInto('bug_id = ?', 1234); $table->update($data, $where); Since the table update() method proxies to the database adapter update() method, the second argument can be an array of SQL expressions. The expressions are combined as Boolean terms using an AND operator.
Nota
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 quote(), quoteInto(), and quoteIdentifier() methods of the database adapter.
Nota
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 quote(), quoteInto(), and quoteIdentifier() methods of the database adapter.
326
Zend_Db
$rows = $table->find(1234); // Find multiple rows // Also returns a Rowset $rows = $table->find(array(1234, 5678)); 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. The find() 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 find() method returns an object of type Zend_Db_Table_Rowset_Abstract. 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 find() method. You must provide as many arguments as the number of columns in the table's primary key. 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.
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'));
327
Zend_Db
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.
// 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')); The Zend_Db_Table_Select object is an extension of the Zend_Db_Select object that applies specific restrictions to a query. The enhancements and restrictions are: You can 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. You can specify columns that evaluate expressions from within the selected table. However this will mean that the returned row or rowset will be readOnly and cannot be used for save() operations. A Zend_Db_Table_Row with readOnly status will throw an exception if a save() operation is attempted. You can allow JOIN clauses on a select to allow multi-table lookups. You can not 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 Zend_Db_Table is retained. i.e. A Zend_Db_Table_Row should only reference columns derived from its parent table.
Fetching a rowset
You can query for a set of rows using any criteria other than the primary key values, using the fetchAll() method of the Table class. This method returns an object of type Zend_Db_Table_Rowset_Abstract.
328
Zend_Db
// 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); 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.
Advanced usage
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.
Important
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.
329
Zend_Db
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.
Ejemplo 15.102. Removing the integrity check on Zend_Db_Table_Select to allow JOINed rows
$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);
330
Zend_Db
$row = $table->fetchRow($select); 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 fetchRow() returns PHP's NULL value.
331
Zend_Db
Ejemplo 15.105. Using a Default Metadata Cache for all Table Objects
The following code demonstrates how to set a default metadata cache to be used for all table objects:
< // First, set up the Cache $frontendOptions = array( 'automatic_serialization' => true ); $backendOptions 'cache_dir' ); = array( => '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 {
332
Zend_Db
// ... } // Each instance of Bugs now uses the default metadata cache $bugs = new Bugs();
// First, set up the Cache $frontendOptions = array( 'automatic_serialization' => true ); $backendOptions 'cache_dir' ); = array( => '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));
333
Zend_Db
'TABLE_NAME' 'COLUMN_NAME' 'COLUMN_POSITION' 'DATA_TYPE' 'DEFAULT' 'NULLABLE' 'LENGTH' 'SCALE' 'PRECISION' 'UNSIGNED' 'PRIMARY' 'PRIMARY_POSITION' 'IDENTITY'
=> => => => => => => => => => => => =>
<string>, <string>, <int>, <string>, NULL|<value>, <bool>, <string - length>, NULL|<value>, NULL|<value>, NULL|<bool>, <bool>, <int>, <bool>,
), // additional columns... ); An easy way to get the appropriate values is to use the metadata cache, and then to deserialize values stored in the cache. You can disable this optimization by turning of the metadataCacheInClass flag:
// At instantiation: $bugs = new Bugs(array('metadataCacheInClass' => false)); // Or later: $bugs->setMetadataCacheInClass(false); The flag is enabled by default, which ensures that the $_metadata array is only populated once per instance.
334
Zend_Db
$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); You can change the classes by specifying them with the setRowClass() and setRowsetClass() 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.
335
Zend_Db
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); } } You can also override the delete() method.
336
Zend_Db
Zend_Db_Table_Abstract performs no inflection to map the class name to the table name. If you omit the declaration of $_name in your table class, the class maps to a database table that matches the spelling of the class name exactly. 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. If you prefer to use inflection, then you must implement the transformation yourself, by overriding the _setupTableName() 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.
Zend_Db_Table_Row
Introduction
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. Zend_Db_Table_Row is an implementation of the Row Data Gateway [http://www.martinfowler.com/eaaCatalog/ rowDataGateway.html] pattern.
Fetching a Row
Zend_Db_Table_Abstract provides methods find() and fetchAll(), which each return an object of type Zend_Db_Table_Rowset, and the method fetchRow(), which returns an object of type Zend_Db_Table_Row.
337
Zend_Db
$bugs = new Bugs(); $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1)); A Zend_Db_Table_Rowset object contains a collection of Zend_Db_Table_Row objects. See the section called Zend_Db_Table_Rowset.
$bugs = new Bugs(); $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1)); // Echo the value of the bug_description column echo $row->bug_description;
Nota
Earlier versions of Zend_Db_Table_Row mapped these column accessors to the database column names using a string transformation called inflection. 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.
$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
338
Zend_Db
foreach ($rowArray as $column => $value) { echo "Column: $column\n"; echo "Value: $value\n"; } The array returned from toArray() 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.
$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();
$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();
339
Zend_Db
The optional argument to the createRow() method is an associative array, with which you can populate fields of the new row.
$data = array( 'bug_description' => '...description...', 'bug_status' => 'NEW' ); $bugs = new Bugs(); $newRow = $bugs->createRow($data); // INSERT the new row to the database $newRow->save();
Nota
The createRow() method was called fetchNew() 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.
$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();
Deleting a row
You can call the delete() method on a Row object. This deletes rows in the database matching the primary key in the Row object.
340
Zend_Db
$bugs = new Bugs(); $row = $bugs->fetchRow('bug_id = 1'); // DELETE this row $row->delete(); You do not have to call save() to apply the delete; it is executed against the database immediately.
Serializing a Row
Simply use PHP's serialize() function to create a string containing a byte-stream representation of the Row object argument.
$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.
$rowClone = unserialize($serializedRow); // Now you can use object properties, but read-only echo $rowClone->bug_description;
341
Zend_Db
$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();
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';
342
Zend_Db
} // Or specify a custom Row to be used in one // instance of a Table class. $bugs = new Bugs(array('rowClass' => 'MyRow'));
Row initialization
If application-specific logic needs to be initialized when a row is constructed, you can select to move your tasks to the init() method, which is called after all row metadata has been processed. This is recommended over the __construct method if you do not need to alter the metadata in any programmatic way.
class MyApplicationRow extends Zend_Db_Table_Row_Abstract { protected $_role; public function init() { $this->_role = new MyRoleClass(); } }
343
Zend_Db
$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(); }
Ejemplo 15.127. Ejemplo of a Row class that logs insert data for multiple tables
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. In this example, the logging code is identical in all table classes.
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'; }
344
Zend_Db
Zend_Db classes do not implement inflection by default. See the section called Define Inflection in Zend_Db_Table for an explanation of this policy. If you prefer to use inflection, then you must implement the transformation yourself, by overriding the _transformColumn() method in a custom Row class, and using that custom Row class when you perform queries against your Table class.
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'; You are responsible for writing the functions to perform inflection transformation. Zend Framework does not provide such a function.
Zend_Db_Table_Rowset
Introduction
When you run a query against a Table class using the find() or fetchAll() methods, the result is returned in an object of type Zend_Db_Table_Rowset_Abstract. A Rowset contains a collection of objects descending from Zend_Db_Table_Row_Abstract. You can iterate through the Rowset and access individual Row objects, reading or modifying data in the Rows.
Fetching a Rowset
Zend_Db_Table_Abstract provides methods find() and fetchAll(), each of which returns an object of type Zend_Db_Table_Rowset_Abstract.
345
Zend_Db
$rowCount = count($rowset); if ($rowCount > 0) { echo "found $rowCount rows"; } else { echo 'no rows matched the query'; }
$bugs = new Bugs(); $rowset = $bugs->fetchAll("bug_id = 1"); $row = $rowset->current(); If the Rowset contains zero rows, current() returns PHP's NULL value.
$bugs = new Bugs(); // fetch all records from the table $rowset = $bugs->fetchAll(); foreach ($rowset as $row) {
346
Zend_Db
// 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(); }
$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); // retrieve it $row9 = $rowset->current(); // and use it $row9->assigned_to = 'mmouse'; $row9->save(); getRow() 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 getRow() 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 :
$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();
347
Zend_Db
After you have access to an individual Row object, you can manipulate the Row using methods described in the section called Zend_Db_Table_Row.
$bugs = new Bugs(); $rowset = $bugs->fetchAll(); // Convert object to serialized form $serializedRowset = serialize($rowset); // Now you can write $serializedRowset to a file, etc.
348
Zend_Db
Note that the Rowset object returned is in a disconnected 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).
$rowsetDisconnected = unserialize($serializedRowset); // Now you can use object methods and properties, but read-only $row = $rowsetDisconnected->current(); echo $row->bug_description;
349
Zend_Db
// ...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')); 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.
Zend_Db_Table Relationships
Introduction
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.
350
Zend_Db
The Zend_Db_Table_Row class has methods for querying related rows in other tables.
Defining Relationships
Define classes for each of your tables, extending the abstract class Zend_Db_Table_Abstract, as described in the section called Defining a Table Class. Also see the section called La base de datos de ejemplo for a description of the example database for which the following example code is designed. Below are the PHP class definitions for these tables:
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 'Reporter' => array( 'columns' 'refTableClass' 'refColumns' ), 'Engineer' => array( 'columns' 'refTableClass' 'refColumns' ), 'Verifier' => array( 'columns' 'refTableClass' 'refColumns' ) ); } class BugsProducts extends Zend_Db_Table_Abstract { protected $_name = 'bugs_products'; protected $_referenceMap 'Bug' => array( = array( = array( => 'reported_by', => 'Accounts', => 'account_name'
351
Zend_Db
If you use Zend_Db_Table to emulate cascading UPDATE and DELETE operations, declare the $_dependentTables 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.
Nota
Skip declaration of $_dependentTables if you use referential integrity constraints in the RDBMS server to implement cascading operations. See the section called Cascading Write Operations for more information. Declare the $_referenceMap 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. The rule key is a string used as an index to the $_referenceMap 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. In the example PHP code above, the rule keys in the Bugs table class are: 'Reporter', 'Engineer', 'Verifier', and 'Product'. The value of each rule entry in the $_referenceMap array is also an associative array. The elements of this rule entry are described below: columns => A string or an array of strings naming the foreign key column name(s) in the dependent table. It's common for this to be a single column, but some tables have multi-column keys. refTableClass => The class name of the parent table. Use the class name, not the physical name of the SQL table. 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 bugs table to the products table, but three references from the bugs table to the accounts table. Put each reference in a separate entry in the $_referenceMap array. refColumns => A string or an array of strings naming the primary key column name(s) in the parent table. 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 'columns' entry must match the order of columns in the 'refColumns' entry. It is optional to specify this element. If you don't specify the refColumns, the column(s) reported as the primary key columns of the parent table are used by default.
352
Zend_Db
onDelete => The rule for an action to execute if a row is deleted in the parent table. See the section called Cascading Write Operations for more information. onUpdate => The rule for an action to execute if values in primary key columns are updated in the parent table. See the section called Cascading Write Operations for more information.
353
Zend_Db
$accountsTable = new Accounts(); $accountsRowset = $accountsTable->find(1234); $user1234 = $accountsRowset->current(); $select = $accountsTable->select()->order('name ASC') ->limit(3); $bugsAssignedToUser = $user1234->findDependentRowset('Bugs', 'Engineer', $select); 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: findDependentRowset('<TableClass>', '<Rule>') if you invoke a method on the Row object matching either of the following patterns: $row->find<TableClass>() $row->find<TableClass>By<Rule>() In the patterns above, <TableClass> and <Rule> are strings that correspond to the class name of the dependent table, and the dependent table's rule key that references the parent table.
Nota
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.
$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();
$row->findParentRow($table, [$rule]); 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.
354
Zend_Db
The first argument $table 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.
$bugsTable = new Bugs(); $bugsRowset = $bugsTable->fetchAll(array('bug_status = ?' => 'NEW')); $bug1 = $bugsRowset->current(); $reporter = $bug1->findParentRow('Accounts'); The second argument $rule is optional. It is a string that names the rule key in the $_referenceMap 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. 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 'Reporter'.
$bugsTable = new Bugs(); $bugsRowset = $bugsTable->fetchAll(array('bug_status = ?', 'NEW')); $bug1 = $bugsRowset->current(); $engineer = $bug1->findParentRow('Accounts', 'Engineer'); Alternatively, you can query rows from a parent table using a "magic method". Zend_Db_Table_Row_Abstract invokes the method: findParentRow('<TableClass>', '<Rule>') if you invoke a method on the Row object matching either of the following patterns: $row->findParent<TableClass>([Zend_Db_Table_Select $select]) $row->findParent<TableClass>By<Rule>([Zend_Db_Table_Select $select]) In the patterns above, <TableClass> and <Rule> are strings that correspond to the class name of the parent table, and the dependent table's rule key that references the parent table.
Nota
The table identity and the rule key named in the method call must match the spelling of the class and rule key exactly.
Ejemplo 15.146. Fetching the Parent Row using the Magic Method
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.
355
Zend_Db
$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();
$row->findManyToManyRowset($table, $intersectionTable, [$rule1, [$rule2, [Zend_Db_Table_Select $select] ] ]); This method returns a Zend_Db_Table_Rowset_Abstract containing rows from the table $table, satisfying the many-to-many relationship. The current Row object $row from the origin table is used to find rows in the intersection table, and that is joined to the destination table. The first argument $table 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. The second argument $intersectionTable 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.
$bugsTable = new Bugs(); $bugsRowset = $bugsTable->find(1234); $bug1234 = $bugsRowset->current(); $productsRowset = $bug1234->findManyToManyRowset('Products', 'BugsProducts'); The third and fourth arguments $rule1 and $rule2 are optional. These are strings that name the rule keys in the $_referenceMap array of the intersection table. The $rule1 key names the rule for the relationship from the intersection table to the origin table. In this example, this is the relationship from BugsProducts to Bugs.
356
Zend_Db
The $rule2 key names the rule for the relationship from the intersection table to the destination table. In this example, this is the relationship from Bugs to Products. 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 $_referenceMap 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. 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, $rule1 is 'Reporter' and $rule2 is 'Product'.
Ejemplo 15.148. Fetching a Rowset with the Many-to-many Method By a Specific Rule
This example shows geting a Row object from from the origin table Bugs, and finding rows from the destination table Products, representing products related to that bug.
$bugsTable = new Bugs(); $bugsRowset = $bugsTable->find(1234); $bug1234 = $bugsRowset->current(); $productsRowset = $bug1234->findManyToManyRowset('Products', 'BugsProducts', 'Bug'); 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: findManyToManyRowset('<TableClass>', '<IntersectionTableClass>', '<Rule1>', '<Rule2>') if you invoke a method matching any of the following patterns: $row->find<TableClass>Via<IntersectionTableClass> $select]) ([Zend_Db_Table_Select
$row->find<TableClass>Via<IntersectionTableClass>By<Rule1> ([Zend_Db_Table_Select $select]) $row->find<TableClass>Via<IntersectionTableClass>By<Rule1>And<Rule2> ([Zend_Db_Table_Select $select]) In the patterns above, <TableClass> and <IntersectionTableClass> are strings that correspond to the class names of the destination table and the intersection table, respectively. <Rule1> and <Rule2> are strings that correspond to the rule keys in the intersection table that reference the origin table and the destination table, respectively.
Nota
The table identities and the rule keys named in the method call must match the spelling of the class and rule key exactly.
357
Zend_Db
$bugsRowset = $bugsTable->find(1234); $bug1234 = $bugsRowset->current(); // Use the default reference rule $products = $bug1234->findProductsViaBugsProducts(); // Specify the reference rule $products = $bug1234->findProductsViaBugsProductsByBug();
$productsTable = new Products(); $productsRowset = $productsTable->find(1234); $product1234 = $productsRowset->current(); $product1234->delete(); // Automatically cascades to Bugs table // and deletes dependent rows. Similarly, if you use UPDATE 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. 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 natural key that may change value occasionally, it is more likely that you need to apply cascading updates to dependent tables. To declare a cascading relationship in the Zend_Db_Table, edit the rules in the $_referenceMap. Set the associative array keys 'onDelete' and 'onUpdate' to the string 'cascade' (or the constant self::CASCADE). 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.
358
Zend_Db
359
Zend_Db
There is no support for a cascading INSERT. You must insert a row to a parent table in one operation, and insert row(s) to a dependent table in a separate operation.
Zend_Db_Table_Definition
Introduction
Zend_Db_Table_Definition is a class that can be used to describe the relationships and configuration options that should be used when Zend_Db_Table is used via concrete instantiation.
Basic Usage
For all of the same options that are available when configuring an extended Zend_Db_Table_Abstract class, those options are also available when describing a definition file. This definition file should be passed to the class at instantiation time so that it can know the full definition of all tables in said definition. Below is a definition that will describe the table names and relationships between table objects. Note: if 'name' is left out of the definition, it will be taken as the key of the defined table (an example of this is in the 'genre' section in the example below.)
360
Zend_Db
) )); As you can see, the same options you'd generally see inside of an extended Zend_Db_Table_Abstract class are documented in this array as well. When passed into Zend_Db_Table constructor, this definition is persisted to any tables it will need to create in order to return the proper rows. Below is an example of the primary table instantiation as well as the findDependentRowset() and findManyToManyRowset() calls that will correspond to the data model described above:
Advanced Usage
Sometimes you want to use both paradigms for defining and using the table gateway: both by extension and concrete instantiation. To do this simply leave out any table configurations out of the definition. This will allow Zend_Db_Table to look for the actual refered class instead of the definition key. Building on the example above, we will allow for one of the table configurations to be a Zend_Db_Table_Abstract extended class, while keeping the rest of the tables as part of the definition. We will also show how one would interact with this new definition.
361
Zend_Db
'refTableClass' => 'author', 'refColumns' => 'id' ) ); } $definition = new Zend_Db_Table_Definition(array( 'author' => array( 'name' => 'author', 'dependentTables' => array('MyBook') ), 'genre' => null, 'book_to_genre' => array( 'referenceMap' => array( 'book' => array( 'columns' => 'book_id', 'refTableClass' => 'MyBook', 'refColumns' => 'id' ), 'genre' => array( 'columns' => 'genre_id', 'refTableClass' => 'genre', 'refColumns' => 'id' ) ) ) )); $authorTable = new Zend_Db_Table('author', $definition); $authors = $authorTable->fetchAll(); foreach ($authors as $author) { echo $author->id . ': ' . $author->first_name . ' ' . $author->last_name . PHP_EOL; $books = $author->findDependentRowset(new MyBook()); foreach ($books as $book) { echo ' Book: ' . $book->title . PHP_EOL; $genreOutputArray = array(); $genres = $book->findManyToManyRowset('genre', 'book_to_genre'); foreach ($genres as $genreRow) { $genreOutputArray[] = $genreRow->name; } echo ' Genre: ' . implode(', ', $genreOutputArray) . PHP_EOL; } }
362
Zend_Debug::dump($var, $label=null, $echo=true); El argumento $var especifica la expresin o variable sobre la cual el mtodo Zend_Debug::dump() generar informacin. El argumento boleano $echo especifica si la salida de Zend_Debug::dump() es o no mostrada. Si es verdadera, la salida es mostrada. A pesar del valor del argumento $echo, el retorno de este mtodo contiene la salida. Puede ser til comprender que el mtodo Zend_Debug::dump() envuelve la funcin de PHP var_dump() [http://php.net/var_dump]. Si el flujo de salida es detectado como una presentacin de la web, la salida de var_dump() es escapada usando htmlspecialchars() [http://php.net/htmlspecialchars] y envuelta con el tag (X)HTML pre.
363
364
{ identifier: '<name>', <label: '<label>',> items: [ { name: '...', label: '...', someKey: '...' }, ... ] } Zend_Dojo_Data ofrece una interfaz simple para la construccin de estas estructuras programticamente, interactuando con ellos, y serializndolos a un array o a JSON.
Uso de Zend_Dojo_Data
En su forma ms simple, dojo.data requiere que se proporcione el nombre del campo identificador en cada item, y un conjunto de items (datos). Puede pasarlos tanto via el constructor, o via mutators:
365
Zend_Dojo
366
Zend_Dojo
// Establece el "numRows" a 100 $data->setMetadata('numRows', 100); // Establece varios items a la vez: $data->setMetadata(array( 'numRows' => 100, 'sort' => 'name', )); // Inspecciona un nico valor de metadatos: $numRows = $data->getMetadata('numRows'); // Inspecciona todos los metadatos: $metadata = $data->getMetadata(); // Elimina un item de metadatos: $data->clearMetadata('numRows'); // Elimina todos los metadatos: $data->clearMetadata();
// Usando getItem(): $item = $data->getItem('foo'); // O usando notacin de array: $item = $data['foo']; Si conoce el identificador, puede utilizarlo para recuperar un item, actualizarlo, borrarlo, crearlo, o probarlo:
367
Zend_Dojo
// Actualizar o crear un item: $data['foo'] = array('title' => 'Foo', 'email' => 'foo@foo.com'); // Borrar un item: unset($data['foo']); // Efectuar una prueba para un item: if (isset($data[foo])) { } Tambin puede hacer un loop sobre todos los items. Internamente, todos los items se almacenan como arrays. foreach ($data as $item) { echo $item['title'] . ': ' . $item['description'] . "\n"; } O inclusive contar para ver cuntos tems tiene: echo count($data), " items encontrados!"; Por ltimo, como la clase implementa __toString(), tambin puede convertirlo a JSON simplemente con "echo" de PHP o convertirlo a string: echo $data; // echo como un string JSON $json = (string) $data; // conversin a string == conversin a JSON
Mtodos Disponibles
Adems de los mtodos necesarios para aplicar las interfaces enumeradas anteriormente, estn disponibles los siguientes mtodos. setItems($items): establece varios items a la vez, sobrescribiendo cualquier item que figurase anteriormente en el objeto. $items debe ser un array o un objeto Traversable. setItem($item, $id = null): establece un item individual, opcionalmente puede pasar un identificador explcito. Sobreescribe el item si ya existe en la coleccin. Los items vlidos incluyen a arrays asociativos, objetos implementando toArray(), o cualquier objeto con propiedades pblicas. addItem($item, $id = null): aade un item individual, opcionalmente puede pasar un identificador explcito. Generar una excepcin si el item ya existe en la coleccin. Los items vlidos incluyen a arrays asociativos, objetos implementando toArray(), o cualquier objeto con propiedades pblicas. addItems($items): agrega mltiples items a la vez, aadiendolos a cualquiera de los items actuales. Generar una excepcin si alguno de los nuevos items tiene un identificador concordante a un identificador ya existente en la coleccin. $items debe ser un array o un objeto Traversable. getItems(): recupera todos los items como un array de arrays. hasItem($id): determina si un item con el identificador dado existe en la coleccin. getItem($id): recupera un item con el identificador dado de la coleccin; el item retornado ser un array asociativo. Si ningn item coincide, se devolver un valor null.
368
Zend_Dojo
removeItem($id): elimina de la coleccin un item con el identificador dado. clearItems(): elimina todos los items de la coleccin. setIdentifier($identifier): establece el nombre del campo que representa el identificador nico para cada item en la coleccin. getIdentifier(): recupera el nombre del campo identificador. setLabel($label): establece el nombre de un campo para ser utilizado como la etiqueta a mostrar para un item. getLabel(): recupera la etiqueta del nombre del campo. toArray(): enviar el objeto a un array. Como mnimo, el array contendr las claves 'identifier', 'items', y 'label' si una etiqueta de campo ha sido establecida en el objeto. toJson(): enviar el objeto a una representacin JSON.
$view->addHelperPath('Zend/Dojo/View/Helper/', 'Zend_Dojo_View_Helper'); Alternativamente, puede usar el mtodo de Zend_Dojo enableView() para que haga el trabajo por usted:
Zend_Dojo::enableView($view);
369
Zend_Dojo
$view->addHelperPath('Zend/Dojo/View/Helper/', 'Zend_Dojo_View_Helper'); El paso siguiente, el view script. En este caso, vamos a especificar que vamos a estar utilizando un FilteringSelect -- que consumir un almacn personalizado basado en QueryReadStore, al que llamamos 'PairedStore' y almacenado en nuestro mdulo 'custom'.
<?php // establecer el data store para FilteringSelect ?> <div dojoType="custom.PairedStore" jsId="stateStore" url="/data/autocomplete/type/state/format/ajax" requestMethod="get"></div> <?php // Elemento de entrada: ?> State: <input id="state" dojoType="dijit.form.FilteringSelect" store="stateStore" pageSize="5" /> <?php // establecer elementos requeridos por dojo: $this->dojo()->enable() ->setDjConfigOption('parseOnLoad', true) ->registerModulePath('custom', '../custom/') ->requireModule('dijit.form.FilteringSelect') ->requireModule('custom.PairedStore'); ?> En nuestro script de esquema, vamos entonces a comprobar si Dojo est habilitado, y si es as, haremos algunas configuraciones ms generales y lo ensamblaremos:
<?php echo $this->doctype() ?> <html> <head> <?php echo $this->headTitle() ?> <?php echo $this->headMeta() ?> <?php echo $this->headLink() ?> <?php echo $this->headStyle() ?> <?php if ($this->dojo()->isEnabled()){ $this->dojo()->setLocalPath('/js/dojo/dojo.js') ->addStyleSheetModule('dijit.themes.tundra'); echo $this->dojo(); } ?> <?php echo $this->headScript() ?>
370
Zend_Dojo
</head> <body class="tundra"> <?php echo $this->layout()->content ?> <?php echo $this->inlineScript() ?> </body> </html> En este punto, slo necesita asegurarse de que sus archivos estn en el lugar correcto y que ha creado el punto final de accin para su FilteringSelect!
Temas
Dojo permite la creacin de los temas de su dijits (widgets). Puede seleccionar uno pasndolo en un path de mdulo: $view->dojo()->addStylesheetModule('dijit.themes.tundra');
371
Zend_Dojo
La ruta del mdulo es descubierta por utilizar el carcter '.' como separador de directorio y utilizando el ltimo valor en la lista como el nombre del archivo CSS en ese directorio del tema a usar; en el ejemplo de arriba, Dojo buscar el tema en 'dijit/themes/tundra/tundra.css'. Cuando se utiliza un tema, es importante recordar pasar la calse del tema a, por lo menos un contenedor rodeando cualquier dijits que se utilice; el caso de uso ms comn es pasrselo en el body: <body class="tundra">
Mtodos Disponibles
El ayudante de vista dojo() siempre devuelve una instancia del contenedor del marcador de posicin dojo. Ese objeto contenedor dispone de los siguientes mtodos: setView(Zend_View_Interface $view): establecer una instancia de vista en el contenedor. enable(): habilitar explcitamente la integracin de Dojo. disable(): deshabilitar la integracin de Dojo. isEnabled(): determinar cundo la integracin de Dojo est habilitada o no. requireModule($module): establecer una sentencia dojo.require getModules(): determinar qu mdulos han sido requeridos. registerModulePath($module, $path): registrar un path de un mdulo personalizado de Dojo.
372
Zend_Dojo
getModulePaths(): obtener la lista de los paths de mdulos registrados. addLayer($path): aadir una capa (construccin personalizada) del path a utilizar. getLayers(): conseguir una lista de todos los paths de capas registrados (construccin personalizada). removeLayer($path): eliminar la capa que concuerde con $path de la lista de capas registradas (construccin personalizada). setCdnBase($url): establecer la URL base para un CDN; tpicamente, una de las Zend_Dojo::CDN_BASE_AOL o Zend_Dojo::CDN_BASE_GOOGLE, pero slo necesita ser el string del URL antes del nmero de versin. getCdnBase(): recuperar el CDN de la url base a utilizar. setCdnVersion($version = null): establecer cul es la versin de Dojo a utilizar desde el CDN. getCdnVersion(): recuperar que versin de Dojo ser utilizada desde el CDN. setCdnDojoPath($path): establecer el path relativo a un archivo dojo.js o dojo.xd.js sobre un CDN; tpicamente, uno de los Zend_Dojo::CDN_DOJO_PATH_AOL o Zend_Dojo::CDN_DOJO_PATH_GOOGLE, pero slo debe ser el string del path detrs del nmero de versin. getCdnDojoPath(): recuperar el ltimo segmento del path del CDN de la url apuntando al archivo dojo.js. useCdn(): decirle al contenedor que utilice el CDN; implcitamente permite integracin. setLocalPath($path): decirle al contenedor el path a una instalacin local de Dojo (deber ser una ruta relativa al servidor, y contener el propio archivo dojo.js); implcitamente permite integracin. getLocalPath(): determinar qu ruta local a Dojo est siendo utilizada. useLocalPath(): la integracin est utilizando un path local de Dojo? setDjConfig(array $config): conjunto de valores de configuracin dojo/dijit (espera un array asociativo). setDjConfigOption($option, $value): establecer un nico valor de configuracin para dojo/dijit. getDjConfig(): obtener todos los valores de configuracin de dojo/dijit. getDjConfigOption($option, $default = null): conseguir un nico valor de configuracin de dojo/dijit. addStylesheetModule($module): agregar una hoja de estilo sobre la base del tema de un mdulo. getStylesheetModules(): obtener hojas de estilo registradas como temas de mdulos. addStylesheet($path): agregar una hoja de estilo local para su uso con Dojo. getStylesheets(): obtener hojas de estilo locales Dojo. addOnLoad($spec, $function = null): agregar un lambda para dojo.onLoad para llamadas. Si se pasa un argumento, se supone que que puede ser tanto el nombre de una funcin o dar por terminado javascript. Si se pasan dos argumentos, el primero se supone que es el nombre de la variable de la instancia de un objeto y el segundo ya sea un nombre de mtodo en ese objeto o un cierre a utilizar con ese objeto. prependOnLoad($spec, $function = null): exactamente como addOnLoad(), excluyendo agregar al principio el comienzo de onLoad stack.
373
Zend_Dojo
getOnLoadActions(): recuperar todas las acciones dojo.onLoad registradas con el contenedor. Esto ser un array de arrays. onLoadCaptureStart($obj = null): capturar los datos que se utilizarn como lambda para dojo.onLoad(). Si se provee $obj, los cdigos JS capturados sern considerados un cierre a utilizar con ese objeto Javascript. onLoadCaptureEnd($obj = null): finalizar la captura de datos para su uso con dojo.onLoad(). javascriptCaptureStart(): captura javascript arbitrario para ser incluido en Dojo JS (onLoad, require, etc. statements). javascriptCaptureEnd(): finalizar la captura de javascript. __toString(): emitir el contenedor a un string; muestra todo el estilo HTML y elementos del script.
374
Zend_Dojo
Elementos del Form: stos estn diseados para ser consumidos con Zend_Form, pero pueden ser utilizados standalone tambin en sus scripts de vista. Cada elemento de ayudante de vista dijit espera los siguientes argumentos: $id: el nombre del elemento o el DOM ID. $value (opcional): el valor actual de ese elemento. $params (opcional): parmetros especficos de dijit. Bsicamente, cualquier atributo no HTML que pueda utilizarse para configurar un dijit. $attribs (opcional): cualquiera de los otros atributos adicionales HTML que deberan ser utilizados para mostrar el dijit. Si se pasa la clave 'id' en este array, ser utilizado por el elemento DOM id del form, y $id ser utilizado por su nombre. Algunos de los elementos requieren ms argumentos; esto se observ con el elemento individual ayudante de descripciones. Con el fin de utilizar estos ayudantes de vista, necesita registrar el path a los ayudantes de vista dojo con su objeto vista.
<?php echo $view->accordionContainer( 'foo', $content, array( 'duration' => 200, ), array( 'style' => 'width: 200px; height: 300px;', ), ); ?> AccordionPane: dijit.layout.AccordionPane. Para su uso en AccordionContainer.
375
Zend_Dojo
$content, array( 'title' => 'Pane Title', ), array( 'style' => 'background-color: lightgray;', ), ); ?> BorderContainer: dijit.layout.BorderContainer. Logra diseos con cuadros opcionalmente redimensionables como se puede ver en una aplicacin tradicional.
<?php echo $view->borderContainer( 'foo', $content, array( 'design' => 'headline', ), array( 'style' => 'width: 100%; height: 100%', ), ); ?> ContentPane: dijit.layout.ContentPane. Usarlo dentro de cualquier contenedor excepto AccordionContainer.
<?php echo $view->contentPane( 'foo', $content, array( 'title' => 'Pane Title', 'region' => 'left', ), array( 'style' => 'width: 120px; background-color: lightgray;', ), ); ?> SplitContainer: dijit.layout.SplitContainer. Permite cuadros de contenido redimensionables, discontinuado en Dojo en favor de BorderContainer.
<?php echo $view->splitContainer( 'foo', $content, array( 'orientation' => 'horizontal', 'sizerWidth' => 7, 'activeSizing' => true, ), array( 'style' => 'width: 400px; height: 500px;', ), ); ?>
376
Zend_Dojo
StackContainer: dijit.layout.StackContainer. Todos los cuadros dentro de un StackContainer se colocan en una pila; crea botones o funcionalidades a ser revelados uno a uno.
<?php echo $view->stackContainer( 'foo', $content, array(), array( 'style' => 'width: 400px; height: 500px; border: 1px;', ), ); ?> TabContainer: dijit.layout.TabContainer. Todos los cuadros dentro de un TabContainer se colocan en una pila, con pestaas colocadas a un lado para cambiar entre ellos.
<?php echo $view->tabContainer( 'foo', $content, array(), array( 'style' => 'width: 400px; height: 500px; border: 1px;', ), ); ?> Los siguientes mtodos de captura estn disponibles para todos los esquemas de contenedores: captureStart($id, array $params = array(), array $attribs = array()): inicia la captura del contenido a incluir en un contenedor. $params hace referencia a dijit params para utilizar con el contenedor, mientras que $attribs se refiere a cualquier atributo general HTML a utilizar. Los contenedores pueden estar anidados durante la captura, mientras no hayan IDs duplicados. captureEnd($id): finalizar la captura del contenido a incluir en un contenedor. $id debe referirse a un id anteriormente utilizado con la llamada captureStart(). Regresa el string representando al contenedor y su contenido, como si simplemente pasara el contenido al ayudante mismo.
$view->borderContainer()->captureStart('masterLayout', array('design' => 'headline')); echo $view->contentPane( 'menuPane', 'This is the menu pane', array('region' => 'top'), array('style' => 'background-color: darkblue;') ); echo $view->contentPane(
377
Zend_Dojo
'navPane', 'This is the navigation pane', array('region' => 'left'), array('style' => 'width: 200px; background-color: lightblue;') ); echo $view->contentPane( 'mainPane', 'This is the main content pane area', array('region' => 'center'), array('style' => 'background-color: white;') ); echo $view->contentPane( 'statusPane', 'Status area', array('region' => 'bottom'), array('style' => 'background-color: lightgray;') ); echo $view->borderContainer()->captureEnd('masterLayout');
<?php echo $view->button( 'foo', 'Show Me!', array('iconClass' => 'myButtons'), ); ?> CheckBox: dijit.form.CheckBox. Muestra un checkbox. Acepta opcionalmente un quinto argumento, el array $checkedOptions, que puede contener: un array indexado con dos valores, un valor verificado y otro no, en ese orden; o un array asociativo con las claves 'checkedValue' y 'unCheckedValue'. Si $checkedOptions no fueron suministradas, se asume 1 y 0.
378
Zend_Dojo
array(), array('checkedValue' => 'foo', 'unCheckedValue' => 'bar') ); ?> ComboBox: dijit.layout.ComboBox. Los ComboBoxes son un hbrido entre un cuadro de seleccin y uno de texto con autocompletado. La diferencia fundamental es que puede escribir una opcin que no est en la lista de las opciones disponibles, y que todava considera vlido el input. Opcionalmente acepta un quinto argumento, un array asociativo $options; si lo hay, ComboBox ser presentado como un select. Note tambin que la label values del array $options ser devuelto al form -- y no los valores en si mismos. Alternativamente, puede pasar informacin sobre un datastrore dojo.data para utilizar con el elemento. Si la hay, el ComboBox ser presentado como un texto input, y traer sus opciones va ese datastore. Para especificar un datastore, proporcionar una de las siguientes $params combinaciones de claves: La clave 'store', con un valor de array; el array debe contener las claves: store: el nombre de la variable javascript representando el datastore (este podra ser el nombre que desea para su uso). type: el tipo de datastore a usar; e.g., 'dojo.data.ItemFileReadStore'. params (opcional): un array asociativo de pares clave/valor a utilizar para configurar el datastore. El 'url' param es un ejemplo tpico. Las claves: store: un string indicando el nombre del datastore a usar. storeType: un string indicando el tipo de datastore dojo.data a usar (e.g., 'dojo.data.ItemFileReadStore'). storeParams: un array asociativo de pares clave/valor con los cuales configurar el datastore.
// Como un elemento select: echo $view->comboBox( 'foo', 'bar', array( 'autocomplete' => false, ), array(), array( 'foo' => 'Foo', 'bar' => 'Bar', 'baz' => 'Baz', ) ); // Como en elemento habilitado de dojo.data: echo $view->comboBox( 'foo', 'bar', array( 'autocomplete' => false, 'store' => 'stateStore',
379
Zend_Dojo
'storeType' 'storeParams' ), );
CurrencyTextBox: dijit.form.CurrencyTextBox. Se hereda de ValidationTextBox, y proporciona validacin de moneda del lado del cliente. Se espera que el parmetro dijit 'currency' ser siempre proporcionado con el cdigo adecuado de 3 caracteres de la moneda. Tambin puede especificar cualquiera de los parmetros dijit vlidos para ValidationTextBox y TextBox.
echo $view->currencyTextBox( 'foo', '$25.00', array('currency' => 'USD'), array('maxlength' => 20) );
$view->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=utf-8'); Por supuesto, esto significa que necesitar para garantizar que el marcador de posicin headMeta() est dentro de una sentencia "echo" de PHP en su script. DateTextBox: dijit.form.DateTextBox. Es heredada de ValidationTextBox, y ofrece tanto validacin de fechas de lado del cliente, as como un calendario desplegable desde el cual elegir una fecha. Puede especificar cualquiera de los parmetros dijit disponibles para ValidationTextBox o TextBox.
echo $view->dateTextBox( 'foo', '2008-07-11', array('required' => true) ); Editor: dijit.Editor. Proporciona un editor WYSIWYG mediante el cual los usuarios pueden crear o editar el contenido. dijit.Editor es un editor pluggable y extensible, con una variedad de parmetros que puede utilizar para personalizacin; para ms detalles vea la documentacin de dijit.Editor [http://dojotoolkit.org/book/ dojo-book-0-9/part-2-dijit/advanced-editing-and-display/editor-rich-text].
echo $view->editor('foo'); FilteringSelect: dijit.form.FilteringSelect. Similar a ComboBox, este es un hbrido de select/text que puede hacer una lista de opciones o aquellos retornados va un dojo.data datastore. A diferencia de ComboBox, sin embargo, FilteringSelect no permite escribir una opcin ni siquieraen en su lista. Adems, opera como un select standard en que los valores de opcin, no las etiquetas, son devueltos cuando el form se enva.
380
Zend_Dojo
Por favor vea la informacin anterior sobre ComboBox para ejemplos y las opciones disponibles para definir datastores. HorizontalSlider y VerticalSlider: dijit.form.HorizontalSlider y dijit.form.VerticalSlider. Los sliders permiten a los widgets de UI seleccionar nmeros en un rango dado; las variantes son horizontales y verticales. En lo ms elemental, exigen los parmetros dijit 'minimum', 'maximum', y 'discreteValues'. Estos definen el rango de valores. Otras opciones comunes son las siguientes: 'intermediateChanges' se puede ajustar para indicar cuando disparar o no eventos onChange mientras el handler est siendo arrastrado. 'clickSelect' se establece para permitir hacer click en un lugar del deslizador para ajustar el valor. 'pageIncrement' puede especificar el valor de aumento/decremento cuando se utilizan pageUp y pageDown. 'showButtons' se puede ajustar para permitir ver los botones de ambos extremos del deslizador para manipular el valor. La implementacin de Zend Framework crea un elemento oculto para guardar el valor del deslizador. Opcionalmente puede desear mostrar una regla o etiquetas para el deslizador. Para hacerlo, se asignar uno o ms de los parmetros dijit 'topDecoration' y/o 'bottomDecoration' (HorizontalSlider) o 'leftDecoration' y/o 'rightDecoration' (VerticalSlider). Cada uno de stos espera las siguientes opciones: container: nombre del contenedor. labels (opcional): un array de etiquetas a utilizar. Use strings vacos en cualquiera de los extremos para dotar de etiquetas solamente a los valores internos. Es necesario cuando se especifica uno de las variantes dijit 'Labels'. dijit (opcional): uno de los siguientes ser por defecto la dijits Rule (regla) HorizontalRule, HorizontalRuleLabels, VerticalRule, o VerticalRuleLabels. params (opcional): los dijit params son para configurar la Regla dijit en uso. Los parmetros especficos de estos dijits incluyen: container (opcional): array de parmetros y atributos para el contenedor de la regla. labels (opcional): array de parmetros y atributos para el contenedor de la lista de etiquetas. attribs (opcional): atributos HTML para utilizar con las reglas/etiquetas. Esto debera seguir el formato de opcin params y ser un array asociativo con las claves 'container' y 'labels'. echo $view->horizontalSlider( 'foo', 1, array( 'minimum' => -10, 'maximum' => 10, 'discreteValues' => 11, 'intermediateChanges' => true, 'showButtons' => true, 'topDecoration' => array( 'container' => 'topContainer' 'dijit' => 'HorizontalRuleLabels',
381
Zend_Dojo
'labels' => array( ' ', '20%', '40%', '60%', '80%', ' ', ), 'params' => array( 'container' => array( 'style' => 'height:1.2em; font-size=75%;color:gray;', ), 'labels' => array( 'style' => 'height:1em; font-size=75%;color:gray;', ), ), ), 'bottomDecoration' => array( 'container' => 'bottomContainer' 'labels' => array( '0%', '50%', '100%', ), 'params' => array( 'container' => array( 'style' => 'height:1.2em; font-size=75%;color:gray;', ), 'labels' => array( 'style' => 'height:1em; font-size=75%;color:gray;', ), ), ), ) ); NumberSpinner: dijit.form.NumberSpinner. Text box numrico para entrada, con botones para incremento y decremento. Espera bien un array asociativo del parmetro dijit 'constraints' o simplemente las claves 'min', 'max', y 'places' (estas seran tambin las entradas esperadas del parmetro de restricciones). 'places' puede ser utilizada para indicar en cunto se incrementar y decrementar el nmero giratorio.
echo $view->numberSpinner( 'foo', 5, array( 'min' => -10, 'max' => 10, 'places' => 2, ), array( 'maxlenth' => 3,
382
Zend_Dojo
) ); NumberTextBox: dijit.form.NumberTextBox. NumberTextBox ofrece la capacidad de dar formato y mostrar entradas numricas de una manera localizada, as como validar entradas numricas, opcionalmente en contra de las restricciones dadas.
echo $view->numberTextBox( 'foo', 5, array( 'places' => 4, 'type' => 'percent', ), array( 'maxlength' => 20, ) ); PasswordTextBox: dijit.form.ValidationTextBox est atada a una contrasea. PasswordTextBox ofrece la posibilidad de crear una entrada para contrasea que adhiere al actual tema dijit, as como permitir la validacin del lado del cliente.
echo $view->passwordTextBox( 'foo', '', array( 'required' => true, ), array( 'maxlength' => 20, ) ); RadioButton: dijit.form.RadioButton. Una serie de opciones entre las que slo una puede ser seleccionada. Esta se comporta en todos los sentidos como una de radio normal, pero tiene un look-and-feel consistente con otros dijits. RadioButton acepta un cuarto argumento como opcin, $options, un array asociativo de pares valor/etiqueta utilizado como opciones de radio. Tambin puede pasar estos como la clave options de $attribs.
echo $view->radioButton( 'foo', 'bar', array(), array(), array( 'foo' => 'Foo', 'bar' => 'Bar', 'baz' => 'Baz', ) );
383
Zend_Dojo
SimpleTextarea: dijit.form.SimpleTextarea. Estos actuarn como textareas normales, pero se estilizan usando el tema actual de dijit. No necesita especificar los atributos ya sea de las filas o de las columnas; use ems o porcentajes del ancho y del alto en su lugar.
echo $view->simpleTextarea( 'foo', 'Start writing here...', array(), array('style' => 'width: 90%; height: 5ems;') ); SubmitButton: un dijit.form.Button est atado a un elemento de entrada a enviar. Vea el ayudante de vista de Button para ms detalles; la diferencia fundamental es que este botn puede enviar un form. Textarea: dijit.form.Textarea. stas actuarn como textareas normales, salvo que en lugar de un determinado nmero de filas, se expanden a medida que el usuario tipea. El ancho debe especificarse mediante una regla de estilo.
echo $view->textarea( 'foo', 'Start writing here...', array(), array('style' => 'width: 300px;') ); TextBox: dijit.form.TextBox. Este elemento est presente principalmente para proporcionar un look-and-feel comn entre los diversos elementos dijit, y a ofrecer funcionalidades de base para otras clases derivadas de TextBox (ValidationTextBox, NumberTextBox, CurrencyTextBox, DateTextBox, y TimeTextBox). El parmetro comn de dijit para los flags incluyen 'lowercase' (emitido a minsculas), 'uppercase' (emitido a maysculas), 'propercase' (emitido a Proper Case), y trim (elimina los espacios en blanco iniciales y finales); todos aceptan valores booleanos. Adems, puede especificar los parmetros 'size' y 'maxLength'.
echo $view->textBox( 'foo', 'some text', array( 'trim' => true, 'propercase' => true, 'maxLength' => 20, ), array( 'size' => 20, ) ); TimeTextBox: dijit.form.TimeTextBox. Tambin de la familia TextBox, TimeTextBox proporciona una seleccin desplazable drop down de la cantidad de veces que un usuario podr seleccionar. Los parmetros Dijit le permiten especificar el tiempo disponible para incrementos en el select as como un rango visible de veces en disponibilidad.
384
Zend_Dojo
'', array( 'am.pm' => true, 'visibleIncrement' => 'T00:05:00', // 5-minute increments 'visibleRange' => 'T02:00:00', // show 2 hours of increments ), array( 'size' => 20, ) ); ValidationTextBox: dijit.form.ValidateTextBox. Proporciona validaciones del lado del cliente para un elemento de texto. Se hereda desde TextBox. Los parmetros comunes de dijit incluyen: invalidMessage: un mensaje para mostrar cuando se ha detectado una entrada invlida. promptMessage: un mensaje tooltip de ayuda a utilizar. regExp: una expresin regular a utilizar para validar el texto. La Expresin Regular no requiere de marcadores de lmites. required: si el elemento es necesario o no. Si fuera necesario, y el elemento est incrustado en un dijit.form.Form, ser marcado como invlido y no se enviar.
echo $view->validationTextBox( 'foo', '', array( 'required' => true, 'regExp' => '[\w]+', 'invalidMessage' => 'No se permiten espacios o caracteres especiales', 'promptMessage' => 'Una palabra consiste de caracteres ' . 'alfanumricos y underscores solamente', ), array( 'maxlength' => 20, ) );
Dijits Personalizados
Si ahonda mucho en Dojo, se encontrar escribiendo bastantes dijits personalizados, o utilizando dijits experimentales de Dojox. Si bien Zend Framework no puede apoyar a todos los dijit directamente, si proporciona algn apoyo rudimentario para tipos dijit arbitrarios va el ayudante de vista CustomDijit. La API del ayudante de vista CustomDijit es exactamente lo que cualquier otro dijit es, con una diferencia importante: el tercer argumento de "params" debe contener el atributo "dojotype". El valor de este atributo debe ser la clase Dijit que planea usar. CustomDijit extiende la base del ayudante de vista DijitContainer, que tambin le permite capturar el contenido (utilizando el par de mtodos captureStart()/captureEnd()). captureStart() tambin espera que pase el atributo "dojoType" a su argumento "params".
385
Zend_Dojo
<?php echo $this->customDijit( 'foo', $content, array( 'dojoType' => 'dojox.layout.ContentPane', 'title' => 'Custom pane', 'region' => 'center' ) ); ?> Si quiere capturar el contenido en su lugar, simplemente use el mtodo captureStart(), y pase el "DojoType" al argumento de "params":
<?php $this->customDijit()->captureStart( 'foo', array( 'dojoType' => 'dojox.layout.ContentPane', 'title' => 'Custom pane', 'region' => 'center' ) ); ?> This is the content of the pane <?php echo $this->customDijit()->captureEnd('foo'); ?> Fcilmente puede extender tambin CustomDijit para crear apoyo para sus propios dijits personalizados. Como ejemplo, si extiende dijit.layout.ContentPane para crear su propia clase foo.ContentPane, puede crear el siguiente ayudante de apoyo:
class My_View_Helper_FooContentPane extends Zend_Dojo_View_Helper_CustomDijit { protected $_defaultDojoType = 'foo.ContentPane'; public function fooContentPane( $id = null, $value = null, array $params = array(), array $attribs = array() ) { return $this->customDijit($id, $value, $params, $attribs); } } Mientras que su dijit personalizado siga la misma base API que los dijits oficiales, utilizar o extender CustomDijit debera funcionar correctamente.
386
Zend_Dojo
class My_Form_Custom extends Zend_Form { public function init() { // Dojo habilita el form: Zend_Dojo::enableForm($this); // ... continuar con la definicin del form desde aqu // Dojo habilita todos los sub forms: foreach ($this->getSubForms() as $subForm) { Zend_Dojo::enableForm($subForm); } } } El uso de los decoradores y elementos especficos de dijit form es como usar cualquier otro decorador o elemento de formularios.
387
Zend_Dojo
Decorador DijitElement
Al igual que el decorador ViewHelper, DijitElement espera una propiedad del helper en el elemento que luego usar como el ayudante de vista cuando lo renderice. Los parmetros Dijit suelen ser arrastrados directamente desde el elemento, pero tambin pueden ser pasados como opciones va la clave dijitParams (el valor de esa clave debe ser un array asociativo de opciones). Es importante que cada elemento tenga un nico ID (como trado desde el mtodo getId() del elemento). Si se detectan duplicados dentro del ayudante de vista dojo(), el decorador accionar un aviso, pero luego crear un nico ID aadindole lo que devuelve uniqid() al identificador. El uso estndar es simplemente asociar este decorador como el primero de su cadena de decoradores, sin opciones adicionales.
Decorador DijitForm
El decorador DijitForm es muy similar al Form decorator; de hecho, bsicamente puede ser utilizado de manera intercambiable con l, ya que utiliza el mismo nombre de ayudante de vista ('form'). Dado que dijit.form.Form no requiere ningn parmetro dijit para la configuracin, la principal diferencia es que el ayudante de vista dijit del form exige que se pase un DOM ID para garantizar que la creacin programtica del dijit pueda trabajar. El decorador garantiza esto, pasando el nombre del form como el identificador.
388
Zend_Dojo
389
Zend_Dojo
Los parmetros Dijit se almacenan en la propiedad pblica dijitParams. As, puede habilitar dijit para un elemento de un formulario existente simplemente estableciendo esta propiedad en el elemento; sencillamante no tendr los accessors anteriores a fin de facilitar la manipulacin de parmetros. Adems, los elementos especficos de dijit implementan una lista diferente de decoradores, correspondientes a lo siguiente: $element->addDecorator('DijitElement') ->addDecorator('Errors') ->addDecorator('HtmlTag', array('tag' => 'dd')) ->addDecorator('Label', array('tag' => 'dt')); En efecto, el decorador DijitElement es utilizado en lugar del decorador standard ViewHelper. Finalmente, el elemento base Dijit asegura que el path del ayudante de vista de Dojo se establezca en la vista. Una variante de DijitElement, DijitMulti, ofrece la funcionalidad del elemento abstracto del formulario Multi, permitiendo al desarrollador especificar 'multiOptions' -- tpicamente opciones "select" u opciones de "radio". Los siguientes elementos dijit estn includos en la distribucin standard de Zend Framework.
Button
Si bien no derivan del elemento standard Button ???, implementan la misma funcionalidad, y pueden ser utilizados como una sustitucin de drop-in, como se expone en la siguiente funcionalidad: getLabel() utilizar el nombre del elemento como el rtulo del botn si no se ha provisto el nombre. Adems, traducir el nombre si un adaptador de traduccin encuentra concordancia con un mensaje disponible. isChecked() determina si el valor enviado coincide con la etiqueta; si as fuera, devuelve true. Esto es til para determinar qu botn se utiliz cuando se envi un formulario. Adems, slo los decoradores DijitElement y DtDdWrapper se utilizan para elementos Button.
CheckBox
Si bien no derivan del elemento standard Checkbox ???, aplican la misma funcionalidad. Esto significa exponer los siguientes mtodos: setCheckedValue($value): establecer el valor a usar cuando el elemento est marcado (checked). getCheckedValue(): obtener el valor del item a usar cuando est comprobado (checked). setUncheckedValue($value): establecer el valor del item a utilizar cuando est desactivado (unchecked). getUncheckedValue(): obtener el valor del item a utilizar cuando est desactivado (unchecked).
390
Zend_Dojo
setChecked($flag): marcar el elemento como activado (checked) o desactivado (unchecked). isChecked(): determina si el elemento est activo (checked) actualmente.
ComboBox y FilteringSelect
Como se seal en la documentacin del ayudante de vista de ComboBox dijit ???, los ComboBoxes son un hbrido entre "select" y "text input", permitiendo el autocompletado y la capacidad para especificar una alternativa a las opciones provistas. FilteringSelects es lo mismo, pero no permite entradas arbitrarias.
getStoreType(): obtiene la clase del datastore a usar. setStoreParams(array $params): establece cualquiera de los parmetros utilizados para configurar el objeto datastore. Como ejemplo, el datastore dojo.data.ItemFileReadStore esperara un parmetro 'url' apuntando a un lugar que devolvera el objeto dojo.data. getStoreParams(): obtiene cualquiera de los parmetros del datastore actualmente establecido; si no hay ninguno, se devuelve un array vaco. setAutocomplete($flag): indica si ser usado o no el elemento seleccionado una vez que el usuario deje el elemento.
391
Zend_Dojo
getAutocomplete(): obtener el valor del flag de autocomplete. Por defecto, si no hay ningn dojo.data registrado con el elemento, este elemento registra un validador InArray que valida contra las claves del array de las opciones registradas. Puede desactivar este comportamiento ya sea llamando a setRegisterInArrayValidator(false), o pasando un valor false a la clave de configuracin registerInArrayValidator.
CurrencyTextBox
El CurrencyTextBox principalmente brinda apoyo a la entrada de moneda. La moneda puede ser localizada, y puede manejar tanto a valores fraccionarios como no fraccionarios.
392
Zend_Dojo
Internamente, CurrencyTextBox deriva de NumberTextBox, ValidationTextBox, y TextBox; todos los mtodos disponibles a esas clases estn disponibles. Adems, pueden utilizarse los siguientes mtodos restrictivos: setCurrency($currency): establecer el tipo de moneda a usar; y debe seguir la especificacin ISO-4217 [http://en.wikipedia.org/wiki/ISO_4217] getCurrency(): recupera el tipo de moneda actual. setSymbol($symbol): establece el smbolo de 3 letras ISO-4217 [http://en.wikipedia.org/wiki/ISO_4217] de la moneda a usar. getSymbol(): recupera el smbolo de la moneda actual. setFractional($flag): establece si la moneda debera permitir o no valores fraccionarios. getFractional(): recupera el status del flag fraccional.
'Currency:', true, 'USD', 'Invalid amount. ' . 'Include dollar sign, commas, and cents.', => false,
DateTextBox
DateTextBox establece un calendario desplegable (drop-down) para seleccionar una fecha, as como validacin y formateo de fechas del lado del clente. Internamente, DateTextBox deriva de ValidationTextBox y TextBox; todos los mtodos disponibles a esas clases estn disponibles. Adems, los siguientes mtodos pueden utilizarse para establecer restricciones individuales: setAmPm($flag) y getAmPm(): Cundo usar o no los strings AM/PM en los fortmatos de horas. setStrict($flag) y getStrict(): Cundo usar o no el matching para una expresin regular estricta al validar la entrada. Si es falso, que es el valor por defecto, ser indulgente sobre espacios en blanco y algunas abreviaturas. setLocale($locale) y getLocale(): Establece y recupera la localidad a utilizar con este elemento especfico. setDatePattern($pattern) y getDatePattern(): provee y recupera el patrn de formato de fechas unicode [http://www.unicode.org/reports/tr35/#Date_Format_Patterns] para el formateo de fechas. setFormatLength($formatLength) y getFormatLength(): proporciona y recupera la longitud del tipo de formato a usar; debe ser uno de los siguientes: "long", "short", "medium" o "full". setSelector($selector) y getSelector(): proporciona y recupera el estilo del selector; debe ser "date" o "time".
393
Zend_Dojo
Editor
Editor proporciona un editor WYSIWYG que puede ser utilizado tanto para crear como para editar contenidos HTML ricos. dijit.Editor es pluggable y podr ampliarse con plugins personalizados si lo desea; para ms detalles vea en la documentacin de dijit.Editor [http://dojotoolkit.org/book/dojo-book-0-9/part-2-dijit/advanced-editing-anddisplay/editor-rich-text]. El elemento form de Editor proporciona un nmero de accessors y mutators para manipular diversos parmetros dijit, tal como sigue: captureEvents son eventos que se conectan al rea de edicin en si. Los siguientes accessors y mutators estn disponibles para manipular la captura de eventos: addCaptureEvent($event) addCaptureEvents(array $events) setCaptureEvents(array $events) getCaptureEvents() hasCaptureEvent($event) removeCaptureEvent($event) clearCaptureEvents() events son eventos DOM estndar, como onClick, onKeyup, etc. Los siguientes accessors y mutators estn disponibles para manipular eventos: addEvent($event) addEvents(array $events) setEvents(array $events) getEvents() hasEvent($event) removeEvent($event) clearEvents()
394
Zend_Dojo
plugins aaden funcionalidad al Editor -- herramientas adicionales para la barra de herramientas, estilos adicionales a permitir, etc. Los siguientes accessors y mutators estn disponibles para manipular plugins: addPlugin($plugin) addPlugins(array $plugins) setPlugins(array $plugins) getPlugins() hasPlugin($plugin) removePlugin($plugin) clearPlugins() editActionInterval se utiliza para agrupar eventos para deshacer operaciones. Por defecto, este valor es de 3 segundos. El mtodo setEditActionInterval($interval) puede ser usado para establecer el valor, mientras que getEditActionInterval() lo recuperar. focusOnLoad se utiliza para determinar si este editor en particular recibir atencin cuando la pgina se haya cargado. Por defecto, esto es falso. El mtodo setFocusOnLoad($flag) puede usarse para establecer el valor, mientras que getFocusOnLoad() lo recuperar. height especifica la altura del editor; por defecto, es de 300px. El mtodo setHeight($height) puede ser utilizado para establecer el valor, mientras que getHeight() lo recupera. inheritWidth se utiliza para determinar si el editor utilizar el ancho del contenedor padre o simplemente toma por defecto el 100% del ancho. Por defecto, esto es falso (es decir, llenar el ancho de la ventana). El mtodo setInheritWidth($flag) puede ser utilizado para establecer el valor, mientras que getInheritWidth() lo recuperar. minHeight indica la altura mnima del editor; por defecto, es de 1em. El mtodo setMinHeight($height) puede ser utilizado para establecer el valor, mientras que getMinHeight() lo recuperar. styleSheets indica qu otras hojas de estilo CSS deberan ser utilizadas para incidir sobre la pantalla del Editor. Por defecto, ninguna est registrada, y hereda la pgina de estilos. Los siguientes accessors y mutators estn disponibles para manipular al editor de hojas de estilo (stylesheets): addStyleSheet($styleSheet) addStyleSheets(array $styleSheets) setStyleSheets(array $styleSheets) getStyleSheets() hasStyleSheet($styleSheet) removeStyleSheet($styleSheet) clearStyleSheets()
395
Zend_Dojo
<sect3 id="zend.dojo.form.elements.horizontalSlider"> <title>HorizontalSlider</title> <para> HorizontalSlider proporciona un widget deslizador de UI para seleccionar un valor numrico dentro de un rango. Internamente, establece el valor de un elemento oculto que es enviado por el formulario. </para> <para> HorizontalSlider proviene del elemento abstracto <link linkend="zend.dojo.form.elements.slider">Slider dijit</link>. Adems, tiene una variedad de mtodos de ajuste y configuracin de reglas deslizantes y etiquetas para esas reglas. </para>
<itemizedlist> <listitem> <para> <methodname>setTopDecorationDijit($dijit)</methodname> y <methodname>setBottomDecorationDijit($dijit)</methodname>: establecen e nombre de la dijit a utilizar bien para la parte superior o inferior de la barra deslizante. Esto no debera incluir el prefijo "dijit.form.", sino slo el ltimo nombre -- "HorizontalRule" o "HorizontalRuleLabels". </para> </listitem> <listitem> <para> <methodname>setTopDecorationContainer($container)</methodname> y <methodname>setBottomDecorationContainer($container)</methodname>: especifican el nombre a utilizar para el elemento contenedor de las reglas; por ejemplo 'Toprule', 'topContainer', etc. </para> </listitem> <listitem> <para> <methodname>setTopDecorationLabels(array $labels)</methodname> y
396
Zend_Dojo
<methodname>setBottomDecorationLabels(array $labels)</methodname>: establecen las etiquetas a usar por uno de los tipos RuleLabels dijit. Debe ser un array indexado; especificar un nico espacio vaco para saltar a la posicin de una determinada etiqueta (como ser al comienzo o al final). </para> </listitem> <listitem> <para> <methodname>setTopDecorationParams(array $params)</methodname> y <methodname>setBottomDecorationParams(array $params)</methodname>: parmetros dijit para utilizar al configurar la Regla o RuleLabels dijit. </para> </listitem> <listitem> <para> <methodname>setTopDecorationAttribs(array $attribs)</methodname> y <methodname>setBottomDecorationAttribs(array $attribs)</methodname>: atributos HTML para especificar una Regla dada o el elemento contenedor de HTML RuleLabels. </para> </listitem> <listitem> <para> <methodname>getTopDecoration()</methodname> y <methodname>getBottomDecoration()</methodname>: recuperar todos los metadatos para una determinada Regla o definicin de RuleLabels, tal como han sido provistos por los mutators anteriores. </para> </listitem> </itemizedlist> <example id="zend.dojo.form.elements.horizontalSlider.example"> <title>Ejemplo de Uso del Elemento HorizontalSlider dijit</title> <para> Lo siguiente crear un deslizador horizontal de seleccin con valores enteros que van desde -10 a 10. La parte superior tendr etiquetas en las marcas del 20%, 40%, 60%, y 80%. La parte inferior ser una regla con marcas en el 0, 50%, y 100%. Cada vez que se cambie el valor, el elemento oculto almacenar el valor actualizado. </para> <programlisting language="php"><![CDATA[ $form->addElement( 'HorizontalSlider', 'horizontal', array(
397
Zend_Dojo
'label' => 'HorizontalSlider', 'value' => 5, 'minimum' => -10, 'maximum' => 10, 'discreteValues' => 11, 'intermediateChanges' => true, 'showButtons' => true, 'topDecorationDijit' => 'HorizontalRuleLabels', 'topDecorationContainer' => 'topContainer', 'topDecorationLabels' => array( ' ', '20%', '40%', '60%', '80%', ' ', ), 'topDecorationParams' => array( 'container' => array( 'style' => 'height:1.2em; font-size=75%;color:gray;', ), 'list' => array( 'style' => 'height:1em; font-size=75%;color:gray;', ), ), 'bottomDecorationDijit' => 'HorizontalRule', 'bottomDecorationContainer' => 'bottomContainer', 'bottomDecorationLabels' => array( '0%', '50%', '100%', ), 'bottomDecorationParams' => array( 'list' => array( 'style' => 'height:1em; font-size=75%;color:gray;', ), ), ) );
NumberSpinner
Un nmero spinner es un elemento de texto para introducir valores numricos; tambin incluye elementos de incremento y decremento del valor por una cantidad fija. Se encuentran disponibles los siguientes mtodos: setDefaultTimeout($timeout) y getDefaultTimeout(): establece y recupera el tiempo de espera predeterminado en milisegundos, entre cuando el botn se mantiene presionado y cambia el valor. setTimeoutChangeRate($rate) y getTimeoutChangeRate(): establece y recupera la tasa en milisegundos, en la que se harn cambios cuando un botn se mantiene presionado. setLargeDelta($delta) y getLargeDelta(): establece y recupera la cantidad en la que el valor numrico debera cambiar cuando un botn se mantiene presionado.
398
Zend_Dojo
setSmallDelta($delta) y getSmallDelta(): establece y recupera el delta con la que el nmero debera cambiar cuando se pulsa un botn una vez. setIntermediateChanges($flag) y getIntermediateChanges(): establece y recupera el flag que indica si debe o no ser mostrado cada cambio de valor cuando un botn se mantiene presionado. setRangeMessage($message) y getRangeMessage(): establece y recupera el mensaje indicando el rango de valores disponibles. setMin($value) y getMin(): establece y recupera el valor mnimo posible. setMax($value) y getMax(): establece y recupera el valor mximo posible.
=> => => => => => => => => =>
NumberTextBox
Un cuadro de texto numrico es un elemento de texto de introduccin de valores numricos; a diferencia de NumberSpinner, se introducen manualmente. Se pueden proporcionar validaciones y restricciones para garantizar que el nmero permanece en un rango o formato particular. Internmente, NumberTextBox proviene de ValidationTextBox y TextBox; todos los mtodos disponibles a esas clases estn disponibles. Adems, los siguientes mtodos pueden utilizarse para establecer restricciones individuales: setLocale($locale) y getLocale(): especifica y recupera un "locale" determinado o alternativo para usar con este dijit. setPattern($pattern) y getPattern(): establece y recupera un patrn de formato numrico [http:// www.unicode.org/reports/tr35/#Number_Format_Patterns] a usar en el formateo de nmeros. setType($type) y getType(): establece y recupera el tipo de formato numrico a utilizar (debern ser uno de 'decimal', 'percent', o 'currency'). setPlaces($places) y getPlaces(): establece y recupera el nmero de decimales que soportar. setStrict($flag) y getStrict(): establece y recupera el valor estricto del flag, que indica cunta indulgencia es permitida en relacin con espacios en blanco y con caracteres no numricos.
399
Zend_Dojo
PasswordTextBox
PasswordTextBox es simplemente un ValidationTextBox que est ligado a una contrasea; su nico objetivo es permitir la entrada de texto de contraseas de dijit que tambin proporciona validacin del lado del cliente. Internmente, NumberTextBox proviene de ValidationTextBox y TextBox; todos los mtodos disponibles a esas clases estn disponibles.
'Password', true, true, true, '^[a-z0-9]{6,}$', 'Invalid password; ' . 'must be at least 6 alphanumeric characters',
RadioButton
RadioButton envuelve a elementos standard de entrada tipo radio para brindar un look-and-feel consistente con otros dojo dijits. RadioButton se extiende desde DijitMulti, que le permite especificar la seleccin de opciones va los mtodos setMultiOptions() y setMultiOption(). Por defecto, este elemento registra un validador InArray que valida contra las calves del array de las opciones registradas. Puede desactivar este comportamiento ya sea llamando a setRegisterInArrayValidator(false), o pasando un valor falso a la clave de configuracin registerInArrayValidator.
400
Zend_Dojo
SimpleTextarea
SimpleTextarea acta principalmente como un textarea estndar de HTML. Sin embargo, no permite establecer filas ni columnas. En su lugar, el ancho de textarea debe especificarse utilizando medidas CSS estndar. A diferencia de Textarea, esta no aumentar automticamente.
401
Zend_Dojo
setMinimum($value) y getMinimum(): establece y recupera el valor mnimo del deslizador. setPageIncrement($value) y getPageIncrement(): establece la cantidad en que cambiar el deslizador por eventos del teclado. Ejemplos de uso provistos con cada clase extendida concretamente.
SubmitButton
Si bien no hay Dijit llamado SubmitButton, incluimos uno aqu para proporcionar un botn dijit capaz de enviar un formulario sin que se exijan ligaduras con javascript. Funciona exactamente igual que el Button dijit.
TextBox
Textbox se incluy principalmente para proporcionar una entrada de texto con apariencia coherente y con el lookand-feel de los dems dijits. Sin embargo, tambin incluye algunas pequeas capacidades de filtrado y validacin, representadas en los mtodos siguientes: setLowercase($flag) y getLowercase(): establece y recupera el flag que indica si la entrada debe o no ser presentada en minsculas. setPropercase($flag) y getPropercase(): establece y recupera el flag que indica si la entrada debe ser o no ser presentada como Proper Case. setUppercase($flag) y getUppercase(): establece y recupera el flag que indica si la entrada debe ser presentada como maysculas (UPPERCASE). setTrim($flag) y getTrim(): establece y recupera el flag que indica si los espacios al comienzo o al final deben ser eliminados o no. setMaxLength($length) y getMaxLength(): establece y recupera la longitud mxima del input.
402
Zend_Dojo
Textarea
Textarea acta principalmente como un textarea estndar de HTML. Sin embargo, no permite establecer filas y columnas. En su lugar, el ancho de la textarea debe especificarse utilizando medidas CSS estndar; las filas debe omitirse totalmente. Luego, la textarea crecer verticalmente tanto como texto se aada a ella.
TimeTextBox
TimeTextBox es una entrada de texto que proporciona una lista desplegable (drop-down) para seleccionar un tiempo (fecha y hora). La lista desplegable, puede ser configurada para mostrar una cierta ventana de tiempo, con incrementos especificados. Internamente, TimeTextBox proviene de DateTextBox, ValidationTextBox y TextBox; todos los mtodos disponibles a esas clases estn disponibles. Adems, los siguientes mtodos pueden utilizarse para establecer restricciones individuales: setTimePattern($pattern) y getTimePattern(): establece y recupera el patrn de formato de fecha y hora unicode [http://www.unicode.org/reports/tr35/#Date_Format_Patterns] para el formato correspondiente. setClickableIncrement($format) y getClickableIncrement(): establece y recupera el string ISO-8601 [http://en.wikipedia.org/wiki/ISO_8601] representando la cantidad de tiempo a incrementar cada vez que se recolecta un elemento clickable. setVisibleIncrement($format) y getVisibleIncrement(): establece y recupera el incremento visible en el selector de tiempo; debe seguir los formatos ISO-8601. setVisibleRange($format) y getVisibleRange(): establece y recupera el intervalo de tiempo visible en el selector de tiempo en cualquier momento; debe seguir los formatos ISO-8601.
403
Zend_Dojo
ValidationTextBox
ValidationTextBox ofrece la posibilidad de aadir validaciones y limitaciones a una entrada de texto. Internamente, proviene de TextBox, y aade los siguientes accessors y mutators para manejar parmetros dijit: setInvalidMessage($message) y getInvalidMessage(): establece y recupera el mensaje de tooltip para mostrar cuando el valor no se valid. setPromptMessage($message) y getPromptMessage(): establece y recupera el mensaje de tooltip a mostrar para el uso del elemento. setRegExp($regexp) y getRegExp(): establece y recupera la expresin regular a utilizar para validar el elemento. La expresin regular no necesita lmites (a diferencia de la familia de funciones preg*, de PHP). setConstraint($key, $value) y getConstraint($key): establece y recupera restricciones adicionales para utilizar al validar el elemento; se utiliza principalmente con subclases. Las restricciones son almacenados en la clave 'constraints' de los parmetros dijit. setConstraints(array $constraints) y getConstraints(): establece y recupera las restricciones para utilizar al validar el elemento; se utiliza principalmente con subclases. hasConstraint($key): prueba si una restriccin dada existe. removeConstraint($key) y clearConstraints(): elimina una restriccin individual o todas las restricciones para el elemento.
VerticalSlider
VerticalSlider es el hermano de HorizontalSlider, y opera en todos los sentidos como ese elemento. La nica diferencia real es que los mtodos 'top*' y 'bottom*' son sustituidos por 'left*' y 'right*', y en lugar de utilizar HorizontalRule y HorizontalRuleLabels, debe usarse VerticalRule y VerticalRuleLabels.
404
Zend_Dojo
$form->addElement( 'VerticalSlider', 'foo', array( 'label' => 'VerticalSlider', 'value' => 5, 'style' => 'height: 200px; width: 3em;', 'minimum' => -10, 'maximum' => 10, 'discreteValues' => 11, 'intermediateChanges' => true, 'showButtons' => true, 'leftDecorationDijit' => 'VerticalRuleLabels', 'leftDecorationContainer' => 'leftContainer', 'leftDecorationLabels' => array( ' ', '20%', '40%', '60%', '80%', ' ', ), 'rightDecorationDijit' => 'VerticalRule', 'rightDecorationContainer' => 'rightContainer', 'rightDecorationLabels' => array( '0%', '50%', '100%', ), ) );
class My_Form_Test extends Zend_Dojo_Form { /** * Opciones para usar con elementos select */
405
Zend_Dojo
protected $_selectOptions = array( 'red' => 'Rouge', 'blue' => 'Bleu', 'white' => 'Blanc', 'orange' => 'Orange', 'black' => 'Noir', 'green' => 'Vert', ); /** * Inicializacin del Formn * * @return void */ public function init() { $this->setMethod('post'); $this->setAttribs(array( 'name' => 'masterForm', )); $this->setDecorators(array( 'FormElements', array('TabContainer', array( 'id' => 'tabContainer', 'style' => 'width: 600px; height: 500px;', 'dijitParams' => array( 'tabPosition' => 'top' ), )), 'DijitForm', )); $textForm = new Zend_Dojo_Form_SubForm(); $textForm->setAttribs(array( 'name' => 'textboxtab', 'legend' => 'Text Elements', 'dijitParams' => array( 'title' => 'Text Elements', ), )); $textForm->addElement( 'TextBox', 'textbox', array( 'value' => 'some text', 'label' => 'TextBox', 'trim' => true, 'propercase' => true, ) ) ->addElement( 'DateTextBox', 'datebox', array( 'value' => '2008-07-05',
406
Zend_Dojo
'label' => 'DateTextBox', 'required' => true, ) ) ->addElement( 'TimeTextBox', 'timebox', array( 'label' => 'TimeTextBox', 'required' => true, ) ) ->addElement( 'CurrencyTextBox', 'currencybox', array( 'label' => 'CurrencyTextBox', 'required' => true, // 'currency' => 'USD', 'invalidMessage' => 'Invalid amount. ' . 'Include dollar sign, commas, ' . 'and cents.', // 'fractional' => true, // 'symbol' => 'USD', // 'type' => 'currency', ) ) ->addElement( 'NumberTextBox', 'numberbox', array( 'label' => 'NumberTextBox', 'required' => true, 'invalidMessage' => 'Invalid elevation.', 'constraints' => array( 'min' => -20000, 'max' => 20000, 'places' => 0, ) ) ) ->addElement( 'ValidationTextBox', 'validationbox', array( 'label' => 'ValidationTextBox', 'required' => true, 'regExp' => '[\w]+', 'invalidMessage' => 'Invalid non-space text.', ) ) ->addElement( 'Textarea', 'textarea',
407
Zend_Dojo
array( 'label' => 'Textarea', 'required' => true, 'style' => 'width: 200px;', ) ); $editorForm = new Zend_Dojo_Form_SubForm(); $editorForm->setAttribs(array( 'name' => 'editortab', 'legend' => 'Editor', 'dijitParams' => array( 'title' => 'Editor' ), )) $editorForm->addElement( 'Editor', 'wysiwyg', array( 'label' => 'Editor', 'inheritWidth' => 'true', ) ); $toggleForm = new Zend_Dojo_Form_SubForm(); $toggleForm->setAttribs(array( 'name' => 'toggletab', 'legend' => 'Toggle Elements', )); $toggleForm->addElement( 'NumberSpinner', 'ns', array( 'value' => '7', 'label' => 'NumberSpinner', 'smallDelta' => 5, 'largeDelta' => 25, 'defaultTimeout' => 1000, 'timeoutChangeRate' => 100, 'min' => 9, 'max' => 1550, 'places' => 0, 'maxlength' => 20, ) ) ->addElement( 'Button', 'dijitButton', array( 'label' => 'Button', ) ) ->addElement( 'CheckBox', 'checkbox',
408
Zend_Dojo
array( 'label' => 'CheckBox', 'checkedValue' => 'foo', 'uncheckedValue' => 'bar', 'checked' => true, ) ) ->addElement( 'RadioButton', 'radiobutton', array( 'label' => 'RadioButton', 'multiOptions' => array( 'foo' => 'Foo', 'bar' => 'Bar', 'baz' => 'Baz', ), 'value' => 'bar', ) ); $selectForm = new Zend_Dojo_Form_SubForm(); $selectForm->setAttribs(array( 'name' => 'selecttab', 'legend' => 'Select Elements', )); $selectForm->addElement( 'ComboBox', 'comboboxselect', array( 'label' => 'ComboBox (select)', 'value' => 'blue', 'autocomplete' => false, 'multiOptions' => $this->_selectOptions, ) ) ->addElement( 'ComboBox', 'comboboxremote', array( 'label' => 'ComboBox (remoter)', 'storeId' => 'stateStore', 'storeType' => 'dojo.data.ItemFileReadStore', 'storeParams' => array( 'url' => '/js/states.txt', ), 'dijitParams' => array( 'searchAttr' => 'name', ), ) ) ->addElement( 'FilteringSelect', 'filterselect', array(
409
Zend_Dojo
'label' => 'FilteringSelect (select)', 'value' => 'blue', 'autocomplete' => false, 'multiOptions' => $this->_selectOptions, ) ) ->addElement( 'FilteringSelect', 'filterselectremote', array( 'label' => 'FilteringSelect (remoter)', 'storeId' => 'stateStore', 'storeType' => 'dojo.data.ItemFileReadStore', 'storeParams' => array( 'url' => '/js/states.txt', ), 'dijitParams' => array( 'searchAttr' => 'name', ), ) ); $sliderForm = new Zend_Dojo_Form_SubForm(); $sliderForm->setAttribs(array( 'name' => 'slidertab', 'legend' => 'Slider Elements', )); $sliderForm->addElement( 'HorizontalSlider', 'horizontal', array( 'label' => 'HorizontalSlider', 'value' => 5, 'minimum' => -10, 'maximum' => 10, 'discreteValues' => 11, 'intermediateChanges' => true, 'showButtons' => true, 'topDecorationDijit' => 'HorizontalRuleLabels', 'topDecorationContainer' => 'topContainer', 'topDecorationLabels' => array( ' ', '20%', '40%', '60%', '80%', ' ', ), 'topDecorationParams' => array( 'container' => array( 'style' => 'height:1.2em; ' . 'font-size=75%;color:gray;', ), 'list' => array( 'style' => 'height:1em; ' .
410
Zend_Dojo
'font-size=75%;color:gray;', ), ), 'bottomDecorationDijit' => 'HorizontalRule', 'bottomDecorationContainer' => 'bottomContainer', 'bottomDecorationLabels' => array( '0%', '50%', '100%', ), 'bottomDecorationParams' => array( 'list' => array( 'style' => 'height:1em; ' . 'font-size=75%;color:gray;', ), ), ) ) ->addElement( 'VerticalSlider', 'vertical', array( 'label' => 'VerticalSlider', 'value' => 5, 'style' => 'height: 200px; width: 3em;', 'minimum' => -10, 'maximum' => 10, 'discreteValues' => 11, 'intermediateChanges' => true, 'showButtons' => true, 'leftDecorationDijit' => 'VerticalRuleLabels', 'leftDecorationContainer' => 'leftContainer', 'leftDecorationLabels' => array( ' ', '20%', '40%', '60%', '80%', ' ', ), 'rightDecorationDijit' => 'VerticalRule', 'rightDecorationContainer' => 'rightContainer', 'rightDecorationLabels' => array( '0%', '50%', '100%', ), ) ); $this->addSubForm($textForm, 'textboxtab') ->addSubForm($editorForm, 'editortab') ->addSubForm($toggleForm, 'toggletab') ->addSubForm($selectForm, 'selecttab')
411
Zend_Dojo
->addSubForm($sliderForm, 'slidertab'); } }
412
Zend_Dojo
and compiles them to a single file, optionally stripping whitespace and comments, and performing code heuristics to allow further minification of variable names. Additionally, it can do CSS minification. In order to create a build layer, you would traditionally create a JavaScript file that has dojo.require statements for each dependency, and optionally some additional code that might run when the script is loaded. As an example:
dojo.provide("custom.main"); dojo.require("dijit.layout.TabContainer"); dojo.require("dijit.layout.ContentPane"); dojo.require("dijit.form.Form"); dojo.require("dijit.form.Button"); dojo.require("dijit.form.TextBox"); This script is generally referred to as a "layer" script. Then, in your application's layout, you'd instruct Dojo to load this module:
<html> <head> <script type="text/javascript" src="/js/dojo/dojo.js"></script> <script type="text/javascript"> dojo.registerModulePath("custom", "../custom/"); dojo.require("custom.main"); </script> If you use Zend_Dojo to do this, you'd do the following:
$view->dojo()->registerModulePath('custom', '../custom/') ->requireModule('custom.main'); But since Zend_Dojo aggregates your various dojo.require statements, how do you create your layer script? You could open each page and view the generated dojo.require statements, and cut and paste them into a layer script file manually. However, a better solution exists: since Zend_Dojo aggregates this information already, you can simply pull that information and build your layer file. This is the purpose of Zend_Dojo_BuildLayer.
413
Zend_Dojo
'layerName' => 'custom.main', )); $layerContents = $build->generateLayerScript(); $filename = APPLICATION_PATH . '/../public/js/custom/main.js'; if (!dir_exists(dirname($filename))) { mkdir(dirname($filename)); } file_put_contents($filename, $layerContents); When should you do the above? For it to work correctly, you need to do it after all view scripts and the layout have been rendered, to ensure that the dojo() helper is fully populated. One easy way to do so is using a front controller plugin, with a dispatchLoopShutdown() hook:
class App_Plugin_DojoLayer extends Zend_Controller_Plugin_Abstract { public $layerScript = APPLICATION_PATH . '/../public/js/custom/main.js'; protected $_build; public function dispatchLoopShutdown() { if (!file_exists($this->layerScript)) { $this->generateDojoLayer(); } } public function getBuild() { if (null === $this->_build) { $this->_build = new Zend_Dojo_BuildLayer(array( 'view' => $view, 'layerName' => 'custom.main', )); } return $this->_build; } public function generateDojoLayer() { $build = $this->getBuild(); $layerContents = $build->generateLayerScript(); if (!dir_exists(dirname($this->layerScript))) { mkdir(dirname($this->layerScript)); } file_put_contents($this->layerScript, $layerContents); } }
414
Zend_Dojo
BuildLayer options
The above functionality will suffice for most situations. For those needing more customization, a variety of options may be invoked.
$build->setView($view);
$build->setLayerName("custom.main");
$build = new Zend_Dojo_BuildLayer(array( 'view' => $view, 'layerName' => 'custom.main', 'consumeOnLoad' => true, )); Alternately, you can use the setConsumeOnLoad() method after instantiation:
$build->setConsumeOnLoad(true);
$build = new Zend_Dojo_BuildLayer(array( 'view' => $view, 'layerName' => 'custom.main', 'consumeJavascript' => true, ));
415
Zend_Dojo
Alternately, you can use the setConsumeJavascript() method after instantiation: $build->setConsumeJavascript(true);
public function dispatchLoopShutdown() { if (!file_exists($this->layerScript)) { $this->generateDojoLayer(); } if (!file_exists($this->buildProfile)) { $this->generateBuildProfile(); } } public function generateDojoLayer() { /* ... */ } public function generateBuildProfile() { $profile = $this->getBuild()->generateBuildProfile(); file_put_contents($this->buildProfile, $profile); } } As noted, with module layers, you should only create the file once.
416
Zend_Dojo
{ action: optimize: layerOptimize: copyTests: loader: cssOptimize: } You can pass in whatever key and value pairs you want; the Dojo build script will ignore those it does not understand. As an example of setting options: "release", "shrinksafe", "shrinksafe", false, "default", "comments"
// A single option: $build->addProfileOption('version', 'zend-1.3.1'); // Several options: $build->addProfileOptions(array( 'loader' => 'xdomain', 'optimize' => 'packer', )); // Or overwrite options: $build->setProfileOptions(array( 'version' => 'custom-1.3.1', 'loader' => 'shrinksafe', 'optimize' => 'shrinksafe', ));
417
418
Zend_Dom_Query
Zend_Dom_Query provides mechanisms for querying XML and (X)HTML documents utilizing either XPath or CSS selectors. It was developed to aid with functional testing of MVC applications, but could also be used for rapid development of screen scrapers. CSS selector notation is provided as a simpler and more familiar notation for web developers to utilize when querying documents with XML structures. The notation should be familiar to anybody who has developed Cascading Style Sheets or who utilizes Javascript toolkits that provide functionality for selecting nodes utilizing CSS selectors (Prototype's $$() [http://prototypejs.org/api/utility/dollar-dollar] and Dojo's dojo.query [http://api.dojotoolkit.org/ jsdoc/dojo/HEAD/dojo.query] were both inspirations for the component).
Theory of Operation
To use Zend_Dom_Query, you instantiate a Zend_Dom_Query object, optionally passing a document to query (a string). Once you have a document, you can use either the query() or queryXpath() methods; each method will return a Zend_Dom_Query_Result object with any matching nodes. The primary difference between Zend_Dom_Query and using DOMDocument + DOMXPath is the ability to select against CSS selectors. You can utilize any of the following, in any combination: element types: provide an element type to match: 'div', 'a', 'span', 'h2', etc. style attributes: CSS style attributes to match: '.error', 'div.error', 'label.required', etc. If an element defines more than one style, this will match as long as the named style is present anywhere in the style declaration. id attributes: element ID attributes to match: '#content', 'div#nav', etc. arbitrary attributes: arbitrary element attributes to match. Three different types of matching are provided: exact match: the attribute exactly matches the string: 'div[bar="baz"]' would match a div element with a "bar" attribute that exactly matches the value "baz". word match: the attribute contains a word matching the string: 'div[bar~="baz"]' would match a div element with a "bar" attribute that contains the word "baz". '<div bar="foo baz">' would match, but '<div bar="foo bazbat">' would not. substring match: the attribute contains the string: 'div[bar*="baz"]' would match a div element with a "bar" attribute that contains the string "baz" anywhere within it. direct descendents: utilize '>' between selectors to denote direct descendents. 'div > span' would select only 'span' elements that are direct descendents of a 'div'. Can also be used with any of the selectors above. descendents: string together multiple selectors to indicate a hierarchy along which to search. 'div .foo span #one' would select an element of id 'one' that is a descendent of arbitrary depth beneath a 'span' element, which is in turn
419
Zend_Dom
a descendent of arbitrary depth beneath an element with a class of 'foo', that is an descendent of arbitrary depth beneath a 'div' element. For example, it would match the link to the word 'One' in the listing below:
<div> <table> <tr> <td class="foo"> <div> Lorem ipsum <span class="bar"> <a href="/foo/bar" id="one">One</a> <a href="/foo/baz" id="two">Two</a> <a href="/foo/bat" id="three">Three</a> <a href="/foo/bla" id="four">Four</a> </span> </div> </td> </tr> </table> </div> Once you've performed your query, you can then work with the result object to determine information about the nodes, as well as to pull them and/or their content directly for examination and manipulation. Zend_Dom_Query_Result implements Countable and Iterator, and store the results internally as DOMNodes/DOMElements. As an example, consider the following call, that selects against the HTML above:
$dom = new Zend_Dom_Query($html); $results = $dom->query('.foo .bar a'); $count = count($results); // get number of matches: 4 foreach ($results as $result) { // $result is a DOMElement } Zend_Dom_Query also allows straight XPath queries utilizing the queryXpath() method; you can pass any valid XPath query to this method, and it will return a Zend_Dom_Query_Result object.
Methods Available
The Zend_Dom_Query family of classes have the following methods available.
Zend_Dom_Query
The following methods are available to Zend_Dom_Query: setDocumentXml($document): specify an XML string to query against. setDocumentXhtml($document): specify an XHTML string to query against. setDocumentHtml($document): specify an HTML string to query against. setDocument($document): specify a string to query against; Zend_Dom_Query will then attempt to autodetect the document type.
420
Zend_Dom
getDocument(): retrieve the original document string provided to the object. getDocumentType(): retrieve the document type of the document provided to the object; will be one of the DOC_XML, DOC_XHTML, or DOC_HTML class constants. query($query): query the document using CSS selector notation. queryXpath($xPathQuery): query the document using XPath notation.
Zend_Dom_Query_Result
As mentioned previously, Zend_Dom_Query_Result implements both Iterator and Countable, and as such can be used in a foreach loop as well as with the count() function. Additionally, it exposes the following methods: getCssQuery(): return the CSS selector query used to produce the result (if any). getXpathQuery(): return the XPath query used to produce the result. Internally, Zend_Dom_Query converts CSS selector queries to XPath, so this value will always be populated. getDocument(): retrieve the DOMDocument the selection was made against.
421
422
try { // Calling Zend_Loader::loadClass() with a non-existant class will cause // an exception to be thrown in Zend_Loader Zend_Loader::loadClass('nonexistantclass'); } catch (Zend_Exception $e) { echo "Caught exception: " . get_class($e) . "\n"; echo "Message: " . $e->getMessage() . "\n"; // Other code to recover from the error } Zend_Exception can be used as a catch-all exception class in a catch block to trap all exceptions thrown by Zend Framework classes. This can be useful when the program can not recover by catching a specific exception type. The documentation for each Zend Framework component and class will contain specific information on which methods throw exceptions, the circumstances that cause an exception to be thrown, and the class of all exceptions that may be thrown.
423
424
Be aware
Many RSS feeds have different channel and item properties available. The RSS specification provides for many optional properties, so be aware of this when writing code to work with RSS data.
// Loop over each channel item and store relevant data foreach ($slashdotRss as $item) { $channel['items'][] = array( 'title' => $item->title(), 'link' => $item->link(), 'description' => $item->description() ); }
425
Zend_Feed
Importing Feeds
Zend_Feed enables developers to retrieve feeds very easily. If you know the URI of a feed, simply use the Zend_Feed::import() method:
$feed = Zend_Feed::import('http://feeds.example.com/feedName'); You can also use Zend_Feed to fetch the contents of a feed from a file or the contents of a PHP string variable:
// importing a feed from a text file $feedFromFile = Zend_Feed::importFile('feed.xml'); // importing a feed from a PHP string variable $feedFromPHP = Zend_Feed::importString($feedString); In each of the examples above, an object of a class that extends Zend_Feed_Abstract is returned upon success, depending on the type of the feed. If an RSS feed were retrieved via one of the import methods above, then a Zend_Feed_Rss object would be returned. On the other hand, if an Atom feed were imported, then a Zend_Feed_Atom object is returned. The import methods will also throw a Zend_Feed_Exception object upon failure, such as an unreadable or malformed feed.
Custom feeds
Zend_Feed enables developers to create custom feeds very easily. You just have to create an array and to import it with Zend_Feed. This array can be imported with Zend_Feed::importArray() or with Zend_Feed::importBuilder(). In this last case the array will be computed on the fly by a custom data source implementing Zend_Feed_Builder_Interface.
array( //required 'title' => 'title of the feed', 'link' => 'canonical url to the feed', // optional 'lastUpdate' => 'timestamp of the update date', 'published' => 'timestamp of the publication date',
426
Zend_Feed
// required 'charset' => 'charset of the textual data', // optional 'description' => 'short description of the feed', 'author' => 'author/publisher of the feed', 'email' => 'email of the author', // optional, ignored if atom is used 'webmaster' => 'email address for person responsible ' . 'for technical issues', // optional 'copyright' 'image' 'generator' 'language'
'copyright notice', 'url to image', 'generator', 'language the feed is written in',
// optional, ignored if atom is used 'ttl' => 'how long in minutes a feed can be cached ' . 'before refreshing', 'rating' => 'The PICS rating for the channel.', // optional, ignored if atom is used // a cloud to be notified of updates 'cloud' => array( // required 'domain' => 'domain of the cloud, e.g. rpc.sys.com', // optional, defaults to 80 'port' => 'port to connect to', // required 'path' => 'path of the cloud, e.g. /RPC2', 'registerProcedure' => 'procedure to call, e.g. myCloud.rssPlsNotify', 'protocol' => 'protocol to use, e.g. soap or xml-rpc' ), // optional, ignored if atom is used // a text input box that can be displayed with the feed 'textInput' => array( // required 'title' => 'label of the Submit button in the text input area', 'description' => 'explains the text input area', 'name' => 'the name of the text object in the text input area', 'link' => 'URL of the CGI script processing text input requests' ), // optional, ignored if atom is used // Hint telling aggregators which hours they can skip 'skipHours' => array( // up to 24 rows whose value is a number between 0 and 23 // e.g 13 (1pm)
427
Zend_Feed
'hour in 24 format' ), // optional, ignored if atom is used // Hint telling aggregators which days they can skip 'skipDays ' => array( // up to 7 rows whose value is // Monday, Tuesday, Wednesday, Thursday, Friday, Saturday or Sunday // e.g Monday 'a day to skip' ), // optional, ignored if atom is used // Itunes extension data 'itunes' => array( // optional, default to the main author value 'author' => 'Artist column', // optional, default to the main author value // Owner of the podcast 'owner' => array( 'name' => 'name of the owner', 'email' => 'email of the owner' ), // optional, default to the main image value 'image' => 'album/podcast art', // optional, default to the main description value 'subtitle' => 'short description', 'summary' => 'longer description', // optional 'block' => 'Prevent an episode from appearing (yes|no)', // required, Category column and in iTunes Music Store Browse 'category' => array( // up to 3 rows array( // required 'main' => 'main category', // optional 'sub' => 'sub category' ) ), // optional 'explicit' => 'parental advisory graphic (yes|no|clean)', 'keywords' => 'a comma separated list of 12 keywords maximum', 'new-feed-url' => 'used to inform iTunes of new feed URL location' ), 'entries' => array(
428
Zend_Feed
array( //required 'title' => 'title of the feed entry', 'link' => 'url to a feed entry', // required, only text, no html 'description' => 'short version of a feed entry', // optional 'guid' => 'id of the article, ' . 'if not given link value will used', // optional, can contain html 'content' => 'long version', // optional 'lastUpdate' => 'timestamp of the publication date', 'comments' => 'comments page of the feed entry', 'commentRss' => 'the feed url of the associated comments', // optional, original source of the feed entry 'source' => array( // required 'title' => 'title of the original source', 'url' => 'url of the original source' ), // optional, list of the attached categories 'category' => array( array( // required 'term' => 'first category label', // optional 'scheme' => 'url that identifies a categorization scheme' ), array( // data for the second category and so on ) ), // optional, list of the enclosures of the feed entry 'enclosure' => array( array( // required 'url' => 'url of the linked enclosure', // optional 'type' => 'mime type of the enclosure', 'length' => 'length of the linked content in octets' ), array(
429
Zend_Feed
//data for the second enclosure and so on ) ) ), array( //data for the second entry and so on ) ) ); References: RSS 2.0 specification: RSS 2.0 [http://blogs.law.harvard.edu/tech/rss] Atom specification: RFC 4287 [http://tools.ietf.org/html/rfc4287] WFW specification: Well Formed Web [http://wellformedweb.org/news/wfw_namespace_elements] iTunes specification: iTunes Technical Specifications [http://www.apple.com/itunes/store/podcaststechspecs.html]
Nota
Zend_Feed_Builder serves as a concrete implementation to demonstrate the usage. Users are encouraged to make their own classes to implement Zend_Feed_Builder_Interface. Here is an example of Zend_Feed::importBuilder() usage:
// importing a feed from a custom builder source $atomFeedFromArray = Zend_Feed::importBuilder(new Zend_Feed_Builder($array)); // the following line is equivalent to the above; // by default a Zend_Feed_Atom instance is returned $atomFeedFromArray = Zend_Feed::importBuilder(new Zend_Feed_Builder($array), 'atom'); // importing a rss feed from a custom builder array $rssFeedFromArray = Zend_Feed::importBuilder(new Zend_Feed_Builder($array), 'rss');
430
Zend_Feed
assert($feed instanceof Zend_Feed_Abstract); // dump the feed to standard output print $feed->saveXML(); // send http headers and dump the feed $feed->send();
$feedArray = Zend_Feed::findFeeds('http://www.example.com/news.html'); Here the findFeeds() method returns an array of Zend_Feed_Abstract objects that are referenced by <link> tags on the news.html web page. Depending on the type of each feed, each respective entry in the $feedArray array may be a Zend_Feed_Rss or Zend_Feed_Atom instance. Zend_Feed will throw a Zend_Feed_Exception upon failure, such as an HTTP 404 response code or a malformed feed.
echo $channel->title(); Note the function syntax. Zend_Feed uses a convention of treating properties as XML object if they are requested with variable "getter" syntax ($obj->property) and as strings if they are access with method syntax ($obj>property()). This enables access to the full text of any individual node while still allowing full access to all children. If channel properties have attributes, they are accessible using PHP's array syntax:
echo $channel->category['domain']; Since XML attributes cannot have children, method syntax is not necessary for accessing attribute values. Most commonly you'll want to loop through the feed and do something with its entries. Zend_Feed_Abstract implements PHP's Iterator interface, so printing all titles of articles in a channel is just a matter of:
431
Zend_Feed
If you are not familiar with RSS, here are the standard elements you can expect to be available in an RSS channel and in individual RSS items (entries). Required channel elements: title - The name of the channel link - The URL of the web site corresponding to the channel description - A sentence or several describing the channel Common optional channel elements: pubDate - The publication date of this set of content, in RFC 822 date format language - The language the channel is written in category - One or more (specified by multiple tags) categories the channel belongs to RSS <item> elements do not have any strictly required elements. However, either title or description must be present. Common item elements: title - The title of the item link - The URL of the item description - A synopsis of the item author - The author's email address category - One more categories that the item belongs to comments - URL of comments relating to this item pubDate - The date the item was published, in RFC 822 date format In your code you can always test to see if an element is non-empty with:
if ($item->propname()) { // ... proceed. } If you use $item->propname instead, you will always get an empty object which will evaluate to TRUE, so your check will fail. For further information, the official RSS 2.0 specification is available at: http://blogs.law.harvard.edu/tech/rss
432
Zend_Feed
$feed = new Zend_Feed_Atom('http://atom.example.com/feed/'); echo 'The feed contains ' . $feed->count() . ' entries.' . "\n\n"; foreach ($feed as $entry) { echo 'Title: ' . $entry->title() . "\n"; echo 'Summary: ' . $entry->summary() . "\n\n"; } In an Atom feed you can expect to find the following feed properties: title - The feed's title, same as RSS's channel title id - Every feed and entry in Atom has a unique identifier link - Feeds can have multiple links, which are distinguished by a type attribute The equivalent to RSS's channel link would be type="text/html". if the link is to an alternate version of the same content that's in the feed, it would have a rel="alternate" attribute. subtitle - The feed's description, equivalent to RSS' channel description author->name() - The feed author's name author->email() - The feed author's email address Atom entries commonly have the following properties: id - The entry's unique identifier title - The entry's title, same as RSS item titles link - A link to another format or an alternate view of this entry summary - A summary of this entry's content content - The full content of the entry; can be skipped if the feed just contains summaries author - with name and email sub-tags like feeds have published - the date the entry was published, in RFC 3339 format updated - the date the entry was last updated, in RFC 3339 format For more information on Atom and plenty of resources, see http://www.atomenabled.org/.
433
Zend_Feed
Ejemplo 20.4. Using the Entry Object Directly for a Single-Entry Atom Feed
$entry = new Zend_Feed_Entry_Atom('http://atom.example.com/feed/1'); echo $entry->title();
434
Zend_Feed
// Now do the custom part. Zend_Feed::registerNamespace('myns', 'http://www.example.com/myns/1.0'); $entry->{'myns:myelement_one'} = 'my first custom value'; $entry->{'myns:container_elt'}->part1 = 'first nested custom part'; $entry->{'myns:container_elt'}->part2 = 'second nested custom part'; echo $entry->saveXML();
Ejemplo 20.7. Extending the Atom Entry Class with Custom Namespaces
/** * The custom entry class automatically knows the feed URI (optional) and * can automatically add extra namespaces. */ class MyEntry extends Zend_Feed_Entry_Atom { public function __construct($uri = 'http://www.example.com/myfeed/', $xml = null) { parent::__construct($uri, $xml); Zend_Feed::registerNamespace('myns', 'http://www.example.com/myns/1.0'); } public function __get($var) { switch ($var) { case 'myUpdated': // Translate myUpdated to myns:updated. return parent::__get('myns:updated'); default: return parent::__get($var); } } public function __set($var, $value) { switch ($var) { case 'myUpdated':
435
Zend_Feed
// Translate myUpdated to myns:updated. parent::__set('myns:updated', $value); break; default: parent::__set($var, $value); } } public function __call($var, $unused) { switch ($var) { case 'myUpdated': // Translate myUpdated to myns:updated. return parent::__call('myns:updated', $unused); default: return parent::__call($var, $unused); } } } Then to use this class, you'd just instantiate it directly and set the myUpdated property:
$entry = new MyEntry(); $entry->myUpdated = '2005-04-19T15:30'; // method-style call is handled by __call function $entry->myUpdated(); // property-style call is handled by __get function $entry->myUpdated;
Zend_Feed_Reader
Introduction
Zend_Feed_Reader is a component used to consume RSS and Atom feeds of any version, including RDF/RSS 1.0, RSS 2.0 and Atom 0.3/1.0. The API for retrieving feed data is deliberately simple since Zend_Feed_Reader is capable of searching any feed of any type for the information requested through the API. If the typical elements containing this information are not present, it will adapt and fall back on a variety of alternative elements instead. This ability to choose from alternatives removes the need for users to create their own abstraction layer on top of the component to make it useful or have any in-depth knowledge of the underlying standards, current alternatives, and namespaced extensions. Internally, Zend_Feed_Reader works almost entirely on the basis of making XPath queries against the feed XML's Document Object Model. The DOM is not exposed though a chained property API like Zend_Feed though the underlying DOMDocument, DOMElement and DOMXPath objects are exposed for external manipulation. This singular approach to parsing is consistent and the component offers a plugin system to add to the Feed and Entry level API by writing Extensions on a similar basis. Performance is assisted in three ways. First of all, Zend_Feed_Reader supports caching using Zend_Cache to maintain a copy of the original feed XML. This allows you to skip network requests for a feed URI if the cache is
436
Zend_Feed
valid. Second, the Feed and Entry level API is backed by an internal cache (non-persistant) so repeat API calls for the same feed will avoid additional DOM/XPath use. Thirdly, importing feeds from a URI can take advantage of HTTP Conditional GET requests which allow servers to issue an empty 304 response when the requested feed has not changed since the last time you requested it. In the final case, an instance of Zend_Cache will hold the last received feed along with the ETag and Last-Modified header values sent in the HTTP response. In relation to Zend_Feed, Zend_Feed_Reader was formulated as a free standing replacement for Zend_Feed but it is not backwards compatible with Zend_Feed. Rather it is an alternative following a different ideology focused on being simple to use, flexible, consistent and extendable through the plugin system. Zend_Feed_Reader is also not capable of constructing feeds through this will be addressed at a future date.
Importing Feeds
Importing a feed with Zend_Feed_Reader is not that much different to Zend_Feed. Feeds can be imported from a string, file, URI or an instance of type Zend_Feed_Abstract. Importing from a URI can additionally utilise a HTTP Conditional GET request. If importing fails, an exception will be raised. The end result will be an object of type Zend_Feed_Reader_FeedInterface, the core implementations of which are Zend_Feed_Reader_Feed_Rss and Zend_Feed_Reader_Feed_Atom (Zend_Feed took all the short names!). Both objects support multiple (all existing) versions of these broad feed types. In the following example, we import an RDF/RSS 1.0 feed and extract some basic information that can be saved to a database or elsewhere.
$feed = Zend_Feed_Reader::import('http://www.planet-php.net/rdf/'); $data = array( 'title' => $feed->getTitle(), 'link' => $feed->getLink(), 'dateModified' => $feed->getDateModified(), 'description' => $feed->getDescription(), 'language' => $feed->getLanguage(), 'entries' => array(), ); foreach ($feed as $entry) { $edata = array( 'title' => $entry->getTitle(), 'description' => $entry->getDescription(), 'dateModified' => $entry->getDateModified(), 'author' => $entry->getAuthor(), 'link' => $entry->getLink(), 'content' => $entry->getContent() ); $data['entries'][] = $edata; } The example above demonstrates Zend_Feed_Reader's API, and it also demonstrates some of it's internal operation. In reality, the RDF feed selected does not have any native date or author elements, however it does utilise the Dublin Core 1.1 module which offers namespaced creator and date elements. Zend_Feed_Reader falls back on these and similar options if no relevant native elements exist. If it absolutely cannot find an alternative it will return NULL, indicating the information could not be found in the feed. You should note that classes implementing Zend_Feed_Reader_FeedInterface also implement the SPL Iterator and Countable interfaces. Feeds can also be imported from strings, files, and even objects of type Zend_Feed_Abstract.
437
Zend_Feed
// from a URI $feed = Zend_Feed_Reader::import('http://www.planet-php.net/rdf/'); // from a String $feed = Zend_Feed_Reader::importString($feedXmlString); // from a file $feed = Zend_Feed_Reader::importFile('./feed.xml'); // from a Zend_Feed_Abstract object $zfeed = Zend_Feed::import('http://www.planet-php.net/atom/'); $feed = Zend_Feed_Reader::importFeed($zfeed);
$feed = Zend_Feed_Reader::import('http://www.planet-php.net/rdf/'); $xpathPrefix = $feed->getXpathPrefix(); $xpath = $feed->getXpath(); $xpath->registerNamespace('admin', 'http://webns.net/mvcb/'); $reportErrorsTo = $xpath->evaluate('string(' . $xpathPrefix . '/admin:errorReportsTo)');
Warning
If you register an already registered namespace with a different prefix name to that used internally by Zend_Feed_Reader, it will break the internal operation of this component.
438
Zend_Feed
Nota
While it's a little off track, you should also consider adding a cache to Zend_Loader_PluginLoader which is used by Zend_Feed_Reader to load Extensions.
439
Zend_Feed
$feed = Zend_Feed_Reader::import('http://www.planet-php.net/rdf/'); In the example above, with HTTP Conditional GET requests enabled, the response header values for ETag and LastModified will be cached along with the feed. For the next 24hrs (the cache lifetime), feeds will only be updated on the cache if a non-304 response is received containing a valid RSS or Atom XML document. If you intend on managing request headers from outside Zend_Feed_Reader, you can set the relevant If-NoneMatches and If-Modified-Since request headers via the URI import method. $lastEtagReceived = '5e6cefe7df5a7e95c8b1ba1a2ccaff3d'; $lastModifiedDateReceived = 'Wed, 08 Jul 2009 13:37:22 GMT'; $feed = Zend_Feed_Reader::import( $uri, $lastEtagReceived, $lastModifiedDateReceived );
440
Zend_Feed
} The available keys are href, rel which will always be 'alternate', type which will be one of application/ rss+xml, application/rdf+xml or application/atom+xml and feed. feed is only available if you preserve the ArrayObject (i.e. do not cast it to an array) and using it triggers an attempt to load the feed into a Zend_Feed_Reader_FeedAbstract instance. This is a lazy loaded attempt - feeds are never loaded until you try to access them using this method.
getDateCreated()
getDateModified() getLanguage()
441
Zend_Feed
getGenerator()
Returns the generator of the feed, e.g. the software which generated it. This may differ between RSS and Atom since Atom defines a different notation. Returns any copyright notice associated with the feed Returns an array of all Hub Server URI endpoints which are advertised by the feed for using with the Pubsubhubbub Protocol, allowing subscriptions to the feed for real-time updates.
getCopyright() getHubs()
Given the variety of feeds in the wild, some of these methods will undoubtedly return NULL indicating the relevant information couldn't be located. Where possible, Zend_Feed_Reader will fall back on alternative elements during its search. For example, searching an RSS feed for a modification date is more complicated than it looks. RSS 2.0 feeds should include a <lastBuildDate> tag and/or a <pubDate> element. But what if it doesn't, maybe this is an RSS 1.0 feed? Perhaps it instead has an <atom:updated> element with identical information (Atom may be used to supplement RSS's syntax)? Failing that, we could simply look at the entries, pick the most recent, and use its <pubDate> element. Assuming it exists... Many feeds also use Dublin Core 1.0/1.1 <dc:date> elements for feeds/entries. Or we could find Atom lurking again. The point is, Zend_Feed_Reader was designed to know this. When you ask for the modification date (or anything else), it will run off and search for all these alternatives until it either gives up and returns NULL, or finds an alternative that should have the right answer. In addition to the above methods, all Feed objects implement methods for retrieving the DOM and XPath objects for the current feeds as described earlier. Feed objects also implement the SPL Iterator and Countable interfaces. The extended API is summarised below.
getXpath()
getXpathPrefix() getEncoding()
442
Zend_Feed
valid()
Checks that the current entry index is valid, i.e. it does fall below 0 and does not exceed the number of entries existing. Returns an array of all Extension objects loaded for the current feed (note: both feed-level and entrylevel Extensions exist, and only feed-level Extensions are returned here). The array keys are of the form {ExtensionName}_Feed. Returns an Extension object for the feed registered under the provided name. This allows more fine-grained access to Extensions which may otherwise be hidden within the implementation of the standard API methods. Returns a static class constant (e.g. Zend_Feed_Reader::TYPE_ATOM_03, i.e. Atom 0.3) indicating exactly what kind of feed is being consumed.
getExtensions()
getExtension(string $name)
getType()
getDateCreated()
getDateModified() getContent()
getEnclosure()
443
Zend_Feed
Returns the number of comments made on this entry at the time the feed was last generated Returns a URI pointing to the HTML page where comments can be made on this entry = Returns a URI pointing to a feed of the provided type containing all comments for this entry (type defaults to Atom/RSS depending on current feed type).
The extended API for entries is identical to that for feeds with the exception of the Iterator methods which are not needed here.
Caution
There is often confusion over the concepts of modified and created dates. In Atom, these are two clearly defined concepts (so knock yourself out) but in RSS they are vague. RSS 2.0 defines a single <pubDate> element which typically refers to the date this entry was published, i.e. a creation date of sorts. This is not always the case, and it may change with updates or not. As a result, if you really want to check whether an entry has changed, don't rely on the results of getDateModified(). Instead, consider tracking the MD5 hash of three other elements concatenated, e.g. using getTitle(), getDescription() and getContent(). If the entry was trully updated, this hash computation will give a different result than previously saved hashes for the same entry. Further muddying the waters, dates in feeds may follow different standards. Atom and Dublin Core dates should follow ISO 8601, and RSS dates should follow RFC 822 or RFC 2822 which is also common. Date methods will throw an exception if Zend_Date cannot load the date string using one of the above standards.
Warning
The values returned from these methods are not validated. This means users must perform validation on all retrieved data including the filtering of any HTML such as from getContent() before it is output from your application. Remember that most feeds come from external sources, and therefore the default assumption should be that they cannot be trusted.
getXpathPrefix() getEncoding()
getExtensions()
444
Zend_Feed
getExtension(string $name)
Returns an Extension object for the entry registered under the provided name. This allows more fine-grained access to Extensions which may otherwise be hidden within the implementation of the standard API methods. Returns a static class constant (e.g. Zend_Feed_Reader::TYPE_ATOM_03, i.e. Atom 0.3) indicating exactly what kind of feed is being consumed.
getType()
The Core Extensions are somewhat special since they are extremely common and multi-faceted. For example, we have a Core Extension for Atom. Atom is implemented as an Extension (not just a base class) because it doubles as a valid RSS module - you can insert Atom elements into RSS feeds. I've even seen RDF feeds which use a lot of Atom in place of more common Extensions like Dublin Core.
445
Zend_Feed
The additional non-Core Extensions are offered but not registered to Zend_Feed_Reader by default. If you want to use them, you'll need to tell Zend_Feed_Reader to load them in advance of importing a feed. Additional nonCore Extensions will be included in future iterations of the component. Registering an Extension with Zend_Feed_Reader, so it is loaded and its API is available to Feed and Entry objects, is a simple affair using the Zend_Loader_PluginLoader. Here we register the optional Slash Extension, and discover that it can be directly called from the Entry level API without any effort. Note that Extension names are case sensitive and use camel casing for multiple terms. Zend_Feed_Reader::registerExtension('Syndication'); $feed = Zend_Feed_Reader::import('http://rss.slashdot.org/Slashdot/slashdot'); $updatePeriod = $feed->current()->getUpdatePeriod(); In the simple example above, we checked how frequently a feed is being updated using the getUpdatePeriod() method. Since it's not part of Zend_Feed_Reader's core API, it could only be a method supported by the newly registered Syndication Extension. As you can also notice, the new methods from Extensions are accessible from the main API using PHP's magic methods. As an alternative, you can also directly access any Extension object for a similar result as seen below. Zend_Feed_Reader::registerExtension('Syndication'); $feed = Zend_Feed_Reader::import('http://rss.slashdot.org/Slashdot/slashdot'); $syndication = $feed->getExtension('Syndication'); $updatePeriod = $syndication->getUpdatePeriod();
446
Zend_Feed
<jungle:dayPopular>http://example.com/junglebooks/book/938</jungle:dayPopular> <item> <title>Review Of Flatland: A Romance of Many Dimensions</title> <link>http://example.com/junglebooks/review/987</link> <author>Confused Physics Student</author> <content:encoded> A romantic square?! </content:encoded> <pubDate>Thu, 25 Jun 2009 20:03:28 -0700</pubDate> <jungle:isbn>048627263X</jungle:isbn> </item> </channel> </rss> Implementing this new ISBN element as a simple entry level extension would require the following class (using your own class namespace outside of Zend). class My_FeedReader_Extension_JungleBooks_Entry extends Zend_Feed_Reader_Extension_EntryAbstract { public function getIsbn() { if (isset($this->_data['isbn'])) { return $this->_data['isbn']; } $isbn = $this->_xpath->evaluate( 'string(' . $this->getXpathPrefix() . '/jungle:isbn)' ); if (!$isbn) { $isbn = null; } $this->_data['isbn'] = $isbn; return $this->_data['isbn']; } protected function _registerNamespaces() { $this->_xpath->registerNamespace( 'jungle', 'http://example.com/junglebooks/rss/module/1.0/' ); } } This extension is easy enough to follow. It creates a new method getIsbn() which runs an XPath query on the current entry to extract the ISBN number enclosed by the <jungle:isbn> element. It can optionally store this to the internal non-persistent cache (no need to keep querying the DOM if it's called again on the same entry). The value is returned to the caller. At the end we have a protected method (it's abstract so it must exist) which registers the Jungle Books namespace for their custom RSS module. While we call this an RSS module, there's nothing to prevent the same element being used in Atom feeds - and all Extensions which use the prefix provided by getXpathPrefix() are actually neutral and work on RSS or Atom feeds with no extra code. Since this Extension is stored outside of Zend Framework, you'll need to register the path prefix for your Extensions so Zend_Loader_PluginLoader can find them. After that, it's merely a matter of registering the Extension, if it's not already loaded, and using it in practice.
447
Zend_Feed
if(!Zend_Feed_Reader::isRegistered('JungleBooks')) { Zend_Feed_Reader::addPrefixPath( '/path/to/My/FeedReader/Extension', 'My_FeedReader_Extension' ); Zend_Feed_Reader::registerExtension('JungleBooks'); } $feed = Zend_Feed_Reader::import('http://example.com/junglebooks/rss'); // ISBN for whatever book the first entry in the feed was concerned with $firstIsbn = $feed->current()->getIsbn(); Writing a feed level Extension is not much different. The example feed from earlier included an unmentioned <jungle:dayPopular> element which Jungle Books have added to their standard to include a link to the day's most popular book (in terms of visitor traffic). Here's an Extension which adds a getDaysPopularBookLink() method to the feel level API. class My_FeedReader_Extension_JungleBooks_Feed extends Zend_Feed_Reader_Extension_FeedAbstract { public function getDaysPopularBookLink() { if (isset($this->_data['dayPopular'])) { return $this->_data['dayPopular']; } $dayPopular = $this->_xpath->evaluate( 'string(' . $this->getXpathPrefix() . '/jungle:dayPopular)' ); if (!$dayPopular) { $dayPopular = null; } $this->_data['dayPopular'] = $dayPopular; return $this->_data['dayPopular']; } protected function _registerNamespaces() { $this->_xpath->registerNamespace( 'jungle', 'http://example.com/junglebooks/rss/module/1.0/' ); } } Let's repeat the last example using a custom Extension to show the method being used. if(!Zend_Feed_Reader::isRegistered('JungleBooks')) { Zend_Feed_Reader::addPrefixPath( '/path/to/My/FeedReader/Extension', 'My_FeedReader_Extension' ); Zend_Feed_Reader::registerExtension('JungleBooks'); } $feed = Zend_Feed_Reader::import('http://example.com/junglebooks/rss');
448
Zend_Feed
// URI to the information page of the day's most popular book with visitors $daysPopularBookLink = $feed->getDaysPopularBookLink(); // ISBN for whatever book the first entry in the feed was concerned with $firstIsbn = $feed->current()->getIsbn(); Going through these examples, you'll note that we don't register feed and entry Extensions separately. Extensions within the same standard may or may not include both a feed and entry class, so Zend_Feed_Reader only requires you to register the overall parent name, e.g. JungleBooks, DublinCore, Slash. Internally, it can check at what level Extensions exist and load them up if found. In our case, we have a full set of Extensions now: JungleBooks_Feed and JungleBooks_Entry.
449
450
Limitation
The current implementation of Zend_File_Transfer is limited to HTTP Post Uploads. Other adapters supporting downloads and other protocols will be added in future releases. Unimplemented methods will throw an exception. For now, you should use Zend_File_Transfer_Adapter_Http directly. As soon as there are multiple adapters available you can use a common interface.
Forms
When you are using Zend_Form you should use the APIs provided by Zend_Form and not Zend_File_Transfer directly. The file transfer support in Zend_Form is implemented with Zend_File_Transfer, so the information in this chapter may be useful for advanced users of Zend_Form. The usage of Zend_File_Transfer is relatively simple. It consists of two parts. The HTTP form does the upload, while the Zend_File_Transfer handles the uploaded files. See the following example:
<form enctype="multipart/form-data" action="/file/upload" method="POST"> <input type="hidden" name="MAX_FILE_SIZE" value="100000" /> Choose a file to upload: <input name="uploadedfile" type="file" /> <br /> <input type="submit" value="Upload File" /> </form> For convenience, you can use Zend_Form_Element_File instead of building the HTML manually. The next step is to create the receiver of the upload. In our example the receiver is located at /file/upload. So next we will create the file controller and the upload action.
$adapter = new Zend_File_Transfer_Adapter_Http(); $adapter->setDestination('C:\temp'); if (!$adapter->receive()) { $messages = $adapter->getMessages(); echo implode("\n", $messages); }
451
Zend_File
This code listing demonstrates the simplest usage of Zend_File_Transfer. A local destination is set with the setDestination method, then the receive() method is called. if there are any upload errors, an error will be returned.
Attention
This example is suitable only for demonstrating the basic API of Zend_File_Transfer. You should never use this code listing in a production environment, because severe security issues may be introduced. You should always use validators to increase security.
Checking Files
Zend_File_Transfer has several methods that check for various states of the specified file. These are useful if you must process files after they have been uploaded. These methods include: isValid($files = null): This method will check if the given files are valid, based on the validators that are attached to the files. If no files are specified, all files will be checked. You can call isValid() before calling receive(); in this case, receive() will not call isValid internally again when receiving the file. isUploaded($files = null): This method will check if the specified files have been uploaded by the user. This is useful when you have defined one or more optional files. When no files are specified, all files will be checked. isReceived($files = null): This method will check if the given files have already been received. When no files are specified, all files will be checked.
452
Zend_File
// validators are ok ? if (!$upload->isValid($file)) { print "Sorry but $file is not what we wanted"; continue; } } $upload->receive();
Nota
Note that the file name can change after you receive the file, because all filters will be applied once the file is received. So you should always call getFileName() after the files have been received. getFileSize() returns per default the real filesize in SI notation which means you will get 2kB instead of 2048. If you need only the plain size set the useByteString option to false.
453
Zend_File
$upload->receive(); // Returns the sizes from all files as array if more than one file was uploaded $size = $upload->getFileSize(); // Switches of the SI notation to return plain numbers $upload->setOption(array('useByteString' => false)); $size = $upload->getFileSize(); getHash() accepts the name of a hash algorithm as first parameter. For a list of known algorithms refer to PHP's hash_algos method [http://php.net/hash_algos]. If you don't specify an algorithm, the crc32 algorithm will be used by default.
Nota
Note that if the given file or form name contains more than one file, the returned value will be an array. getMimeType() returns the mimetype of a file. If more than one file was uploaded it returns an array, otherwise a string.
Nota
Note that this method uses the fileinfo extension if it is available. If this extension can not be found, it uses the mimemagic extension. When no extension was found it uses the mimetype given by the fileserver when the file was uploaded.
454
Zend_File
First, you need to have either APC or uploadprogress to be enabled. Note that you can disable this feature of APC within your php.ini. Second, you need to have the proper hidden fields added in the form which sends the files. When you use Zend_Form_Element_File this hidden fields are automatically added by Zend_Form. When the above two points are provided then you are able to get the actual progress of the file upload by using the getProgress method. Actually there are 2 official ways to handle this.
Ejemplo 21.7. Using the progressbar adapter to retrieve the actual state
$adapter = new Zend_ProgressBar_Adapter_Console(); $upload = Zend_File_Transfer_Adapter_Http::getProgress($adapter); $upload = null; while (!$upload['done']) { $upload = Zend_File_Transfer_Adapter_Http:getProgress($upload); } The complete handling is done by getProgress() for you in the background.
455
Zend_File
session: This optional key takes the name of a session namespace which will be used within Zend_ProgressBar. When this key is not given it defaults to Zend_File_Transfer_Adapter_Http_ProgressBar. All other returned keys are provided directly from the extensions and will not be checked. The following example shows a possible manual usage:
while (!$upload['done']) { $upload = Zend_File_Transfer_Adapter_Http:getProgress($upload); print "\nActual progress:".$upload['message']; // do whatever you need }
456
Zend_File
Md5: This validator checks for the md5 hash value of the content from a file. It is based on the Hash validator and provides a convenient and simple validator that only supports Md5. MimeType: This validator validates the MIME type of files. It can also validate MIME types and will throw an error if the MIME type of a specified file does not match. NotExists: This validator checks for the existence of files. It will throw an error when an given file does exist. Sha1: This validator checks for the sha1 hash value of the content from a file. It is based on the Hash validator and provides a convenient and simple validator that only supports sha1. Size: This validator is able to check files for its file size. It provides a minimum and maximum size range and will throw an error when either of these thesholds are crossed. Upload: This validator is internal. It checks if an upload has resulted in an error. You must not set it, as it's automatically set by Zend_File_Transfer itself. So you do not use this validator directly. You should only know that it exists. WordCount: This validator is able to check the number of words within files. It provides a minimum and maximum count and will throw an error when either of these thresholds are crossed.
457
Zend_File
$upload->addValidator('Size', false, 20000); // Set a file size with 20 bytes minimum and 20000 bytes maximum $upload->addValidator('Size', false, array('min' => 20, 'max' => 20000)); // Set a file size with 20 bytes minimum and 20000 bytes maximum and // a file count in one step $upload->setValidators(array( 'Size' => array('min' => 20, 'max' => 20000), 'Count' => array('min' => 1, 'max' => 3), ));
$upload = new Zend_File_Transfer(); // Set a file size with 20000 bytes and limits it only to 'file2' $upload->addValidator('Size', false, 20000, 'file2'); Normally, you should use the addValidators() method, which can be called multiple times.
$upload = new Zend_File_Transfer(); // Set a file size with 20000 bytes $upload->addValidator('Size', false, 20000) ->addValidator('Count', false, 2) ->addValidator('Filessize', false, 25000);
Nota
Note that setting the same validator multiple times is allowed, but doing so can lead to issues when using different options for the same validator. Last but not least, you can simply check the files using isValid().
458
Zend_File
$upload->addValidator('Size', false, 20000) ->addValidator('Count', false, 2) ->addValidator('Filessize', false, 25000); if ($upload->isValid()) { print "Validation failure"; }
Nota
Note that isValid() will be called automatically when you receive the files and have not called it previously. When validation has failed it is a good idea to get information about the problems found. To get this information, you can use the methods getMessages() which returns all validation messages as array, getErrors() which returns all error codes, and hasErrors() which returns true as soon as a validation error has been found.
Count Validator
The Count validator checks for the number of files which are provided. It supports the following option keys: min: Sets the minimum number of files to transfer.
Nota
When using this option you must give the minimum number of files when calling this validator the first time; otherwise you will get an error in return. With this option you can define the minimum number of files you expect to receive. max: Sets the maximum number of files to transfer. With this option you can limit the number of files which are accepted but also detect a possible attack when more files are given than defined in your form. If you initiate this validator with a string or integer, the value will be used as max. Or you can also use the methods setMin() and setMax() to set both options afterwards and getMin() and getMax() to retrieve the actual set values.
Nota
Note that this validator stores the number of checked files internally. The file which exceeds the maximum will be returned as error.
459
Zend_File
Crc32 Validator
The Crc32 validator checks the content of a transferred file by hashing it. This validator uses the hash extension from PHP with the crc32 algorithm. It supports the following options: *: Sets any key or use a numeric array. The values will be used as hash to validate against. You can set multiple hashes by using different keys. Each will be checked and the validation will fail only if all values fail.
ExcludeExtension Validator
The ExcludeExtension validator checks the file extension of the specified files. It supports the following options: *: Sets any key or use a numeric array. The values will be used to check whether the given file does not use this file extension. case: Sets a boolean indicating whether validation should be case-sensitive. The default is not case sensitive. Note that this key can be applied to for all available extensions. This validator accepts multiple extensions, either as a comma-delimited string, or as an array. You may also use the methods setExtension(), addExtension(), and getExtension() to set and retrieve extensions. In some cases it is useful to match in a case-sensitive fashion. So the constructor allows a second parameter called $case which, if set to true, validates the extension by comparing it with the specified values in a case-sensitive fashion.
460
Zend_File
Nota
Note that this validator only checks the file extension. It does not check the file's MIME type.
ExcludeMimeType Validator
The ExcludeMimeType validator checks the MIME type of transferred files. It supports the following options: *: Sets any key individually or use a numeric array. Sets the MIME type to validate against. With this option you can define the MIME type of files that are not to be accepted. headerCheck: If set to TRUE this option will check the HTTP Information for the file type when the fileInfo or mimeMagic extensions can not be found. The default value for this option is FALSE. This validator accepts multiple MIME types, either as a comma-delimited string, or as an array. You may also use the methods setMimeType(), addMimeType(), and getMimeType() to set and retrieve the MIME types.
Nota
Note that disallowing groups of MIME types will disallow all members of this group even if this is not intentional. When you disallow 'image' you will disallow all types of images like 'image/jpeg' or 'image/vasa'. When you are not sure if you want to disallow all types, you should disallow only specific MIME types instead of complete groups.
Exists Validator
The Exists validator checks for the existence of specified files. It supports the following options: *: Sets any key or use a numeric array to check if the specific file exists in the given directory. This validator accepts multiple directories, either as a comma-delimited string, or as an array. You may also use the methods setDirectory(), addDirectory(), and getDirectory() to set and retrieve directories.
461
Zend_File
Nota
Note that this validator checks whether the specified file exists in all of the given directories. The validation will fail if the file does not exist in any of the given directories.
Extension Validator
The Extension validator checks the file extension of the specified files. It supports the following options: *: Sets any key or use a numeric array to check whether the specified file has this file extension. case: Sets whether validation should be done in a case-sensitive fashion. The default is no case sensitivity. Note the this key is used for all given extensions. This validator accepts multiple extensions, either as a comma-delimited string, or as an array. You may also use the methods setExtension(), addExtension(), and getExtension() to set and retrieve extension values. In some cases it is useful to test in a case-sensitive fashion. Therefore the constructor takes a second parameter $case, which, if set to true, will validate the extension in a case-sensitive fashion.
Nota
Note that this validator only checks the file extension. It does not check the file's MIME type.
462
Zend_File
FilesSize Validator
The FilesSize validator checks for the aggregate size of all transferred files. It supports the following options: min: Sets the minimum aggregate file size. This option defines the minimum aggregate file size to be transferred. max: Sets the maximum aggregate file size. This option limits the aggregate file size of all transferred files, but not the file size of individual files. bytestring: Defines whether a failure is to return a user-friendly number or the plain file size. This option defines whether the user sees '10864' or '10MB'. The default value is true, so '10MB' is returned if you did not specify otherwise. You can initialize this validator with a string, which will then be used to set the max option. You can also use the methods setMin() and setMax() to set both options after construction, along with getMin() and getMax() to retrieve the values that have been set previously. The size itself is also accepted in SI notation as handled by most operating systems. That is, instead of specifying 20000 bytes, 20kB may be given. All file sizes are converted using 1024 as the base value. The following Units are accepted: kB, MB, GB, TB, PB and EB. Note that 1kB is equal to 1024 bytes, 1MB is equal to 1024kB, and so on.
Nota
Note that this validator internally stores the file size of checked files. The file which exceeds the size will be returned as an error.
ImageSize Validator
The ImageSize validator checks the size of image files. It supports the following options: minheight: Sets the minimum image height. maxheight: Sets the maximum image height.
463
Zend_File
minwidth: Sets the minimum image width. maxwidth: Sets the maximum image width. The methods setImageMin() and setImageMax() also set both minimum and maximum values, while the methods getMin() and getMax() return the currently set values. For your convenience there are also the setImageWidth() and setImageHeight() methods, which set the minimum and maximum height and width of the image file. They, too, have corresponding getImageWidth() and getImageHeight() methods to retrieve the currently set values. To bypass validation of a particular dimension, the relevent option simply should not be set.
IsCompressed Validator
The IsCompressed validator checks if a transferred file is a compressed archive, such as zip or arc. This validator is based on the MimeType validator and supports the same methods and options. You may also limit this validator to particular compression types with the methods described there.
Nota
Note that there is no check if you set a MIME type that is not a archive. For example, it would be possible to define gif files to be accepted by this validator. Using the 'MimeType' validator for files which are not archived will result in more readable code.
464
Zend_File
IsImage Validator
The IsImage validator checks if a transferred file is a image file, such as gif or jpeg. This validator is based on the MimeType validator and supports the same methods and options. You can limit this validator to particular image types with the methods described there.
Nota
Note that there is no check if you set a MIME type that is not an image. For example, it would be possible to define zip files to be accepted by this validator. Using the 'MimeType' validator for files which are not images will result in more readable code.
Hash Validator
The Hash validator checks the content of a transferred file by hashing it. This validator uses the hash extension from PHP. It supports the following options: *: Takes any key or use a numeric array. Sets the hash to validate against. You can set multiple hashes by passing them as an array. Each file is checked, and the validation will fail only if all files fail validation. algorithm: Sets the algorithm to use for hashing the content. You can set multiple algorithm by calling the addHash() method multiple times.
465
Zend_File
Nota
This validator supports about 34 different hash algorithms. The most common include 'crc32', 'md5' and 'sha1'. A comprehesive list of supports hash algorithms can be found at the hash_algos method [http://php.net/ hash_algos] on the php.net site [http://php.net].
Md5 Validator
The Md5 validator checks the content of a transferred file by hashing it. This validator uses the hash extension for PHP with the md5 algorithm. It supports the following options: *: Takes any key or use a numeric array. You can set multiple hashes by passing them as an array. Each file is checked, and the validation will fail only if all files fail validation.
MimeType Validator
The MimeType validator checks the MIME type of transferred files. It supports the following options: *: Sets any key or use a numeric array. Sets the MIME type to validate against. Defines the MIME type of files to be accepted. headerCheck: If set to TRUE this option will check the HTTP Information for the file type when the fileInfo or mimeMagic extensions can not be found. The default value for this option is FALSE. magicfile: The magicfile to be used. With this option you can define which magicfile to use. When it's not set or empty, the MAGIC constant will be used instead. This option is available since Zend Framework 1.7.1. This validator accepts multiple MIME type, either as a comma-delimited string, or as an array. You may also use the methods setMimeType(), addMimeType(), and getMimeType() to set and retrieve MIME type. You can also set the magicfile which shall be used by fileinfo with the 'magicfile' option. Additionally there are convenient setMagicFile() and getMagicFile() methods which allow later setting and retrieving of the magicfile parameter. This methods are available since Zend Framework 1.7.1.
466
Zend_File
Nota
Note that allowing groups of MIME types will accept all members of this group even if your application does not support them. When you allow 'image' you will also get 'image/xpixmap' or 'image/vasa' which could be problematic. When you are not sure if your application supports all types you should better allow only defined MIME types instead of the complete group.
Nota
This component will use the fileinfo extension if it is available. If it's not, it will degrade to the mime_content_type function. And if the function call fails it will use the MIME type which is given by HTTP. You should be aware of possible security problems when you have whether fileinfo nor mime_content_type available. The MIME type given by HTTP is not secure and can be easily manipulated.
NotExists Validator
The NotExists validator checks for the existence of the provided files. It supports the following options: *: Set any key or use a numeric array. Checks whether the file exists in the given directory. This validator accepts multiple directories either as a comma-delimited string, or as an array. You may also use the methods setDirectory(), addDirectory(), and getDirectory() to set and retrieve directories.
467
Zend_File
$upload = new Zend_File_Transfer(); // Add the temp directory to check $upload->addValidator('NotExists', false, '\temp'); // Add two directories using the array notation $upload->addValidator('NotExists', false, array('\home\images', '\home\uploads') );
Nota
Note that this validator checks if the file does not exist in all of the provided directories. The validation will fail if the file does exist in any of the given directories.
Sha1 Validator
The Sha1 validator checks the content of a transferred file by hashing it. This validator uses the hash extension for PHP with the sha1 algorithm. It supports the following options: *: Takes any key or use a numeric array. You can set multiple hashes by passing them as an array. Each file is checked, and the validation will fail only if all files fail validation.
Size Validator
The Size validator checks for the size of a single file. It supports the following options: min: Sets the minimum file size. max: Sets the maximum file size. bytestring: Defines whether a failure is returned with a user-friendly number, or with the plain file size. With this option you can define if the user gets '10864' or '10MB'. Default value is true which returns '10MB'. You can initialize this validator with a string, which will then be used to set the max option. You can also use the methods setMin() and setMax() to set both options after construction, along with getMin() and getMax() to retrieve the values that have been set previously.
468
Zend_File
The size itself is also accepted in SI notation as handled by most operating systems. That is, instead of specifying 20000 bytes, 20kB may be given. All file sizes are converted using 1024 as the base value. The following Units are accepted: kB, MB, GB, TB, PB and EB. Note that 1kB is equal to 1024 bytes, 1MB is equal to 1024kB, and so on.
WordCount Validator
The WordCount validator checks for the number of words within provided files. It supports the following option keys: min: Sets the minimum number of words to be found. max: Sets the maximum number of words to be found. If you initiate this validator with a string or integer, the value will be used as max. Or you can also use the methods setMin() and setMax() to set both options afterwards and getMin() and getMax() to retrieve the actual set values.
469
Zend_File
Encrypt: This filter can encrypt a file. LowerCase: This filter can lowercase the content of a textfile. Rename: This filter can rename files, change the location and even force overwriting of existing files. UpperCase: This filter can uppercase the content of a textfile.
470
Zend_File
// Set a new destination path and limits it only to 'file2' $upload->addFilter('Rename', 'C:\picture\uploads', 'file2'); Generally you should simply use the addFilters() method, which can be called multiple times.
$upload = new Zend_File_Transfer(); // Set a filesize with 20000 bytes $upload->addFilter('Rename', 'C:\picture\newjpg', 'file1') ->addFilter('Rename', 'C:\picture\newgif', 'file2');
Nota
Note that even though setting the same filter multiple times is allowed, doing so can lead to issues when using different options for the same filter.
Decrypt filter
The Decrypt filter allows to decrypt a encrypted file. This filter makes use of Zend_Filter_Decrypt. It supports the Mcrypt and OpenSSL extensions from PHP. Please read the related section for details about how to set the options for decryption and which options are supported. This filter supports one additional option which can be used to save the decrypted file with another filename. Set the filename option to change the filename where the decrypted file will be stored. If you suppress this option, the decrypted file will overwrite the original encrypted file.
471
Zend_File
Encrypt filter
The Encrypt filter allows to encrypt a file. This filter makes use of Zend_Filter_Encrypt. It supports the Mcrypt and OpenSSL extensions from PHP. Please read the related section for details about how to set the options for encryption and which options are supported. This filter supports one additional option which can be used to save the encrypted file with another filename. Set the filename option to change the filename where the encrypted file will be stored. If you suppress this option, the encrypted file will overwrite the original file.
LowerCase filter
The LowerCase filter allows to change the content of a file to lowercase. You should use this filter only on textfiles. At initiation you can give a string which will then be used as encoding. Or you can use the setEncoding() method to set it afterwards.
472
Zend_File
Nota
Note that due to the fact that the options for the LowerCase filter are optional, you must give a null as second parameter (the options) when you want to limit it to a single file element.
Rename filter
The Rename filter allows to change the destination of the upload, the filename and also to overwrite existing files. It supports the following options: source: The name and destination of the old file which shall be renamed. target: The new directory, or filename of the file. overwrite: Sets if the old file overwrites the new one if it already exists. The default value is false. Additionally you can also use the method setFile() to set files, which erases all previous set, addFile() to add a new file to existing ones, and getFile() to get all actually set files. To simplify things, this filter understands several notations and that methods and constructor understand the same notations.
Tabla 21.1. Different notations of the rename filter and their meaning
notation addFile('C:\uploads') description Specifies a new location for all files when the given string is a directory. Note that you will get an exception when the file already exists, see the overwriting parameter. Specifies a new location and filename for all files when the given string is not detected as directory. Note that you will get an exception when the file already exists, see the overwriting parameter. Specifies a new location and filename for all files when the given string is not detected as directory and overwrites an existing file with the same target name. Note, that you will get no notification that a file was overwritten.
addFile('C:\uploads\file.ext')
473
Zend_File
description Specifies a new location for all files in the old location when the given strings are detected as directory. Note that you will get an exception when the file already exists, see the overwriting parameter. Specifies a new location for all files in the old location when the given strings are detected as directory and overwrites and existing file with the same target name. Note, that you will get no notification that a file was overwritten.
UpperCase filter
The UpperCase filter allows to change the content of a file to uppercase. You should use this filter only on textfiles. At initiation you can give a string which will then be used as encoding. Or you can use the setEncoding() method to set it afterwards.
Nota
Note that due to the fact that the options for the UpperCase filter are optional, you must give a null as second parameter (the options) when you want to limit it to a single file element.
474
Qu es un filtro?
En el mundo fsico, un filtro se suele utilizar para eliminar partes no deseadas de lo ingresado, y la vez lo ingresado pasa a travs de un filtro de salida (por ejemplo, el caf). En este caso, un filtro es un operador que devuelve una parte de los datos de entrada. Este tipo de filtro es til para aplicaciones web, para la supresin de entradas ilegales y/o que no se ajustan, eliminacin de los espacios en blanco innecesarios, etc This basic definition of a filter may be extended to include generalized transformations upon input. A common transformation applied in web applications is the escaping of HTML entities. For example, if a form field is automatically populated with untrusted input (e.g., from a web browser), this value should either be free of HTML entities or contain only escaped HTML entities, in order to prevent undesired behavior and security vulnerabilities. To meet this requirement, HTML entities that appear in the input must either be removed or escaped. Of course, which approach is more appropriate depends on the situation. A filter that removes the HTML entities operates within the scope of the first definition of filter - an operator that produces a subset of the input. A filter that escapes the HTML entities, however, transforms the input (e.g., "&" is transformed to "&"). Supporting such use cases for web developers is important, and "to filter," in the context of using Zend_Filter, means to perform some transformations upon input data. Esta definicin bsica de un filtro puede ser extendido para incluir transformaciones generalizadas sobre la entrada. Una transformacin comn requerida en las aplicaciones web es la de escapar las entidades HTML. Por ejemplo, si un campo del formulario es completado automticamente y contiene datos no verificados (por ejemplo, datos ingresados desde un navegador web), este valor debe estar libre de las entidades HTML o slo contener entidades HTML de forma escapada, a fin de evitar comportamientos no deseados y vulnerabilidades de seguridad. Para cumplir este requerimiento, las entidades HTML que aparecen en los datos introducidos deben ser suprimidos o escapados. Por supuesto, el enfoque ms adecuado depende del contexto y de la situcin. Un filtro que quita las entidades HTML funciona dentro del mbito o alcance de la primera definicin del filtro - un operador que produce un subconjunto de la entrada. Un filtro que escapa a las entidades HTML, sin embargo, transforma la entrada (por ejemplo, " &" se transforma en " &"). El Apoyo a los casos de uso como para la web los desarrolladores es importante, y "filtrar", en el contexto de la utilizacin de Zend_Filter , los medios para realizar algunas transformaciones en los datos de entrada.
475
Zend_Filter
Namespaces
When working with self defined filters you can give a forth parameter to Zend_Filter::filterStatic() which is the namespace where your filter can be found. echo Zend_Filter::filterStatic( '"', 'MyFilter', array($parameters), array('FirstNamespace', 'SecondNamespace') ); Zend_Filter allows also to set namespaces as default. This means that you can set them once in your bootstrap and have not to give them again for each call of Zend_Filter::filterStatic(). The following code snippet is identical to the above one. Zend_Filter::setDefaultNamespaces(array('FirstNamespace', 'SecondNamespace')); echo Zend_Filter::filterStatic('"', 'MyFilter', array($parameters)); echo Zend_Filter::filterStatic('"', 'OtherFilter', array($parameters)); For your convinience there are following methods which allow the handling of namespaces: Zend_Filter::getDefaultNamespaces(): Returns all set default namespaces as array. Zend_Filter::setDefaultNamespaces(): Sets new default namespaces and overrides any previous set. It accepts eighter a string for a single namespace of an array for multiple namespaces. Zend_Filter::addDefaultNamespaces(): Adds additional namespaces to already set ones. It accepts eighter a string for a single namespace of an array for multiple namespaces. Zend_Filter::hasDefaultNamespaces(): Returns true when one or more default namespaces are set, and false when no default namespaces are set.
476
Zend_Filter
Alnum
Returns the string $value, removing all but alphabetic and digit characters. This filter includes an option to also allow white space characters.
Nota
The alphabetic characters mean characters that makes up words in each language. However, the english alphabet is treated as the alphabetic characters in following languages: Chinese, Japanese, Korean. The language is specified by Zend_Locale.
Alpha
Returns the string $value, removing all but alphabetic characters. This filter includes an option to also allow white space characters.
BaseName
Given a string containing a path to a file, this filter will return the base name of the file
Callback
This filter allows you to use own methods in conjunction with Zend_Filter. You don't have to create a new filter when you already have a method which does the job. Let's expect we want to create a filter which reverses a string.
$filter = new Zend_Filter_Callback('strrev'); print $filter->filter('Hello!'); // returns "!olleH" As you can see it's really simple to use a callback to define a own filter. It is also possible to use a method, which is defined within a class, by giving an array as callback.
// Our classdefinition class MyClass { public function Reverse($param); } // The filter definition $filter = new Zend_Filter_Callback(array('MyClass', 'Reverse')); print $filter->filter('Hello!'); To get the actual set callback use getCallback() and to set another callback use setCallback().
477
Zend_Filter
It is also possible to define default parameters, which are given to the called method as array when the filter is executed. This array will be concatenated with the value which will be filtered.
$filter = new Zend_Filter_Callback( array( 'callback' => 'MyMethod', 'options' => array('key' => 'param1', 'key2' => 'param2') ) ); $filter->filter(array('value' => 'Hello')); When you would call the above method definition manually it would look like this:
Nota
You should note that defining a callback method which can not be called will raise an exception.
Generic handling
To create a compression filter you need to select the compression format you want to use. The following description takes the Bz2 adapter. Details for all other adapters are described after this section. The two filters are basically identical, in that they utilize the same backends. Zend_Filter_Compress should be used when you wish to compress items, and Zend_Filter_Decompress should be used when you wish to decompress items. For instance, if we want to compress a string, we have to initiate Zend_Filter_Compress and indicate the desired adapter.
478
Zend_Filter
To use a different adapter, you simply specify it to the constructor. You may also provide an array of options or Zend_Config object. If you do, provide minimally the key "adapter", and then either the key "options" or "adapterOptions" (which should be an array of options to provide to the adapter on instantiation). $filter = new Zend_Filter_Compress(array( 'adapter' => 'Bz2', 'options' => array( 'blocksize' => 8, ), ));
Creating an archive
Creating an archive file works almost the same as compressing a string. However, in this case we need an additional parameter which holds the name of the archive we want to create. $filter = new Zend_Filter_Compress(array( 'adapter' => 'Bz2', 'options' => array( 'archive' => 'filename.bz2', ), )); $compressed = $filter->filter('Uncompressed string');
479
Zend_Filter
// Returns true on success and creates the archive file In the above example the uncompressed string is compressed, and is then written into the given archive file.
Decompressing an archive
Decompressing an archive file works almost like compressing it. You must specify either the archive parameter, or give the filename of the archive when you decompress the file. $filter = new Zend_Filter_Decompress('Bz2'); $compressed = $filter->filter('filename.bz2'); // Returns true on success and decompresses the archive file Some adapters support decompressing the archive into another subdirectory. In this case you can set the target parameter. $filter = new Zend_Filter_Decompress(array( 'adapter' => 'Zip', 'options' => array(
480
Zend_Filter
'target' => 'C:\temp', ) )); $compressed = $filter->filter('filename.zip'); // Returns true on success and decompresses the archive file // into the given target directory
Bz2 Adapter
The Bz2 Adapter can compress and decompress: Strings Files Directories This adapter makes use of PHP's Bz2 extension. To customize compression, this adapter supports the following options: Archive: This parameter sets the archive file which should be used or created. Blocksize: This parameter sets the blocksize to use. It can be from '0' to '9'. The default value is '4'. All options can be set at instantiation or by using a related method. For example, the related methods for 'Blocksize' are getBlocksize() and setBlocksize(). You can also use the setOptions() method which accepts all options as array.
Gz Adapter
The Gz Adapter can compress and decompress: Strings Files Directories This adapter makes use of PHP's Zlib extension. To customize the compression this adapter supports the following options: Archive: This parameter sets the archive file which should be used or created. Level: This compression level to use. It can be from '0' to '9'. The default value is '9'. Mode: There are two supported modes. 'compress' and 'deflate'. The default value is 'compress'. All options can be set at initiation or by using a related method. For example, the related methods for 'Level' are getLevel() and setLevel(). You can also use the setOptions() method which accepts all options as array.
Lzf Adapter
The Lzf Adapter can compress and decompress:
481
Zend_Filter
Strings
Rar Adapter
The Rar Adapter can compress and decompress: Files Directories
Tar Adapter
The Tar Adapter can compress and decompress: Files Directories
482
Zend_Filter
To customize the compression this adapter supports the following options: Archive: This parameter sets the archive file which should be used or created. Mode: A mode to use for compression. Supported are either 'null' which means no compression at all, 'Gz' which makes use of PHP's Zlib extension and 'Bz2' which makes use of PHP's Bz2 extension. The default value is 'null'. Target: The target where the decompressed files will be written to. All options can be set at instantiation or by using a related method. For example, the related methods for 'Target' are getTarget() and setTarget(). You can also use the setOptions() method which accepts all options as array.
Directory usage
When compressing directories with Tar then the complete file path is used. This means that created Tar files will not only have the subdirectory but the complete path for the compressed file.
Zip Adapter
The Zip Adapter can compress and decompress: Strings Files Directories
Decrypt
This filter will decrypt any given string with the provided setting. Therefor it makes use of Adapters. Actually there are adapters for the Mcrypt and OpenSSL extensions from php. For details about how to encrypt content look at the Encrypt filter. As the basics are covered within the Encrypt filter, we will describe here only the needed additional methods and changes for decryption.
483
Zend_Filter
There is one emminent difference for you. When you did not provide a vector at encryption you need to get it after you encrypted the content by using the getVector() method on the encryption filter. Without the correct vector you will not be able to decrypt the content. As soon as you have provided all options decryption is as simple as encryption.
// Use the default blowfish settings $filter = new Zend_Filter_Decrypt('myencryptionkey'); // Set the vector with which the content was encrypted $filter->setVector('myvector'); $decrypted = $filter->filter('encoded_text_normally_unreadable'); print $decrypted;
Nota
Note that you will get an exception if the mcrypt extension is not available in your environment.
Nota
You should also note that all settings which be checked when you create the instance or when you call setEncryption(). If mcrypt detects problem with your settings an exception will be thrown.
// Use openssl and provide a private key $filter = new Zend_Filter_Decrypt(array( 'adapter' => 'openssl', 'private' => '/path/to/mykey/private.pem' )); // of course you can also give the envelope keys at initiation $filter->setEnvelopeKey(array( '/key/from/encoder/first.pem', '/key/from/encoder/second.pem' ));
Nota
Note that the OpenSSL adapter will not work when you do not provide valid keys.
484
Zend_Filter
Optionally it could be necessary to provide the passphrase for decrypting the keys themself by using the setPassphrase() method.
// Use openssl and provide a private key $filter = new Zend_Filter_Decrypt(array( 'adapter' => 'openssl', 'private' => '/path/to/mykey/private.pem' )); // of course you can also give the envelope keys at initiation $filter->setEnvelopeKey(array( '/key/from/encoder/first.pem', '/key/from/encoder/second.pem' )); $filter->setPassphrase('mypassphrase'); At last, decode the content. Our complete example for decrypting the previously encrypted content looks like this.
// Use openssl and provide a private key $filter = new Zend_Filter_Decrypt(array( 'adapter' => 'openssl', 'private' => '/path/to/mykey/private.pem' )); // of course you can also give the envelope keys at initiation $filter->setEnvelopeKey(array( '/key/from/encoder/first.pem', '/key/from/encoder/second.pem' )); $filter->setPassphrase('mypassphrase'); $decrypted = $filter->filter('encoded_text_normally_unreadable'); print $decrypted;
Digits
Returns the string $value, removing all but digit characters.
Dir
Returns directory name component of path.
Encrypt
This filter will encrypt any given string with the provided setting. Therefor it makes use of Adapters. Actually there are adapters for the Mcrypt and OpenSSL extensions from php. As these two encryption methodologies work completely different, also the usage of the adapters differ. You have to select the adapter you want to use when initiating the filter.
485
Zend_Filter
$filter1 = new Zend_Filter_Encrypt(array('adapter' => 'mcrypt')); // Use the OpenSSL adapter $filter2 = new Zend_Filter_Encrypt(array('adapter' => 'openssl')); To set another adapter you can also use setAdapter(), and the getAdapter() method to receive the actual set adapter. // Use the Mcrypt adapter $filter = new Zend_Filter_Encrypt(); $filter->setAdapter('openssl');
Nota
When you do not supply the adapter option or do not use setAdapter, then the Mcrypt adapter will be used per default.
Nota
Note that you will get an exception if the mcrypt extension is not available in your environment.
Nota
You should also note that all settings which be checked when you create the instance or when you call setEncryption(). If mcrypt detects problem with your settings an exception will be thrown. You can get/set the encryption vector by calling getVector() and setVector(). A given string will be truncated or padded to the needed vector size of the used algorithm.
486
Zend_Filter
Nota
Note that when you are not using an own vector, you must get the vector and store it. Otherwise you will not be able to decode the encoded string.
// Use the default blowfish settings $filter = new Zend_Filter_Encrypt('myencryptionkey'); // Set a own vector, otherwise you must call getVector() // and store this vector for later decryption $filter->setVector('myvector'); // $filter->getVector(); $encrypted = $filter->filter('text_to_be_encoded'); print $encrypted; // For decryption look at the Decrypt filter
// Use openssl and provide a private key $filter = new Zend_Filter_Encrypt(array( 'adapter' => 'openssl', 'private' => '/path/to/mykey/private.pem' )); // of course you can also give the public keys at initiation $filter->setPublicKey(array( '/public/key/path/first.pem', '/public/key/path/second.pem' ));
Nota
Note that the OpenSSL adapter will not work when you do not provide valid keys. When you want to encode also the keys, then you have to provide a passphrase with the setPassphrase() method. When you want to decode content which was encoded with a passphrase you will not only need the public key, but also the passphrase to decode the encrypted key.
487
Zend_Filter
// Use openssl and provide a private key $filter = new Zend_Filter_Encrypt(array( 'adapter' => 'openssl', 'private' => '/path/to/mykey/private.pem' )); // of course you can also give the public keys at initiation $filter->setPublicKey(array( '/public/key/path/first.pem', '/public/key/path/second.pem' )); $filter->setPassphrase('mypassphrase'); At last, when you use OpenSSL you need to give the receiver the encrypted content, the passphrase when have provided one, and the envelope keys for decryption. This means for you, that you have to get the envelope keys after the encryption with the getEnvelopeKey() method. So our complete example for encrypting content with OpenSSL look like this. // Use openssl and provide a private key $filter = new Zend_Filter_Encrypt(array( 'adapter' => 'openssl', 'private' => '/path/to/mykey/private.pem' )); // of course you can also give the public keys at initiation $filter->setPublicKey(array( '/public/key/path/first.pem', '/public/key/path/second.pem' )); $filter->setPassphrase('mypassphrase'); $encrypted = $filter->filter('text_to_be_encoded'); $envelope = $filter->getEnvelopeKey(); print $encrypted; // For decryption look at the Decrypt filter
HtmlEntities
Returns the string $value, converting characters to their corresponding HTML entity equivalents where they exist.
Int
Returns (int) $value
LocalizedToNormalized
This filter will change any given localized input to it's normalized representation. It uses in Background Zend_Locale to do this transformation for you.
488
Zend_Filter
This allows your user to enter informations in his own language notation, and you can then store the normalized value into your database for example.
Nota
Please note that normalization is not equal to translation. This filter can not translate strings from one language into another like you could expect with months or names of days. The following input types can be normalized: integer: Integer numbers, which are localized, will be normalized to the english notation. float: Float numbers, which are localized, will be normalized to the english notation. numbers: Other numbers, like real, will be normalized to the english notation. time: Time values, will be normalized to a named array. date: Date values, will be normalized to a named array. Any other input will be returned as it, without changing it.
Nota
You should note that normalized output is always given as string. Otherwise your environment would transfer the normalized output automatically to the notation used by the locale your environment is set to.
// Initiate the filter $filter = new Zend_Filter_LocalizedToNormalized(); $filter->filter('123.456,78'); // returns the value '123456.78' Let's expect you have set the locale 'de' as application wide locale. Zend_Filter_LocalizedToNormalized will take the set locale and use it to detect which sort of input you gave. In our example it was a value with precision. Now the filter will return you the normalized representation for this value as string. You can also control how your normalized number has to look like. Therefor you can give all options which are also used by Zend_Locale_Format. The most common are: date_format locale precision For details about how these options are used take a look into this Zend_Locale chapter. Below is a example with defined precision so you can see how options work:
489
Zend_Filter
// Numeric Filter $filter = new Zend_Filter_LocalizedToNormalized(array('precision' => 2)); $filter->filter('123.456'); // returns the value '123456.00' $filter->filter('123.456,78901'); // returns the value '123456.79'
// Initiate the filter $filter = new Zend_Filter_LocalizedToNormalized(); $filter->filter('12.April.2009'); // returns array('day' => '12', 'month' => '04', 'year' => '2009') Let's expect you have set the locale 'de' again. Now the input is automatically detected as date, and you will get a named array in return. Of course you can also control how your date input looks like with the date_format and the locale option.
// Date Filter $filter = new Zend_Filter_LocalizedToNormalized( array('date_format' => 'ss:mm:HH') ); $filter->filter('11:22:33'); // returns array('hour' => '33', 'minute' => '22', 'second' => '11')
NormalizedToLocalized
This filter is the reverse of the filter Zend_Filter_LocalizedToNormalized and will change any given normalized input to it's localized representation. It uses in Background Zend_Locale to do this transformation for you. This allows you to give your user any stored normalised value in a localized manner, your user is more common to.
Nota
Please note that localization is not equal to translation. This filter can not translate strings from one language into another like you could expect with months or names of days. The following input types can be localized: integer: Integer numbers, which are normalized, will be localized to the set notation. float: Float numbers, which are normalized, will be localized to the set notation. numbers: Other numbers, like real, will be localized to the set notation.
490
Zend_Filter
time: Time values, will be localized to a string. date: Date values, will be normalized to a string. Any other input will be returned as it, without changing it.
// Initiate the filter $filter = new Zend_Filter_NormalizedToLocalized(); $filter->filter(123456.78); // returns the value '123.456,78' Let's expect you have set the locale 'de' as application wide locale. Zend_Filter_NormalizedToLocalized will take the set locale and use it to detect which sort of output you want to have. In our example it was a value with precision. Now the filter will return you the localized representation for this value as string. You can also control how your localized number has to look like. Therefor you can give all options which are also used by Zend_Locale_Format. The most common are: date_format locale precision For details about how these options are used take a look into this Zend_Locale chapter. Below is a example with defined precision so you can see how options work:
// Numeric Filter $filter = new Zend_Filter_NormalizedToLocalized(array('precision' => 2)); $filter->filter(123456); // returns the value '123.456,00' $filter->filter(123456.78901); // returns the value '123.456,79'
// Initiate the filter $filter = new Zend_Filter_NormalizedToLocalized(); $filter->filter(array('day' => '12', 'month' => '04', 'year' => '2009'); // returns '12.04.2009'
491
Zend_Filter
Let's expect you have set the locale 'de' again. Now the input is automatically detected as date, and will be returned in the format defined by the locale 'de'. Of course you can also control how your date input looks like with the date_format, and the locale option.
// Date Filter $filter = new Zend_Filter_LocalizedToNormalized( array('date_format' => 'ss:mm:HH') ); $filter->filter(array('hour' => '33', 'minute' => '22', 'second' => '11')); // returns '11:22:33'
Null
This filter will change the given input to be NULL if it meets specific criteria. This is often necessary when you work with databases and want to have a NULL value instead of a boolean or any other type.
$filter = new Zend_Filter_Null(); $value = ''; $result = $filter->filter($value); // returns null instead of the empty string This means that without providing any configuration, Zend_Filter_Null will accept all input types and return NULL in the same cases as empty(). Any other value will be returned as is, without any changes.
492
Zend_Filter
// converts false to null $filter = new Zend_Filter_Null(Zend_Filter_Null::BOOLEAN); // converts false and 0 to null $filter = new Zend_Filter_Null( Zend_Filter_Null::BOOLEAN + Zend_Filter_Null::INTEGER ); // converts false and 0 to null $filter = new Zend_Filter_Null( array( Zend_Filter_Null::BOOLEAN, Zend_Filter_Null::INTEGER )); // converts false and 0 to null $filter = new Zend_Filter_Null(array( 'boolean', 'integer', )); You can also give an instance of Zend_Config to set the wished types. To set types afterwards use setType().
StripNewlines
Returns the string $value without any newline control characters.
RealPath
This filter will resolve given links and pathnames and returns canonicalized absolute pathnames. References to '/./', '/../' and extra '/' characters in the input path will be stripped. The resulting path will not have any symbolic link, '/./' or '/../' character. Zend_Filter_RealPath will return FALSE on failure, e.g. if the file does not exist. On BSD systems Zend_Filter_RealPath doesn't fail if only the last path component doesn't exist, while other systems will return FALSE.
$filter = new Zend_Filter_RealPath(); $path = '/www/var/path/../../mypath'; $filtered = $filter->filter($path); // returns '/www/mypath' Sometimes it is useful to get also paths when they don't exist, f.e. when you want to get the real path for a path which you want to create. You can then either give a FALSE at initiation, or use setExists() to set it.
$filter = new Zend_Filter_RealPath(false); $path = '/www/var/path/../../non/existing/path'; $filtered = $filter->filter($path); // returns '/www/non/existing/path' // even when file_exists or realpath would return false
493
Zend_Filter
StringToLower
This filter converts any input to be lowercased. $filter = new Zend_Filter_StringToLower(); print $filter->filter('SAMPLE'); // returns "sample" Per default it will only handle characters from the actual locale of your server. Characters from other charsets would be ignored. Still, it's possible to also lowercase them when the mbstring extension is available in your environment. Simply set the wished encoding when initiating the StringToLower filter. Or use the setEncoding() method to change the encoding afterwards. // using UTF-8 $filter = new Zend_Filter_StringToLower('UTF-8'); // or give an array which can be useful when using a configuration $filter = new Zend_Filter_StringToLower(array('encoding' => 'UTF-8')); // or do this afterwards $filter->setEncoding('ISO-8859-1');
StringToUpper
This filter converts any input to be uppercased. $filter = new Zend_Filter_StringToUpper(); print $filter->filter('Sample'); // returns "SAMPLE" Like the StringToLower filter, this filter handles only characters from the actual locale of your server. Using different character sets works the same as with StringToLower. $filter = new Zend_Filter_StringToUpper(array('encoding' => 'UTF-8')); // or do this afterwards $filter->setEncoding('ISO-8859-1');
StringTrim
Returns the string $value with characters stripped from the beginning and end.
494
Zend_Filter
StripTags
This filter returns the input string, with all HTML and PHP tags stripped from it, except those that have been explicitly allowed. In addition to the ability to specify which tags are allowed, developers can specify which attributes are allowed across all allowed tags and for specific tags only. Finally, this filter offers control over whether comments (e.g., <!-- ... -->) are removed or allowed.
Filter Chains
Often multiple filters should be applied to some value in a particular order. For example, a login form accepts a username that should be only lowercase, alphabetic characters. Zend_Filter provides a simple method by which filters may be chained together. The following code illustrates how to chain together two filters for the submitted username: <// Create a filter chain and add filters to the chain $filterChain = new Zend_Filter(); $filterChain->addFilter(new Zend_Filter_Alpha()) ->addFilter(new Zend_Filter_StringToLower()); // Filter the username $username = $filterChain->filter($_POST['username']); Filters are run in the order they were added to Zend_Filter. In the above example, the username is first removed of any non-alphabetic characters, and then any uppercase characters are converted to lowercase. Any object that implements Zend_Filter_Interface may be used in a filter chain.
Writing Filters
Zend_Filter supplies a set of commonly needed filters, but developers will often need to write custom filters for their particular use cases. The task of writing a custom filter is facilitated by implementing Zend_Filter_Interface. Zend_Filter_Interface defines a single method, filter(), that may be implemented by user classes. An object that implements this interface may be added to a filter chain with Zend_Filter::addFilter(). The following example demonstrates how to write a custom filter: class MyFilter implements Zend_Filter_Interface { public function filter($value) { // perform some transformation upon $value to arrive on $valueFiltered return $valueFiltered; } } To add an instance of the filter defined above to a filter chain: $filterChain = new Zend_Filter(); $filterChain->addFilter(new MyFilter());
495
Zend_Filter
Zend_Filter_Input
Zend_Filter_Input provides a declarative interface to associate multiple filters and validators, apply them to collections of data, and to retrieve input values after they have been processed by the filters and validators. Values are returned in escaped format by default for safe HTML output. Consider the metaphor that this class is a cage for external data. Data enter the application from external sources, such as HTTP request parameters, HTTP headers, a web service, or even read from a database or another file. Data are first put into the cage, and subsequently the application can access data only by telling the cage what the data should be and how they plan to use it. The cage inspects the data for validity. It might apply escaping to the data values for the appropriate context. The cage releases data only if it can fulfill these responsibilities. With a simple and convenient interface, it encourages good programming habits and makes developers think about how data are used. Filters transform input values, by removing or changing characters within the value. The goal is to "normalize" input values until they match an expected format. For example, if a string of numeric digits is needed, and the input value is "abc123", then it might be a reasonable transformation to change the value to the string "123". Validators check input values against criteria and report whether they passed the test or not. The value is not changed, but the check may fail. For example, if a string must look like an email address, and the input value is "abc123", then the value is not considered valid. Escapers transform a value by removing magic behavior of certain characters. In some output contexts, special characters have meaning. For example, the characters '<' and '>' delimit HTML tags, and if a string containing those characters is output in an HTML context, the content between them might affect the output or functionality of the HTML presentation. Escaping the characters removes the special meaning, so they are output as literal characters. To use Zend_Filter_Input, perform the following steps: 1. Declare filter and validator rules 2. Create the filter and validator processor 3. Provide input data 4. Retrieve validated fields and other reports The following sections describe the steps for using this class.
$filters = array( 'month' => 'Digits', 'account' => 'StringTrim' ); $validators = array( 'account' => 'Alpha'
496
Zend_Filter
); Each key in the $filters array above is the name of a rule for applying a filter to a specific data field. By default, the name of the rule is also the name of the input data field to which to apply the rule. You can declare a rule in several formats: A single string scalar, which is mapped to a class name. $validators = array( 'month' => 'Digits', ); An object instance of one of the classes that implement Zend_Filter_Interface or Zend_Validate_Interface. $digits = new Zend_Validate_Digits(); $validators = array( 'month' => $digits ); An array, to declare a chain of filters or validators. The elements of this array can be strings mapping to class names or filter/validator objects, as in the cases described above. In addition, you can use a third choice: an array containing a string mapping to the class name followed by arguments to pass to its constructor. $validators = array( 'month' => array( 'Digits', // string new Zend_Validate_Int(), // object instance array('Between', 1, 12) // string with constructor arguments ) );
Nota
If you declare a filter or validator with constructor arguments in an array, then you must make an array for the rule, even if the rule has only one filter or validator. You can use a special "wildcard" rule key '*' in either the filters array or the validators array. This means that the filters or validators declared in this rule will be applied to all input data fields. Note that the order of entries in the filters array or validators array is significant; the rules are applied in the same order in which you declare them. $filters = array( '*' => 'StringTrim', 'month' => 'Digits' );
497
Zend_Filter
$input = new Zend_Filter_Input($filters, $validators); You can specify input data as the third constructor argument. The data structure is an associative array. The keys are field names, and the values are data values. The standard $_GET and $_POST superglobal variables in PHP are examples of this format. You can use either of these variables as input data for Zend_Filter_Input.
$data = $_GET; $input = new Zend_Filter_Input($filters, $validators, $data); Alternatively, use the setData() method, passing an associative array of key/value pairs the same format as described above.
$input = new Zend_Filter_Input($filters, $validators); $input->setData($newData); The setData() method redefines data in an existing Zend_Filter_Input object without changing the filtering and validation rules. Using this method, you can run the same rules against different sets of input data.
if ($input->isValid()) { echo "OK\n"; } This method accepts an optional string argument, naming an individual field. If the specified field passed validation and is ready for fetching, isValid('fieldName') returns TRUE.
498
Zend_Filter
if ($input->hasInvalid() || $input->hasMissing()) { $messages = $input->getMessages(); } // getMessages() simply returns the merge of getInvalid() and // getMissing() if ($input->hasInvalid()) { $invalidFields = $input->getInvalid(); } if ($input->hasMissing()) { $missingFields = $input->getMissing(); } if ($input->hasUnknown()) { $unknownFields = $input->getUnknown(); } The results of the getMessages() method is an associative array, mapping a rule name to an array of error messages related to that rule. Note that the index of this array is the rule name used in the rule declaration, which may be different from the names of fields checked by the rule. The getMessages() method returns the merge of the arrays returned by the getInvalid() and getMissing(). These methods return subsets of the messages, related to validation failures, or fields that were declared as required but missing from the input. The getErrors() method returns an associative array, mapping a rule name to an array of error identifiers. Error identifiers are fixed strings, to identify the reason for a validation failure, while messages can be customized. See the section called Uso bsico de validadores for more information. You can specify the message returned by getMissing() using the 'missingMessage' option, as an argument to the Zend_Filter_Input constructor or using the setOptions() method.
$options = array( 'missingMessage' => "Field '%field%' is required" ); $input = new Zend_Filter_Input($filters, $validators, $data, $options); // alternative method: $input = new Zend_Filter_Input($filters, $validators, $data); $input->setOptions($options); And you can also add a translator which gives you the ability to provide multiple languages for the messages which are returned by Zend_Filter_Input.
$translate = new Zend_Translate_Adapter_Array(array( Zend_Filter_Input::MISSING_MESSAGE => "Where is the field?" ); $input = new Zend_Filter_Input($filters, $validators, $data);
499
Zend_Filter
$input->setTranslator($translate); When you are using an application wide translator, then it will also be used by Zend_Filter_Input. In this case you will not have to set the translator manually. The results of the getUnknown() method is an associative array, mapping field names to field values. Field names are used as the array keys in this case, instead of rule names, because no rule mentions the fields considered to be unknown fields.
$m = $input->month; // escaped output from magic accessor $m = $input->getEscaped('month'); // escaped output $m = $input->getUnescaped('month'); // not escaped By default, when retrieving a value, it is filtered with the Zend_Filter_HtmlEntities. This is the default because it is considered the most common usage to output the value of a field in HTML. The HtmlEntities filter helps prevent unintentional output of code, which can result in security problems.
Nota
As shown above, you can retrieve the unescaped value using the getUnescaped() method, but you must write code to use the value safely, and avoid security issues such as vulnerability to cross-site scripting attacks.
$validators = array('*' => array()); $input = new Zend_Filter_Input($filters, $validators, $data, $options); But be warned that using this notation introduces a security leak which could be used for cross-site scripting attacks. Therefor you should always set individual validators for each field. You can specify a different filter for escaping values, by specifying it in the constructor options array:
$options = array('escapeFilter' => 'StringTrim'); $input = new Zend_Filter_Input($filters, $validators, $data, $options); Alternatively, you can use the setDefaultEscapeFilter() method:
$input = new Zend_Filter_Input($filters, $validators, $data); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); In either usage, you can specify the escape filter as a string base name of the filter class, or as an object instance of a filter class. The escape filter can be an instance of a filter chain, an object of the class Zend_Filter.
500
Zend_Filter
Filters to escape output should be run in this way, to make sure they run after validation. Other filters you declare in the array of filter rules are applied to input data before data are validated. If escaping filters were run before validation, the process of validation would be more complex, and it would be harder to provide both escaped and unescaped versions of the data. So it is recommended to declare filters to escape output using setDefaultEscapeFilter(), not in the $filters array. There is only one method getEscaped(), and therefore you can specify only one filter for escaping (although this filter can be a filter chain). If you need a single instance of Zend_Filter_Input to return escaped output using more than one filtering method, you should extend Zend_Filter_Input and implement new methods in your subclass to get values in different ways.
$filters = array( 'month' => array( 'Digits', // filter name at integer index [0] 'fields' => 'mo' // field name at string index ['fields'] ) ); In the example above, the filter rule applies the 'digits' filter to the input field named 'mo'. The string 'month' simply becomes a mnemonic key for this filtering rule; it is not used as the field name if the field is specified with the 'fields' metacommand, but it is used as the rule name. The default value of the 'fields' metacommand is the index of the current rule. In the example above, if the 'fields' metacommand is not specified, the rule would apply to the input field named 'month'. Another use of the 'fields' metacommand is to specify fields for filters or validators that require multiple fields as input. If the 'fields' metacommand is an array, the argument to the corresponding filter or validator is an array of the values of those fields. For example, it is common for users to specify a password string in two fields, and they must type the same string in both fields. Suppose you implement a validator class that takes an array argument, and returns TRUE if all the values in the array are equal to each other.
$validators = array( 'password' => array( 'StringEquals', 'fields' => array('password1', 'password2') ) ); // Invokes hypothetical class Zend_Validate_StringEquals,
501
Zend_Filter
// passing an array argument containing the values of the two input // data fields named 'password1' and 'password2'. If the validation of this rule fails, the rule key ('password') is used in the return value of getInvalid(), not any of the fields named in the 'fields' metacommand.
502
Zend_Filter
$validators = array( 'address2' => array( 'Alnum', 'allowEmpty' => true ) ); The default value of this metacommand is FALSE. In the uncommon case that you declare a validation rule with no validators, but the 'allowEmpty' metacommand is FALSE (that is, the field is considered invalid if it is empty), Zend_Filter_Input returns a default error message that you can retrieve with getMessages(). You can specify this message using the 'notEmptyMessage' option, as an argument to the Zend_Filter_Input constructor or using the setOptions() method.
$options = array( 'notEmptyMessage' => "A non-empty value is required for field '%field%'" ); $input = new Zend_Filter_Input($filters, $validators, $data, $options); // alternative method: $input = new Zend_Filter_Input($filters, $validators, $data); $input->setOptions($options);
503
Zend_Filter
new Zend_Validate_Between(1,12), new Zend_Validate_GreaterThan(0), 'breakChainOnFailure' => true ) ); $input = new Zend_Filter_Input(null, $validators); The default value of this metacommand is FALSE. The validator chain class, Zend_Validate, is more flexible with respect to breaking chain execution than Zend_Filter_Input. With the former class, you can set the option to break the chain on failure independently for each validator in the chain. With the latter class, the defined value of the 'breakChainOnFailure' metacommand for a rule applies uniformly for all validators in the rule. If you require the more flexible usage, you should create the validator chain yourself, and use it as an object in the validator rule definition: // Create validator chain with non-uniform breakChainOnFailure // attributes $chain = new Zend_Validate(); $chain->addValidator(new Zend_Validate_Digits(), true); $chain->addValidator(new Zend_Validate_Between(1,12), false); $chain->addValidator(new Zend_Validate_GreaterThan(0), true); // Declare validator rule using the chain defined above $validators = array( 'month' => $chain ); $input = new Zend_Filter_Input(null, $validators);
504
Zend_Filter
$validators = array( 'month' => array( 'digits', new Zend_Validate_Between(1, 12), 'messages' => array( // use default message for validator [0] // set new message for validator [1] 1 => 'A month value must be between 1 and 12' ) ) ); If one of your validators has multiple error messages, they are identified by a message key. There are different keys in each validator class, serving as identifiers for error messages that the respective validator class might generate. Each validate class defines constants for its message keys. You can use these keys in the 'messages' metacommand by passing an associative array instead of a string.
$validators = array( 'month' => array( 'digits', new Zend_Validate_Between(1, 12), 'messages' => array( 'A month must consist only of digits', array( Zend_Validate_Between::NOT_BETWEEN => 'Month value %value% must be between ' . '%min% and %max%', Zend_Validate_Between::NOT_BETWEEN_STRICT => 'Month value %value% must be strictly between ' . '%min% and %max%' ) ) ) ); You should refer to documentation for each validator class to know if it has multiple error messages, the keys of these messages, and the tokens you can use in the message templates. If you have only one validator in validation rule or all used validators has the same messages set, then they can be referenced without additional array construction:
$validators = array( 'month' => array( new Zend_Validate_Between(1, 12), 'messages' => array( Zend_Validate_Between::NOT_BETWEEN => 'Month value %value% must be between ' . '%min% and %max%', Zend_Validate_Between::NOT_BETWEEN_STRICT => 'Month value %value% must be strictly between ' . '%min% and %max%' ) ) );
505
Zend_Filter
// The default is set so all fields allow an empty string. $options = array('allowEmpty' => true); // You can override this in a rule definition, // if a field should not accept an empty string. $validators = array( 'month' => array( 'Digits', 'allowEmpty' => false ) ); $input = new Zend_Filter_Input($filters, $validators, $data, $options); The 'fields', 'messages', and 'default' metacommands cannot be set using this technique.
$options = array('filterNamespace' => 'My_Namespace_Filter', 'validatorNamespace' => 'My_Namespace_Validate'); $input = new Zend_Filter_Input($filters, $validators, $data, $options); Alternatively, you can use the addValidatorPrefixPath($prefix, $path) or addFilterPrefixPath($prefix, $path) methods, which directly proxy to the plugin loader that is used by Zend_Filter_Input:
$input->addValidatorPrefixPath('Other_Namespace', 'Other/Namespace'); $input->addFilterPrefixPath('Foo_Namespace', 'Foo/Namespace'); // // // // Now the search order for validators is: 1. My_Namespace_Validate 2. Other_Namespace 3. Zend_Validate
506
Zend_Filter
// 3. Zend_Filter You cannot remove Zend_Filter and Zend_Validate as namespaces, you only can add namespaces. Userdefined namespaces are searched first, Zend namespaces are searched last.
Nota
As of version 1.5 the function addNamespace($namespace) was deprecated and exchanged with the plugin loader and the addFilterPrefixPath and addValidatorPrefixPath were added. Also the constant Zend_Filter_Input::INPUT_NAMESPACE is now deprecated. The constants Zend_Filter_Input::VALIDATOR_NAMESPACE and Zend_Filter_Input::FILTER_NAMESPACE are available in releases after 1.7.0.
Nota
As of version 1.0.4, Zend_Filter_Input::NAMESPACE, having value namespace, was changed to Zend_Filter_Input::INPUT_NAMESPACE, having value inputNamespace, in order to comply with the PHP 5.3 reservation of the keyword namespace.
Zend_Filter_Inflector
Zend_Filter_Inflector is a general purpose tool for rules-based inflection of strings to a given target. As an example, you may find you need to transform MixedCase or camelCasedWords into a path; for readability, OS policies, or other reasons, you also need to lower case this, and you want to separate the words using a dash ('-'). An inflector can do this for you. Zend_Filter_Inflector implements Zend_Filter_Interface; you perform inflection by calling filter() on the object instance.
Operation
An inflector requires a target and one or more rules. A target is basically a string that defines placeholders for variables you wish to substitute. These are specified by prefixing with a ':': :script. When calling filter(), you then pass in an array of key/value pairs corresponding to the variables in the target.
507
Zend_Filter
Each variable in the target can have zero or more rules associated with them. Rules may be either static or refer to a Zend_Filter class. Static rules will replace with the text provided. Otherwise, a class matching the rule provided will be used to inflect the text. Classes are typically specified using a short name indicating the filter name stripped of any common prefix. As an example, you can use any Zend_Filter concrete implementations; however, instead of referring to them as 'Zend_Filter_Alpha' or 'Zend_Filter_StringToLower', you'd specify only 'Alpha' or 'StringToLower'.
// use Zend_Filter_Word_CamelCaseToDash as a rule $inflector->addRules(array('script' => 'Word_CamelCaseToDash')); To set alternate paths, Zend_Filter_Inflector has a utility method that proxies to the plugin loader, addFilterPrefixPath():
$inflector->addFilterPrefixPath('My_Filter', 'My/Filter/'); Alternatively, you can retrieve the plugin loader from the inflector, and interact with it directly:
$loader = $inflector->getPluginLoader(); $loader->addPrefixPath('My_Filter', 'My/Filter/'); For more options on modifying the paths to filters, please see the PluginLoader documentation.
// Via constructor: $inflector = new Zend_Filter_Inflector('#foo/#bar.#sfx', null, '#'); // Via accessor: $inflector->setTargetReplacementIdentifier('#'); Typically, you will set the target via the constructor. However, you may want to re-set the target later (for instance, to modify the default inflector in core components, such as the ViewRenderer or Zend_Layout). setTarget() can be used for this purpose:
$inflector = $layout->getInflector();
508
Zend_Filter
$inflector->setTarget('layouts/:script.phtml'); Additionally, you may wish to have a class member for your class that you can use to keep the inflector target updated -- without needing to directly update the target each time (thus saving on method calls). setTargetReference() allows you to do this:
class Foo { /** * @var string Inflector target */ protected $_target = 'foo/:bar/:baz.:suffix'; /** * Constructor * @return void */ public function __construct() { $this->_inflector = new Zend_Filter_Inflector(); $this->_inflector->setTargetReference($this->_target); } /** * Set target; updates target in inflector * * @param string $target * @return Foo */ public function setTarget($target) { $this->_target = $target; return $this; } }
Inflection Rules
As mentioned in the introduction, there are two types of rules: static and filter-based.
Nota
It is important to note that regardless of the method in which you add rules to the inflector, either one-byone, or all-at-once; the order is very important. More specific names, or names that might contain other rule names, must be added before least specific names. For example, assuming the two rule names 'moduleDir' and 'module', the 'moduleDir' rule should appear before module since 'module' is contained within 'moduleDir'. If 'module' were added before 'moduleDir', 'module' will match part of 'moduleDir' and process it leaving 'Dir' inside of the target uninflected.
Static Rules
Static rules do simple string substitution; use them when you have a segment in the target that will typically be static, but which you want to allow the developer to modify. Use the setStaticRule() method to set or modify the rule:
509
Zend_Filter
$inflector = new Zend_Filter_Inflector(':script.:suffix'); $inflector->setStaticRule('suffix', 'phtml'); // change it later: $inflector->setStaticRule('suffix', 'php'); Much like the target itself, you can also bind a static rule to a reference, allowing you to update a single variable instead of require a method call; this is often useful when your class uses an inflector internally, and you don't want your users to need to fetch the inflector in order to update it. The setStaticRuleReference() method is used to accomplish this: class Foo { /** * @var string Suffix */ protected $_suffix = 'phtml'; /** * Constructor * @return void */ public function __construct() { $this->_inflector = new Zend_Filter_Inflector(':script.:suffix'); $this->_inflector->setStaticRuleReference('suffix', $this->_suffix); } /** * Set suffix; updates suffix static rule in inflector * * @param string $suffix * @return Foo */ public function setSuffix($suffix) { $this->_suffix = $suffix; return $this; } }
510
Zend_Filter
Filter object. Any object instance implementing Zend_Filter_Interface may be passed as a filter. Array. An array of one or more strings or filter objects as defined above. $inflector = new Zend_Filter_Inflector(':script.:suffix'); // Set rule to use Zend_Filter_Word_CamelCaseToDash filter $inflector->setFilterRule('script', 'Word_CamelCaseToDash'); // Add rule to lowercase string $inflector->addFilterRule('script', new Zend_Filter_StringToLower()); // Set rules en-masse $inflector->setFilterRule('script', array( 'Word_CamelCaseToDash', new Zend_Filter_StringToLower() ));
Utility Methods
Zend_Filter_Inflector has a number of utility methods for retrieving and setting the plugin loader, manipulating and retrieving rules, and controlling if and when exceptions are thrown. setPluginLoader() can be used when you have configured your own plugin loader and wish to use it with Zend_Filter_Inflector; getPluginLoader() retrieves the currently set one. setThrowTargetExceptionsOn() can be used to control whether or not filter() throws an exception when a given replacement identifier passed to it is not found in the target. By default, no exceptions are thrown. isThrowTargetExceptionsOn() will tell you what the current value is.
511
Zend_Filter
getRules($spec = null) can be used to retrieve all registered rules for all variables, or just the rules for a single variable. getRule($spec, $index) fetches a single rule for a given variable; this can be useful for fetching a specific filter rule for a variable that has a filter chain. $index must be passed. clearRules() will clear all currently registered rules.
512
513
Zend_Form
button checkbox (o varios checkboxes a la vez con multiCheckbox) hidden image password radio reset select (tanto regulares como de multi-seleccin) submit text textarea Tiene dos opciones para aadir elementos a un formulario; puede instanciar elementos concretos y pasarlos como objetos, o simplemente puede pasar el tipo de elemento y Zend_Form instaciar por usted un objeto del tipo correspondiente. Algunos ejemplos:
// 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'); De manera predeterminada, stos no tienen validadores o filtros. Esto significa que tendr que configurar sus elementos con un mnimo de validadores, y potencialmente filtros. Puede hacer esto (a) antes de pasar el elemento al formulario, (b) va opciones de configuracin pasadas cuando crea un elemento a travs de Zend_Form, o (c) recuperar el elemento del objeto form y configurndolo posteriormente. Veamos primero la creacin de validadores para la instancia de un elemento concreto. Puede pasar objetos Zend_Validate_* o el nombre de un validador para utilizar:
$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'); Cuando se utiliza esta segunda opcin, si el constructor del validador acepta argumentos, se pueden pasar en un array como tercer parmetro:
// Pasando un patrn
514
Zend_Form
$username->addValidator('regex', false, array('/^[a-z]/i')); (El segundo parmetro se utiliza para indicar si el fallo debera prevenir la ejecucin de validadores posteriores o no; por defecto, el valor es false.) Puede tambin desear especificar un elemento como requerido. Esto puede hacerse utilizando un mtodo de acceso o pasando una opcin al crear el elemento. En el primer caso:
// Hace este elemento requerido: $username->setRequired(true); Cuando un elemento es requerido, un validador 'NotEmpty' (NoVacio) es aadido a la parte superior de la cadena de validaciones, asegurando que el elemento tenga algn valor cuando sea requerido. Los filtros son registrados bsicamente de la misma manera que los validadores. Para efectos ilustrativos, vamos a agregar un filtro para poner en minsculas el valor final:
$username->addValidator('alnum') ->addValidator('regex', false, array('/^[a-z]/')) ->setRequired(true) ->addFilter('StringToLower'); // o, de manera ms compacta: $username->addValidators(array('alnum', array('regex', false, '/^[a-z]/i') )) ->setRequired(true) ->addFilters(array('StringToLower')); Tan simple como esto, realizarlo para cada uno de los elementos del formulario puede resultar un poco tedioso. Intentemos la opcin (b) arriba mencionada. Cuando creamos un nuevo elemento utilizando Zend_Form::addElement() como fbrica, opcionalmente podemos pasar las opciones de configuracin. stas pueden incluir validadores y los filtros que se van a utilizar. Por lo tanto, para hacer todo lo anterior implcitamente, intente lo siguiente:
$form->addElement('text', 'username', array( 'validators' => array( 'alnum', array('regex', false, '/^[a-z]/i') ), 'required' => true, 'filters' => array('StringToLower'), ));
Nota
Si encuentra que est asignando elementos con las mismas opciones en varios lugares, podra considerar crear su propia subclase de Zend_Form_Element y utilizar sta; a largo plazo le permitir escribir menos.
515
Zend_Form
Generar un formulario
Generar un formulario es simple. La mayora de los elementos utilizan un auxiliar de Zend_View para generarse a s mismos, por lo tanto necesitan un objeto vista con el fin de generarse. Adems, tiene dos opciones: usar el mtodo render() del formulario, o simplemente mostrarlo con echo. // Llamando a render() explicitamente, y pasando un objeto vista opcional: echo $form->render($view); // Suponiendo un objeto vista ha sido previamente establecido va setView(): echo $form; De manera predeterminada, Zend_Form y Zend_Form_Element intentarn utilizar el objeto vista inicializado en el ViewRenderer, 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: <?php echo $this->form Detrs del teln, Zend_Form utiliza "decoradores" (decorators) para generar la salida. Estos decoradores pueden reemplazar, aadir o anteponer contenido, y tienen plena introspeccin al elemento que les es pasado. Como resultado, puede combinar mltiples decoradores para lograr efectos personalizados. Predeterminadamente, Zend_Form_Element actualmente combina cuatro decoradores para obtener su salida; la configuracin sera como sigue: $element->addDecorators(array( 'ViewHelper', 'Errors', array('HtmlTag', array('tag' => 'dd')), array('Label', array('tag' => 'dt')), )); (Donde <HELPERNAME> es el nombre de un view helper que utilizar, y vara segn el elemento) Lo anterior crea una salida como la siguiente: <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> (Aunque no con el mismo formato.) Puede cambiar los decoradores usados para un elemento si desea tener diferente salida; vase la seccin sobre decoradores para mayor informacin. 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 <form>, como cualquier atributo que establezca va setAttribs() y familia.
516
Zend_Form
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:
if ($form->isValid($_POST)) { // Correcto! } else { // Fallo! } Con solicitudes AJAX, a veces puede ignorar la validacin de un solo elemento, o grupo de elementos. isValidPartial() validar parcialmente el formulario. A diferencia de isValid(), que como sea, si alguna clave no esta presente, no ejecutar las validaciones para ese elemento en particular.
if ($form->isValidPartial($_POST)) { // de los elementos presentes, todos pasaron las validaciones } else { // uno u ms elementos probados no pasaron las validaciones } Un mtodo adicional, processAjax(), puede tambin ser usado para validar formularios parciales. A diferencia de isValidPartial(), regresa una cadena en formato JSON conteniendo mensajes de error en caso de fallo. Asumiendo que sus validaciones han pasado, ahora puede obtener los valores filtrados:
$values = $form->getValues(); Si necesita los valores sin filtrar en algn punto, utilice:
$unfiltered = $form->getUnfilteredValues();
517
Zend_Form
if (!$form->isValid($_POST)) { echo $form; // o asigne al objeto vista y genere una vista... $this->view->form = $form; return $this->render('form'); } Si quiere inspeccionar los errores, tiene dos mtodos. getErrors() regresa una matriz asociativa de nombres / cdigos de elementos (donde cdigos es una matriz de cdigos de error). getMessages() regresa una matriz asociativa de nombres / mensajes de elementos (donde mensajes es una matriz asociativa de pares cdigo de error / mensaje de error). Si un elemento no tiene ningn error, no ser incluido en la matriz.
$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); // Aade los elementos al formulario: $form->addElement($username) ->addElement($password) // uso de addElement() como fbrica para crear el botn 'Login': ->addElement('submit', 'login', array('label' => 'Login'));
518
Zend_Form
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 validacin; Se vuelve a mostrar el formulario $this->view->form = $form; return $this->render('form'); } $values = $form->getValues(); // ahora intenta y autentica... } } Y un script para la vista que muestra el formulario:
<h2>Please login:</h2> <?php echo $this->form Como notar en el cdigo del controlador, hay ms trabajo por hacer: mientras la informacin enviada sea vlida, necesitar todava realizar la autenticacin usando Zend_Auth, por ejemplo.
[development]
519
Zend_Form
; metainformacin 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" Entonces puede pasarlo al constructor del formulario:
$config = new Zend_Config_Ini($configFile, 'development'); $form = new Zend_Form($config->user->login); y el formulario entero ser definido.
Conclusin
Esperamos que despus de este pequeo tutorial sea capaz de descubrir el poder y flexibilidad de Zend_Form. Contine leyendo para profundizar ms en el tema.
520
Zend_Form
La clase base, Zend_Form_Element, funciona por defecto para varios casos, pero es mejor extender la clase para elementos con fines especiales de uso comn. Adicionalmente, Zend Framework contiene un nmero de elementos XHTML estndar; puede leer de ellos en el captulo Elementos Estndares
Cargadores de Plugin
Zend_Form_Element hace uso de Zend_Loader_PluginLoader 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 mtodos de acceso generales usados para su recuperacin y modificacin. Los siguientes tipos de cargadores son usados con los varios mtodos del cargador de plugin: 'validate', 'filter', y 'decorator'. Los nombres son sensibles a maysculas y minsculas. Los mtodos usados para interactuar con los cargadores de plugin son los siguientes: setPluginLoader($loader, $type): $loader es el propio objeto cargador, mientras $type es uno de los tipos arriba mencionados. Esto establece el cargador de plugin para el tipo dado en el objeto cargador recin especificado. getPluginLoader($type): obtiene el cargador de plugin asociado con $type. addPrefixPath($prefix, $path, $type = null): agrega una asociacin prefijo/ruta para el cargador especificado por $type. Si $type es null, se intentar agregar la ruta a todos los cargadores, aadiendo 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 jerarqua comn, este mtodo es conveniente para establecer el prefijo para todas ellas. addPrefixPaths(array $spec): le permite aadir varias rutas de una sola vez a uno o ms cargadores de plugin. Se espera cada elemento de la matriz sea un array con claves 'path', 'prefix', y 'type'. Validadores, filtros y decoradores personalizados son una manera simple de compartir funcionalidad entre formularios y encapsular funcionalidad personalizada.
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;
521
Zend_Form
} $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; } } } Ahora diremos al elemento que use esta ruta cuando busque por decoradores:
$element->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator'); Alternativamente, podemos hacerlo en el formulario para asegurar que todos los decoradores usen esta ruta:
$form->addElementPrefixPath('My_Decorator', 'My/Decorator/', 'decorator'); Con esta ruta aadida, cuando agregue un decorador, la ruta 'My/Decorator' ser consultada primero en bsqueda de la existencia del decorador en este lugar. Como resultado, 'My_Decorator_Label' ahora ser utilizado cuando el decorador 'Label' sea requerido.
Filters
A menudo es til y/o necesario realizar alguna normalizacin en la entrada antes de la validacin por ejemplo, puede querer eliminar todo el HTML, pero realizar las validaciones sobre lo restante para asegurarse que el envo es vlido. 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 Zend_Filter, y Zend_Form_Element que soportan cadenas de filtros, permitindole especificar mltiples filtros secuenciales a utilizar. El filtrado sucede tanto en la validacin como cuando recupera el valor del elemento va getValue():
522
Zend_Form
$filtered = $element->getValue();
Los filtros pueden ser agregados a la pila de dos maneras: pasndolo en una instancia de filtro especfica proveyendo un nombre de filtro el correspondiente nombre corto o completo de la clase Veamos algunos ejemplos:
// Instancia especfica 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'); Los nombres cortos son tpicamente el nombre del filtro sin el prefijo. En el caso predeterminado, esto se refiere a sin el prefijo 'Zend_Filter_'. Adems, la primera letra no necesita estar en mayscula.
$element->addPrefixPath('My_Filter', 'My/Filter/', 'filter'); (Recuerde que el tercer argumento indica el cargador de plugin sobre el cual ha de ejecutarse la accin.) Si en algn momento necesita un valor no filtrado, use el mtodo getUnfilteredValue():
$unfiltered = $element->getUnfilteredValue(); Para mayor informacin sobre filtros, vea la documentacin de Zend_Filter. Mtodos asociados con filtros incluyen: addFilter($nameOfFilter, array $options = null) addFilters(array $filters) setFilters(array $filters) (sobreescribe todos los filtros) getFilter($name) (recupera un objeto filtro por su nombre) getFilters() (recupera todos los filtros)
523
Zend_Form
removeFilter($name) (elimina un filtro por su nombre) clearFilters() (elimina todos los filtros)
Validadores
Si sigue el mantra de seguridad "filtrar la entrada, escapar la salida" querr validar ("filtrar la entrada") los datos de los formularios. En Zend_Form cada elemento contiene su propia cadena de validadores, consistente en validadores Zend_Validate_*. Los validadores pueden ser agregados de dos maneras: pasndolo en una instancia de validador especfica proveyendo un nombre de validador el correspondiente nombre corto o completo de clase Veamos algunos ejemplos:
// Instancia especfica 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'); Los nombres cortos son tpicamente el nombre del validador sin el prefijo. En el caso predeterminado, esto se refiere a sin el prefijo 'Zend_Validate_'. Adems, la primera letra no necesita estar en mayscula.
$element->addPrefixPath('My_Validator', 'My/Validator/', 'validate'); (Recuerde que el tercer argumento indica el cargador de plugin sobre el cual ha de ejecutarse la accin.) Si el fallo de un validador debe evitar validaciones posteriores, pase el boleano true como segundo parmetro:
$element->addValidator('alnum', true); Si est usando la cadena nombre para aadir el validador, y la clase del validador acepta argumentos para su constructor, puede pasarlos a el tercer parmetro de addValidator() como un array:
524
Zend_Form
$element->addValidator('StringLength', false, array(6, 20)); 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 Zend_Validate_StringLenth con los parmetros $min y $max:
$element->addValidators(array( array('NotEmpty', true), array('alnum'), array('stringLength', false, array(6, 20)), )); Si quiere ser ms detallado o explcito, puede utilizar las claves 'validator', 'breakChainOnFailure', y 'options' en el array:
$element->addValidators(array( array( 'validator' => 'NotEmpty', 'breakChainOnFailure' => true), array('validator' => 'alnum'), array( 'validator' => 'stringLength', 'options' => array(6, 20)), )); Este uso es bueno para ilustrar cmo puede configurar validadores en un archivo de configuracin:
525
Zend_Form
element.validators.strlen.options.max = 20 Note que cada elemento tiene una clave, la necesite o no; esta es una limitacin del uso de archivos de configuracin -- pero tambin ayuda a hacer ms explicito el para qu son usados los argumentos. Slo recuerde que cualesquiera opciones del validador deben ser especificadas en orden. Para validar un elemento, pase el valor a isValid():
Contexto de validacin
Zend_Form_Element::isValid()> soporta un argumento adicional, $context. Zend_Form::isValid() pasa todo el conjunto de datos procesados a $context cuando valida un formulario, y Zend_Form_Element::isValid()>, 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 estndar que tiene campos para la contrasea y la confirmacin de la contrasea; una validacin sera que los dos campos coincidan. Este validador puede tener un aspecto como el siguiente:
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; }
526
Zend_Form
$this->_error(self::NOT_MATCH); return false; } } Los validadores son procesados en orden. Cada validador es procesado, a menos que un validador creado con un valor true para breakChainOnFailure falle su validacin. Asegrese de especificar sus validadores en un orden razonable. Despus de una validacin fallida, puede recuperar los cdigos y mensajes de error de la cadena del validador:
$errors = $element->getErrors(); $messages = $element->getMessages(); (Nota: los mensajes de error retornados son un array asociativo de pares cdigo / mensaje de error.) En adicin a los validadores, puede especificar que un elemento es necesario, usando setRequired(true). Por defecto, esta bandera es false, lo que significa que pasar su cadena de validadores si ningn valor es pasado a isValid(). Puede modificar este comportamiento en un nmero de maneras: Por defecto, cuando un elemento es requerido, una bandera, 'allowEmpty', tambin es true. Esto quiere decir que si un valor empty es evaluado pasndolo a isValid(), los validadores sern saltados. Puede intercalar esta bandera usando el mtodo de acceso setAllowEmpty($flag); cuando la bandera es false, si un valor es pasado, los validadores seguirn ejecutndose. Por defecto, si un elemento es requerido, pero no contiene un validador 'NotEmpty', isValid() aadir uno en la cima de la pila, con la bandera breakChainOnFailure establecido. Esto hace que la bandera requerida tenga un significado semntico: si ningn valor es pasado, inmediatamente invalidamos el envo y se le notifica al usuario, e impedimos que otros validadores se ejecuten en lo que ya sabemos son datos invlidos. Si no quiere este comportamiento, puede desactivarlo pasando un valor false a setAutoInsertNotEmptyValidator($flag); esto prevendr a isValid() de colocar un validador 'NotEmpty' en la cadena de validaciones. Para mayor informacin sobre validadores, vea la documentacin de Zend_Validate.
527
Zend_Form
addValidator($nameOrValidator, $breakChainOnFailure = false, array $options = null) addValidators(array $validators) setValidators(array $validators) (sobreescribe todos los validadores) getValidator($name) (recupera un objeto validador por nombre) getValidators() (recupera todos los validadores) removeValidator($name) (elimina un validador por nombre) clearValidators() (elimina todos los validadores)
Decoradores
Una dolencia particular para muchos desarrolladores web es la creacin del XHTML para formularios por ellos mismos. Para cada elemento, el desarrollador necesita crear la marcacin para el elemento mismo, comnmente una
528
Zend_Form
etiqueta (label), y, si son amables con sus usuarios, la marcacin para mostrar mensajes de errores de validacin. Cuanto ms elementos en una pgina, menos trivial se convierte esta tarea. Zend_Form_Element intenta resolver este problema mediante el uso de "decoradores". Los decoradores son clases simples que tienen mtodos de acceso al elemento y mtodos para generar el contenido. Para obtener mayor informacin sobre cmo trabajan los decoradores, consulte por favor la seccin sobre Zend_Form_Decorator. Los decoradores usados por defecto por Zend_Form_Element son: ViewHelper: 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, Zend_Form_Element especifica el auxiliar vista 'formText', pero cada subclase especifica diferentes auxiliares. Errors: aade mensajes de error al elemento usando Zend_View_Helper_FormErrors. Si no est presente, no se aade nada. Description: aade la descripcin del elemento. Si no est presente, no se aade nada. Por defecto, la descripcin es generada dentro de una etiqueta <p> con un class 'description'. HtmlTag: envuelve el elemento y los errores en una etiqueta HTML <dd>. Label: aade al comienzo una etiqueta al elemento usando Zend_View_Helper_FormLabel, y envolvindola en una etiqueta <dt>. Si ninguna etiqueta es provista, solo la etiqueta de la definicin es generada.
$element = new Zend_Form_Element('foo', array('disableLoadDefaultDecorators' => true) ); Esta opcin puede ser combinada junto con cualquier otra opcin que pase, ya sea como un array de opciones o en un objeto Zend_Config. 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 colocacin en el modo apropiado. Por dar un ejemplo, aqu esta el cdigo que registran los decoradores por defecto:
$this->addDecorators(array( array('ViewHelper'), array('Errors'), array('Description', array('tag' => 'p', 'class' => 'description')), array('HtmlTag', array('tag' => 'dd')), array('Label', array('tag' => 'dt')), )); 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'
529
Zend_Form
para mostrarlos. Si una descripcin est presente, el decorador 'Description' aadir un prrafo con class 'description' conteniendo el texto descriptivo para el contenido agregado. El siguiente decorador, 'HtmlTag', envuelve al elemento, los errores, y la descripcin en una etiqueta HTML <dd>. Finalmente, el ltimo decorador, 'label', recupera la etiqueta del elemento y la pasa al auxiliar vista 'FormLabel', envolvindolo en una etiqueta <dt>; por default el valor es aadido al inicio del contenido. El resultado de la salida bsicamente se ve as:
<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> Para ms informacin sobre decoradores, lea la seccin de Zend_Form_Decorator.
// Alias a 'FooBar': $element->addDecorator(array('FooBar' => 'HtmlTag'), array('tag' => 'div')); // Y recuperandolo posteriormente: $decorator = $element->getDecorator('FooBar'); En los mtodos addDecorators() y setDecorators(), necesitar pasar la opcin 'decorator' en la matriz representando el decorador:
// Y dos decoradores 'HtmlTag', 'FooBar' como alias: $element->addDecorators( array('HtmlTag', array('tag' => 'div')), array( 'decorator' => array('FooBar' => 'HtmlTag'), 'options' => array('tag' => 'dd') ), ); // Y recuperndolos posteriormente:
530
Zend_Form
$htmlTag = $element->getDecorator('HtmlTag'); $fooBar = $element->getDecorator('FooBar'); Mtodos asociados con decoradores incluyen: addDecorator($nameOrDecorator, array $options = null) addDecorators(array $decorators) setDecorators(array $decorators) (sobreescribe todos los decoradores) getDecorator($name) (recupera un objeto decorador por su nombre) getDecorators() (recupera todos los decoradores) removeDecorator($name) (elimina un decorador por su nombre) clearDecorators() (elimina todos los decoradores) Zend_Form_Element tambin utiliza la sobrecarga para permitir generar decoradores especficos. __call() interceptar mtodos que comiencen con el texto 'render' y utilizar el resto del nombre del mtodo para buscar un decorador; si se encuentra, entonces ser generado slo ese decorador. Cualquier argumento pasado al llamado del mtodo ser usado como contenido para pasar al mtodo render() del decorador. Como ejemplo:
// Genera solo el decorador ViewHelper: echo $element->renderViewHelper(); // Genera solo el decorador HtmlTag, pasndole contenido: echo $element->renderHtmlTag("This is the html tag content"); Si el decorador no existe, una excepcin es lanzada.
Metadatos y atributos
Zend_Form_Element manipula una variedad de atributos y medatados del elemento. Atributos bsicos incluyen: name: el nombre del elemento. Emplea los mtodos de acceso setName() y getName(). label: la etiqueta del elemento. Emplea los mtodos de acceso setLabel() y getLabel(). order: el ndice en el cual los elementos deben ir mostrndose en el formulario. Emplea los mtodos de acceso setOrder() y getOrder(). value: El valor del elemento actual. Emplea los mtodos de acceso setValue() y getValue(). description: una descripcin del elemento; a menudo utilizada para proveer un tooltip o ayuda contextual con javascript describiendo el propsito del elemento. Emplea los mtodos de acceso setDescription() y getDescription(). required: bandera que indica si un elemento es requerido o no cuando se efecta la validacin del formulario. Emplea los mtodos de acceso setRequired() y getRequired(). Esta bandera es false por defecto. allowEmpty: bandera indicando si un elemento no-requerido (opcional) debe intentar validar o no valores vacos. Cuando es true, y la bandera required es false, valores vacos no pasarn la cadena de validacin, y se supone
531
Zend_Form
verdadero. Emplea los mtodos de acceso setAllowEmpty() y getAllowEmpty(). Esta bandera es true por defecto. autoInsertNotEmptyValidator: bandera indicando insertar o no un validador 'NotEmpty' cuando un elemento es requerido. Por defecto, esta bandera es true. Establezca la bandera con setAutoInsertNotEmptyValidator($flag) y determine el valor con autoInsertNotEmptyValidator(). Los elementos del formulario pueden requerir metainformacin adicional. Para elementos XHTML del formuladio, por ejemplo, puede querer especificar atributos como el class o id. Para facilitar esto hay un conjunto de mtodos de acceso: setAttrib($name, $value): aade un atributo setAttribs(array $attribs): como addAttribs(), pero sobreescribiendo getAttrib($name): recupera el valor de solo un atributo getAttribs(): recupera todos los atributos como pares clave/valor La mayora de las veces, como sea, puede simplemente acceder a ellos como propiedades de objeto, ya que Zend_Form_Element utiliza la sobrecarga para facilitar el acceso a ellos:
// Equivalente a $element->setAttrib('class', 'text'): $element->class = 'text; Por defecto, todos los atributos son pasados al auxiliar vista usado por el elemento durante la generacin, y generados como atributos de la etiqueta del elemento.
Elementos Estndar
Zend_Form contiene un buen nmero de elementos estndar; por favor lea el captulo Elementos Estndar para todos los detalles.
Mtodos de Zend_Form_Element
Zend_Form_Element tiene muchos, muchos mtodos. Lo que sigue es un sumario de sus funciones, agrupados por tipo: Configuracin: setOptions(array $options) setConfig(Zend_Config $config) I18n: setTranslator(Zend_Translate_Adapter $translator = null) getTranslator() setDisableTranslator($flag) translatorIsDisabled()
532
Zend_Form
Propiedades: setName($name) getName() setValue($value) getValue() getUnfilteredValue() setLabel($label) getLabel() setDescription($description) getDescription() setOrder($order) getOrder() setRequired($flag) getRequired() setAllowEmpty($flag) getAllowEmpty() setAutoInsertNotEmptyValidator($flag) autoInsertNotEmptyValidator() setIgnore($flag) getIgnore() getType() setAttrib($name, $value) setAttribs(array $attribs) getAttrib($name) getAttribs() Cargadores y rutas de plugin: setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type) getPluginLoader($type) addPrefixPath($prefix, $path, $type = null) addPrefixPaths(array $spec)
533
Zend_Form
Validacin: addValidator($validator, $breakChainOnFailure = false, $options = array()) addValidators(array $validators) setValidators(array $validators) getValidator($name) getValidators() removeValidator($name) clearValidators() isValid($value, $context = null) getErrors() getMessages() Filtros: addFilter($filter, $options = array()) addFilters(array $filters) setFilters(array $filters) getFilter($name) getFilters() removeFilter($name) clearFilters() Generacin: setView(Zend_View_Interface $view = null) getView() addDecorator($decorator, $options = null) addDecorators(array $decorators) setDecorators(array $decorators) getDecorator($name) getDecorators() removeDecorator($name) clearDecorators() render(Zend_View_Interface $view = null)
534
Zend_Form
Configuracin
El constructor de Zend_Form_Element acepta tanto una matriz de opciones como un objeto Zend_Config conteniendo opciones, y esto puede configurarse usando setOptions() o setConfig(). Hablando de manera general, las claves son nombradas de la siguiente manera: Si 'set' + clave se refiere a un mtodo de Zend_Form_Element, entonces el valor provisto ser pasado a el mtodo. De otra manera, el valor ser usado para establecer un atributo. Excepciones a la regla incluyen las siguientes: prefixPath ser pasado a addPrefixPaths() Los siguientes setters no pueden establecerse de esta manera: setAttrib (aunque setAttribs funcionar setConfig setOptions setPluginLoader setTranslator setView Como ejemplo, aqu esta un archivo de configuracin pasado para cada tipo de dato configurable:
[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"
535
Zend_Form
Elementos personalizados
Usted puede crear sus propios elementos personalizados simplemente extendiendo la clase Zend_Form_Element. Las razones comunes para hacer esto incluyen: Elementos que comparten validadores y/o filtros comunes Elementos que tienen decoradores con funcionalidad personalizada Hay dos mtodos tpicamente usados para extender un elemento: init(), el cual puede usarse para aadir una lgica de inicializacin personalizada a su elemento, y loadDefaultDecorators(), el cual puede usarse para establecer una lista de decoradores usados por su elemento de manera predeterminada. Como un ejemplo, digamos que todos los elementos de tipo texto en un formulario que est creando, necesitan ser filtrados con StringTrim, validados con una expresin regular, y que quiere usar un decorador personalizado que ha creado para mostrarlos, 'My_Decorator_TextItem'; adicionalmente, tiene un nmero de atributos estndars, incluyendo 'size', 'maxLength', y 'class' que quisiera especificar. Puede definir un elemento tal como sigue:
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'); } } Entonces puede informar a su objeto formulario acerca del prefijo de ruta para elementos de ese tipo, y comenzar creando elementos:
$form->addPrefixPath('My_Element', 'My/Element/', 'element') ->addElement('foo', 'text'); El elemento 'foo' ser ahora del tipo My_Element_Text, y mostrar el comportamiento que ha especificado. Otro mtodo que puede querer sobreescribir cuando extienda Zend_Form_Element es el mtodo loadDefaultDecorators(). Este mtodo carga condicionalmente un grupo de decoradores predefinidos para su elemento; puede querer sustituir su propio decorador en su clase extendida:
536
Zend_Form
{ public function loadDefaultDecorators() { $this->addDecorator('ViewHelper') ->addDecorator('DisplayError') ->addDecorator('Label') ->addDecorator('HtmlTag', array('tag' => 'div', 'class' => 'element')); } } Hay muchas maneras de personalizar elementos; asegrese de leer la documentacin de la API de Zend_Form_Element para conocer todos los mtodos disponibles.
// Objeto form genrico: $form = new Zend_Form(); // Objeto form personalizado: $form = new My_Form() Opcionalmente puede pasarlo en la configuracin, la cual ser usada para establecer el estado del objeto, potencialmente as como tambin crear nuevos elementos:
// Pasando opciones en la configuracin: $form = new Zend_Form($config); Zend_Form 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. La magia de Zend_Form radica en la habilidad para servir como fbrica para elementos y grupos, as como tambin la habilidad de generarse a s mismo a travs de decoradores.
537
Zend_Form
Cargadores de Plugin
Zend_Form hace uso de Zend_Loader_PluginLoader para permitir a los desarroladores especificar la ubicacin de elementos y decoradores alternativos. Cada uno tiene su propio plugin loader asociado, y mtodos de acceso genricos son usados para recuperar y modificar cada uno. Los siguientes tipos de cargadores son usados con los variados mtodos del plugin loader: 'element' y 'decorator'. Los nombres de los tipos no distinguen maysculas de minsculas. Los mtodos usados para interactuar con plugin loaders son los siguientes: setPluginLoader($loader, $type): $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 recin especificado. getPluginLoader($type): recupera el plugin loader asociado con $type. addPrefixPath($prefix, $path, $type = null): agrega una asociacin prefijo/ruta al loader especificado por $type. Si $type es nulo, intentar aadir una ruta a todos los loaders, aadiendo el prefijo "_Element" y "_Decorator"; y aadiendo la ruta con "Element/" y "Decorator/". Si tiene todas sus clases form element extras bajo una jerarqua comn, ste es un mtodo coveniente para establecer el prefijo de base para ellas. addPrefixPaths(array $spec): le permite aadir 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'. Adicionalmente, puede especificar prefijos de rutas para todos los elementos y mostrar grupos creados a travs de una instancia de Zend_Form usando los siguientes mtodos: addElementPrefixPath($prefix, $path, $type = null): Igual que addPrefixPath(), debe especificar un prefijo y ruta de clase. $type, cuando se especifica, tiene que ser uno de los tipos plugin loader especificados por Zend_Form_Element; vea la seccin elemento plugins para ms informacin de valores vlidos para $type. Si $type no es especificado, el mtodo asumir que es un prefijo general para todos los tipos. addDisplayGroupPrefixPath($prefix, $path): Igual que addPrefixPath(), debe especificar un prefijo y ruta de clase; sin embargo, dado que los grupos de visualizacin (display groups) slo soportan decoradores como plugins, $type no es necesario. Elementos y decoradores personalizados son una manera fcil de compartir funcionalidad entre formularios y encapsular funcionalidad personalizada. Vea el ejemplo de Etiqueta Personalizada en la documentacin de elementos para un ejemplo de cmo elementos personalizados pueden ser usados como reemplazos para clases estndar.
Elementos
Zend_Form proporciona varios mtodos de acceso para aadir y eliminar elementos de el formulario. stos pueden tomar instancias de objetos de elemento o servir como fbricas para instanciar el objeto elemento a s mismo. El mtodo ms bsico para aadir un elemento es addElement(). Este mtodo puede tomar tambin un objeto de tipo Zend_Form_Element (o de una clase extendiendo Zend_Form_Element), o argumentos para construir un nuevo elemento -- incluyendo el elemento tipo, nombre y algunas opciones de configuracin. Como algunos ejemplos: // Usando un elemento instanciado: $element = new Zend_Form_Element_Text('foo'); $form->addElement($element); // Usando una fbrica
538
Zend_Form
// // Crea un elemento de tipo Zend_Form_Element_Text con el // nombre de 'foo': $form->addElement('text', 'foo'); // Pasa una opcin etiqueta al elemento: $form->addElement('text', 'foo', array('label' => 'Foo:'));
539
Zend_Form
$form->populate($data); Por otro lado, si se quisera limpiar el formulario antes de llenarlo o validarlo; se puede realizar usando el mtodo reset(): $form->reset();
Operaciones Globales
Ocasionalemnte se necesitarn 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:
Ejemplo 23.2. Determinando rutas de acceso de prefijos para todos los elementos
Se puede determinar rutas de acceso para prefijos para todos los elementos por tipo, o usando un prefijo global. Como ejemplos: // 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/'); // Slo rutas de acceso de filtros: $form->addElementPrefixPath('My_Foo_Filter', 'My/Foo/Filter', 'filter'); // Slo rutas de acceso de validadores: $form->addElementPrefixPath('My_Foo_Validate', 'My/Foo/Validate', 'validate'); // Slo rutas de acceso de decoradores: $form->addElementPrefixPath('My_Foo_Decorator', 'My/Foo/Decorator', 'decorator');
540
Zend_Form
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 propsitos de inclusin o exclusin; si es falso, decorar todos los elementos excepto los pasados en la lista, Como uso estndar del mtodo, cualquier decorador pasado reescribir cualquier decorador previamente determinado en cada elemento. En el siguiente fragmento, indicamos que queremos los decoradores ViewHelper y Label para los elementos 'foo' y 'bar': $form->setElementDecorators( array( 'ViewHelper', 'Label' ), array( 'foo', 'bar' ) ); Por otro lado, con este fragmento, indicaremos que queremos usar solamente los decoradores ViewHelper y Label para cada elemento excepto los elementos 'foo' y 'bar': $form->setElementDecorators( array( 'ViewHelper', 'Label' ), array( 'foo', 'bar' ), false );
541
Zend_Form
$form->setElementFilters(array('StringTrim'));
542
Zend_Form
Puede acceder a los grupos de visualizacin usando el mtodo getDisplayGroup(), o mediante la sobrecarga usando el nombre del grupo de visualizacin: // Usando getDisplayGroup(): $login = $form->getDisplayGroup('login'); // Usando sobrecarga: $login = $form->login;
Operaciones Globales
Al igual que los elementos, existen algunas operaciones que pueden afectar a todos los grupos de visualizacin; stas incluyen determinar decoradores y fijar la ruta de acceso donde buscar los decoradores.
Ejemplo 23.6. Fijando el Prefijo de Ruta del Decorador para todos los Grupos de Visualizacin
Por defecto, los grupos de visualizacin heredan cualquier ruta de decorador que use el formulario; sin embargo, si deberan buscar en una ruta alternativa, puede usar el mtodo addDisplayGroupPrefixPath() method. $form->addDisplayGroupPrefixPath('My_Foo_Decorator', 'My/Foo/Decorator');
543
Zend_Form
permite pasar una instancia determinada, pero permite especificar la clase que usar como una de sus opciones, usando la clave 'displayGroupClass': // Use the 'My_DisplayGroup' class $form->addDisplayGroup( array('username', 'password'), 'user', array('displayGroupClass' => 'My_DisplayGroup') ); Si la clase no ha sido todava cargada, Zend_Form intentar cargarla a travs de Zend_Loader. Tambin puede especificar una clase de grupo de visualizacin por defecto para usar con el formulario, de forma que todos los grupos de visualizacin creados con el objeto formulario usen esa clase: // Use the 'My_DisplayGroup' class for all display groups: $form->setDefaultDisplayGroupClass('My_DisplayGroup'); Esta funcionalidad puede especificarse en configuraciones como 'defaultDisplayGroupClass', y ser cargada con antelacin para asegurar que todos los grupos de visualizacin usen esa clase.
Mtodos Zend_Form_DisplayGroup
Zend_Form_DisplayGroup tiene los siguientes mtodos, agrupados por tipo: Configuracin: setOptions(array $options) setConfig(Zend_Config $config)
544
Zend_Form
Metadatos: setAttrib($key, $value) addAttribs(array $attribs) setAttribs(array $attribs) getAttrib($key) getAttribs() removeAttrib($key) clearAttribs() setName($name) getName() setDescription($value) getDescription() setLegend($legend) getLegend() setOrder($order) getOrder() Elementos: createElement($type, $name, array $options = array()) addElement($typeOrElement, $name, array $options = array()) addElements(array $elements) setElements(array $elements) getElement($name) getElements() removeElement($name) clearElements() Cargadores Complemento: setPluginLoader(Zend_Loader_PluginLoader $loader) getPluginLoader() addPrefixPath($prefix, $path) addPrefixPaths(array $spec)
545
Zend_Form
Decoratores: addDecorator($decorator, $options = null) addDecorators(array $decorators) setDecorators(array $decorators) getDecorator($name) getDecorators() removeDecorator($name) clearDecorators() Generadores: setView(Zend_View_Interface $view = null) getView() render(Zend_View_Interface $view = null) I18n: setTranslator(Zend_Translate_Adapter $translator = null) getTranslator() setDisableTranslator($flag) translatorIsDisabled()
Subformularios
Los Sub formularios sirven para diferentes propsitos: Crear grupos de elementos lgicos. Dado que los sub formularios son simplemente formularios, se pueden validar subformularios como entidades individuales. Crear formularios multi-pginas. Dado que los sub formularios son simplemente formularios, se puede deplegar un sub formulario por separado por pgina, incrementando formularios multi-pginas donde cada formulario tiene su propia validacin lgica. Solo una vez que todos los sub formularios se validen, el formulario se considerara completo. Agrupaciones de visualizacin. Como grupos de visualizacin, los sub formularios, cuando son generados como parte de un formulario ms 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. Un sub formulario puede ser un objeto Zend_Form o mas originalmente, un objeto Zend_Form_SubForm. ste ltimo contiene decoradores apropiados para la inclusin en un formulario extenso (i.e., no se generan adicionales formulario etiquetas HTML, pero si grupos de elementos). Para adjuntar un sub formulario, simplemente adalo al formulario y dle un nombre:
$form->addSubForm($subForm, 'subform');
546
Zend_Form
Se puede recuperar un sub formulario usando ya sea getSubForm($name) o sobrecarga usando el nombre del sub formulario:
// Usando getSubForm(): $subForm = $form->getSubForm('subform'); // Usando sobrecarga: $subForm = $form->subform; Los Subformularios son incluidos en la interaccin del formulario, sin embargo los elementos que lo contienen no lo son
Operaciones Globales
Como los elementos y los grupos de visualizacin, existen algunas operaciones que pueden afectar a todos los sub formularios. A diferencia de los grupos de visualizacin y los elementos, sin embargo, los sub formularios heredan ms funcionalidad del objeto formulario principal, y la nica operacin real que puede realizarse globalmente es determinar decoradores para sub formularios. Para este propsito, existe el mtodo setSubFormDecorators(). 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):
Metadatos y Atributos
Mientras la utilidad de un formulario primariamente deriva de los elementos que contiene, tambin pueden contener otros metadatos, como un nombre (usado a menudo como ID nico en el marcado HTML ); la accion y el mtodo del formulario; el nmero de elementos, grupos y sub formularios que lo contienen; y arbitrariamente metadatos (usualmente usados para determinar atributos HTML para la etiqueta del propio formulario). Se puede determinar y recuperar el nombre del formulario usando el accesor nombre:
547
Zend_Form
// Determinar el nombre: $form->setName('registration'); // Recuperar el nombre: $name = $form->getName(); Para determinar la accin (url en el cual se envia el formulario) y mtodo (mtodo por el cual debera enviar, ej. 'POST' or 'GET'), use los accesores accin y mtodo:
// Determinar la accin y mtodo: $form->setAction('/user/login') ->setMethod('post'); Se puede tambin especificar el tipo de codificacin del fomulario usando el enctype accessors. Zend_Form define dos constantes, Zend_Form::ENCTYPE_URLENCODED y Zend_Form::ENCTYPE_MULTIPART, correspondiente a los valores 'application/x-www-form-urlencoded' y 'multipart/form-data', respectivamente; sin embargo, puede configurarlo con cualquier tipo de codificacin.
Nota
El mtodo, accin y enctype son solo usados internamente para generar, y no para algn tipo de validacin. Zend_Form implementa la interfaz Countable permitindole pasarlo como un argumento para contar:
$numItems = count($form); Determinar metadatos arbitrariamente se realiza a travs de los accesores 'atribs'. Dado que la sobrecarga en Zend_Form es usada para acceder elementos, grupos de visualizacin y subformularios, este es el nico mtodo para acceder a los metadatos.
// 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:
548
Zend_Form
$form->clearAttribs();
Decoradores
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 validacin de errores, enviar valores, etc. La respuesta de Zend_Form a este problema es los decoradores. Los decoradores para objetos Zend_Form pueden ser usados para generar un formulario. El decorador FormElements iterar a travs de todos los elementos en un formulario -- elementos, grupos de visualizacin y subformularios -- y los generar, devolviendo el resultado. Adicionalmente, los decoradores pueden ser usados para envolver el contenido o anteponerlo o postponerlo. Los decoradores por defecto de Zend_Form son FormElements, HtmlTag (envuelve una lista de definicin) y Form; el cdigo equivalente para crearlos es como sigue:
$form->setDecorators(array( 'FormElements', array('HtmlTag', array('tag' => 'dl')), 'Form' )); Que crea la salida como sigue:
<form action="/form/action" method="post"> <dl> ... </dl> </form> Algunos de los atributos se determinan en el objeto formulario que ser usado como atributos HTML de la etiqueta <form>.
$form = new Zend_Form(array('disableLoadDefaultDecorators' => true)); Esta opcin puede ser combinada con alguna otra opcin que usted pueda pasar, tanto como opciones de array o en un objeto Zend_Config
549
Zend_Form
// Alias para 'FooBar': $form->addDecorator(array('FooBar' => 'HtmlTag'), array('tag' => 'div')); // y recuperarlo despus: $form = $element->getDecorator('FooBar'); En los mtodos addDecorators() y setDecorators(), se necesitar pasar la opcin 'decorator' en el array representando el decorador:
// Aadir 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 recuperndolo despus: $htmlTag = $form->getDecorator('HtmlTag'); $fooBar = $form->getDecorator('FooBar'); Puede crear su propio decorador para generar el formulario. Un caso de uso comn 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 visualizacin. Los siguientes mtodos puden ser usados para interactuar con decoradores: addDecorator($decorator, $options = null) addDecorators(array $decorators) setDecorators(array $decorators) getDecorator($name) getDecorators() removeDecorator($name) clearDecorators() Zend_Form tambin usa sobrecarga que permite generar decoradores especficos. __call() interceptar mtodos que lleve con el texto 'render' y use el resto del nombre del mtodo para buscar un decorador; si se encuentran, sern generados por un solo decorador. Cualquier argumento pasado a la llamada del mtodo ser usado como contenido que pasar al mtodo render() del decorador. Como ejemplo:
// 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>");
550
Zend_Form
Validacin
Un caso de uso primario para formularios es validar datos enviados. Zend_Form le permite validar un formulario entero de una vez, o una parte de l, asi como tambin automatizar las respuestas de validacin para XmlHttpRequests (AJAX). Si los datos enviados no son vlidos, contiene mtodos para recuperar los distintos cdigos errores y los mensajes de elementos y subformularios de validaciones fallidas. Para validar un formulario entero, use el mtodo isValid():
if (!$form->isValid($_POST)) { // validacin fallida } isValid() validar cada elemento requerido, y algn elemento no requerido contenido en la data sometida. Algunas veces se necesitar validar slo un subset del dato; para esto use isValidPartial($data):
if (!$form->isValidPartial($data)) { // validacin fallida } isValidPartial() slo intenta validar aquellos elementos en la informacin para los cuales existen similares elementos; si un elemento es no representado en la informacin, es pasado por alto. Cuando se validan elementos o grupos de elementos para un requeirimiento AJAX, tpicamente se validar un subset del formulario, y quiere la respuesta en JSON. processAjax() precisamente realiza eso:
$json = $form->processAjax($data); Entonces, puede simplemente enviar la respuesta JSON al cliente. Si el formulario es vlido, sta ser una respuesta booleana. Si no, ser un objeto javascript conteniendo pares de clave/mensaje, donde cada 'message' es un array de validacin de mensajes de error. Para los formularios que fallan la validacin, se pueden recuperar ambos cdigos de error y mensajes de error, usando getErrors() y getMessages(), respectivamente:
Nota
Dado que los mensajes devueltos por getMessages() son un array de pares de errores cdigo/mensaje, getErrors() no es necesario. Puede recuperar cdigos y mensajes de error para elementos individuales simplemente pasando el nombre del elemento a cada uno:
$codes = $form->getErrors('username');
551
Zend_Form
$messages = $form->getMessages('username');
Nota
Nota: Cuando validamos elementos, Zend_Form enva un segundo argumento a cada mtodo isValid() del elemento: el array de los datos que se estn validando. Esto puede ser usado por validadores individuales para permitirles utilizar otros valores enviados al determinar la validez de los datos. Un ejemplo sera un formulario de registro que requiere tanto una contrasea como una confirmacin de la contrasea; el elemento contrasea puede usar la confirmacin de la contrasea como parte de su validacin.
Mtodos
La siguiente lista es la lista completa de mtodos disponibles para Zend_Form, agrupados por tipo: Configuracin y opciones: setOptions(array $options) setConfig(Zend_Config $config)
552
Zend_Form
Cargadores de plugins y rutas: setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type = null) getPluginLoader($type = null) addPrefixPath($prefix, $path, $type = null) addPrefixPaths(array $spec) addElementPrefixPath($prefix, $path, $type = null) addElementPrefixPaths(array $spec) addDisplayGroupPrefixPath($prefix, $path) Metadato: setAttrib($key, $value) addAttribs(array $attribs) setAttribs(array $attribs) getAttrib($key) getAttribs() removeAttrib($key) clearAttribs() setAction($action) getAction() setMethod($method) getMethod() setName($name) getName() Elementos: addElement($element, $name = null, $options = null) addElements(array $elements) setElements(array $elements) getElement($name) getElements() removeElement($name) clearElements()
553
Zend_Form
setDefaults(array $defaults) setDefault($name, $value) getValue($name) getValues() getUnfilteredValue($name) getUnfilteredValues() setElementFilters(array $filters) setElementDecorators(array $decorators) Subformularios: addSubForm(Zend_Form $form, $name, $order = null) addSubForms(array $subForms) setSubForms(array $subForms) getSubForm($name) getSubForms() removeSubForm($name) clearSubForms() setSubFormDecorators(array $decorators) Grupos de Visualizacin addDisplayGroup(array $elements, $name, $options = null) addDisplayGroups(array $groups) setDisplayGroups(array $groups) getDisplayGroup($name) getDisplayGroups() removeDisplayGroup($name) clearDisplayGroups() setDisplayGroupDecorators(array $decorators) Validacin populate(array $values) isValid(array $data) 554
Zend_Form
isValidPartial(array $data) processAjax(array $data) persistData() getErrors($name = null) getMessages($name = null) Generadores: setView(Zend_View_Interface $view = null) getView() addDecorator($decorator, $options = null) addDecorators(array $decorators) setDecorators(array $decorators) getDecorator($name) getDecorators() removeDecorator($name) clearDecorators() render(Zend_View_Interface $view = null) I18n: setTranslator(Zend_Translate_Adapter $translator = null) getTranslator() setDisableTranslator($flag) translatorIsDisabled()
Configuracin
Zend_Form es totalmente configurable mediante setOptions() y setConfig() (o pasando opciones o un objeto Zend_Config al constructor). Usando estos mtodos, se pueden especificar elementos formulario, grupos de visualizacin, decoradores, y metadatos. Como regla general, si 'set' + la clave de opcin (option key) hacen referencia a mtodos Zend_Form, entonces el valor proporcionado ser pasado al mtodo. Si el accessor no existe, se asume que la clave referencia a un atributo, y ser pasado a setAttrib(). Excepciones a las reglas incluyen lo siguiente: prefixPaths ser pasado a addPrefixPaths() elementPrefixPaths ser pasado a addElementPrefixPaths()
555
Zend_Form
displayGroupPrefixPaths ser pasado a addDisplayGroupPrefixPaths() los siguientes establecedores no pueden ser determinado de sta manera: setAttrib (aunque setAttribs *funcionar*) setConfig setDefault setOptions setPluginLoader setSubForms setTranslator setView Como un ejemplo, aqu esta un archivo de configuracin que pasa la configuracin por cada tipo de datos configurables: [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"
556
Zend_Form
decorators.form.decorator = "Form" El cdigo de arriba fcilmente puede ser abstrado a un XML o un archivo de configuracin basado en arrays PHP.
Formularios personalizados
Una alternativa a usar los formularios basados en configuraciones es realizar una subclase de Zend_Form. Esto tiene muchos beneficios: Se puede centrar la prueba de su formulario facilmente para asegurar las validaciones y generar la ejecucin esperada. Control preciso sobre los individuales elementos. Reutilizacin del objeto formulario, y mejor portabilidad (no se necesita seguir los archivos de configuracin). Implementar funcionalidad personalizada. El caso mas tpico de uso sera el mtodo init() para determinar elementos de formulario especficos y de configuracin:
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(
557
Zend_Form
$username, $password, $submit )); $this->setDecorators(array( 'FormElements', 'Fieldset', 'Form' )); } } Este formulario puede ser instanciado simplemente as:
$form = new My_Form_Login(); y toda la funcionalidad est instalada y lista; no se necesitan archivos de configuracin. (Note que este ejemplo esta simplificado, no contiene validadores o filtros para los elementos.) Otra razn comn para la extension es definir un conjunto de decoradores por defecto. Puede hacerlo sobreescribiendo el mtodo loadDefaultDecorators():
class My_Form_Login extends Zend_Form { public function loadDefaultDecorators() { $this->setDecorators(array( 'FormElements', 'Fieldset', 'Form' )); } }
558
Zend_Form
Antes de que el render() de cada decorador sea llamado, el item actual es determinado en el decorador usando setElement(), dando al decorador conocimiento del item representado. Esto permite crear decoradores que slo 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.
Operacin
Para configurar un decorador, pase un array de opciones o un objeto Zend_Config a este constructor, a un array setOptions(), o a un objeto Zend_Config setConfig(). Opciones estndar incluyen: placement: La ubicacin puede ser cualquiera de los dos 'append' o 'prepend' (caso insensitivo) e indica cualquier contenido pasado a render() ser postpuesto o antepuesto respectivamente. En el caso de que el decorador reemplace el contenido, esta configuracin es ignorada. La configuracin por defecto es adjuntada. separator: El separator es usado entre el contenido pasado a render() 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 configuracin puede ser ignorada. El valor por defecto es PHP_EOL. La interface del decorador especifica los mtodos para interactuar con las opciones. Esto incluye: setOption($key, $value): determina una sola opcin. getOption($key): recuperar un solo valor de opcin. getOptions(): recuperar todas las opciones. removeOption($key): eliminar una sola opcin. clearOptions(): eliminar todas las opciones. Decoradores son diseados para interactuar con varios tipos de clases Zend_Form: Zend_Form, Zend_Form_Element, Zend_Form_DisplayGroup, y todas las clases derivan de ellas. El mtodo setElement() permite determinar el objeto del decorador que esta actualmente trabajando con, y getElement() es usado para recuperarlo. Cada mtodo decorador render() acepta una cadena $content. Cuando el primer decorador es llamado, esta cadena esta tipicamente vaca, mientras las subsecuentes llamadas sern 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.
Decoradores estndar
Zend_Form entrega muchos decoradores estndar; ver el captulo Decoradores estndar para detalles.
Decoradores personalizados
Si encuentra que sus necesidades son complejas o necesita una enorme personalizacin, debera considerar crear un decorador personalizado. Los decoradores necesitan implementar slo Zend_Form_Decorator_Interface. La interface especifica lo siguiente: interface Zend_Decorator_Interface
559
Zend_Form
{ public public public public public public public public public public public } Para hacerlo mas simple, simplemente puede extender Zend_Form_Decorator_Abstract, el cual implementa todos los mtodos excepto render(). Como ejemplo, digamos que quiere reducir el nmero de decoradores que utiliza, y construir un decorador compuesto que se encarg de renderizar la etiqueta generadora, el elemento, cualquier mensaje de error, y descripcin en un div HTML. Puede construir como un decorador compuesto como sigue: 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(); function function function function function function function function function function function __construct($options = null); setElement($element); getElement(); setOptions(array $options); setConfig(Zend_Config $config); setOption($key, $value); getOption($key); getOptions(); removeOption($key); clearOptions(); render($content);
560
Zend_Form
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 $placement $label $input $errors $desc $output = . . . . . = = = = = = $this->getSeparator(); $this->getPlacement(); $this->buildLabel(); $this->buildInput(); $this->buildErrors(); $this->buildDescription();
switch ($placement) { case (self::PREPEND): return $output . $separator . $content; case (self::APPEND): default: return $content . $separator . $output; } } } Puede entonces ubicarlo en el directorio del decorador:
561
Zend_Form
// para un elemento: $element->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator'); // para todos los elementos: $form->addElementPrefixPath('My_Decorator', 'My/Decorator/', 'decorator'); Puede especificar este decorador como compuesto (composite) y adjuntarlo a un elemento: // Sobreescribe los decoradores existentes con este otro: $element->setDecorators(array('Composite')); Mientras este ejemplo mostr cmo crear un decorador que genera salidas complejas de muchas propiedades de elementos, puede tambin crear decoradores que manejen un solo aspecto de un elemento; los decoradores 'Decorator' y 'Label' son excelentes ejemplos para esta prctica. Hacerlo le permite mezclar y combinar decoradores para llegar a complejas salidas -- y tambin anular aspectos de decoracin para personalizar sus necesidades. Por ejemplo, si quiere simplemente desplegar que un error ha ocurrido cuando validbamos un elemento, pero no desplegar individualmente cada uno de los mensajes de error, usted podra crear su propio decorador 'Errores': class My_Decorator_Errors { public function render($content = '') { $output = '<div class="errors">El valor que proporcion no es vlido; 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; } } } En este ejemplo particular, debido al segmento del decorador final, 'Errors', se combina como Zend_Form_Decorator_Errors, ser generado en lugar de el decorador -- significa que no necesitar cambiar ningn decorador para modificar la salida. Nombrando sus decoradores despus de los decoradores existentes estndar, usted puede modificar decoradores sin necesitad de modificar sus elementos decoradores.
562
Zend_Form
Para hacer eso, simplemente render[DecoratorName](), cuando "[DecoratorName]" es el "nombre corto" de su decorador; opcionalmente, puede pasar en el contenido lo que usted quiera. Por ejemplo:
// genera el elemento decorador label: echo $element->renderLabel(); // genera slo el campo display group, con algn contenido: echo $group->renderFieldset('fieldset content'); // genera slo el formulario HTML, con algn contenido: echo $form->renderHtmlTag('wrap this content'); Si el decorador no existe, una excepcin es inicializada. 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.
Zend_Form_Element_Button
Usada para crear elementos HTML de tipo button, Zend_Form_Element_Button extiende Zend_Form_Element_Submit, derivandi sy funcionalidad personalizada. It specifies the 'formButton' view helper for decoration. 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. Because the label is used as part of the element, the button element uses only the ViewHelper and DtDdWrapper decorators. Despus de llenar o validar un formulario, se puede verificar si el botn dado fue pulsado usando el mtodo isChecked().
Zend_Form_Element_Captcha
Los CAPTCHAs son usados para prevenir el envio automtico de formularios por los robots y otros procesos automatizados. The Captcha form element allows you to specify which Zend_Captcha adapter 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). Adapters may be any adapters in Zend_Captcha, 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:
563
Zend_Form
$element->addPrefixPath('My_Captcha', 'My/Captcha/', 'captcha'); Los Captcha entonces pueden ser cargados usando el mtodo setCaptcha(), el cual puede tomar una instancia cualquiera de CAPTCHA instance, o el nombre corto del adaptador captcha:
// instancia concreta: $element->setCaptcha(new Zend_Captcha_Figlet()); // Usando nombre corto: $element->setCaptcha('Dumb'); Si desea cargar sus elementos configuracin, especifique la clave 'captcha' con un array conteniendo la clave 'captcha', o ambas claves 'captcha' y 'captchaOptions':
// 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, ), )); El decorador usado es determinado consultando el adaptador captcha. Por defecto, es usado el Captcha decorator, pero un adaptador puede especificar uno diferente va su mtodogetDecorator(). Como ha notado, el adaptador CAPTCHA acta l mismo como un validador para el elemento. Adicionalmente, el validador NotEmpty no es usado y el elemento es marcado como requerido. En la mayora de los casos, usted no necesitar hacer nada ms para tener un captcha presente en su formulario.
Zend_Form_Element_Checkbox
Las casillas de verificacin (checkboxes) HTML le permiten devolver un valor especfico, pero bsicamente funcionan como los booleanos: cuando est marcada, el valor es enviado; cuando no est marcada, no se enva nada. Internamente, Zend_Form_Element_Checkbox fuerza este estado. 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 setCheckedValue() and setUncheckedValue() 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.
564
Zend_Form
Additionally, setting the value sets the checked property of the checkbox. You can query this using isChecked() or simply accessing the property. Using the setChecked($flag) 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. Zend_Form_Element_Checkbox uses the 'formCheckbox' view helper. The checked value is always used to populate it.
Zend_Form_Element_File
The File form element provides a mechanism for supplying file upload fields to your form. It utilizes Zend_File_Transfer internally to provide this functionality, and the FormFile view helper as also the File decorator to display the form element. By default, it uses the Http transfer adapter, which introspects the $_FILES array and allows you to attach validators and filters. Validators and filters attached to the form element will be attached to the transfer adapter.
565
Zend_Form
Valores de archivo
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 informacin completa llame a getFileName() y le devolver el destino y nombre de archivo completo. Per default the file will automatically be received when you call getValues() on the form. The reason behind this behaviour is, that the file itself is the value of the file element.
$form->getValues();
Nota
Therefor another call of receive() after calling getValues() will not have an effect. Also creating a instance of Zend_File_Transfer will not have an effect as there no file anymore to receive. Still, sometimes you may want to call getValues() without receiving the file. You can archive this by calling setValueDisabled(true). To get the actual value of this flag you can call isValueDisabled().
$element = new Zend_Form_Element_File('foo'); $element->setLabel('Upload an image:') ->setDestination('/var/www/upload') ->setValueDisabled(true); Now the file will not be received when you call getValues(). So you must call receive() on the file element, or an instance of Zend_File_Transfer yourself.
$values = $form->getValues(); if ($form->isValid($form->getPost())) { if (!$form->foo->receive()) { print "Upload error"; } } There are several states of the uploaded file which can be checked with the following methods: isUploaded(): Checks if the file element has been uploaded or not. isReceived(): Checks if the file element has already been received. isFiltered(): Checks if the filters have already been applied to the file element or not.
566
Zend_Form
->setRequired(false); $element->addValidator('Size', false, 102400); $form->addElement($element, 'foo'); // The foo file element is optional but when it's given go into here if ($form->foo->isUploaded()) { // foo file given... do something } Zend_Form_Element_File soporta tambin archivos mltiples. Para llamar el mtodo setMultiFile($count) usted puede establecer la cantidad de elementos file que usted desea crear. Esto le previene de establecer la misma configuracin varias veces.
$element = new Zend_Form_Element_File('foo'); $element->setLabel('Upload an image:') ->setDestination('/var/www/upload'); // asegura mnimo 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 idnticos $element->setMultiFile(3); $form->addElement($element, 'foo'); En su vista usted ahora obtendr 3 elementos para carga de archivos idnticos los cuales comparten la misma configuracin. Para obtener el conjunto del nmero de archivos mltiples simplemente llame a getMultiFile().
$element = new Zend_Form_Element_File('foo'); $element->setLabel('Upload an image:') ->setDestination('/var/www/upload') ->addValidator('Size', false, 102400) // lmite en 100K ->setMaxFileSize(102400); // limita el tamao del archivo en el lado del cliente $form->addElement($element, 'foo');
567
Zend_Form
Zend_Form_Element_Hidden
Los elementos Hidden simplemente inyectan datos que deben ser enviados, pero que el usuario no debe manipular. Zend_Form_Element_Hidden logra esto a travs del uso del helper de vista 'formHidden'.
Zend_Form_Element_Hash
Este elemento provee proteccin de ataques desde CSRF sobre formularios, asegurando que el dato es enviado por la sesin del usuario que gener el formulario y no por un script malicioso. La proteccin se logra mediante la adicin de un elemento hash a un formulario y verificandolo cuando el formulario es enviado. El nombre del elemento hash debe ser nico. Se recomienda usar la opcin salt para el elemento, dos hashes con el mismo nombre y diferentes salts no chocan: $form->addElement('hash', 'no_csrf_foo', array('salt' => 'unique')); Puede establecer el salt ms tarde usando el mtodo setSalt($salt). Internamente, el elemento almacena un identificador nico usando Zend_Session_Namespace, y lo comprueba en el momento que se enva (comprueba que el TTL no ha espirado). El validador 'Identical' entonces es usado para asegurarse que el hash enviado marcha con el hash alamacenado. El helper de vista 'formHidden' es usado para generar el elemento en el formulario.
Zend_Form_Element_Image
Las imgenes pueden ser usadas como elementos de formulario, y le permiten especificar elementos grficos como botones de formulario. Los elementos Image necesitan una imagen fuente. Zend_Form_Element_Image le permite especificar esto usando el mtodo de acceso setImage() (o clave de configuracin 'image'). Opcionalmente, tambin puede especificar un valor para utilizar al momento de enviar la imagen utilizando el mtodo de acceso setImageValue() (o clave de configuracin 'imageValue'). Cuando el valor establecido para el elemento sea igual a imageValue, entonces el mtodo de acceso isChecked() devolver true. Los elementos Image usan el Decorador de Imagen para generar (as como el estandard Errors, HtmlTag, y decorador Label). Opcionalmente, puede especificar una etiqueta para el decorador Image que luego envuelva al elemento imagen.
Zend_Form_Element_MultiCheckbox
En ocasiones, se tiene un conjunto de checkboxes, y se desea agrupar los resultados. Esto es como un Multiselect, pero en lugar de estar en una lista desplegable, necesita mostrarlos en pares checkbox/value (casilla de verificacin/valor). Zend_Form_Element_MultiCheckbox 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.
568
Zend_Form
Por defecto, este elemnto requiere un validador InArray el cual valida contra el array de llaves de las opciones registradas. Se puede desactivar esta caracteristica llamando a setRegisterInArrayValidator(false), o pasando un valor falso a la configuracin de llaves registerInArrayValidator. Se puede manipular las opciones de checkbox usando los siguinetes mtodos: addMultiOption($option, $value) addMultiOptions(array $options) setMultiOptions(array $options) (overwrites existing options) getMultiOption($option) getMultiOptions() removeMultiOption($option) clearMultiOptions() Para marcar los valores confirmados, se necesita pasar un array de valores a setValue(). El siguiente cdigo verificar los valores "bar" y "bat":
$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')); Note que cuando se determina un asimple variable, se debe pasar un array.
Zend_Form_Element_Multiselect
XHTML selector de elementos permite 'multiple' atributos, indicando multiples opciones pueden ser seleccionados por submision, en vez de lo usual. Zend_Form_Element_Multiselect extiende Zend_Form_Element_Select, y define los atributos multiple a 'multiple'. Como las otras clases que heredan de la clase base Zend_Form_Element_Multi, se puede manipular las opciones del selector usando: addMultiOption($option, $value) addMultiOptions(array $options) setMultiOptions(array $options) (overwrites existing options) getMultiOption($option) getMultiOptions() removeMultiOption($option) clearMultiOptions()
569
Zend_Form
Si un adaptador de tranduccin es registrado con el formulario y/o elemnto, la opcin valores ser traducido para propsito de despliegue. Por defecto, este elemento registra un validador InArray el cual valida contra el array de llaves de opciones registradas. se puede deshabilitar esta caracteristica llamando a setRegisterInArrayValidator(false), o pasando un valor falso a la configuracion de llaves registerInArrayValidator.
Zend_Form_Element_Password
Elementos contrasea son basicamente elementos de texto -- excepto que tipicamente no se quiera desplegar la contrasea en los mensajes de error o del elemnto en si cuando el formulario es re desplegado. Zend_Form_Element_Password archiva esto llamando setObscureValue(true) en cada validador (asegurando que la contrasea este oculta en mensajes de validacin de errores), y usando la vista ayuda 'formPassword' (el cual no desplega el valor pasado).
Zend_Form_Element_Radio
elementos de Radio permite especificar muchas opciones, de los cuales se necesita retornar un solo valor. Zend_Form_Element_Radio extiende la clase base Zend_Form_Element_Multi, permitiendonos especificar un numero de opciones, y luego usa la vista ayuda formRadio para desplegar. Por defecto, este elemento registra un validador InArray el cual valida contra el array de llaves de opciones registradas. se puede deshabilitar esta caracteristica llamando a setRegisterInArrayValidator(false), o pasando un valor falso a la configuracion de llaves registerInArrayValidator. configuration key. Como todos los elementos se extienden del elemento clase base Multi, los siguientes mtodos pueden ser usados para manipular las opciones de radio desplegadas: addMultiOption($option, $value) addMultiOptions(array $options) setMultiOptions(array $options) (overwrites existing options) getMultiOption($option) getMultiOptions() removeMultiOption($option) clearMultiOptions()
Zend_Form_Element_Reset
Botones Reset son tipicamente usados para limpiar un formulario, y no son parte de la informacin sometida. Como sea, como ellos sirven como propsito en el despliegue, son incluidos en los elementos estndar. Zend_Form_Element_Reset extends Zend_Form_Element_Submit. Tal cual, la etiqueta es usada para desplegar el botn y ser traducido si el adaptador traduccin esta presente. Se utiliza slo los decoradores 'ViewHelper' y 'DtDdWrapper', nunca debera existir mensajes de error para tales elementos, no se necesitar una etiqueta.
Zend_Form_Element_Select
Cajas selectoras son una manera comn de limitar espeficias opciones para un dado formulario datum. Zend_Form_Element_Select le permite generar esto rpido y fcil.
570
Zend_Form
Por defecto, este elemento registra un validador InArray el cual valida contra el array de llaves de opciones registradas. se puede deshabilitar esta caracteristica llamando a setRegisterInArrayValidator(false), o pasando un valor falso a la configuracion de llaves registerInArrayValidator. configuration key. Como se extiende el elemento base Multi, los siguientes mtodos pueden ser usados para manipular las opciones seleccionadas: addMultiOption($option, $value) addMultiOptions(array $options) setMultiOptions(array $options) (overwrites existing options) getMultiOption($option) getMultiOptions() removeMultiOption($option) clearMultiOptions() Zend_Form_Element_Select usa la vista ayuda 'formSelect' para decoracin.
Zend_Form_Element_Submit
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. Zend_Form_Element_Submit makes this decisioning easy, by adding a isChecked() 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. Zend_Form_Element_Submit usa la etiqueta como el "valor" del botn sometido, traduciendolo si el adaptador traduccin esta presente. isChecked() verifica el valor sometido contra la etiqueta en orden to determinar si el botn ha sido usado. El ViewHelper y DtDdWrapper decoradores generan al elemento. no decorador de etiquetas es usado, como el botn etiqueta es usado cuando se generan los elementos; asi tipicamente, no se asociarn errores con el elemnto sometido.
Zend_Form_Element_Text
Lejos el mas prevaleciente tipo de formulario es el elemento texto, permitido para entrada de texto limitado; es un elemento ideal para la entrada de la informacin. Zend_Form_Element_Text simplemente usa la vista ayuda 'formText' para desplegar el elemento.
Zend_Form_Element_Textarea
Textareas son usadas cuando se espera una larga cantidad de texto y no limites en la cantidad de texto sometido ( otro que el mximo tamao tomado por su servidor or PHP). Zend_Form_Element_Textarea usa la vista ayuda 'textArea' para desplegar tales elementos, ocupando el valor como el contendio del elemento.
571
Zend_Form
Zend_Form_Decorator_Callback
El decorador Callback (llamada de retorno) permite ejecutar una llamada de retorno para mostrar el contenido. Las llamadas de retorno deben especificarse a travs de la opcin 'callback' pasada en la configuracin del decorador, y pueden ser de cualquier valor de llamada de retorno PHP. Los Callbacks deben aceptar tres argumentos: $content (el contenido original enviado al decorador), $element (el objeto que se est decorando), y un array de $options. Un callback de ejemplo sera: class Util { public static function label($content, $element, array $options) { return '<span class="label">' . $element->getLabel() . "</span>"; } } Esta llamada de retorno se especificara como array('Util', 'label'), y generara un (mal) cdigo HTML para la etiqueta. El decorador Callback reemplazar, antepondr o postpondr el contenido original con el que devuelva. El decorador Callback permite especificar un valor null para la opcin placement (colocacin), que reemplazar el contenido original con el valor devuelto de la llamada de retorno; 'prepend' (anteponer) y 'append' (postponer) siguen siendo vlidas.
Zend_Form_Decorator_Captcha
El decorador Captcha se usa junto con el elemento de formulario Captcha. Utiliza el mtodo render() del adaptador del captcha para generar la salida. 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 sesin que hay que comparar, y la entrada es para la verificacin de usuario del captcha. stos elementos son validados como un slo elemento.
Zend_Form_Decorator_Description
El decorador Description puede ser usado para mostrar un conjunto de descripciones de un elemento Zend_Form, Zend_Form_Element, o Zend_Form_DisplayGroup; toma la descripcin usando el mtodo getDescription() del objeto. Por defecto, si no se encuentra la descripcin, no se genera ninguna salida. Si la descripcin est presente, entonces se envolver en una etiqueta p HTML por defecto, aunque tiene la posibilidad de especificar una etiqueta pasando una opcin tag al crear el decorador, o llamando a setTag(). Tambin puede especificar una clase para el tag usando la opcin class o llamando a setClass(); por defecto, se usa la clase 'hint'. La descripcin es escapada utilizando los mecanismos de escapado por defecto del objeto de vista. Puede desactivar esto pasando un valor false a la opcin 'escape' del decorador o el mtodo setEscape().
Zend_Form_Decorator_DtDdWrapper
Los decoradores por defecto utilizan listas de definicin (<dl>) para generar elementos de formulario (form). Dato que los elementos de formulario pueden aparecer en cualquier orden, grupos de visualizacin y subformularios pueden ser encapsulados dentro de otros elementos de formulario. Para mantener estos tipos de elemento particulares dentro de la lista de definicin, DtDdWrapper crea una nuevo trmino de definicin vaco (definition term)(<dt>) y encapsula su contenido en un nuevo dato de definicin (<dd>). La salida queda como sigue:
572
Zend_Form
<dt></dt> <dd><fieldset id="subform"> <legend>Informacin de Usuario</legend> ... </fieldset></dd> Este decorador reemplaza el contenido que se le provee envolvindolo dentro del elemento <dd>.
Zend_Form_Decorator_Errors
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 (<ul>) como elementos de lista (li). El elemento <ul> recibe una clase de "errores". El decorador de Errores puede anteponerse o postponerse al contenido que se le provee.
Zend_Form_Decorator_Fieldset
Por defecto, los grupos de visualizacin y subformularios generan sus contenidos dentro de fieldsets, EL decorador Fieldset busca la opcin 'legend' o bien el mtodo getLegend() en el elemento registrado, y lo usa como campo "legend" si no es vaco. 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.
Zend_Form_Decorator_File
Los elementos de tipo "File" (upload de ficheros) tienen una notacin especial cuando se usan mltiples elementos file o subformularios. El decorador File es usado por Zend_Form_Element_File y permite fijar mltiples elementos file con una nica llamada al mtodo. Se usa automticamente y fija el nombre de cada elemento.
Zend_Form_Decorator_Form
Los objetos Zend_Form 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 accin y el mtodo del objeto Zend Form, y cualquier atributo como atributo HTML.
Zend_Form_Decorator_FormElements
Los formularios(forms), grupos de visualizacin y subformularios son colecciones de elementos. Para poder generar estos elementos, utilizan el decorador FormElements, el cual itera sobre todos los elementos, llamando a render() en cada uno de ellos y unindolos con el separador indicado. Puede anteponer o postponer al contenido que se le enva.
Zend_Form_Decorator_FormErrors
Algunos desarrolladores y diseadores prefieren agrupar todos los mensajes de error en la parte superior del formulario. El decorador FormErrors le permite hacer esto. Por defecto, la lista de errores generada tiene el siguiente marcado:
573
Zend_Form
<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> Puede pasar como parmetro varias opciones para configurar la salida generada: ignoreSubForms: se desactiva o no la recursividad en los subformularios. Por defecto: false (i.e., permitir recursividad). markupElementLabelEnd: Marcado para postponer las etiquetas de elementos. Por defecto: '</b>' markupElementLabelStart: Marcado para anteponer las etiquetas de elementos. Por defecto'<b>' markupListEnd: Marcado para postponer listas de mensajes de error. Por defecto: '</ul>'. markupListItemEnd: Marcado para postponer mensajes de error individuales. Por defecto: '</li>' markupListItemStart: Marcado para anteponer mensajes de error individuales. Por defecto: '<li>' markupListStart: Marcado para anteponer listas de mensajes de error. Por defecto: '<ul class="form-errors">' El decorador FormErrors puede anteponerse o postponerse al contenido que se le provee.
Zend_Form_Decorator_HtmlTag
El decorador HtmlTag le permite utilizar etiquetas HTML para decorador el contenido; la etiqueta utiliza es pasada en la opcin 'tag' , y cualquier otra opcin es usada como atributo HTML de esa etiqueta. Por defecto, el contenido generado reemplaza al contenido envolvindolo en la etiqueta dada. De cualquier forma, se permite especificar una localizacin de tipo 'append' (postponer) o 'prepend' (anteponer).
Zend_Form_Decorator_Image
El decorador Image le permite crear un input HTML de tipo image (<input type="image" ... />), y opcionalmente mostrarlo dentro de otro tag HTML. Por defecto, el decorador usa la propiedad src del elemento, que puede fijarse con el mtodo setImage(), como la ruta de la imagen ('src'). Adicionalmente, la etiqueta del elemento ser usada como la etiqueta 'alt', y imageValue (manipulado con los mtodos setImageValue() y getImageValue()) ser usada como el campo 'value'. Para especificar una etiqueta HTML que utilizar con el elemento, pase la opcin 'tag' al decorador, o llame explcitamente a setTag().
Zend_Form_Decorator_Label
Comnmente, 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 mtodo getLabel() 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 traduccin para la etiqueta.
574
Zend_Form
Opcionalmente, se puede especificar la opcin 'tag'; si se suministra, encapsula la etiqueta en la etiqueta HTML en cuestin. Si la opcin est presenta pero no hay etiqueta, la etiqueta ser generada sin contenido. Puede especificar la clase que usar con la etiqueta mediante la opcin 'class' o llamando a setClass(). 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, podramos querer aadir ':' a la etiqueta o un '*', indicando que el elemento es requerido. Se puede realizar con las siguientes opciones y mtodos: optionalPrefix: fija el texto antepuesto a la etiqueta cuando el elemento es opcional. Utilice los accesores setOptionalPrefix() y getOptionalPrefix() para manipularlo. optionalSuffix: fija el texto pospuesto a la etiqueta cuando el elemento es opcional. Utilice los accesores setOptionalSuffix() y getOptionalSuffix() para manipularlo. requiredPrefix: fija el texto antepuesto a la etiqueta cuando el elemento es requerido. Utilice los accesores setRequiredPrefix() y getRequiredPrefix() para manipularlo. requiredSuffix: fija el texto antepuesto a la etiqueta cuando el elemento es requerido. Utilice los accesores setRequiredSuffix() y getRequiredSuffix() para manipularlo. Por defecto, el decorador Label antecede al contenido provisto; especifique la opcin 'placement' (colocacin) como 'append' para colocarlo despus del contenido.
Zend_Form_Decorator_PrepareElements
Formularios, grupos de visualizacin, y subformularios son colecciones de elementos. Al usar el decorador ViewScript con un formulario o subformulario, resulta til el poder fijar recursvamente el objeto de vista, el traductor (translator)y todos los nombres relacionados (determinados por la notiacin de tabla del subformulario). Esta tarea puede realizarse gracias al decorador 'PrepareElements'. Normalmente, se indicar como el primer decorador en al lista. $form->setDecorators(array( 'PrepareElements', array('ViewScript', array('viewScript' => 'form.phtml')), ));
Zend_Form_Decorator_ViewHelper
La mayora de los elementos utiliza helpers Zend_View 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, anteponindole la cadena 'form': e.g., 'Zend_Form_Element_Text' buscara un view helper del tipo 'formText'. Cualquier atributo del elemento suministrado es pasado al view helper como atributo del elemento. Por defecto, este decorador postpone el contenido; utilice la opcin 'placement' para especificar una localizacin distinta.
Zend_Form_Decorator_ViewScript
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 diseador, o simplemente crear una forma fcil de sobreescribir basado en el mdulo que se est usando. El decorador ViewScript soluciona este problema. El decorador ViewScript requiere una opcin '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
575
Zend_Form
propio espacio de variables; Ninguna variable de la vista ser rellenada, aparte del elemento en s. Distintas variables son entonces rellenadas: element: el elemento decorado content: el contenido pasado al decorador decorator: el propio objeto decorador Del mismo modo, todas las opciones pasadas al decorador a travs de setOptions() que no son usadas internamente (tales como placement, separator, etc.) son pasadas como variables de vista. Como ejemplo, se pueden tener el siguiente elemento: // Fija un decorador ViewScript a un nico elemento , // especificando como opcin 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')))); Un view script puede tener el siguiente aspecto: <div class="<?php echo $this->class ?>"> <?php echo $this->formLabel($this->element->getName(), $this->element->getLabel()) ?> <?php echo $this->{$this->element->helper}( $this->element->getName(), $this->element->getValue(), $this->element->getAttribs() ) ?> <?php echo $this->formErrors($this->element->getMessages()) ?> <div class="hint"><?php echo $this->element->getDescription() ?></div> </div>
576
Zend_Form
// Dentro de un view script usado por un decorador: $this->decorator->setOption('placement', false); Se recomienda usar el decorador ViewScript cuando necesite un control muy preciso sobre cmo generados sus elementos.
Internacionalizacin de Zend_Form
Cada vez ms, desarrolladores necesitan adaptar su contenido para multiples idiomas y regiones. Zend_Form intenta hacer de sta una tarea trivial, y provee funcionalidad en ambas Zend_Translate y Zend_Validate para realizar esa funcionalidad. Por defecto, no se realiza ninguna internacionalizacin (I18n). Para iniciar las caratersticas de I18n en Zend_Form, se necesitar instanciar un objeto Zend_Translate con un adaptador apropiado, y adjuntarlo a Zend_Form y/ o Zend_Validate. Ver la documentacin Zend_Translate para ms informacin sobre crear el objeto traduccin y los archivos de traduccin
// Decir a todas las clases de validacin que se use un adaptador especifico de traducci Zend_Validate_Abstract::setDefaultTranslator($translate); Alternativamente, se puede adjuntar al objeto Zend_Form como un traductor global. Tiene el mismo efecto que traduciendo los mensajes de error de validacin.
// Decir a todas las clases del formulario usar un adaptador especifico, as como tambin // use este adaptador para traducir mensajes de error de validacin Zend_Form::setDefaultTranslator($translate);
577
Zend_Form
Finalmente, se puede adjuntar un traductor a una instancia especifica de un formulario o a elementos especificar usando sus mtodos setTranslator():
// Decir a *esta* instancia del formulario que use un adaptador especifico de traduccin; // ser usado para traducir mensajes de error de validacin para todos los // elementos: $form->setTranslator($translate); // Decir a *este* elemento usar un adaptador especifico de traduccin; ser // usado para traducir los mensajes de error de validacin para este // elemento en particular: $element->setTranslator($translate);
Notacin de array
A muchos desarroladores web experimentados les gusta agrupar elementos relacionados de formulario usando notacin de array en los nombres del elemento. Por ejemplo, si se tienen dos direcciones que se desean capturar, un envo y una direccin de facturacin, se pueden tener elementos idnticos; agrupndolos en un array se puede asegurar que son capturados por separado. Ntese el siguiente formulario por ejemplo:
578
Zend_Form
<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> En este ejemplo, la facturacin y la direccin de envo contienen algunos campos idnticos, eso significa que uno puede sobrescribir al otro. Nosotros podemos resolver esta solucin usando una notacin de array:
579
Zend_Form
<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>
580
Zend_Form
<dt></dt> <dd><input name="save" type="submit" value="Save" /></dd> </dl> </form> En el ejemplo anterior, obtenemos direcciones separadas. En el formulario sometido, ahora tenemos tres elementos, 'guardar' elemento para someterlo, y dos arrays, 'envio' y 'cuenta', cada uno con llaves para los variados elementos. Zend_Form intenta automatizar este proceso con los subformularios. Por defecto, los subformularios son generados usando la notacin de array como se muestra en el anterior formulario HTML listado completo con identificadores. El nombre del array esta basado en el nombre del subformulario, con las llaves basados en los elementos contenidos en el subformulario. Los subformularios pueder ser anidados arbitrariamente, y esto puede crear arrays anidados que reflejan la estructura. Adicionalmente, las validaciones rutinarias en Zend_Form respetan la estructura del array, asegurando que sus formularios sean validados correctamente, no importa cuan arbitrariamente anidados esten los subformularios. No se necesita hacer nada para beneficiarse; ste comportamiento esta activo por defecto. Adicionalmente, existen facilidades que le permiten activar condicionalmente la notacin de un array, as como tambin especificar el especfico array al cual un elemento o coleccion pertenece: Zend_Form::setIsArray($flag): Definiendo la bandera a verdadero, se puede indicar que un formulario entero debera ser tratado como un array. Por defecto, el nombre del formulario ser usado como el nombre del array, a no ser que setElementsBelongTo() haya sido llamado. Si el formulario no tiene un nombre especfico, o si setElementsBelongTo() no ha sido definido, esta bandera ser ignorada (como cuando no hay nombre del array al cual los elementos puedan pertenecer). Se deber determinar si un formulario est siendo tratado como un array usando el accesor isArray(). Zend_Form::setElementsBelongTo($array): Usando este mtodo, se puede especificar el nombre de un array al cual todos los elementos del formulario pertenecen. Se puede determinar el nombre usando el accesor getElementsBelongTo(). Adicionalmente, a nivel del elemento, se pueden especificar elementos individuales que puedan pertenecer a arrays particulares usando el mtodo Zend_Form_Element::setBelongsTo(). Para descubrir el valor que tiene -- sea o no sea definido explcitamente o implcitamente a travs del formulario -- se puede usar el accesor getBelongsTo().
Formularios Multi-Pgina
Actualmente, los formularios multi-pgina no estn oficialmente soportados en Zend_Form; sin embargo, la mayora del soporte para implementarlos est disponible y puede ser utilizado con algunos retoques. La clave para crear fomrularios multi-pgina es utilizar subformularios, pero solo para mostrar un solo subformulario por pgina. Esto le permite someter un solo subformulario a la vez y validarlo, pero no procesar el formulario hasta que todos los subformularios esten completos.
581
Zend_Form
class My_Form_Registration extends Zend_Form { public function init() { // Crea un subformulario usuario: username y 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)) ) )), )); // Crea un subformulario de datos demogrficos : given name, family name, y // 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')) )
582
Zend_Form
)), new Zend_Form_Element_Text('location', array( 'required' => true, 'label' => 'Your Location:', 'filters' => array('StringTrim'), 'validators' => array( array('StringLength', false, array(2)) ) )), )); // Crea un sub fomulario de correos $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))) ) )), )); // Adjuntando los subformlarios al formulario principal $this->addSubForms(array( 'user' => $user, 'demog' => $demog, 'lists' => $lists )); } } Note que no hay botones de enviar, y que ni hemos hecho nada con los decoradores de subformularios -- lo que significa que por defecto sern desplegados como campos. Necesitaremos hacer algo con ellos mientras desplegamos cada subformulario individualmente, y aadir botones de manera que podamos procesarlos realmente -- el cual requerira las propiedades accin y mtodo. Vamos a aadir algunos andamios a nuestras clases para proveer esa informacin:
583
Zend_Form
/** * Prepara un subformulario para mostrar * * @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; } /** * Aade un Boton de envio(submit) a cada subformulario * * @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,
584
Zend_Form
) )); return $this; } /** * Aade el method y el action a cada subformulario * * @param Zend_Form_SubForm $subForm * @return My_Form_Registration */ public function addSubFormActions(Zend_Form_SubForm $subForm) { $subForm->setAction('/registration/process') ->setMethod('post'); return $this; } } Siguiente, necesitamos aadir andamios a nuestro action controller, y tener varias consideraciones. Primero, necesitamos asegurar que persiste la informacin del formulario entre los requerimientos, de esa manera determinar cundo terminar. Segundo, necesitamos alguna lgica para determinar qu segmentos del formulario han sido sometidos, y qu subformulario mostrar de acuerdo a la informacin. Usaremos Zend_Session_Namespace para persistir la informacin, el cual nos ayudar a responder la pregunta de qu formulario someter. Vamos a crear nuestro controlador, y aadir un mtodo para recuperar un formulario instanciado:
class RegistrationController extends Zend_Controller_Action { protected $_form; public function getForm() { if (null === $this->_form) { $this->_form = new My_Form_Registration(); } return $this->_form; } } Ahora, vamos a aadir algunas funcionalidades para determinar qu formulario mostrar. Bsicamente, hasta que el formulario entero sea considerado vlido, necesitamos continuar mostrando segmentos de formulario. Adicionalmente, queremos asegurar que estn en un orden particular: usuario, demog, y despus las listas. Podemos determinar qu informacin ha sido sometida verificando nuestro session namespace para claves particulares representando cada subformulario.
class RegistrationController extends Zend_Controller_Action { // ... protected $_namespace = 'RegistrationController'; protected $_session;
585
Zend_Form
/** * Obtiene el namespace de la sesin que estamos usando * * @return Zend_Session_Namespace */ public function getSessionNamespace() { if (null === $this->_session) { $this->_session = new Zend_Session_Namespace($this->_namespace); } return $this->_session; } /** * Obtiene la lista de Formularios que ya estn almacenados en la sesin * * @return array */ public function getStoredForms() { $stored = array(); foreach ($this->getSessionNamespace() as $key => $value) { $stored[] = $key; } return $stored; } /** * Obtiene la lista de todos los subformularios disponibles * * @return array */ public function getPotentialForms() { return array_keys($this->getForm()->getSubForms()); } /** * Qu subformulario se envio? * * @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)) {
586
Zend_Form
if (is_array($data)) { return $this->getForm()->getSubForm($name); break; } } } return false; } /** * Obtiene el siguiente subformulario para mostrarlo * * @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; } } El mtodo de arriba nos permite usar notaciones tal como "$subForm = $this->getCurrentSubForm();" recuperar el actual subformulario para la validacin, o "$next = $this->getNextSubForm();" obtener el siguiente para mostrar. Ahora, vamos a encontrar la manera para procesar y mostrar varios subformularios. Podemos usar getCurrentSubForm() para determinar si algn subformulario ha sido sometido (los valores de retorno falso indican que ninguno ha sido desplegado o sometido), y getNextSubForm() recupera el formulario que mostrar. Podemos entonces usar el mtodo del formulario prepareSubForm() para asegurar que el formulario est listo para mostrar. Cuando tenemos un formulario sometido, podemos validar el subformulario, y luego verificar si el formulario entero es vlido ahora. Para hacer esas tareas, necesitamos mtodos adicionales que aseguren que la informacin sometida es aadida a la sesin, y que cuando validamos el formulario entero, nosotros validamos contra todos los segmentos de la sesin: class RegistrationController extends Zend_Controller_Action { // ... /** * Es vlido el subformulario? * * @param Zend_Form_SubForm $subForm * @param array $data
587
Zend_Form
* @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; } /** * Es vlido todo el formulario? * * @return bool */ public function formIsValid() { $data = array(); foreach ($this->getSessionNamespace() as $key => $info) { $data[$key] = $info; } return $this->getForm()->isValid($data); } } Ahora que tenemos el trabajo preparado, vamos a construir las acciones para este controlador. Necesitaremos una pgina de destino para el formulario, y luego una accin 'process' para procesar el formulario.
class RegistrationController extends Zend_Controller_Action { // ... public { // // if function indexAction() volver a mostrar la pgina actual, o mostrar el "siguiente" (primer) subformulario (!$form = $this->getCurrentSubForm()) { $form = $this->getNextSubForm();
588
Zend_Form
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'); } // Formulario Vlido! // Render information in a verification page $this->view->info = $this->getSessionNamespace(); $this->render('verification'); } } Como se ha notado, el cdigo actual para procesar el formulario es relativamente simple. Verificamos si tenemos un subformulario actual sometido y si no, retornamos a la pgina de destino. Si tenemos un subformulario, intentaremos validarlo, volvindolo a mostrar si tiene fallos. Si el subformulario es vlido, entonces verificaremos si el formulario es vlido, lo que debera indicar que hemos terminado; si no, mostraremos el siguiente segmento del formulario. Finalmente, mostraremos una pgina de verificacin con el contenido de la sesin. Los scripts de vista son muy simples:
<? // registration/index.phtml ?> <h2>registro</h2> <?php echo $this->form ?> <? // registration/verification.phtml ?> <h2>Gracias por Registrarse!</h2> <p> Aqu est la informacin que nos ha proporcionado: </p> <? // Tienen que construir esto con los items que estan almacenados en los namespaces // de la sesin foreach ($this->info as $info): foreach ($info as $form => $data): ?> <h4><?php echo ucfirst($form) ?>:</h4> <dl> <? foreach ($data as $key => $value): ?> <dt><?php echo ucfirst($key) ?></dt> <? if (is_array($value)): foreach ($value as $label => $val): ?> <dd><?php echo $val ?></dd> <? endforeach; else: ?> <dd><?php echo $this->escape($value) ?></dd> <? endif;
589
Zend_Form
endforeach; ?> </dl> <? endforeach; endforeach Prximas novedades de Zend Framework incluirn componentes para hacer formularios multi pginas mas simples, abstrayendo la sesin y la lgica de orden. Mientras tanto, el ejemplo de arriba debera servir como guia razonable para alcanzar esta tarea en su web.
590
Unsupported services
Zend_Gdata does not provide an interface to any other Google service, such as Search, Gmail, Translation, or Maps. Only services that support the Google Data API are supported.
Structure of Zend_Gdata
Zend_Gata is composed of several types of classes: Service classes - inheriting from Zend_Gdata_App. These also include other classes such as Zend_Gdata, Zend_Gdata_Spreadsheets, etc. These classes enable interacting with APP or GData services and provide the ability to retrieve feeds, retrieve entries, post entries, update entries and delete entries. Query classes - inheriting from Zend_Gdata_Query. These also include other classes for specific services, such as Zend_Gdata_Spreadsheets_ListQuery and Zend_Gdata_Spreadsheets_CellQuery. Query
591
Zend_Gdata
classes provide methods used to construct a query for data to be retrieved from GData services. Methods include getters and setters like setUpdatedMin(), setStartIndex(), and getPublishedMin(). The query classes also have a method to generate a URL representing the constructed query -- getQueryUrl. Alternatively, the query string component of the URL can be retrieved used the getQueryString() method. Feed classes inheriting from Zend_Gdata_App_Feed. These also include other classes such as Zend_Gdata_Feed, Zend_Gdata_Spreadsheets_SpreadsheetFeed, and Zend_Gdata_Spreadsheets_ListFeed. These classes represent feeds of entries retrieved from services. They are primarily used to retrieve data returned from services. Entry classes - inheriting from Zend_Gdata_App_Entry. These also include other classes such as Zend_Gdata_Entry, and Zend_Gdata_Spreadsheets_ListEntry. These classes represent entries retrieved from services or used for constructing data to send to services. In addition to being able to set the properties of an entry (such as the spreadsheet cell value), you can use an entry object to send update or delete requests to a service. For example, you can call $entry->save() to save changes made to an entry back to service from which the entry initiated, or $entry->delete() to delete an entry from the server. Other Data model classes - inheriting from Zend_Gdata_App_Extension. These include classes such as Zend_Gdata_App_Extension_Title (representing the atom:title XML element), Zend_Gdata_Extension_When (representing the gd:when XML element used by the GData Event "Kind"), and Zend_Gdata_Extension_Cell (representing the gs:cell XML element used by Google Spreadsheets). These classes are used purely to store the data retrieved back from services and for constructing data to be sent to services. These include getters and setters such as setText() to set the child text node of an element, getText() to retrieve the text node of an element, getStartTime() to retrieve the start time attribute of a When element, and other similiar methods. The data model classes also include methods such as getDOM() to retrieve a DOM representation of the element and all children and transferFromDOM() to construct a data model representation of a DOM tree.
592
Zend_Gdata
// creates a Zend_Gdata_App_Spreadsheets_CellEntry $entry = $ss->newCellEntry(); // creates a Zend_Gdata_App_Spreadsheets_Extension_Cell $cell = $ss->newCell(); $cell->setText('My cell value'); $cell->setRow('1'); $cell->setColumn('3'); $entry->cell = $cell; // ... $entry can then be used to send an update to a Google Spreadsheet Each service class in the inheritance tree is responsible for registering the appropriate 'packages' (directories) which are to be searched when calling the magic factory method.
Dependencies
Zend_Gdata makes use of Zend_Http_Client to send requests to google.com and fetch results. The response to most Google Data requests is returned as a subclass of the Zend_Gdata_App_Feed or Zend_Gdata_App_Entry classes. Zend_Gdata assumes your PHP application is running on a host that has a direct connection to the Internet. The Zend_Gdata client operates by contacting Google Data servers.
$client = new Zend_Http_Client(); $client->setConfig( ...options... ); $gdata = new Zend_Gdata($client); Beginning with Zend Framework 1.7, support has been added for protocol versioning. This allows the client and server to support new features while maintaining backwards compatibility. While most services will manage this for you, if you create a Zend_Gdata instance directly (as opposed to one of its subclasses), you may need to specify the desired protocol version to access certain server functionality.
593
Zend_Gdata
$client = new Zend_Http_Client(); $client->setConfig( ...options... ); $gdata = new Zend_Gdata($client); $gdata->setMajorProtocolVersion(2); $gdata->setMinorProtocolVersion(null); Also see the sections on authentication for methods to create an authenticated Zend_Http_Client object.
$query = new Zend_Gdata_Query(); $query->setMaxResults(10); echo $query->getMaxResults(); // returns 10 The Zend_Gdata class also implements "magic" getter and setter methods, so you can use the name of the parameter as a virtual member of the class.
594
Zend_Gdata
$query = new Zend_Gdata_Query(); $query->maxResults = 10; echo $query->maxResults; // returns 10 You can clear all parameters with the resetParameters() function. This is useful to do if you reuse a Zend_Gdata object for multiple queries. $query = new Zend_Gdata_Query(); $query->maxResults = 10; // ...get feed... $query->resetParameters(); // ...get a different feed... // clears all parameters
Fetching a Feed
Use the getFeed() function to retrieve a feed from a specified URI. This function returns an instance of class specified as the second argument to getFeed, which defaults to Zend_Gdata_Feed. $gdata = new Zend_Gdata(); $query = new Zend_Gdata_Query( 'http://www.blogger.com/feeds/blogID/posts/default'); $query->setMaxResults(10); $feed = $gdata->getFeed($query); See later sections for special functions in each helper class for Google Data services. These functions help you to get feeds from the URI that is appropriate for the respective service.
595
Zend_Gdata
$feed = $gdata->retrieveAllEntriesForFeed($gdata->getFeed($query)); Keep in mind when calling this function that it may take a long time to complete on large feeds. You may need to increase PHP's execution time limit by calling set_time_limit().
Updating Entries
After retrieving an entry, you can update that entry and save changes back to the server. Here's an example: $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $gdata = new Zend_Gdata($client); $query = new Zend_Gdata_Query( 'http://www.blogger.com/feeds/blogID/posts/default'); $query->setMaxResults(10); $feed = $gdata->getFeed($query); foreach ($feed as $entry) { // update the title to append 'NEW' echo 'Old Title: ' . $entry->title->text; $entry->title->text = $entry->title->text . ' NEW'; // update the entry on the server $newEntry = $entry->save(); echo 'New Title: ' . $newEntry->title->text; }
596
Zend_Gdata
Alternatively, you could construct the XML structure for an entry as a string and pass the string to the insertEntry() function.
$gdata = new Zend_Gdata($authenticatedHttpClient); $entry = $gdata->newEntry(); $entry->title = $gdata->newTitle('Playing football at the park'); $content = $gdata->newContent('We will visit the park and play football'); $content->setType('text'); $entry->content = $content; $entryResult = $gdata->insertEntry($entry, 'http://www.blogger.com/feeds/blogID/posts/default'); echo 'The <id> of the resulting entry is: ' . $entryResult->id->text; To post entries, you must be using an authenticated Zend_Http_Client that you created using the Zend_Gdata_AuthSub or Zend_Gdata_ClientLogin classes.
$gdata = new Zend_Gdata($authenticatedHttpClient); // a Google Data feed $feedUri = ...; $feed = $gdata->getFeed($feedUri); foreach ($feed as $feedEntry) { // Option 1 - delete the entry directly $feedEntry->delete(); // Option 2 - delete the entry by passing the edit URL to // $gdata->delete() // $gdata->delete($feedEntry->getEditLink()->href); } To delete entries, you must be using an authenticated Zend_Http_Client that you created using the Zend_Gdata_AuthSub or Zend_Gdata_ClientLogin classes.
597
Zend_Gdata
browser interface that can react to redirection requests. The ClientLogin solution uses PHP code to supply the account credentials; the user is not required to enter her credentials interactively. The account credentials supplied via the AuthSub mechanism are entered by the user of the web application. Therefore they must be account credentials that are known to that user.
Registered applications
Zend_Gdata currently does not support use of secure tokens, because the AuthSub authentication does not support passing a digital certificate to acquire a secure token.
598
Zend_Gdata
Security notes
The treatment of the $php_self variable in the example above is a general security guideline, it is not specific to Zend_Gdata. You should always filter content you output to http headers. Regarding revoking authentication tokens, it is recommended to do this when the user is finished with her Google Data session. The possibility that someone can intercept the token and use it for malicious purposes is very small, but nevertheless it is a good practice to terminate authenticated access to any service.
599
Zend_Gdata
The most common action is to retrieve a list of books that match a search query. To do so you create a VolumeQuery object and pass it to the Books::getVolumeFeed method. For example, to perform a keyword query, with a filter on viewability to restrict the results to partial or full view books, use the setMinViewability and setQuery methods of the VolumeQuery object. The following code snippet prints the title and viewability of all volumes whose metadata or text matches the query term "domino":
$books = new Zend_Gdata_Books(); $query = $books->newVolumeQuery(); $query->setQuery('domino'); $query->setMinViewability('partial_view'); $feed = $books->getVolumeFeed($query); foreach ($feed as $entry) { echo $entry->getVolumeId(); echo $entry->getTitle(); echo $entry->getViewability(); } The Query class, and subclasses like VolumeQuery, are responsible for constructing feed URLs. The VolumeQuery shown above constructs a URL equivalent to the following:
http://www.google.com/books/feeds/volumes?q=keyword&min-viewability=partial Note: Since Book Search results are public, you can issue a Book Search query without authentication. Here are some of the most common VolumeQuery methods for setting search parameters: setQuery: Specifies a search query term. Book Search searches all book metadata and full text for books matching the term. Book metadata includes titles, keywords, descriptions, author names, and subjects. Note that any spaces, quotes or other punctuation in the parameter value must be URL-escaped. (Use a plus (+) for a space.) To search for an exact phrase, enclose the phrase in quotation marks. For example, to search for books matching the phrase "spy plane", set the q parameter to %22spy+plane%22. You can also use any of the advanced search operators [http://books.google.com/advanced_book_search] supported by Book Search. For example, jane+austen +-inauthor:austen returns matches that mention (but are not authored by) Jane Austen. setStartIndex: Specifies the index of the first matching result that should be included in the result set. This parameter uses a one-based index, meaning the first result is 1, the second result is 2 and so forth. This parameter works in conjunction with the max-results parameter to determine which results to return. For example, to request the third set of 10 resultsresults 21-30set the start-index parameter to 21 and the max-results parameter to 10. Note: This isn't a general cursoring mechanism. If you first send a query with ?start-index=1&max-results=10 and then send another query with ?start-index=11&max-results=10, the service cannot guarantee that the results are equivalent to ?start-index=1&max-results=20, because insertions and deletions could have taken place in between the two queries. setMaxResults: Specifies the maximum number of results that should be included in the result set. This parameter works in conjunction with the start-index parameter to determine which results to return. The default value of this parameter is 10 and the maximum value is 20. setMinViewability: Allows you to filter the results according to the books' viewability status [http:// code.google.com/apis/books/docs/dynamic-links.html#terminology]. This parameter accepts one of three values: 'none' (the default, returning all matching books regardless of viewability), 'partial_view' (returning only
600
Zend_Gdata
books that the user can preview or view in their entirety), or 'full_view' (returning only books that the user can view in their entirety).
Reviews
In addition to ratings, authenticated users can submit reviews or edit their reviews. For information on how to request previously submitted reviews, see Retrieving annotations [#zend.gdata.books.retrieving_annotations].
Adding a review
To add a review, add a Review object to a VolumeEntry and post it to the annotation feed. In the example below, we start from an existing VolumeEntry object. $annotationUrl = $entry->getAnnotationLink()->href;
601
Zend_Gdata
$review
= new Zend_Gdata_Books_Extension_Review();
Editing a review
To update an existing review, first you retrieve the review you want to update, then you modify it, and then you submit it to the annotation feed.
$entryUrl = $entry->getId()->getText(); $review = new Zend_Gdata_Books_Extension_Review(); $review->setText("This book is actually not that good!"); $entry->setReview($review); $books->updateVolume($entry, $entryUrl);
Labels
You can use the Book Search Data API to label volumes with keywords. A user can submit, retrieve and modify labels. See Retrieving annotations [#zend.gdata.books.retrieving_annotations] for how to read previously submitted labels.
$annotationUrl = $entry->getAnnotationLink()->href; $category = new Zend_Gdata_App_Extension_Category( 'rated', 'http://schemas.google.com/books/2008/labels'); $entry->setCategory(array($category)); $books->insertVolume($entry, Zend_Gdata_Books::MY_ANNOTATION_FEED_URI);
$feed = $books->getVolumeFeed( 'http://www.google.com/books/feeds/users/USER_ID/volumes'); <i>(or)</i> $feed = $books->getUserAnnotationFeed(); // print title(s) and rating value foreach ($feed as $entry) { foreach ($feed->getTitles() as $title) { echo $title; } if ($entry->getRating()) {
602
Zend_Gdata
echo 'Rating: ' . $entry->getRating()->getAverage(); } } For a list of the supported query parameters, see the query parameters [#zend.gdata.books.query_parameters] section.
Deleting Annotations
If you retrieved an annotation entry containing ratings, reviews, and/or labels, you can remove all annotations by calling deleteVolume on that entry.
$books->deleteVolume($entry);
$feed = $books->getUserLibraryFeed(); Note: The feed may not contain all of the user's books, because there's a default limit on the number of results returned. For more information, see the max-results query parameter in Searching for books [#zend.gdata.books.searching_for_books].
$query = $books->newVolumeQuery( 'http://www.google.com/books/feeds/users' . '/USER_ID/collections/library/volumes'); $query->setQuery('bear'); $feed = $books->getVolumeFeed($query); For a list of the supported query parameters, see the query parameters [#zend.gdata.books.query_pParameters] section. In addition, you can search for books that have been labeled by the user [#zend.gdata.books.labels]:
603
Zend_Gdata
$entry = new Zend_Gdata_Books_VolumeEntry(); $entry->setId(new Zend_Gdata_App_Extension_Id(VOLUME_ID)); $books->insertVolume( $entry, Zend_Gdata_Books::MY_LIBRARY_FEED_URI ); The following example adds an existing VolumeEntry object to the library:
$books->deleteVolume($entry);
604
Zend_Gdata
browser interface that can react to redirection requests. The ClientLogin solution uses PHP code to supply the account credentials; the user is not required to enter her credentials interactively. The account credentials supplied via the ClientLogin mechanism must be valid credentials for Google services, but they are not required to be those of the user who is using the PHP application.
605
Zend_Gdata
See http://code.google.com/apis/calendar/overview.html [http://code.google.com/apis/calendar/overview.html] for more information about the Google Calendar API.
Authentication
The Google Calendar API allows access to both public and private calendar feeds. Public feeds do not require authentication, but are read-only and offer reduced functionality. Private feeds offers the most complete functionality but requires an authenticated connection to the calendar servers. There are three authentication schemes that are supported by Google Calendar: ClientAuth provides direct username/password authentication to the calendar servers. Since this scheme requires that users provide your application with their password, this authentication is only recommended when other authentication schemes are insufficient. AuthSub allows authentication to the calendar servers via a Google proxy server. This provides the same level of convenience as ClientAuth but without the security risk, making this an ideal choice for web-based applications. MagicCookie allows authentication based on a semi-random URL available from within the Google Calendar interface. This is the simplest authentication scheme to implement, but requires that users manually retrieve their secure URL before they can authenticate, doesn't provide access to calendar lists, and is limited to read-only access. The Zend_Gdata library provides support for all three authentication schemes. The rest of this chapter will assume that you are familiar the authentication schemes available and how to create an appropriate authenticated connection. For more information, please see section the Authentication section of this manual or the Authentication Overview in the Google Data API Developer's Guide [http://code.google.com/apis/gdata/auth.html].
606
Zend_Gdata
// Create an instance of the Calendar service $service = new Zend_Gdata_Calendar($client); A Calendar service using AuthSub can be created in a similar, though slightly more lengthy fashion:
/* * Retrieve the current URL so that the AuthSub server knows where to * redirect the user after authentication is complete. */ function getCurrentUrl() { global $_SERVER; // Filter php_self to avoid a security vulnerability. $php_request_uri = htmlentities(substr($_SERVER['REQUEST_URI'], 0, strcspn($_SERVER['REQUEST_URI'], "\n\r")), ENT_QUOTES); if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') { $protocol = 'https://'; } else { $protocol = 'http://'; } $host = $_SERVER['HTTP_HOST']; if ($_SERVER['HTTP_PORT'] != '' && (($protocol == 'http://' && $_SERVER['HTTP_PORT'] != '80') || ($protocol == 'https://' && $_SERVER['HTTP_PORT'] != '443'))) { $port = ':' . $_SERVER['HTTP_PORT']; } else { $port = ''; } return $protocol . $host . $port . $php_request_uri; } /** * Obtain an AuthSub authenticated HTTP client, redirecting the user * to the AuthSub server to login if necessary. */ function getAuthSubHttpClient() { global $_SESSION, $_GET; // if there is no AuthSub session or one-time token waiting for us, // redirect the user to the AuthSub server to get one. if (!isset($_SESSION['sessionToken']) && !isset($_GET['token'])) { // Parameters to give to AuthSub server $next = getCurrentUrl(); $scope = "http://www.google.com/calendar/feeds/"; $secure = false;
607
Zend_Gdata
$session = true; // Redirect the user to the AuthSub server to sign in $authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure, $session); header("HTTP/1.0 307 Temporary redirect"); header("Location: " . $authSubUrl); exit(); } // Convert an AuthSub one-time token into a session token if needed if (!isset($_SESSION['sessionToken']) && isset($_GET['token'])) { $_SESSION['sessionToken'] = Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']); } // At this point we are authenticated via AuthSub and can obtain an // authenticated HTTP client instance // Create an authenticated HTTP client $client = Zend_Gdata_AuthSub::getHttpClient($_SESSION['sessionToken']); return $client; } // -> Script execution begins here <// Make sure that the user has a valid session, so we can record the // AuthSub session token once it is available. session_start(); // Create an instance of the Calendar service, redirecting the user // to the AuthSub server if necessary. $service = new Zend_Gdata_Calendar(getAuthSubHttpClient()); Finally, an unauthenticated server can be created for use with either public feeds or MagicCookie authentication:
// Create an instance of the Calendar service using an unauthenticated // HTTP client $service = new Zend_Gdata_Calendar(); Note that MagicCookie authentication is not supplied with the HTTP connection, but is instead specified along with the desired visibility when submitting queries. See the section on retrieving events below for an example.
608
Zend_Gdata
The calendar list is always private and must be accessed over an authenticated connection. It is not possible to retrieve another user's calendar list and it cannot be accessed using MagicCookie authentication. Attempting to access a calendar list without holding appropriate credentials will fail and result in a 401 (Authentication Required) status code.
$service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Calendar($client); try { $listFeed= $service->getCalendarListFeed(); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); } Calling getCalendarListFeed() creates a new instance of Zend_Gdata_Calendar_ListFeed containing each available calendar as an instance of Zend_Gdata_Calendar_ListEntry. After retrieving the feed, you can use the iterator and accessors contained within the feed to inspect the enclosed calendars.
echo "<h1>Calendar List Feed</h1>"; echo "<ul>"; foreach ($listFeed as $calendar) { echo "<li>" . $calendar->title . " (Event Feed: " . $calendar->id . ")</li>"; } echo "</ul>";
Retrieving Events
Like the list of calendars, events are also retrieved using the Zend_Gdata_Calendar service class. The event list returned is of type Zend_Gdata_Calendar_EventFeed and contains each event as an instance of Zend_Gdata_Calendar_EventEntry. As before, the iterator and accessors contained within the event feed instance allow inspection of individual events.
Queries
When retrieving events using the Calendar API, specially constructed query URLs are used to describe what events should be returned. The Zend_Gdata_Calendar_EventQuery class simplifies this task by automatically constructing a query URL based on provided parameters. A full list of these parameters is available at the Queries section of the Google Data APIs Protocol Reference [http://code.google.com/apis/gdata/reference.html#Queries]. However, there are three parameters that are worth special attention: User is used to specify the user whose calendar is being searched for, and is specified as an email address. If no user is provided, "default" will be used instead to indicate the currently authenticated user (if authenticated). Visibility specifies whether a users public or private calendar should be searched. If using an unauthenticated session and no MagicCookie is available, only the public feed will be available. Projection specifies how much data should be returned by the server and in what format. In most cases you will want to use the "full" projection. Also available is the "basic" projection, which places most meta-data into each event's content field as human readable text, and the "composite" projection which includes complete text for any comments alongside each event. The "composite" view is often much larger than the "full" view.
609
Zend_Gdata
$query = $service->newEventQuery(); $query->setUser('default'); // Set to $query->setVisibility('private-magicCookieValue') if using // MagicCookie auth $query->setVisibility('private'); $query->setProjection('full'); $query->setOrderby('starttime'); $query->setFutureevents('true'); // Retrieve the event list from the calendar server try { $eventFeed = $service->getCalendarEventFeed($query); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); } // Iterate through the list of events, outputting them as an HTML list echo "<ul>"; foreach ($eventFeed as $event) { echo "<li>" . $event->title . " (Event ID: " . $event->id . ")</li>"; } echo "</ul>"; Additional properties such as ID, author, when, event status, visibility, web content, and content, among others are available within Zend_Gdata_Calendar_EventEntry. Refer to the Zend Framework API Documentation [http://framework.zend.com/apidoc/core/] and the Calendar Protocol Reference [http://code.google.com/apis/gdata/ reference.html] for a complete list.
$query->setStartMin('2006-12-01'); $query->setStartMax('2006-12-16'); Note that startMin is inclusive whereas startMax is exclusive. As a result, only events through 2006-12-15 23:59:59 will be returned.
610
Zend_Gdata
$query->setQuery("dogfood");
$query = $service->newEventQuery(); $query->setUser('default'); $query->setVisibility('private'); $query->setProjection('full'); $query->setEvent($eventId); try { $event = $service->getCalendarEventEntry($query); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); } In a similar fashion, if the event URL is known, it can be passed directly into getCalendarEntry() to retrieve a specific event. In this case, no query object is required since the event URL contains all the necessary information to retrieve the event.
$eventURL = "http://www.google.com/calendar/feeds/default/private" . "/full/g829on5sq4ag12se91d10uumko"; try { $event = $service->getCalendarEventEntry($eventURL); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); }
Creating Events
Creating Single-Occurrence Events
Events are added to a calendar by creating an instance of Zend_Gdata_EventEntry and populating it with the appropriate data. The calendar service instance (Zend_Gdata_Calendar) is then used to used to transparently covert the event into XML and POST it to the calendar server. Creating events requires either an AuthSub or ClientAuth authenticated connection to the calendar server. At a minimum, the following attributes should be set: Title provides the headline that will appear above the event within the Google Calendar UI. When indicates the duration of the event and, optionally, any reminders that are associated with it. See the next section for more information on this attribute. Other useful attributes that may optionally set include: Author provides information about the user who created the event.
611
Zend_Gdata
Content provides additional information about the event which appears when the event details are requested from within Google Calendar. EventStatus indicates whether the event is confirmed, tentative, or canceled. Hidden removes the event from the Google Calendar UI. Transparency indicates whether the event should be consume time on the user's free/busy list. WebContent allows links to external content to be provided within an event. Where indicates the location of the event. Visibility allows the event to be hidden from the public event lists. For a complete list of event attributes, refer to the Zend Framework API Documentation [http://framework.zend.com/ apidoc/core/] and the Calendar Protocol Reference [http://code.google.com/apis/gdata/reference.html]. Attributes that can contain multiple values, such as where, are implemented as arrays and need to be created accordingly. Be aware that all of these attributes require objects as parameters. Trying instead to populate them using strings or primitives will result in errors during conversion to XML. Once the event has been populated, it can be uploaded to the calendar server by passing it as an argument to the calendar service's insertEvent() function. // Create a new entry using the calendar service's magic factory method $event= $service->newEventEntry(); // Populate the event with the desired information // Note that each attribute is crated as an instance of a matching class $event->title = $service->newTitle("My Event"); $event->where = array($service->newWhere("Mountain View, California")); $event->content = $service->newContent(" This is my awesome event. RSVP required."); // Set the date using RFC 3339 format. $startDate = "2008-01-20"; $startTime = "14:00"; $endDate = "2008-01-20"; $endTime = "16:00"; $tzOffset = "-08"; $when = $service->newWhen(); $when->startTime = "{$startDate}T{$startTime}:00.000{$tzOffset}:00"; $when->endTime = "{$endDate}T{$endTime}:00.000{$tzOffset}:00"; $event->when = array($when); // Upload the event to the calendar server // A copy of the event as it is recorded on the server is returned $newEvent = $service->insertEvent($event);
612
Zend_Gdata
All-day events can be scheduled by specifying only the date omitting the time when setting startTime and endTime. Likewise, zero-duration events can be specified by omitting the endTime. In all cases, date/time values should be provided in RFC3339 [http://www.ietf.org/rfc/rfc3339.txt] format.
// Schedule the event to occur on December 05, 2007 at 2 PM PST (UTC-8) // with a duration of one hour. $when = $service->newWhen(); $when->startTime = "2007-12-05T14:00:00-08:00"; $when->endTime="2007-12-05T15:00:00:00-08:00"; // Apply the when property to an event $event->when = array($when); The when attribute also controls when reminders are sent to a user. Reminders are stored in an array and each event may have up to find reminders associated with it. For a reminder to be valid, it needs to have two attributes set: method and a time. Method can accept one of the following strings: "alert", "email", or "sms". The time should be entered as an integer and can be set with either the property minutes, hours, days, or absoluteTime. However, a valid request may only have one of these attributes set. If a mixed time is desired, convert to the most precise unit available. For example, 1 hour and 30 minutes should be entered as 90 minutes.
// Create a new reminder object. It should be set to send an email // to the user 10 minutes beforehand. $reminder = $service->newReminder(); $reminder->method = "email"; $reminder->minutes = "10"; // Apply the reminder to an existing event's when property $when = $event->when[0]; $when->reminders = array($reminder);
// Create a new entry using the calendar service's magic factory method $event= $service->newEventEntry(); // Populate the event with the desired information // Note that each attribute is crated as an instance of a matching class $event->title = $service->newTitle("My Recurring Event");
613
Zend_Gdata
$event->where = array($service->newWhere("Palo Alto, California")); $event->content = $service->newContent(' This is my other awesome event, ' . ' occurring all-day every Tuesday from . '2007-05-01 until 207-09-04. No RSVP required.'); // Set the duration and frequency by specifying a recurrence pattern. $recurrence = "DTSTART;VALUE=DATE:20070501\r\n" . "DTEND;VALUE=DATE:20070502\r\n" . "RRULE:FREQ=WEEKLY;BYDAY=Tu;UNTIL=20070904\r\n"; $event->recurrence = $service->newRecurrence($recurrence); // Upload the event to the calendar server // A copy of the event as it is recorded on the server is returned $newEvent = $service->insertEvent($event);
Using QuickAdd
QuickAdd is a feature which allows events to be created using free-form text entry. For example, the string "Dinner at Joe's Diner on Thursday" would create an event with the title "Dinner", location "Joe's Diner", and date "Thursday". To take advantage of QuickAdd, create a new QuickAdd property set to "true" and store the freeform text as a content property.
// Create a new entry using the calendar service's magic factory method $event= $service->newEventEntry(); // Populate the event with the desired information $event->content= $service->newContent("Dinner at Joe's Diner on Thursday"); $event->quickAdd = $service->newQuickAdd("true"); // Upload the event to the calendar server // A copy of the event as it is recorded on the server is returned $newEvent = $service->insertEvent($event);
Modifying Events
Once an instance of an event has been obtained, the event's attributes can be locally modified in the same way as when creating an event. Once all modifications are complete, calling the event's save() method will upload the changes to the calendar server and return a copy of the event as it was created on the server. In the event another user has modified the event since the local copy was retrieved, save() will fail and the server will return a 409 (Conflict) status code. To resolve this a fresh copy of the event must be retrieved from the server before attempting to resubmit any modifications.
// Get the first event in the user's event list $event = $eventFeed[0]; // Change the title to a new value $event->title = $service->newTitle("Woof!");
614
Zend_Gdata
// Upload the changes to the server try { $event->save(); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); }
Deleting Events
Calendar events can be deleted either by calling the calendar service's delete() method and providing the edit URL of an event or by calling an existing event's own delete() method. In either case, the deleted event will still show up on a user's private event feed if an updateMin query parameter is provided. Deleted events can be distinguished from regular events because they will have their eventStatus property set to "http://schemas.google.com/g/2005#event.canceled".
// Option 2: Events can be deleted supplying the edit URL of the event // to the calendar service, if known $service->delete($event->getEditLink()->href);
// Extract the comment URL from the first event in a user's feed list $event = $eventFeed[0]; $commentUrl = $event->comments->feedLink->url; // Retrieve the comment list for the event try { $commentFeed = $service->getFeed($commentUrl); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); } // Output each comment as an HTML list echo "<ul>"; foreach ($commentFeed as $comment) { echo "<li><em>Comment By: " . $comment->author->name "</em><br/>" . $comment->content . "</li>"; } echo "</ul>";
615
Zend_Gdata
Upload a Document
You can create a new Google Document by uploading a word processing document, spreadsheet, or presentation. This example is from the interactive Docs.php sample which comes with the library. It demonstrates uploading a file and printing information about the result from the server. /** * Upload the specified document * * @param Zend_Gdata_Docs $docs The service object to use for communicating * with the Google Documents server. * @param boolean $html True if output should be formatted for display in a * web browser. * @param string $originalFileName The name of the file to be uploaded. The * MIME type of the file is determined from the extension on this file * name. For example, test.csv is uploaded as a comma separated volume * and converted into a spreadsheet. * @param string $temporaryFileLocation (optional) The file in which the * data for the document is stored. This is used when the file has been * uploaded from the client's machine to the server and is stored in * a temporary file which does not have an extension. If this parameter * is null, the file is read from the originalFileName. */ function uploadDocument($docs, $html, $originalFileName, $temporaryFileLocation) { $fileToUpload = $originalFileName; if ($temporaryFileLocation) { $fileToUpload = $temporaryFileLocation;
616
Zend_Gdata
} // Upload the file and convert it into a Google Document. The original // file name is used as the title of the document and the MIME type // is determined based on the extension on the original file name. $newDocumentEntry = $docs->uploadFile($fileToUpload, $originalFileName, null, Zend_Gdata_Docs::DOCUMENTS_LIST_FEED_URI); echo "New Document Title: "; if ($html) { // Find the URL of the HTML view of this document. $alternateLink = ''; foreach ($newDocumentEntry->link as $link) { if ($link->getRel() === 'alternate') { $alternateLink = $link->getHref(); } } // Make the title link to the document on docs.google.com. echo "<a href=\"$alternateLink\">\n"; } echo $newDocumentEntry->title."\n"; if ($html) {echo "</a>\n";} }
617
Zend_Gdata
Authentication
The Google Health API allows programmatic access to a user's Health profile. There are three authentication schemes that are supported by Google Health: ClientLogin provides direct username/password authentication to the Health servers. Since this method requires that users provide your application with their password, this authentication scheme is only recommended for installed/ desktop applications. AuthSub allows a user to authorize the sharing of their private data. This provides the same level of convenience as ClientLogin but without the security risk, making it an ideal choice for web-based applications. For Google Health, AuthSub must be used in registered and secure mode--meaning that all requests to the API must be digitally signed. OAuth is an alternative to AuthSub. Although this authentication scheme is not discussed in this document, more information can be found in the Health Data API Developer's Guide [http://code.google.com/apis/health/ developers_guide_protocol.html#OAuth].
618
Zend_Gdata
See Authentication Overview in the Google Data API documentation [http://code.google.com/apis/gdata/auth.html] for more information on each authentication method.
// Parameters for ClientLogin authentication $healthServiceName = Zend_Gdata_Health::HEALTH_SERVICE_NAME; //$h9ServiceName = Zend_Gdata_Health::H9_SANDBOX_SERVICE_NAME; $user = "user@gmail.com"; $pass = "pa$$w0rd"; // Create an authenticated HTTP client $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $healthServiceName); // Create an instance of the Health service $service = new Zend_Gdata_Health($client); A Health service using AuthSub can be created in a similar, though slightly more lengthy fashion. AuthSub is the recommend interface to communicate with Google Health because each token is directly linked to a specific profile in the user's account. Unlike other Google Data APIs, it is required that all requests from your application be digitally signed.
/* * Retrieve the current URL so that the AuthSub server knows where to * redirect the user after authentication is complete. */ function getCurrentUrl() { $phpRequestUri = htmlentities(substr($_SERVER['REQUEST_URI'], 0, strcspn($_SERVER['REQUEST_URI'], "\n\r")), ENT_QUOTES); if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') { $protocol = 'https://'; } else { $protocol = 'http://'; }
619
Zend_Gdata
$host = $_SERVER['HTTP_HOST']; if ($_SERVER['SERVER_PORT'] != '' && (($protocol == 'http://' && $_SERVER['SERVER_PORT'] != '80') || ($protocol == 'https://' && $_SERVER['SERVER_PORT'] != '443'))) { $port = ':' . $_SERVER['SERVER_PORT']; } else { $port = ''; } return $protocol . $host . $port . $phpRequestUri; } /* * Redirect a user to AuthSub if they do not have a valid session token. * If they're coming back from AuthSub with a single-use token, instantiate * a new HTTP client and exchange the token for a long-lived session token * instead. */ function setupClient($singleUseToken = null) { $client = null; // Fetch a new AuthSub token? if (!$singleUseToken) { $next = getCurrentUrl(); $scope = 'https://www.google.com/health/feeds'; $authSubHandler = 'https://www.google.com/health/authsub'; $secure = 1; $session = 1; $authSubURL = Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure, $session, $authSubHandler); // 1 - allows posting notices && allows reading profile data $permission = 1; $authSubURL .= '&permission=' . $permission; echo '<a href="' . $authSubURL . '">Your Google Health Account</a>'; } else { $client = new Zend_Gdata_HttpClient(); // This sets your private key to be used to sign subsequent requests $client->setAuthSubPrivateKeyFile('/path/to/your/rsa_private_key.pem', null, true); $sessionToken = Zend_Gdata_AuthSub::getAuthSubSessionToken(trim($singleUseToken), $client); // Set the long-lived session token for subsequent requests $client->setAuthSubToken($sessionToken); } return $client;
620
Zend_Gdata
} // -> Script execution begins here <session_start(); $client = setupClient(@$_GET['token']); // Create an instance of the Health service $userH9Sandbox = false; $healthService = new Zend_Gdata_Health($client, 'googleInc-MyTestAppName-v1.0', $userH9Sandbox); NOTE: the remainder of this document will assume you are using AuthSub for authentication.
Profile Feed
To query the user's profile feed, make sure your initial AuthSub token was requested with the permission=1 parameter set. The process of extracting data from the profile requires two steps, sending a query and iterating through the resulting feed.
621
Zend_Gdata
$entries = $profileFeed->getEntries(); foreach ($entries as $entry) { $medications = $entry->getCcr()->getMedications(); //$conditions = $entry->getCcr()->getConditions(); //$immunizations = $entry->getCcr()->getImmunizations(); // print the CCR xml (this will just be the entry's medications) foreach ($medications as $med) { $xmlStr = $med->ownerDocument->saveXML($med); echo "<pre>" . $xmlStr . "</pre>"; } } Here, the getCcr() method is used in conjunction with a magic helper to drill down and extract just the medication data from the entry's CCR. The formentioned magic helper takes the form getCATEGORYNAME(), where CATEGORYNAME is a supported Google Health category. See the Google Health reference Guide [http:// code.google.com/apis/health/reference.html#CatQueries] for the possible categories. To be more efficient, you can also use category queries to only return the necessary CCR from the Google Health servers. Then, iterate through those results:
$query = new Zend_Gdata_Health_Query(); $query->setDigest("true"); $query->setCategory("condition"); $profileFeed = $healthService->getHealthProfileFeed($query); // Since the query contained digest=true, only one Atom entry is returned $entry = $profileFeed->entry[0]; $conditions = $entry->getCcr()->getConditions(); // print the CCR xml (this will just be the profile's conditions) foreach ($conditions as $cond) { $xmlStr = $cond->ownerDocument->saveXML($cond); echo "<pre>" . $xmlStr . "</pre>"; }
622
Zend_Gdata
$client = Zend_Gdata_ClientLogin::getHttpClient('user@gmail.com', 'pa$$word', 'health'); $healthService = new Zend_Gdata_Health($client); $feed = $healthService->getHealthProfileListFeed(); // print each profile's name and id $entries = $feed->getEntries(); foreach ($entries as $entry) { echo '<p>Profile name: ' . $entry->getProfileName() . '<br>'; echo 'profile ID: ' . $entry->getProfileID() . '</p>'; } Once you've determined which profile to use, call setProfileID() with the profileID as an argument. This will restrict subsequent API requests to be against that particular profile:
// use the first profile $profileID = $feed->entry[0]->getProfileID(); $healthService->setProfileID($profileID); $profileFeed = $healthService->getHealthProfileFeed(); $profileID = $healthService->getProfileID(); echo '<p><b>Queried profileID</b>: ' . $profileID . '</p>';
Sending a notice
Notices can be sent by using the sendHealthNotice() method for the Health service:
$healthService = new Zend_Gdata_Health($client); $subject = "Title of your notice goes here"; $body = "Notice body can contain <b>html</b> entities"; $ccr = '<ContinuityOfCareRecord xmlns="urn:astm-org:CCR"> <Body> <Problems> <Problem> <DateTime> <Type><Text>Start date</Text></Type>
623
Zend_Gdata
<ExactDateTime>2007-04-04T07:00:00Z</ExactDateTime> </DateTime> <Description> <Text>Aortic valve disorders</Text> <Code> <Value>410.10</Value> <CodingSystem>ICD9</CodingSystem> <Version>2004</Version> </Code> </Description> <Status><Text>Active</Text></Status> </Problem> </Problems> </Body> </ContinuityOfCareRecord>'; $responseEntry = $healthService->sendHealthNotice($subject, $body, "html", $ccr);
Create a Spreadsheet
The Spreadsheets data API does not currently provide a way to programmatically create or delete a spreadsheet.
$service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $spreadsheetService = new Zend_Gdata_Spreadsheets($client); $feed = $spreadsheetService->getSpreadsheetFeed();
624
Zend_Gdata
$query = new Zend_Gdata_Spreadsheets_DocumentQuery(); $query->setSpreadsheetKey($spreadsheetKey); $feed = $spreadsheetService->getWorksheetFeed($query); The resulting Zend_Gdata_Spreadsheets_WorksheetFeed object feed represents the response from the server. Among other things, this feed contains a list of Zend_Gdata_Spreadsheets_WorksheetEntry objects ($feed->entries), each of which represents a single worksheet.
$query = new Zend_Gdata_Spreadsheets_ListQuery(); $query->setSpreadsheetKey($spreadsheetKey); $query->setWorksheetId($worksheetId); $listFeed = $spreadsheetService->getListFeed($query); The resulting Zend_Gdata_Spreadsheets_ListFeed object $listfeed represents a response from the server. Among other things, this feed contains an array of Zend_Gdata_Spreadsheets_ListEntry objects ($listFeed->entries), each of which represents a single row in a worksheet. Each Zend_Gdata_Spreadsheets_ListEntry contains an array, custom, which contains the data for that row. You can extract and display this array:
$rowData = $listFeed->entries[1]->getCustom(); foreach($rowData as $customEntry) { echo $customEntry->getColumnName() . " = " . $customEntry->getText(); } An alternate version of this array, customByName, allows direct access to an entry's cells by name. This is convenient when trying to access a specific header:
625
Zend_Gdata
Reverse-sort Rows
By default, rows in the feed appear in the same order as the corresponding rows in the GUI; that is, they're in order by row number. To get rows in reverse order, set the reverse properties of the Zend_Gdata_Spreadsheets_ListQuery object to true:
$query = new Zend_Gdata_Spreadsheets_ListQuery(); $query->setSpreadsheetKey($spreadsheetKey); $query->setWorksheetId($worksheetId); $query->setReverse('true'); $listFeed = $spreadsheetService->getListFeed($query); Note that if you want to order (or reverse sort) by a particular column, rather than by position in the worksheet, you can set the orderby value of the Zend_Gdata_Spreadsheets_ListQuery object to column:<the header of that column>.
$query = new Zend_Gdata_Spreadsheets_ListQuery(); $query->setSpreadsheetKey($spreadsheetKey); $query->setWorksheetId($worksheetId); $query->setSpreadsheetQuery('name=John and age>25'); $listFeed = $spreadsheetService->getListFeed($query);
Add a Row
Rows can be added to a spreadsheet by using the insertRow method of the Spreadsheet service.
$insertedListEntry = $spreadsheetService->insertRow($rowData, $spreadsheetKey, $worksheetId); The $rowData parameter contains an array of column keys to data values. The method returns a Zend_Gdata_Spreadsheets_SpreadsheetsEntry object which represents the inserted row. Spreadsheets inserts the new row immediately after the last row that appears in the list-based feed, which is to say immediately before the first entirely blank row.
Edit a Row
Once a Zend_Gdata_Spreadsheets_ListEntry object is fetched, its rows can be updated by using the updateRow method of the Spreadsheet service.
626
Zend_Gdata
$updatedListEntry = $spreadsheetService->updateRow($oldListEntry, $newRowData); The $oldListEntry parameter contains the list entry to be updated. $newRowData contains an array of column keys to data values, to be used as the new row data. The method returns a Zend_Gdata_Spreadsheets_SpreadsheetsEntry object which represents the updated row.
Delete a Row
To delete a row, simply invoke deleteRow on the Zend_Gdata_Spreadsheets object with the existing entry to be deleted:
$spreadsheetService->deleteRow($listEntry); Alternatively, you can call the delete method of the entry itself:
$listEntry->delete();
$query = new Zend_Gdata_Spreadsheets_CellQuery(); $query->setSpreadsheetKey($spreadsheetKey); $query->setWorksheetId($worksheetId); $cellFeed = $spreadsheetService->getCellFeed($query); The resulting Zend_Gdata_Spreadsheets_CellFeed object $cellFeed represents a response from the server. Among other things, this feed contains an array of Zend_Gdata_Spreadsheets_CellEntry objects ($cellFeed>entries), each of which represents a single cell in a worksheet. You can display this information:
foreach($cellFeed as $cellEntry) { $row = $cellEntry->cell->getRow(); $col = $cellEntry->cell->getColumn(); $val = $cellEntry->cell->getText(); echo "$row, $col = $val\n"; }
627
Zend_Gdata
$query = new Zend_Gdata_Spreadsheets_CellQuery(); $query->setMinCol(1); $query->setMaxCol(1); $query->setMinRow(2); $feed = $spreadsheetService->getCellsFeed($query); This requests all the data in column 1, starting with row 2.
$updatedCell = $spreadsheetService->updateCell($row, $col, $inputValue, $spreadsheetKey, $worksheetId); The new data is placed in the specified cell in the worksheet. If the specified cell contains data already, it will be overwritten. Note: Use updateCell to change the data in a cell, even if the cell is empty.
Authentication
The Provisioning API does not support authentication via AuthSub and anonymous access is not permitted. All HTTP connections must be authenticated using ClientAuth authentication.
628
Zend_Gdata
$domain = "example.com"; $query = new Zend_Gdata_Gapps_UserQuery($domain, $arg); When using a service class factory method to create a query, the service class will automatically set the query's domain to match its own domain. As a result, it is not necessary to specify the domain as part of the constructor arguments.
$gdata->createUser('foo', 'Random', 'User', ''); Users can also be created by instantiating UserEntry, providing a username, given name, family name, and password, then calling insertUser() on a service object to upload the entry to the server.
$user = $gdata->newUserEntry(); $user->login = $gdata->newLogin(); $user->login->username = 'foo'; $user->login->password = ''; $user->name = $gdata->newName(); $user->name->givenName = 'Random'; $user->name->familyName = 'User'; $user = $gdata->insertUser($user); The user's password should normally be provided as cleartext. Optionally, the password can be provided as an SHA-1 digest if login->passwordHashFunction is set to 'SHA-1'.
629
Zend_Gdata
$user = $gdata->retrieveUser('foo'); echo echo echo echo echo echo 'Username: ' . $user->login->userName . "\n"; 'Given Name: ' . $user->name->givenName . "\n"; 'Family Name: ' . $user->name->familyName . "\n"; 'Suspended: ' . ($user->login->suspended ? 'Yes' : 'No') . "\n"; 'Admin: ' . ($user->login->admin ? 'Yes' : 'No') . "\n" 'Must Change Password: ' . ($user->login->changePasswordAtNextLogin ? 'Yes' : 'No') . "\n"; echo 'Has Agreed To Terms: ' . ($user->login->agreedToTerms ? 'Yes' : 'No') . "\n"; Users can also be retrieved by creating an instance of Zend_Gdata_Gapps_UserQuery, setting its username property to equal the username of the user that is to be retrieved, and calling getUserEntry() on a service object with that query.
$query = $gdata->newUserQuery('foo'); $user = $gdata->getUserEntry($query); echo echo echo echo echo echo 'Username: ' . $user->login->userName . "\n"; 'Given Name: ' . $user->login->givenName . "\n"; 'Family Name: ' . $user->login->familyName . "\n"; 'Suspended: ' . ($user->login->suspended ? 'Yes' : 'No') . "\n"; 'Admin: ' . ($user->login->admin ? 'Yes' : 'No') . "\n" 'Must Change Password: ' . ($user->login->changePasswordAtNextLogin ? 'Yes' : 'No') . "\n"; echo 'Has Agreed To Terms: ' . ($user->login->agreedToTerms ? 'Yes' : 'No') . "\n"; If the specified user cannot be located a ServiceException will be thrown with an error code of Zend_Gdata_Gapps_Error::ENTITY_DOES_NOT_EXIST. ServiceExceptions will be covered in the section called Handling errors.
$feed = $gdata->retrieveAllUsers(); foreach ($feed as $user) { echo " * " . $user->login->username . ' (' . $user->name->givenName . ' ' . $user->name->familyName . ")\n"; } This will create a Zend_Gdata_Gapps_UserFeed object which holds each user on the domain. Alternatively, call getUserFeed() with no options. Keep in mind that on larger domains this feed may be paged by the server. For more information on paging, see the section called Working with Multi-page Feeds.
630
Zend_Gdata
echo " * " . $user->login->username . ' (' . $user->name->givenName . ' ' . $user->name->familyName . ")\n"; }
$user = $gdata->retrieveUser('foo'); $user->login->password = ''; $user = $user->save(); Note that it is not possible to recover a password in this manner as stored passwords are not made available via the Provisioning API for security reasons.
$user = $gdata->retrieveUser('foo'); $user->login->changePasswordAtNextLogin = true; $user = $user->save(); Similarly, this can be undone by setting the login->changePasswordAtNextLogin property to FALSE.
$gdata->suspendUser('foo'); $gdata->restoreUser('foo'); Alternatively, you can set the UserEntry's login->suspended property to TRUE.
$user = $gdata->retrieveUser('foo'); $user->login->suspended = true; $user = $user->save(); To restore the user's access, set the login->suspended property to FALSE.
631
Zend_Gdata
Creating a nickname
Nicknames can be created by calling the createNickname() convenience method: $gdata->createNickname('foo', 'bar'); Nicknames can also be created by instantiating NicknameEntry, providing the nickname with a name and an owner, then calling insertNickname() on a service object to upload the entry to the server. $nickname = $gdata->newNicknameEntry(); $nickname->login = $gdata->newLogin('foo'); $nickname->nickname = $gdata->newNickname('bar'); $nickname = $gdata->insertNickname($nickname);
Retrieving a nickname
Nicknames can be retrieved by calling the retrieveNickname() convenience method. This will return NULL if a user is not found. $nickname = $gdata->retrieveNickname('bar'); echo 'Nickname: ' . $nickname->nickname->name . "\n";
632
Zend_Gdata
echo 'Owner: ' . $nickname->login->username . "\n"; Individual nicknames can also be retrieved by creating an instance of Zend_Gdata_Gapps_NicknameQuery, setting its nickname property to equal the nickname that is to be retrieved, and calling getNicknameEntry() on a service object with that query. $query = $gdata->newNicknameQuery('bar'); $nickname = $gdata->getNicknameEntry($query); echo 'Nickname: ' . $nickname->nickname->name . "\n"; echo 'Owner: ' . $nickname->login->username . "\n"; As with users, if no corresponding nickname is found a ServiceException will be thrown with an error code of Zend_Gdata_Gapps_Error::ENTITY_DOES_NOT_EXIST. Again, these will be discussed in the section called Handling errors.
633
Zend_Gdata
Alternatively, call getNicknameFeed() on a service object with no arguments. $feed = $gdata->getNicknameFeed(); foreach ($feed as $nickname) { echo ' * ' . $nickname->nickname->name . ' => ' . $nickname->login->username . "\n"; }
Deleting a nickname
Deleting a nickname to which you already hold a NicknameEntry for is a simple as calling delete() on that entry. $nickname = $gdata->retrieveNickname('bar'); $nickname->delete(); For nicknames which you do not hold a NicknameEntry for, use the deleteNickname() convenience method. $gdata->deleteNickname('bar');
634
Zend_Gdata
This will create a Zend_Gdata_Gapps_EmailListFeed object which holds each email list associated with the specified recipient. Alternatively, create a new Zend_Gdata_Gapps_EmailListQuery, set its recipient property to the desired email address, and submit the query by calling getEmailListFeed() on a service object. $query = $gdata->newEmailListQuery(); $query->setRecipient('baz@somewhere.com'); $feed = $gdata->getEmailListFeed($query); foreach ($feed as $list) { echo ' * ' . $list->emailList->name . "\n"; }
635
Zend_Gdata
$feed = $gdata->retrieveAllRecipients('friends'); foreach ($feed as $recipient) { echo ' * ' . $recipient->who->email . "\n"; } Alternatively, construct a new EmailListRecipientQuery, set its emailListName property to match the desired email list, and call getEmailListRecipientFeed() on a service object.
$query = $gdata->newEmailListRecipientQuery(); $query->setEmailListName('friends'); $feed = $gdata->getEmailListRecipientFeed($query); foreach ($feed as $recipient) { echo ' * ' . $recipient->who->email . "\n"; } This will create a Zend_Gdata_Gapps_EmailListRecipientFeed object which holds each recipient for the selected email list.
$gdata->removeRecipientFromEmailList('baz@somewhere.com', 'friends');
Handling errors
In addition to the standard suite of exceptions thrown by Zend_Gdata, requests using the Provisioning API may also throw a Zend_Gdata_Gapps_ServiceException. These exceptions indicate that a API specific error occurred which prevents the request from completing. Each ServiceException instance may hold one or more Error objects. Each of these objects contains an error code, reason, and (optionally) the input which triggered the exception. A complete list of known error codes is provided in the Zend Framework API documentation under Zend_Gdata_Gapps_Error. Additionally, the authoritative error list is available online at Google Apps Provisioning API V2.0 Reference: Appendix D [http://code.google.com/apis/ apps/gdata_provisioning_api_v2.0_reference.html#appendix_d]. While the complete list of errors received is available within ServiceException as an array by calling getErrors(), often it is convenient to know if one specific error occurred. For these cases the presence of an error can be determined by calling hasError(). The following example demonstrates how to detect if a requested resource doesn't exist and handle the fault gracefully:
636
Zend_Gdata
try { $user = $gdata->getUserEntry($query); } catch (Zend_Gdata_Gapps_ServiceException $e) { // Set the user to null if not found if ($e->hasError(Zend_Gdata_Gapps_Error::ENTITY_DOES_NOT_EXIST)) { $user = null; } else { throw $e; } } return $user; }
Authentication
The Google Base API allows access to both public and private base feeds. Public feeds do not require authentication, but are read-only and offer reduced functionality. Private feeds offers the most complete functionality but requires an authenticated connection to the base servers. There are three authentication schemes that are supported by Google Base: ClientAuth provides direct username/password authentication to the base servers. Since this scheme requires that users provide your application with their password, this authentication is only recommended when other authentication schemes are insufficient. AuthSub allows authentication to the base servers via a Google proxy server. This provides the same level of convenience as ClientAuth but without the security risk, making this an ideal choice for web-based applications. The Zend_Gdata library provides support for all three authentication schemes. The rest of this chapter will assume that you are familiar the authentication schemes available and how to create an appropriate authenticated connection. For more information, please see section the section called Google Data Client Authentication. or the Authentication Overview in the Google Data API Developer's Guide [http://code.google.com/apis/gdata/auth.html].
637
Zend_Gdata
638
Zend_Gdata
$port = ''; } return $protocol . $host . $port . $php_request_uri; } /** * Obtain an AuthSub authenticated HTTP client, redirecting the user * to the AuthSub server to login if necessary. */ function getAuthSubHttpClient() { global $_SESSION, $_GET; // If there is no AuthSub session or one-time token waiting for us, // redirect the user to the AuthSub server to get one. if (!isset($_SESSION['sessionToken']) && !isset($_GET['token'])) { // Parameters to give to AuthSub server $next = getCurrentUrl(); $scope = "http://www.google.com/base/feeds/items/"; $secure = false; $session = true; // Redirect the user to the AuthSub server to sign in $authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure, $session); header("HTTP/1.0 307 Temporary redirect"); header("Location: " . $authSubUrl); exit(); } // Convert an AuthSub one-time token into a session token if needed if (!isset($_SESSION['sessionToken']) && isset($_GET['token'])) { $_SESSION['sessionToken'] = Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']); } // At this point we are authenticated via AuthSub and can obtain an // authenticated HTTP client instance // Create an authenticated HTTP client $client = Zend_Gdata_AuthSub::getHttpClient($_SESSION['sessionToken']); return $client; } // -> Script execution begins here <// Make sure http://code.google.com/apis/gdata/reference.html#Queriesthat // the user has a valid session, so we can record the // AuthSub session token once it is available.
639
Zend_Gdata
session_start(); // Create an instance of the Base service, redirecting the user // to the AuthSub server if necessary. $service = new Zend_Gdata_Gbase(getAuthSubHttpClient()); Finally, an unauthenticated server can be created for use with snippets feeds:
// Create an instance of the Base service using an unauthenticated HTTP client $service = new Zend_Gdata_Gbase();
Retrieve Items
You can query customer items feed or snippets feed to retrieve items. It involves two steps, sending a query and iterating through the returned feed.
$service = new Zend_Gdata_Gbase($client); $query = $service->newItemQuery(); $query->setBq('[title:Programming]'); $query->setOrderBy('modification_time'); $query->setSortOrder('descending'); $query->setMaxResults('5'); $feed = $service->getGbaseItemFeed($query); A full list of these parameters is available at the Query parameters section [http://code.google.com/apis/base/itemsfeed.html#QueParameters] of the Customer Items Feed documentation.
$service = new Zend_Gdata_Gbase(); $query = $service->newSnippetQuery(); $query->setBq('[title:Programming]'); $query->setOrderBy('modification_time'); $query->setSortOrder('descending'); $query->setMaxResults('5'); $feed = $service->getGbaseSnippetFeed($query);
640
Zend_Gdata
A full list of these parameters is available at the Query parameters section [http://code.google.com/apis/base/snippetsfeed.html#Parameters] of the Snippets Feed documentation.
foreach ($feed->entries as $entry) { // Get all attributes and print out the name and text value of each // attribute $baseAttributes = $entry->getGbaseAttributes(); foreach ($baseAttributes as $attr) { echo "Attribute " . $attr->name . " : " . $attr->text . "<br>"; } } Or, you can look for specific attribute name and iterate through the results that match:
foreach ($feed->entries as $entry) { // Print all main ingredients <g:main_ingredient> $baseAttributes = $entry->getGbaseAttribute("main_ingredient"); foreach ($baseAttributes as $attr) { echo "Main ingredient: " . $attr->text . "<br>"; } }
Insert an Item
Items can be added by using the insertGbaseItem() method for the Base service:
$service = new Zend_Gdata_Gbase($client); $newEntry = $service->newItemEntry(); // Add title $title = "PHP Developer Handbook"; $newEntry->title = $service->newTitle(trim($title)); // Add some content $content = "Essential handbook for PHP developers."; $newEntry->content = $service->newContent($content); $newEntry->content->type = 'text';
641
Zend_Gdata
// Define product type $itemType = "Products"; $newEntry->itemType = $itemType; // Add item specific attributes $newEntry->addGbaseAttribute("product_type", "book", "text"); $newEntry->addGbaseAttribute("price", "12.99 USD", "floatUnit"); $newEntry->addGbaseAttribute("quantity", "10", "int"); $newEntry->addGbaseAttribute("weight", "2.2 lbs", "numberUnit"); $newEntry->addGbaseAttribute("condition", "New", "text"); $newEntry->addGbaseAttribute("author", "John Doe", "text"); $newEntry->addGbaseAttribute("edition", "First Edition", "text"); $newEntry->addGbaseAttribute("pages", "253", "number"); $newEntry->addGbaseAttribute("publisher", "My Press", "text"); $newEntry->addGbaseAttribute("year", "2007", "number"); $newEntry->addGbaseAttribute("payment_accepted", "Google Checkout", "text"); $dryRun = true; $createdEntry = $service->insertGbaseItem($newEntry, $dryRun);
Modify an Item
You can update each attribute element of an item as you iterate through them:
// Update the title $newTitle = "PHP Developer Handbook Second Edition"; $entry->title = $service->newTitle($newTitle); // Find <g:price> attribute and update the price $baseAttributes = $entry->getGbaseAttribute("price"); if (is_object($baseAttributes[0])) { $newPrice = "16.99 USD"; $baseAttributes[0]->text = $newPrice; } // Find <g:pages> attribute and update the number of pages $baseAttributes = $entry->getGbaseAttribute("pages"); if (is_object($baseAttributes[0])) { $newPages = "278"; $baseAttributes[0]->text = $newPages; // Update the attribute type from "number" to "int" if ($baseAttributes[0]->type == "number") { $newType = "int"; $baseAttributes[0]->type = $newType; } } // Remove <g:label> attributes $baseAttributes = $entry->getGbaseAttribute("label"); foreach ($baseAttributes as $note) { $entry->removeGbaseAttribute($note);
642
Zend_Gdata
} // Add new attributes $entry->addGbaseAttribute("note", "PHP 5", "text"); $entry->addGbaseAttribute("note", "Web Programming", "text"); // Save the changes by invoking save() on the entry object itself $dryRun = true; $entry->save($dryRun); // Or, save the changes by calling updateGbaseItem() on the service object // $dryRun = true; // $service->updateGbaseItem($entry, $dryRun); After making the changes, either invoke save($dryRun) method on the Zend_Gdata_Gbase_ItemEntry object or call updateGbaseItem($entry, $dryRun) method on the Zend_Gdata_Gbase object to save the changes.
Delete an Item
You can remove an item by calling deleteGbaseItem() method:
$dryRun = false; $service->deleteGbaseItem($entry, $dryRun); Alternatively, you can invoke delete() on the Zend_Gdata_Gbase_ItemEntry object:
Authentication
The API provides authentication via AuthSub (recommended) and ClientAuth. HTTP connections must be authenticated for write support, but non-authenticated connections have read-only access.
643
Zend_Gdata
Before any transactions can occur, this connection needs to be made. Creating a connection to the Picasa servers involves two steps: creating an HTTP client and binding a Zend_Gdata_Photos service instance to that client.
Authentication
The Google Picasa API allows access to both public and private photo feeds. Public feeds do not require authentication, but are read-only and offer reduced functionality. Private feeds offers the most complete functionality but requires an authenticated connection to the Picasa servers. There are three authentication schemes that are supported by Google Picasa : ClientAuth provides direct username/password authentication to the Picasa servers. Since this scheme requires that users provide your application with their password, this authentication is only recommended when other authentication schemes are insufficient. AuthSub allows authentication to the Picasa servers via a Google proxy server. This provides the same level of convenience as ClientAuth but without the security risk, making this an ideal choice for web-based applications. The Zend_Gdata library provides support for both authentication schemes. The rest of this chapter will assume that you are familiar the authentication schemes available and how to create an appropriate authenticated connection. For more information, please see section the Authentication section of this manual or the Authentication Overview in the Google Data API Developer's Guide [http://code.google.com/apis/gdata/auth.html].
644
Zend_Gdata
* $_SERVER['HTTPS'] = (on|off|) * $_SERVER['HTTP_HOST'] = value of the Host: header * $_SERVER['SERVER_PORT'] = port number (only used if not http/80,https/443) * $_SERVER['REQUEST_URI'] = the URI after the method of the HTTP request * * @return string Current URL */ function getCurrentUrl() { global $_SERVER; /** * Filter php_self to avoid a security vulnerability. */ $php_request_uri = htmlentities(substr($_SERVER['REQUEST_URI'], 0, strcspn($_SERVER['REQUEST_URI'], "\n\r")), ENT_QUOTES); if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') { $protocol = 'https://'; } else { $protocol = 'http://'; } $host = $_SERVER['HTTP_HOST']; if ($_SERVER['SERVER_PORT'] != '' && (($protocol == 'http://' && $_SERVER['SERVER_PORT'] != '80') || ($protocol == 'https://' && $_SERVER['SERVER_PORT'] != '443'))) { $port = ':' . $_SERVER['SERVER_PORT']; } else { $port = ''; } return $protocol . $host . $port . $php_request_uri; } /** * Returns the AuthSub URL which the user must visit to authenticate requests * from this application. * * Uses getCurrentUrl() to get the next URL which the user will be redirected * to after successfully authenticating with the Google service. * * @return string AuthSub URL */ function getAuthSubUrl() { $next = getCurrentUrl(); $scope = 'http://picasaweb.google.com/data'; $secure = false; $session = true; return Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure, $session); } /** * Returns a HTTP client object with the appropriate headers for communicating
645
Zend_Gdata
* with Google using AuthSub authentication. * * Uses the $_SESSION['sessionToken'] to store the AuthSub session token after * it is obtained. The single use token supplied in the URL when redirected * after the user succesfully authenticated to Google is retrieved from the * $_GET['token'] variable. * * @return Zend_Http_Client */ function getAuthSubHttpClient() { global $_SESSION, $_GET; if (!isset($_SESSION['sessionToken']) && isset($_GET['token'])) { $_SESSION['sessionToken'] = Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']); } $client = Zend_Gdata_AuthSub::getHttpClient($_SESSION['sessionToken']); return $client; } /** * Create a new instance of the service, redirecting the user * to the AuthSub server if necessary. */ $service = new Zend_Gdata_Photos(getAuthSubHttpClient()); Finally, an unauthenticated server can be created for use with public feeds: // Create an instance of the service using an unauthenticated HTTP client $service = new Zend_Gdata_Photos();
646
Zend_Gdata
Projection sets the format of the data returned in the feed, as either "api" or "base". Normally, "api" is desired. The default is "api". Type sets the type of element to be returned, as either "feed" or "entry". The default is "feed". Access sets the visibility of items to be returned, as "all", "public", or "private". The default is "all". Non-public elements will only be returned if the query is searching for the authenticated user. Tag sets a tag filter for returned items. When a tag is set, only items tagged with this value will return. Kind sets the kind of elements to return. When kind is specified, only entries that match this value will be returned. ImgMax sets the maximum image size for entries returned. Only image entries smaller than this value will be returned. Thumbsize sets the thumbsize of entries that are returned. Any retrieved entry will have a thumbsize equal to this value. User sets the user whose data is being searched for. The default is "default". AlbumId sets the id of the album being searched for. This element only applies to album and photo queries. In the case of photo queries, this specifies the album that contains the requested photo. The album id is mutually exclusive with the album's name. Setting one unsets the other. AlbumName sets the name of the album being searched for. This element only applies to the album and photo queries. In the case of photo queries, this specifies the album that contains the requested photo. The album name is mutually exclusive with the album's id. Setting one unsets the other. PhotoId sets the id of the photo being searched for. This element only applies to photo queries.
Retrieving A User
The service supports retrieving a user feed and list of the user's content. If the requested user is also the authenticated user, entries marked as "hidden" will also be returned. The user feed can be accessed by passing the username to the getUserFeed method:
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); try { $userFeed = $service->getUserFeed("sample.user"); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); } Or, the feed can be accessed by constructing a query, first:
647
Zend_Gdata
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $query = new Zend_Gdata_Photos_UserQuery(); $query->setUser("sample.user"); try { $userFeed = $service->getUserFeed(null, $query); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); } Constructing a query also provides the ability to request a user entry object:
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $query = new Zend_Gdata_Photos_UserQuery(); $query->setUser("sample.user"); $query->setType("entry"); try { $userEntry = $service->getUserEntry($query); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); }
Retrieving An Album
The service supports retrieving an album feed and a list of the album's content. The album feed is accessed by constructing a query object and passing it to getAlbumFeed:
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $query = new Zend_Gdata_Photos_AlbumQuery(); $query->setUser("sample.user"); $query->setAlbumId("1"); try { $albumFeed = $service->getAlbumFeed($query); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); } Alternatively, the query object can be given an album name with setAlbumName. Setting the album name is mutually exclusive with setting the album id, and setting one will unset the other. Constructing a query also provides the ability to request an album entry object:
648
Zend_Gdata
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $query = new Zend_Gdata_Photos_AlbumQuery(); $query->setUser("sample.user"); $query->setAlbumId("1"); $query->setType("entry"); try { $albumEntry = $service->getAlbumEntry($query); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); }
Retrieving A Photo
The service supports retrieving a photo feed and a list of associated comments and tags. The photo feed is accessed by constructing a query object and passing it to getPhotoFeed: $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $query = new Zend_Gdata_Photos_PhotoQuery(); $query->setUser("sample.user"); $query->setAlbumId("1"); $query->setPhotoId("100"); try { $photoFeed = $service->getPhotoFeed($query); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); } Constructing a query also provides the ability to request a photo entry object: $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $query = new Zend_Gdata_Photos_PhotoQuery(); $query->setUser("sample.user"); $query->setAlbumId("1"); $query->setPhotoId("100"); $query->setType("entry"); try { $photoEntry = $service->getPhotoEntry($query); } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage();
649
Zend_Gdata
Retrieving A Comment
The service supports retrieving comments from a feed of a different type. By setting a query to return a kind of "comment", a feed request can return comments associated with a specific user, album, or photo. Performing an action on each of the comments on a given photo can be accomplished as follows: $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $query = new Zend_Gdata_Photos_PhotoQuery(); $query->setUser("sample.user"); $query->setAlbumId("1"); $query->setPhotoId("100"); $query->setKind("comment"); try { $photoFeed = $service->getPhotoFeed($query); foreach ($photoFeed as $entry) { if ($entry instanceof Zend_Gdata_Photos_CommentEntry) { // Do something with the comment } } } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); }
Retrieving A Tag
The service supports retrieving tags from a feed of a different type. By setting a query to return a kind of "tag", a feed request can return tags associated with a specific photo. Performing an action on each of the tags on a given photo can be accomplished as follows: $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $query = new Zend_Gdata_Photos_PhotoQuery(); $query->setUser("sample.user"); $query->setAlbumId("1"); $query->setPhotoId("100"); $query->setKind("tag"); try { $photoFeed = $service->getPhotoFeed($query); foreach ($photoFeed as $entry) { if ($entry instanceof Zend_Gdata_Photos_TagEntry) {
650
Zend_Gdata
// Do something with the tag } } } catch (Zend_Gdata_App_Exception $e) { echo "Error: " . $e->getMessage(); }
Creating Entries
The service has functions to create albums, photos, comments, and tags.
Creating An Album
The service supports creating a new album for an authenticated user:
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $entry = new Zend_Gdata_Photos_AlbumEntry(); $entry->setTitle($service->newTitle("test album")); $service->insertAlbumEntry($entry);
Creating A Photo
The service supports creating a new photo for an authenticated user:
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); // $photo is the name of a file uploaded via an HTML form $fd = $service->newMediaFileSource($photo["tmp_name"]); $fd->setContentType($photo["type"]); $entry = new Zend_Gdata_Photos_PhotoEntry(); $entry->setMediaSource($fd); $entry->setTitle($service->newTitle($photo["name"])); $albumQuery = new Zend_Gdata_Photos_AlbumQuery; $albumQuery->setUser("sample.user"); $albumQuery->setAlbumId("1"); $albumEntry = $service->getAlbumEntry($albumQuery); $service->insertPhotoEntry($entry, $albumEntry);
Creating A Comment
The service supports creating a new comment for a photo:
651
Zend_Gdata
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $entry = new Zend_Gdata_Photos_CommentEntry(); $entry->setTitle($service->newTitle("comment")); $entry->setContent($service->newContent("comment")); $photoQuery = new Zend_Gdata_Photos_PhotoQuery; $photoQuery->setUser("sample.user"); $photoQuery->setAlbumId("1"); $photoQuery->setPhotoId("100"); $photoQuery->setType('entry'); $photoEntry = $service->getPhotoEntry($photoQuery); $service->insertCommentEntry($entry, $photoEntry);
Creating A Tag
The service supports creating a new tag for a photo:
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $entry = new Zend_Gdata_Photos_TagEntry(); $entry->setTitle($service->newTitle("tag")); $photoQuery = new Zend_Gdata_Photos_PhotoQuery; $photoQuery->setUser("sample.user"); $photoQuery->setAlbumId("1"); $photoQuery->setPhotoId("100"); $photoQuery->setType('entry'); $photoEntry = $service->getPhotoEntry($photoQuery); $service->insertTagEntry($entry, $photoEntry);
Deleting Entries
The service has functions to delete albums, photos, comments, and tags.
Deleting An Album
The service supports deleting an album for an authenticated user:
652
Zend_Gdata
$albumQuery = new Zend_Gdata_Photos_AlbumQuery; $albumQuery->setUser("sample.user"); $albumQuery->setAlbumId("1"); $albumQuery->setType('entry'); $entry = $service->getAlbumEntry($albumQuery); $service->deleteAlbumEntry($entry, true);
Deleting A Photo
The service supports deleting a photo for an authenticated user:
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $photoQuery = new Zend_Gdata_Photos_PhotoQuery; $photoQuery->setUser("sample.user"); $photoQuery->setAlbumId("1"); $photoQuery->setPhotoId("100"); $photoQuery->setType('entry'); $entry = $service->getPhotoEntry($photoQuery); $service->deletePhotoEntry($entry, true);
Deleting A Comment
The service supports deleting a comment for an authenticated user:
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $photoQuery = new Zend_Gdata_Photos_PhotoQuery; $photoQuery->setUser("sample.user"); $photoQuery->setAlbumId("1"); $photoQuery->setPhotoId("100"); $photoQuery->setType('entry'); $path = $photoQuery->getQueryUrl() . '/commentid/' . "1000"; $entry = $service->getCommentEntry($path); $service->deleteCommentEntry($entry, true);
Deleting A Tag
The service supports deleting a tag for an authenticated user:
653
Zend_Gdata
$service = Zend_Gdata_Photos::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); $service = new Zend_Gdata_Photos($client); $photoQuery = new Zend_Gdata_Photos_PhotoQuery; $photoQuery->setUser("sample.user"); $photoQuery->setAlbumId("1"); $photoQuery->setPhotoId("100"); $photoQuery->setKind("tag"); $query = $photoQuery->getQueryUrl(); $photoFeed = $service->getPhotoFeed($query); foreach ($photoFeed as $entry) { if ($entry instanceof Zend_Gdata_Photos_TagEntry) { if ($entry->getContent() == $tagContent) { $tagEntry = $entry; } } } $service->deleteTagEntry($tagEntry, true);
654
Zend_Gdata
Authentication
The YouTube Data API allows read-only access to public data, which does not require authentication. For any write requests, a user needs to authenticate either using ClientLogin or AuthSub authentication. Please refer to the Authentication section in the PHP Developer's Guide [http://code.google.com/apis/youtube/ developers_guide_php.html#Authentication] for more detail.
655
Zend_Gdata
echo $videoEntry->getVideoDescription(); echo "\n\n\n"; } For more details on the different query parameters, please refer to the Reference Guide [http://code.google.com/apis/youtube/reference.html#Searching_for_videos]. The available helper functions in Zend_Gdata_YouTube_VideoQuery [http://framework.zend.com/apidoc/core/Zend_Gdata/ Zend_Gdata_YouTube_VideoQuery.html] for each of these parameters are described in more detail in the PHP Developer's Guide [http://code.google.com/apis/youtube/developers_guide_php.html#SearchingVideos].
656
Zend_Gdata
Alternatively, you could just retrieve the feed using the URL:
657
Zend_Gdata
echo $commentEntry->title->text . "\n"; echo $commentEntry->content->text . "\n\n\n"; } Comments can also be retrieved for a video if you have a copy of the Zend_Gdata_YouTube_VideoEntry [http:// framework.zend.com/apidoc/core/Zend_Gdata/Zend_Gdata_YouTube_VideoEntry.html] object:
Feed
of
Video
Comments
from
$yt = new Zend_Gdata_YouTube(); $videoEntry = $yt->getVideoEntry('abc123813abc'); // we don't know the video ID in this example, but we do have the URL $commentFeed = $yt->getVideoCommentFeed(null, $videoEntry->comments->href);
658
Zend_Gdata
659
Zend_Gdata
The code below creates a blank Zend_Gdata_YouTube_VideoEntry [http://framework.zend.com/apidoc/core/ Zend_Gdata/Zend_Gdata_YouTube_VideoEntry.html] to be uploaded. A Zend_Gdata_App_MediaFileSource [http://framework.zend.com/apidoc/core/Zend_Gdata/Zend_Gdata_App_MediaFileSource.html] object is then used to hold the actual video file. Under the hood, the Zend_Gdata_YouTube_Extension_MediaGroup [http:// framework.zend.com/apidoc/core/Zend_Gdata/Zend_Gdata_YouTube_Extension_MediaGroup.html] object is used to hold all of the video's meta-data. Our helper methods detailed below allow you to just set the video meta-data without having to worry about the media group object. The $uploadUrl is the location where the new entry gets posted to. This can be specified either with the $userName of the currently authenticated user, or, alternatively, you can simply use the string 'default' to refer to the currently authenticated user.
660
Zend_Gdata
} catch (Zend_Gdata_App_HttpException $httpException) { echo $httpException->getRawResponseBody(); } catch (Zend_Gdata_App_Exception $e) { echo $e->getMessage(); } To upload a video as private, simply use: $myVideoEntry->setVideoPrivate(); prior to performing the upload. $videoEntry->isVideoPrivate() can be used to check whether a video entry is private or not.
Browser-based upload
Browser-based uploading is performed almost identically to direct uploading, except that you do not attach a Zend_Gdata_App_MediaFileSource [http://framework.zend.com/apidoc/core/ Zend_Gdata/Zend_Gdata_App_MediaFileSource.html] object to the Zend_Gdata_YouTube_VideoEntry [http:// framework.zend.com/apidoc/core/Zend_Gdata/Zend_Gdata_YouTube_VideoEntry.html] you are constructing. Instead you simply submit all of your video's meta-data to receive back a token element which can be used to construct an HTML upload form.
661
Zend_Gdata
'</form>';
Other Functions
In addition to the functionality described above, the YouTube API contains many other functions that allow you to modify video meta-data, delete video entries and use the full range of community features on the site. Some of the community features that can be modified through the API include: ratings, comments, playlists, subscriptions, user profiles, contacts and messages. Please refer to the full documentation available in the PHP Developer's Guide [http://code.google.com/apis/youtube/ developers_guide_php.html] on code.google.com.
try { $client =
662
Zend_Gdata
Zend_Gdata_ClientLogin::getHttpClient($username, $password); } catch(Zend_Gdata_App_Exception $ex) { // Report the exception to the user die($ex->getMessage()); } The following exception subclasses are used by Zend_Gdata: Zend_Gdata_App_AuthException indicates that the user's account credentials were not valid. Zend_Gdata_App_BadMethodCallException indicates that a method was called for a service that does not support the method. For example, the CodeSearch service does not support post(). Zend_Gdata_App_HttpException indicates that an HTTP request was not successful. Provides the ability to get the full Zend_Http_Response object to determine the exact cause of the failure in cases where $e>getMessage() does not provide enough details. Zend_Gdata_App_InvalidArgumentException is thrown when the application provides a value that is not valid in a given context. For example, specifying a Calendar visibility value of "banana", or fetching a Blogger feed without specifying any blog name. Zend_Gdata_App_CaptchaRequiredException is thrown when a ClientLogin attempt receives a CAPTCHA challenge from the authentication service. This exception contains a token ID and a URL to a CAPTCHA challenge image. The image is a visual puzzle that should be displayed to the user. After collecting the user's response to the challenge image, the response can be included with the next ClientLogin attempt.The user can alternatively be directed to this website: https://www.google.com/accounts/DisplayUnlockCaptcha Further information can be found in the ClientLogin documentation. You can use these exception subclasses to handle specific exceptions differently. See the API documentation for information on which exception subclasses are thrown by which methods in Zend_Gdata.
try { $client = Zend_Gdata_ClientLogin::getHttpClient($username, $password, $service); } catch(Zend_Gdata_App_AuthException $authEx) { // The user's credentials were incorrect. // It would be appropriate to give the user a second try. ... } catch(Zend_Gdata_App_HttpException $httpEx) { // Google Data servers cannot be contacted. die($httpEx->getMessage);}
663
664
Using Zend_Http_Client
The class constructor optionally accepts a URL as its first parameter (can be either a string or a Zend_Uri_Http object), and an array or Zend_Config object containing configuration options. Both can be left out, and set later using the setUri() and setConfig() methods.
Nota
Zend_Http_Client uses Zend_Uri_Http to validate URLs. This means that some special characters like the pipe symbol ('|') or the caret symbol ('^') will not be accepted in the URL by default. This can be modified by setting the 'allow_unwise' option of Zend_Uri to 'true'. See the section called Allowing "Unwise" characters in URIs for more information.
Configuration Parameters
The constructor and setConfig() method accept an associative array of configuration parameters, or a Zend_Config object. Setting these parameters is optional, as they all have default values.
665
Zend_Http
Parameter strict
Description
Expected Values
Whether perform validation boolean on header names. When set to false, validation functions will be skipped. Usually this should not be changed Whether to strictly follow boolean the RFC when redirecting (see the section called HTTP Redirections) User agent identifier string string (sent in request headers) Connection (seconds) timeout integer
strictredirects
false
HTTP protocol version string (usually '1.1' or '1.0') Connection adapter class mixed to use (see the section called Zend_Http_Client Connection Adapters) Whether to enable keep- boolean alive connections with the server. Useful and might improve performance if several consecutive requests to the same server are performed. Whether to store boolean last response for later retrieval with getLastResponse(). If set to false getLastResponse() will return null.
keepalive
false
storeresponse
true
666
Zend_Http
If no method is specified, the method set by the last setMethod() call is used. If setMethod() was never called, the default request method is GET (see the above example).
667
Zend_Http
Note that when sending POST requests, you can set both GET and POST parameters. On the other hand, while setting POST parameters for a non-POST request will not trigger and error, it is useless. Unless the request is a POST request, POST parameters are simply ignored.
Ejemplo 25.6. Forcing RFC 2616 Strict Redirections on 301 and 302 Responses
// Strict Redirections $client->setConfig(array('strictredirects' => true)); // Non-strict Redirections $client->setConfig(array('strictredirects' => false)); You can always get the number of redirections done after sending a request using the getRedirectionsCount() method.
668
Zend_Http
$cookie = Zend_Http_Cookie::fromString('flavor=chocolate%20chips'); $client->setCookie($cookie); For more information about Zend_Http_Cookie objects, see the section called Zend_Http_Cookie and Zend_Http_CookieJar. Zend_Http_Client also provides the means for cookie stickiness - that is having the client internally store all sent and received cookies, and resend them automatically on subsequent requests. This is useful, for example when you need to log in to a remote site first and receive and authentication or session ID cookie before sending further requests.
669
Zend_Http
setHeader() can also be easily used to set multiple headers in one call, by providing an array of headers as a single parameter:
File Uploads
You can upload files through HTTP using the setFileUpload method. This method takes a file name as the first parameter, a form name as the second parameter, and data as a third optional parameter. If the third data parameter is null, the first file name parameter is considered to be a real file on disk, and Zend_Http_Client will try to read this file and upload it. If the data parameter is not null, the first file name parameter will be sent as the file name, but no actual file needs to exist on the disk. The second form name parameter is always required, and is equivalent to the "name" attribute of an >input< tag, if the file was to be uploaded through an HTML form. A fourth optional parameter provides the file's content-type. If not specified, and Zend_Http_Client reads the file from the disk, the mime_content_type function will be used to guess the file's content type, if it is available. In any case, the default MIME type will be application/octet-stream.
Uploading files
When uploading files, the HTTP request content-type is automatically set to multipart/form-data. Keep in mind that you must send a POST or PUT request in order to upload files. Most servers will ignore the requests body on other request methods.
670
Zend_Http
HTTP Authentication
Currently, Zend_Http_Client only supports basic HTTP authentication. This feature is utilized using the setAuth() method, or by specifying a username and a password in the URI. The setAuth() method takes 3 parameters: The user name, the password and an optional authentication type parameter. As mentioned, currently only basic authentication is supported (digest authentication support is planned).
671
Zend_Http
When performing several requests to the same host, it is highly recommended to enable the 'keepalive' configuration flag. This way, if the server supports keep-alive connections, the connection to the server will only be closed once all requests are done and the Client object is destroyed. This prevents the overhead of opening and closing TCP connections to the server. When you perform several requests with the same client, but want to make sure all the request-specific parameters are cleared, you should use the resetParameters() method. This ensures that GET and POST parameters, request body and request-specific headers are reset and are not reused in the next request.
Resetting parameters
Note that non-request specific headers are not reset when the resetParameters method is used. As a matter of fact, only the 'Content-length' and 'Content-type' headers are reset. This allows you to set-and-forget headers like 'Accept-language' and 'Accept-encoding' Another feature designed specifically for consecutive requests is the Cookie Jar object. Cookie Jars allow you to automatically save cookies set by the server in the first request, and send them on consecutive requests transparently. This allows, for example, going through an authentication request before sending the actual data fetching request. If your application requires one authentication request per user, and consecutive requests might be performed in more than one script in your application, it might be a good idea to store the Cookie Jar object in the user's session. This way, you will only need to authenticate the user once every session.
672
Zend_Http
673
Zend_Http
It is recommended to use persistent TCP connections only if you connect to the same server very frequently, and are sure that the server is capable of handling a large number of concurrent connections. In any case you are encouraged to benchmark the effect of persistent connections on both the client speed and server load before using this option. Additionally, when using persistent connections it is recommended to enable Keep-Alive HTTP requests as described in the section called Configuration Parameters - otherwise persistent connections might have little or no effect.
Ejemplo 25.16. Setting stream context options for the Socket adapter
674
Zend_Http
// Array of options $options = array( 'socket' => array( // Bind local socket side to a specific interface 'bindto' => '10.1.2.3:50505' ), 'ssl' => array( // Verify server side certificate, // do not accept invalid or self-signed SSL certificates 'verify_peer' => true, 'allow_self_signed' => false, // Capture the peer's certificate 'capture_peer_cert' => true ) ); // Create an adapter object and attach it to the HTTP client $adapter = new Zend_Http_Client_Adapter_Socket(); $client = new Zend_Http_Client(); $client->setAdapter($adapter); // Method 1: pass the options array to setStreamContext() $adapter->setStreamContext($options); // Method 2: create a stream context and pass it to setStreamContext() $context = stream_context_create($options); $adapter->setStreamContext($context); // Method 3: get the default stream context and set the options on it $context = $adapter->getStreamContext(); stream_context_set_option($context, $options); // Now, preform the request $response = $client->request(); // If everything went well, you can now access the context again $opts = stream_context_get_options($adapter->getStreamContext()); echo $opts['ssl']['peer_certificate'];
Nota
Note that you must set any stream context options before using the adapter to preform actual requests. If no context is set before preforming HTTP requests with the Socket adapter, a default stream context will be created. This context resource could be accessed after preforming any requests using the getStreamContext() method.
675
Zend_Http
Using the Proxy adapter requires several additional configuration parameters to be set, in addition to the default 'adapter' option:
Proxy user name, if required string Proxy password, if required string Proxy HTTP authentication string type
Zend_Http_Client::AUTH_BASIC (default)
proxy_host should always be set - if it is not set, the client will fall back to a direct connection using Zend_Http_Client_Adapter_Socket. proxy_port defaults to '8080' - if your proxy listens on a different port you must set this one as well. proxy_user and proxy_pass are only required if your proxy server requires you to authenticate. Providing these will add a 'Proxy-Authentication' header to the request. If your proxy does not require authentication, you can leave these two options out. proxy_auth sets the proxy authentication type, if your proxy server requires authentication. Possibly values are similar to the ones accepted by the Zend_Http_Client::setAuth() method. Currently, only basic authentication (Zend_Http_Client::AUTH_BASIC) is supported.
Nota
Since the proxy adapter inherits from Zend_Http_Client_Adapter_Socket, you can use the stream context access method (see the section called Customizing and accessing the Socket adapter stream context) to set stream context options on Proxy connections as demonstrated above.
676
Zend_Http
$putFileSize = filesize("filepath"); $putFileHandle = fopen("filepath", "r"); $adapter = new Zend_Http_Client_Adapter_Curl(); $client = new Zend_Http_Client(); $client->setAdapter($adapter); $adapter->setConfig(array( 'curloptions' => array( CURLOPT_INFILE => $putFileHandle, CURLOPT_INFILESIZE => $putFileSize ) )); $client->request("PUT");
677
Zend_Http
678
Zend_Http
// Set the next successive response $adapter->addResponse( "HTTP/1.1 200 OK" . "\r\n" . "Content-Type: text/html" . "\r\n" . "\r\n" . '<html>' . ' <head><title>My Pet Store Home Page</title></head>' . ' <body><p>...</p></body>' . '</html>'); // inject the http client object ($client) into your object // being tested and then test your object's behavior below The setResponse() method clears any responses in the Zend_Http_Client_Adapter_Test's buffer and sets the first response that will be returned. The addResponse() method will add successive responses. The responses will be replayed in the order that they were added. If more requests are made than the number of responses stored, the responses will cycle again in order. In the example above, the adapter is configured to test your object's behavior when it encounters a 302 redirect. Depending on your application, following a redirect may or may not be desired behavior. In our example, we expect that the redirect will be followed and we configure the test adapter to help us test this. The initial 302 response is set up with the setResponse() method and the 200 response to be returned next is added with the addResponse() method. After configuring the test adapter, inject the HTTP client containing the adapter into your object under test and test its behavior. If you need the adapter to fail on demand you can use setNextRequestWillFail($flag). The method will cause the next call to connect() to throw an Zend_Http_Client_Adapter_Exception exception. This can be useful when your application caches content from an external site (in case the site goes down) and you want to test this feature.
// Further requests will work as expected until you call setNextRequestWillFail(true) again
679
Zend_Http
680
Zend_Http
// Send request to the remote server. // This function is expected to return the full request // (headers and body) as a string } /** * Read response from server * * @return string */ public function read() { // Read response from remote server and return it as a string } /** * Close the connection to the server * */ public function close() { // Close the connection to the remote server - called last. } } // Then, you could use this adapter: $client = new Zend_Http_Client(array( 'adapter' => 'MyApp_Http_Client_Adapter_BananaProtocol' ));
681
Zend_Http
$name: The name of the cookie (eg. 'PHPSESSID') (required) $value: The value of the cookie (required) $domain: The cookie's domain (eg. '.example.com') (required) $expires: Cookie expiration time, as UNIX time stamp (optional, defaults to null). If not set, cookie will be treated as a 'session cookie' with no expiration time. $path: Cookie path, eg. '/foo/bar/' (optional, defaults to '/') $secure: Boolean, Whether the cookie is to be sent over secure (HTTPS) connections only (optional, defaults to boolean FALSE) By calling the fromString() static method, with a cookie string as represented in the 'Set-Cookie' HTTP response header or 'Cookie' HTTP request header. In this case, the cookie value must already be encoded. When the cookie string does not contain a 'domain' part, you must provide a reference URI according to which the cookie's domain and path will be set.
Nota
When instantiating a cookie object using the Zend_Http_Cookie::fromString() method, the cookie value is expected to be URL encoded, as cookie strings should be. However, when using the constructor, the cookie value string is expected to be the real, decoded value. A cookie object can be transferred back into a string, using the __toString() magic method. This method will produce a HTTP request "Cookie" header string, showing the cookie's name and value, and terminated by a semicolon (';'). The value will be URL encoded, as expected in a Cookie header:
682
Zend_Http
$cookie = new Zend_Http_Cookie('foo', 'two words', '.example.com', time() + 7200, '/path'); // Will print out 'foo=two+words;' : echo $cookie->__toString(); // This is actually the same: echo (string) $cookie; // In PHP 5.2 and higher, this also works: echo $cookie;
683
Zend_Http
// // // //
echo date('Y-m-d', $cookie->getExpiryTime()); // Will echo '2005-02-28' echo ($cookie->isExpired() ? 'Yes' : 'No'); // Will echo 'Yes' echo ($cookie->isExpired(strtotime('2005-01-01') ? 'Yes' : 'No'); // Will echo 'No' echo ($cookie->isSessionCookie() ? 'Yes' : 'No'); // Will echo 'No'
684
Zend_Http
$cookie->match('https://example.com/foo.php'); // Will return false, because the path is wrong $cookie->match('https://www.example.com/somedir/foo.php', false); // Will return false, because session cookies are not matched $cookie->match('https://sub.domain.example.com/somedir/otherdir/foo.php'); // Will return true // Create another cookie object - now, not secure, with expiration time // in two hours $cookie = Zend_Http_Cookie::fromString('foo=two+words; ' + 'domain=www.example.com; ' + 'expires=' . date(DATE_COOKIE, time() + 7200)); $cookie->match('http://www.example.com/'); // Will return true $cookie->match('https://www.example.com/'); // Will return true - non secure cookies can go over secure connections // as well! $cookie->match('http://subdomain.example.com/'); // Will return false, because the domain is wrong $cookie->match('http://www.example.com/', true, time() + (3 * 3600)); // Will return false, because we added a time offset of +3 hours to // current time
685
Zend_Http
Zend_Http_CookieJar->addCookiesFromResponse($response, $ref_uri): Add all cookies set in a single HTTP response to the jar. $response is expected to be a Zend_Http_Response object with SetCookie headers. $ref_uri is the request URI, either as a string or a Zend_Uri_Http object, according to which the cookies' default domain and path will be set.
686
Zend_Http
Zend_Http_Response
Introduction
Zend_Http_Response provides easy access to an HTTP responses message, as well as a set of static methods for parsing HTTP response messages. Usually, Zend_Http_Response is used as an object returned by a Zend_Http_Client request. In most cases, a Zend_Http_Response object will be instantiated using the factory() method, which reads a string containing an HTTP response message, and returns a new Zend_Http_Response object:
687
Zend_Http
Boolean isRedirect(): Whether the response is a redirection response or not. Returns TRUE for HTTP 3xx response codes
Accessor Methods
The main goal of the response object is to provide easy access to various response parameters. int getStatus(): Get the HTTP response status code (eg. 200, 504, etc.) string getMessage(): Get the HTTP response status message (eg. "Not Found", "Authorization Required") string getBody(): Get the fully decoded HTTP response body string getRawBody(): Get the raw, possibly encoded HTTP response body. If the body was decoded using GZIP encoding for example, it will not be decoded. array getHeaders(): Get the HTTP response headers as an associative array (eg. 'Content-type' => 'text/html') string|array getHeader($header): Get a specific HTTP response header, specified by $header string getHeadersAsString($status_line = true, $br = "\n"): Get the entire set of headers as a string. If $status_line is true (default), the first status line (eg. "HTTP/1.1 200 OK") will also be returned. Lines are broken with the $br parameter (Can be, for example, "<br />") string asString($br = "\n"): Get the entire response message as a string. Lines are broken with the $br parameter (Can be, for example, "<br />"). You can also use the magic method __toString() when casting the object as a string. It will then proxy to asString()
688
Zend_Http
689
690
<form action="http://example.com/server" method="POST"> <input type='image' src='/images/ic.png' align='center' width='120px' style='cursor:pointer' /> <object type="application/x-informationCard" name="xmlToken"> <param name="tokenType" value="urn:oasis:names:tc:SAML:1.0:assertion" /> <param name="requiredClaims" value="http://.../claims/privatepersonalidentifier http://.../claims/givenname http://.../claims/surname" /> </object> </form> In the example above, the requiredClaims <param> tag is used to identify pieces of information known as claims (i.e. person's first name, last name) which the web site (a.k.a "relying party") needs in order a user to authenticate using an information card. For your reference, the full URI (for instance the givenname claim) is as follows: http:// schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname When the above HTML is activated by a user (clicks on it), the browser will bring up a card selection program which not only shows them which information cards meet the requirements of the site, but also allows them to select which information card to use if multiple meet the criteria. This information card is transmitted as an XML document to the specified POST URL and is ready to be processed by the Zend_InfoCard component. Note, Information cards can only be HTTP POSTed to SSL-encrypted URLs. Please consult your web server's documentation on how to set up SSL encryption.
691
Zend_InfoCard
<?php if (isset($_POST['xmlToken'])) { $adapter = new Zend_Auth_Adapter_InfoCard($_POST['xmlToken']); $adapter->addCertificatePair('/usr/local/Zend/apache2/conf/server.key', '/usr/local/Zend/apache2/conf/server.crt'); $auth = Zend_Auth::getInstance(); $result = $auth->authenticate($adapter); switch ($result->getCode()) { case Zend_Auth_Result::SUCCESS: $claims = $result->getIdentity(); print "Given Name: {$claims->givenname}<br />"; print "Surname: {$claims->surname}<br />"; print "Email Address: {$claims->emailaddress}<br />"; print "PPI: {$claims->getCardID()}<br />"; break; case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID: print "The Credential you provided did not pass validation"; break; default: case Zend_Auth_Result::FAILURE: print "There was an error processing your credentials."; break; } if (count($result->getMessages()) > 0) { print "<pre>"; var_dump($result->getMessages()); print "</pre>"; } } ?> <hr /> <div id="login" style="font-family: arial; font-size: 2em;"> <p>Simple Login Demo</p> <form method="post"> <input type="submit" value="Login" /> <object type="application/x-informationCard" name="xmlToken"> <param name="tokenType" value="urn:oasis:names:tc:SAML:1.0:assertion" /> <param name="requiredClaims" value="http://.../claims/givenname http://.../claims/surname http://.../claims/emailaddress http://.../claims/privatepersonalidentifier" /> </object> </form> </div>
692
Zend_InfoCard
In the example above, we first create an instance of the Zend_Auth_Adapter_InfoCard and pass the XML data posted by the card selector into it. Once an instance has been created you must then provide at least one SSL certificate public/private key pair used by the web server that received the HTTP POST. These files are used to validate the destination of the information posted to the server and are a requirement when using Information Cards. Once the adapter has been configured, you can then use the standard Zend_Auth facilities to validate the provided information card token and authenticate the user by examining the identity provided by the getIdentity() method.
<?php if (isset($_POST['xmlToken'])) { $infocard = new Zend_InfoCard(); $infocard->addCertificatePair('/usr/local/Zend/apache2/conf/server.key', '/usr/local/Zend/apache2/conf/server.crt'); $claims = $infocard->process($_POST['xmlToken']); if($claims->isValid()) { print "Given Name: {$claims->givenname}<br />"; print "Surname: {$claims->surname}<br />"; print "Email Address: {$claims->emailaddress}<br />"; print "PPI: {$claims->getCardID()}<br />"; } else { print "Error Validating identity: {$claims->getErrorMsg()}"; } } ?> <hr /> <div id="login" style="font-family: arial; font-size: 2em;"> <p>Simple Login Demo</p> <form method="post"> <input type="submit" value="Login" /> <object type="application/x-informationCard" name="xmlToken"> <param name="tokenType" value="urn:oasis:names:tc:SAML:1.0:assertion" /> <param name="requiredClaims" value="http://.../claims/givenname http://.../claims/surname http://.../claims/emailaddress http://.../claims/privatepersonalidentifier" /> </object> </form> </div> In the example above, we use the Zend_InfoCard component independently to validate the token provided by the user. As was the case with the Zend_Auth_Adapter_InfoCard, we create an instance of Zend_InfoCard and then set one or more SSL certificate public/private key pairs used by the web server. Once configured, we can use the process() method to process the information card and return the results.
693
Zend_InfoCard
// ... public function submitinfocardAction() { if (!isset($_REQUEST['xmlToken'])) { throw new ZBlog_Exception('Expected an encrypted token ' . 'but was not provided'); } $infoCard = new Zend_InfoCard(); $infoCard->addCertificatePair(SSL_CERTIFICATE_PRIVATE, SSL_CERTIFICATE_PUB); try { $claims = $infoCard->process($request['xmlToken']); } catch(Zend_InfoCard_Exception $e) { // TODO Error processing your request throw $e; } if ($claims->isValid()) { $db = ZBlog_Data::getAdapter();
694
Zend_InfoCard
$ppi = $db->quote($claims->getCardID()); $fullname = $db->quote("{$claims->givenname} {$claims->surname}"); $query = "UPDATE blogusers SET ppi = $ppi, real_name = $fullname WHERE username='administrator'"; try { $db->query($query); } catch(Exception $e) { // TODO Failed to store in DB } $this->view->render(); return; } else { throw new ZBlog_Exception("Infomation card failed security checks"); } }
class myAdapter implements Zend_InfoCard_Adapter_Interface { public function storeAssertion($assertionURI, $assertionID, $conditions) { /* Store the assertion and its conditions by ID and URI */ } public function retrieveAssertion($assertionURI, $assertionID) { /* Retrieve the assertion by URI and ID */ } public function removeAssertion($assertionURI, $assertionID)
695
Zend_InfoCard
696
Uso Bsico
El uso de Zend_Json consiste en utilizar los Zend_Json::encode() y Zend_Json::decode(). dos mtodos pblicos estticos disponibles:
// Recuperar un valor: $phpNative = Zend_Json::decode($encodedValue); // Codificarlo para regresarlo al cliente: $json = Zend_Json::encode($phpNative);
697
Zend_Json
// Decodifica objetos JSON como objetos PHP $phpNative = Zend_Json::decode($encodedValue, Zend_Json::TYPE_OBJECT); Por lo tanto, cualquiera de los objetos decodificados son devueltos como objetos StdClass con propiedades correspondientea a pares clave/valor en la notacin JSON. La recomendacin de Zend Framework es que el desarrollador debe decidir cmo decodificar objetos JSON. Si debe crearse un objeto de un determinado tipo, puede ser creado en el cdigo del desarrollador y alimentado con datos de los valores decodificados utilizando Zend_Json.
Codificador/Decodificador Interno
Zend_Json tiene dos modos diferentes dependiendo de si ext/json est habilitada o no en su instalacin PHP. Si ext/ json est instalado por defecto, las funciones json_encode() y json_decode() se utilizan para la codificacin y decodificacin JSON. Si ext/json no est instalado, una implementacin de Zend Framework en cdigo PHP es utilizada para la codificacin/decodificacin. Esto es considerablemente ms lento que usando la extensin de PHP, pero se comporta exactamente igual. Tambin algunas veces puede querer utilizar el codificador/decodificador interno incluso si tiene ext/json instalado. Puede hacer esto llamando a:
Zend_Json::$useBuiltinEncoderDecoder = true:
Expresiones JSON
Javascript hace uso intenso de las funciones annimas de llamadas de retorno, que pueden guardarse en variables del objeto JSON. Aunque solo funcionan si no regresaron dentro comillas dobles, que es lo que hace naturalmente Zend_Json. Con la Expression de apoyo para Zend_Json este apoyo puede codificar objetos JSON con callbacks validos de javascript. Esto funciona tanto con json_encode() como con el codificador interno. Un callback javascript se representa usando el objero Zend_Json_Expr. Este implementa el patrn del objeto valor y es inmutable. Se puede establecer la expresin de javascript como el primer argumento del constructor. Por defecto Zend_Json::encode no codifica callbacks javascript, usted tiene que pasar la opcin 'enableJsonExprFinder' = true dentro de la funcin encode. Si se habilita, la expresin de apoyo trabaja para todas las expresiones anidadas en grandes estructuras de objetos. Un ejemplo de uso se vera as:
$data = array( 'onClick' => new Zend_Json_Expr('function() {' . 'alert("Yo soy un callback vlido de javascript ' . 'creado por Zend_Json"); }'), 'other' => 'sin expresin', ); $jsonObjectWithExpression = Zend_Json::encode( $data, false, array('enableJsonExprFinder' => true)
698
Zend_Json
);
// la funcin fromXml simplemente toma un string conteniendo XML // como entrada. $jsonContents = Zend_Json::fromXml($xmlStringContents, true); Zend_Json::fromXml() funcin que hace la conversin del parmetro de entrada formateado como un string XML y devuelve el string de salida equivalente formateado a JSON. En caso de cualquier entrada con formato XML errneo o un error en la lgica de conversin, esta funcin arrojar una excepcin. La conversin lgica tambin usa tcnicas recursivas para recorrer el rbol XML. Soporta una recursin de hasta 25 niveles de profundidad. Ms all de esa profundidad, arrojar una Zend_Json_Exception. Hay varios archivos XML con diversos grados de complejidad provistas en el directorio de tests de Zend Framework. Se pueden utilizar para probar la funcionalidad de la caracterstica xml2json. El siguiente es un ejemplo simple que muestra tanto el string de entrada XML pasado a y al string JSON de salida devuelto como resultado de la funcin Zend_Json::fromXml(). Este ejemplo utiliz el parmetro de la funcin opcional como para no ignorar los atributos XML durante la conversin. Por lo tanto, puede notar que el string resultante JSON incluye una representacin de los atributos XML presentes en el string de entrada XML. String de entrada XML pasada a la funcin Zend_Json::fromXml():
<?xml version="1.0" encoding="UTF-8"?> <books> <book id="1"> <title>Code Generation in Action</title> <author><first>Jack</first><last>Herrington</last></author> <publisher>Manning</publisher> </book> <book id="2"> <title>PHP Hacks</title> <author><first>Jack</first><last>Herrington</last></author> <publisher>O'Reilly</publisher> </book> <book id="3"> <title>Podcasting Hacks</title> <author><first>Jack</first><last>Herrington</last></author> <publisher>O'Reilly</publisher>
699
Zend_Json
{ "books" : { "book" : [ { "@attributes" : { "id" : "1" }, "title" : "Code Generation in Action", "author" : { "first" : "Jack", "last" : "Herrington" }, "publisher" : "Manning" }, { "@attributes" : { "id" : "2" }, "title" : "PHP Hacks", "author" : { "first" : "Jack", "last" : "Herrington" }, "publisher" : "O'Reilly" }, { "@attributes" : { "id" : "3" }, "title" : "Podcasting Hacks", "author" : { "first" : "Jack", "last" : "Herrington" }, "publisher" : "O'Reilly" } ]} } Ms detalles sobre esta caracterstica xml2json pueden encontrarse en la propuesta original. Eche un vistazo a la Zend_xml2json proposal [http://tinyurl.com/2tfa8z].
700
Zend_Json
Agrega una o ms funciones y/o clases/objetos al objeto servidor para handle() -- maneja -- el requerimiento Zend_Json_Server utiliza the section called Zend_Server_Reflection para realizar reflexin sobre cualquiera de las clases o funciones agregadas, y utiliza esa informacin para construir tanto la SMD y hacer cumplir el mtodo de llamado de firmas. Como tal, es imperativo que cualquier de las funciones agregadas y/o los mtodos de clase tengan mnimamente una plena documentacin de PHP docblocks: Todos los parmetros y sus tipos de variables esperados El tipo de variable del valor de retorno Zend_Json_Server escucha por solicitudes POST nicamente en este momento; afortunadamente, la mayora de las implementaciones del cliente JSON-RPC en los medios en el momento de escribir esto, slo requieren a POST como es. Esto hace que sea fcil de utilizar el mismo punto final del servidor para manejar a ambas peticiones as como para entregar el servicio SMD, como se muestra en el siguiente ejemplo.
/** * Calculator - clase de ejemplo para exponer via JSON-RPC */ class Calculator { /** * Devuelve la suma de dos variables * * @param int $x * @param int $y * @return int */ public function add($x, $y) { return $x + $y; } /** * Devuelve la diferencia de dos variables * * @param int $x * @param int $y * @return int */ public function subtract($x, $y) { return $x - $y; } /** * Devuelve el producto de dos variables
701
Zend_Json
* * @param int $x * @param int $y * @return int */ public function multiply($x, $y) { return $x * $y; } /** * Devuelve la divisin de dos variables * * @param int $x * @param int $y * @return float */ public function divide($x, $y) { return $x / $y; } } Ntese que cada mtodo tiene un docblock con entradas indicando cada parmetro y su tipo, as como una entrada para el valor de retorno. Esto es absolutamente crtico cuando se usa Zend_Json_Server -- o cualquier otro componente del servidor en Zend Framework, por esa cuestin. Ahora, crearemos un script para manejar las peticiones:
$server = new Zend_Json_Server(); // Indicar que funcionalidad est disponible: $server->setClass('Calculator'); // Manejar el requerimiento: $server->handle(); Sin embargo, esto no soluciona el problema de devolucin de un SMD para que el cliente JSON-RPC pueda autodescubrir los mtodos. Esto puede lograrse determinando el mtodo del requerimiento HTTP, y luego especificando algn servidor de metadatos:
$server = new Zend_Json_Server(); $server->setClass('Calculator'); if ('GET' == $_SERVER['REQUEST_METHOD']) { // Indica el punto final de la URL, y la versin en uso de JSON-RPC: $server->setTarget('/json-rpc.php') ->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2); // Capturar el SMD $smd = $server->getServiceMap(); // Devolver el SMD al cliente
702
Zend_Json
header('Content-Type: application/json'); echo $smd; return; } $server->handle(); Si utiliza el servidor JSON-RPC con Dojo toolkit, tambin necesitar establecer un flag de compatibilidad especial para garantizar que los dos interoperen correctamente:
$server = new Zend_Json_Server(); $server->setClass('Calculator'); if ('GET' == $_SERVER['REQUEST_METHOD']) { $server->setTarget('/json-rpc.php') ->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2); $smd = $server->getServiceMap(); // Establecer la compatibilidad con Dojo: $smd->setDojoCompatible(true); header('Content-Type: application/json'); echo $smd; return; } $server->handle();
Detalles Avanzados
Aunque la mayor funcionalidad de Zend_Json_Server se puntualiza en Ejemplo 27.1, Uso de Zend_Json_Server, hay ms funcionalidad avanzada disponible.
Zend_Json_Server
Zend_Json_Server es la clase ncleo en la propuesta JSON-RPC; que maneja todas las peticiones y como respuesta devuelve un conjunto de datos. Tiene los siguientes mtodos: addFunction($function): Especifica la funcin de espacio del usuario para agregar al servidor. setClass($class): Especifica una clase u objeto para agregar al servidor; todos los mtodos pblicos de ese item sern expuestos como mtodos JSON-RPC. fault($fault = null, Zend_Json_Server_Error. $code = 404, $data = null): Crea y devuelve un objeto
handle($request = false): Maneja una solicitud JSON-RPC; opcionalmente, pasa un objeto Zend_Json_Server_Request a utlizar (crea uno por defecto). getFunctions(): Devuelve una lista de todos los mtodos agregados. setRequest(Zend_Json_Server_Request $request): Especifica un objeto solicitud para el servidor a utilizar.
703
Zend_Json
getRequest(): Recupera el objeto solicitud usado por el servidor. setResponse(Zend_Json_Server_Response servidor a utilizar. $response): Establece el objeto respuesta para el
getResponse(): Recupera el objeto respuesta usado por el servidor. setAutoEmitResponse($flag): Indica si el servidor debera emitir automticamente la respuesta y todas las cabeceras; por defecto, esto es verdadero. autoEmitResponse(): Determina si la auto-emisin de la respuesta est habilitada. getServiceMap(): Recupera la descripcin del mapa de servicio en el form de un objeto Zend_Json_Server_Smd.
Zend_Json_Server_Request
El medio ambiente de una solicitud JSON-RPC est encapsulado en el objeto Zend_Json_Server_Request. Este objeto le permite establecer porciones necesarias de la solicitud JSON-RPC, incluida el ID de la solicitud, parmetros y especificaciones de la versin JSON-RPC. Tiene la capacidad de cargarse a s mismo via JSON o un conjunto de opciones, y puede mostrase a si mismo como JSON va el mtodo toJson(). El objeto solicitud tiene los siguientes mtodos disponibles: setOptions(array $options): Especifica la configuracin del objeto. $options puede contener claves que concuerden con cualuier mtodo 'set': setParams(), setMethod(), setId(), y setVersion(). addParam($value, $key = null): Agrega un parmetro para usar con el mtodo de llamada. Los parmetros pueden ser slo los valores, o pueden incluir opcionalmente el nombre del parmetro. addParams(array $params): Agrega mltiples parmetros a la vez; proxies a addParam() setParams(array parmetros existentes. $params): Establece todos los parmetros a la vez; sobrescribe cualquiera de los
getParam($index): Recupera un parmetro por posicin o por el nombre. getParams(): Recupera todos los parmetros a la vez. setMethod($name): Establece el mtodo para llamar. getMethod(): Recupera el mtodo que ser llamado. isMethodError(): Determinar si la solicitud est malformada o no y si dara como resultado un error. setId($name): Establecer el identificador de solicitud(utilizado por el cliente para igualar las solicitudes de respuestas). getId(): Recuperar el identificador de solicitudes. setVersion($version): Establecer la versin de la especificacin JSON-RPC que conforma la solicitud. Puede ser '1.0' o '2.0'. getVersion(): Recuperar la versin de la especificacin JSON-RPC utilizados por la solicitud. loadJson($json): Cargar el objeto solicitud de una cadena JSON. toJson(): Mostrar la solicitud como un string JSON.
704
Zend_Json
Una versin especfica de HTTP est disponible a travs de Zend_Json_Server_Request_Http. Esta clase podr recuperar la solicitud via php://input, y permite el acceso JSON sin procesar va el mtodo getRawJson().
Zend_Json_Server_Response
La respuesta del conjunto de datos JSON-RPC es encapsulada en el objeto Zend_Json_Server_Response. Este objeto le permite ajustar el valor de retorno de la solicitud, siendo la respuesta un error o no, el identificador de solicitud, con que versin de especificacin esta conformada la respuesta de JSON-RPC, y, opcionalmente el mapa de servicio. El objeto respuesta tiene los siguientes mtodos disponibles: setResult($value): Establecer el resultado de la respuesta. getResult(): Recuperar el resultado de la respuesta. setError(Zend_Json_Server_Error $error): Establecer un objeto error. Si ya est, este ser utilizado como la respuesta cuando se serialize a JSON. getError(): Recuperar el objeto error, si lo hubiera. isError(): Si la respuesta es una respuesta de error o no. setId($name): Establecer el identificador de solicitud (de manera que la respuesta del cliente pueda coincidir con la solicitud original). getId(): Recuperar el identificador de solicitud. setVersion($version): Establecer la versin JSON-RPC con la que deba estar conformada la respuesta. getVersion(): Recuperar la versin JSON-RPC con la cumple la respuesta. toJson(): Serializar la respuesta a JSON. Si la respuesta es una respuesta de error, serializar el objeto error. setServiceMap($serviceMap): Establecer el objeto mapa de servicio para la respuesta. getServiceMap(): Recuperar el objeto mapa de servicio, si hubiera alguno. Una versin especfica de HTTP est disponible a travs de Zend_Json_Server_Response_Http. Esta clase enviar las cabeceras HTTP apropiadas as como serializar la respuesta como JSON.
Zend_Json_Server_Error
JSON-RPC tiene un formato especial para informar condiciones de error. Todos los errores necesitan proporcionar, mnimamente, un mensaje de error y un cdigo de error; opcionalmente, pueden proporcionar datos adicionales, tales como un backtrace. Los cdigos de error derivan de los recomendados por el proyecto XML-RPC EPI [http://xmlrpc-epi.sourceforge.net/ specs/rfc.fault_codes.php]. Zend_Json_Server apropiadamente asigna el cdigo sobre la base de la condicin de error. Para las excepciones de la aplicacin, se utiliza el cdigo '-32000'. Zend_Json_Server_Error expone los siguientes mtodos: setCode($code): Establece el cdigo de error; si el cdigo de error no est en el rango de aceptacin de XMLRPC, -32000 ser asignado. getCode(): Recuperar el actual cdigo de error.
705
Zend_Json
setMessage($message): Establecer el mensaje de error. getMessage(): Recuperar el mensaje de error actual. setData($data): Establecer el conjunto de datos auxiliares para calificar ms adelante el error, tal como un backtrace. getData(): Recuperar cualquier auxiliar actual de errores de datos. toArray(): Mandar el error a un array. El array contendr las claves 'code', 'message', y 'data'. toJson(): Mandar el error a una representacin de error JSON-RPC.
Zend_Json_Server_Smd
SMD quiere decir Service Mapping Description, un esquema JSON que define cmo un cliente puede interactuar con un servicio web en particular. En el momento de escribir esto, la especificacin [http://groups.google.com/group/jsonschema/web/service-mapping-description-proposal] todava no ha sido ratificada oficialmente, pero ya est en uso en Dojo toolkit as como en otros clientes consumidores de JSON-RPC. En su aspecto ms bsico, un SMD indica el mtodo de transporte (POST, GET, TCP/IP, etc), el tipo de envoltura de la solicitud (generalmente se basa en el protocolo del servidor), el objetivo URL del proveedor del servicio, y un mapa de los servicios disponibles. En el caso de JSON-RPC, el servicio de mapa es una lista de los mtodos disponibles, en el que cada mtodo documenta los parmetros disponibles y sus tipos, as como los tipos de valores esperados a devolver. Zend_Json_Server_Smd Proporciona un objeto orientado para construir servicios de mapas. Bsicamente, pasa los metadatos describiendo el servicio usando mutators, y especifica los servicios (mtodos y funciones). Las descripciones de los servicios son tpicamente instancias de Zend_Json_Server_Smd_Service; tambin puede pasar toda la informacin como un array a los diversos mutators de servicios en Zend_Json_Server_Smd, y que instanciar on objeto de servicio por usted. Los objetos de servicio contienen informacin como el nombre del servicio (tpicamente, la funcin o el nombre del mtodo), los parmetros (nombres, tipos y posicin), y el tipo del valor de retorno. Opcionalmente, cada servicio puede tener su propio objetivo y envoltura, aunque esta funcionalidad rara vez es utilizada. Zend_Json_Server Realmente todo esto sucede entre bambalinas para usted, utilizando reflexin sobre las clases y funciones agregadas; debe crear su propio servicio de mapas slo si necesita brindar funcionalidad personalizada que la introspeccin de clase y funcin no puede ofrecer. Los mtodos disponibles en Zend_Json_Server_Smd incluyen: setOptions(array $options): Establecer un objeto SMD desde un array de opciones. Todos los mutators (mtodos comenzando con 'set') se pueden usar como claves. setTransport($transport): Establecer el transporte usado para acceder al servicio; nicamente POST es actualmente soportado. getTransport(): Obtener el servicio de transporte actual. setEnvelope($envelopeType): Establecer la envoltura de la solicitud que debera ser utilizada para acceder al servicio. Actualmente las constantes soportadas son Zend_Json_Server_Smd::ENV_JSONRPC_1 y Zend_Json_Server_Smd::ENV_JSONRPC_1. getEnvelope(): Obtener la envoltura de la peticin actual. setContentType($type): Establecer el tipo de contenido que deben utilizar las solicitudes (por defecto, es 'application/json).
706
Zend_Json
getContentType(): Conseguir el tipo del contenido actual para las solicitudes al servicio. setTarget($target): Establecer el punto final de la URL para el servicio. getTarget(): Obtener el punto final de la URL para el servicio. setId($id): Normalmente, este es el punto final de la URL del servicio (igual que el objetivo). getId(): Recuperar el ID del servicio (normalmente el punto final de la URL del servicio). setDescription($description): Establecer una descripcin del servicio (tpicamente informacin narrativa que describe el propsito del servicio). getDescription(): Obtener la descripcin del servicio. setDojoCompatible($flag): Establecer un flag que indique si el SMD es compatible o no con el toolkit de Dojo. Cuando sea verdadero, el JSON SMD ser formateado para cumplir con el formato que espera el cliente de Dojo JSON-RPC. isDojoCompatible(): Devuelve el valor del flag de compatibilidad de Dojo (falso, por defecto). addService($service): Aade un servicio al mapa. Puede ser un array de informacin a pasar al constructor de Zend_Json_Server_Smd_Service, o una instancia de esa clase. addServices(array $services): Agrega mltiples servicios a la vez. setServices(array $services): Agrega mltiples servicios a la vez, sobreescribiendo cualquiera de los servicios previamente establecidos. getService($name): Ontiene el servicio por su nombre. getServices(): Obtener todos los servicios agregados. removeService($name): Elimina un servicio del mapa. toArray(): Mandar el mapa de servicio a un array. toDojoArray(): Mandar el mapa de servicio a un array compatible con Dojo Toolkit. toJson(): Mandar el mapa de servicio a una representacin JSON. Zend_Json_Server_Smd_Service tiene los siguientes mtodos: setOptions(array $options): Establecer el estado del objeto dede un array. Cualquier mutator (mtodos comenzando con 'set') puede ser utilizado como una clave y establecerlo mediante este mtodo. setName($name): Establecer el nombre del servicio (tpicamente, la funcin o el nombre del mtodo). getName(): Recuperar el nombre del servicio. setTransport($transport): Establecer el servicio de transporte (actualmente, slo transportes apoyados por Zend_Json_Server_Smd son permitidos). getTransport(): Recuperar el transporte actual. setTarget($target): Establecer el punto final de la URL del servicio (tpicamente, este ser el mismo que el SMD en general, al cual el servicio est agregado). getTarget(): Obtener el punto final de la URL del servicio.
707
Zend_Json
setEnvelope($envelopeType): Establecer la envoltura del servicio (actualmente, slo se permiten las envolturas soportadas por Zend_Json_Server_Smd. getEnvelope(): Recuperar el tipo de envoltura del servicio. addParam($type, array $options = array(), $order = null): Aadir un parmetro para el servicio. Por defecto, slo el tipo de parmetro es necesario. Sin embargo, tambin puede especificar el orden, as como opciones tales como: name: el nombre del parmetro optional: cundo el parmetro es opcional o no default: un valor por defecto para el parmetro description: texto describiendo el parmetro addParams(array $params): Agregar varios parmetros a la vez; cada param debera ser un array asociativo conteniendo mnimamente la clave 'type' describiendo el tipo de parmetro y, opcionalmente la clave 'order'; cualquiera de las otras claves sern pasados como $options a addOption(). setParams(array $params): Establecer muchos parmetros a la vez, sobrescribiendo cualquiera de los parmetros existentes. getParams(): Recuperar todos los parmetros actualmente establecidos. setReturn($type): Establecer el tipo del valor de retorno del servicio. getReturn(): Obtener el tipo del valor de retorno del servicio. toArray(): Mandar el servicio a un array. toJson(): Mandar el servicio a una representacin JSON.
708
Layout scripts
In both cases, however, you'll need to create a layout script. Layout scripts simply utilize Zend_View (or whatever view implementation you are using). Layout variables are registered with a Zend_Layout placeholder, and may be accessed via the placeholder helper or by fetching them as object properties of the layout object via the layout helper. As an example:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>My Site</title> </head> <body> <?php // fetch 'content' key using layout helper:
709
Zend_Layout
echo $this->layout()->content; // fetch 'foo' key using placeholder helper: echo $this->placeholder('Zend_Layout')->foo; // fetch layout object and retrieve various keys from it: $layout = $this->layout(); echo $layout->bar; echo $layout->baz; ?> </body> </html> Because Zend_Layout utilizes Zend_View for rendering, you can also use any view helpers registered, and also have access to any previously assigned view variables. Particularly useful are the various placeholder helpers, as they allow you to retrieve content for areas such as the <head> section, navigation, etc.:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <?php echo $this->headTitle() ?> <?php echo $this->headScript() ?> <?php echo $this->headStyle() ?> </head> <body> <?php echo $this->render('header.phtml') ?> <div id="nav"><?php echo $this->placeholder('nav') ?></div> <div id="content"><?php echo $this->layout()->content ?></div> <?php echo $this->render('footer.phtml') ?> </body> </html>
// In your bootstrap:
710
Zend_Layout
Zend_Layout::startMvc(); startMvc() can take an optional array of options or Zend_Config object to customize the instance; these options are detailed in the section called Zend_Layout Configuration Options. In an action controller, you may then access the layout instance as an action helper:
class FooController extends Zend_Controller_Action { public function barAction() { // disable layouts for this action: $this->_helper->layout->disableLayout(); } public function bazAction() { // use different layout script with this action: $this->_helper->layout->setLayout('foobaz'); }; } In your view scripts, you can then access the layout object via the layout view helper. This view helper is slightly different than others in that it takes no arguments, and returns an object instead of a string value. This allows you to immediately call methods on the layout object:
<?php $this->layout()->setLayout('foo'); // set alternate layout ?> At any time, you can fetch the Zend_Layout instance registered with the MVC via the getMvcInstance() static method:
// Returns null if startMvc() has not first been called $layout = Zend_Layout::getMvcInstance(); Finally, Zend_Layout's front controller plugin has one important feature in addition to rendering the layout: it retrieves all named segments from the response object and assigns them as layout variables, assigning the 'default' segment to the variable 'content'. This allows you to access your application content and render it in your view scripts. As an example, let's say your code first hits FooController::indexAction(), which renders some content to the default response segment, and then forwards to NavController::menuAction(), which renders content to the 'nav' response segment. Finally, you forward to CommentController::fetchAction() and fetch some comments, but render those to the default response segment as well (which appends content to that segment). Your view script could then render each separately:
<body> <!-- renders /nav/menu --> <div id="nav"><?php echo $this->layout()->nav ?></div> <!-- renders /foo/index + /comment/fetch --> <div id="content"><?php echo $this->layout()->content ?></div>
711
Zend_Layout
</body> This feature is particularly useful when used in conjunction with the ActionStack action helper and plugin, which you can use to setup a stack of actions through which to loop, and thus create widgetized pages.
$layout = new Zend_Layout(); // Set a layout script path: $layout->setLayoutPath('/path/to/layouts'); // set some variables: $layout->content = $content; $layout->nav = $nav; // choose a different layout script: $layout->setLayout('foo'); // render final layout echo $layout->render();
Sample Layout
Sometimes a picture is worth a thousand words. The following is a sample layout script showing how it might all come together.
712
Zend_Layout
713
Zend_Layout
The actual order of elements may vary, depending on the CSS you've setup; for instance, if you're using absolute positioning, you may be able to have the navigation displayed later in the document, but still show up at the top; the same could be said for the sidebar or header. The actual mechanics of pulling the content remain the same, however.
Ejemplos
The following examples assume the following $options array and $config object:
$options = array( 'layout' => 'foo', 'layoutPath' => '/path/to/layouts', 'contentKey' => 'CONTENT', );
714
Zend_Layout
/** [layout] layout = "foo" layoutPath = "/path/to/layouts" contentKey = "CONTENT" */ $config = new Zend_Config_Ini('/path/to/layout.ini', 'layout');
715
Zend_Layout
716
Zend_Layout
desire to write your own, you can specify the name of the plugin class to load by passing the pluginClass option to the startMvc() method. Any plugin class you write for this purpose will need to extend Zend_Controller_Plugin_Abstract, and should accept a layout object instance as an argument to the constructor. Otherwise, the details of your implementation are up to you. The default plugin class used is Zend_Layout_Controller_Plugin_Layout.
// Set the inflector target: $layout->setInflectorTarget('layouts/:script.:suffix'); // Set the layout view script suffix: $layout->setViewSuffix('php');
717
Zend_Layout
$inflector = new Zend_Filter_Inflector('layouts/:script.:suffix'); $inflector->addRules(array( ':script' => array('Word_CamelCaseToUnderscore'), 'suffix' => 'html' )); $layout->setInflector($inflector);
718
Theory of operation
This component currently consists of the main Zend_Ldap class, that conceptually represents a binding to a single LDAP server and allows for executing operations against a LDAP server such as OpenLDAP or ActiveDirectory (AD) servers. The parameters for binding may be provided explicitly or in the form of an options array. Zend_Ldap_Node provides an object-oriented interface for single LDAP nodes and can be used to form a basis for an active-record-like interface for a LDAP-based domain model. The component provides several helper classes to perform operations on LDAP entries (Zend_Ldap_Attribute) such as setting and retrieving attributes (date values, passwords, boolean values, ...), to create and modify LDAP filter strings (Zend_Ldap_Filter) and to manipulate LDAP distinguished names (DN) (Zend_Ldap_Dn). Additionally the component abstracts LDAP schema browsing for OpenLDAP and ActiveDirectoy servers Zend_Ldap_Node_Schema and server information retrieval for OpenLDAP-, ActiveDirectory- and Novell eDirectory servers (Zend_Ldap_Node_RootDse). Using the Zend_Ldap class depends on the type of LDAP server and is best summarized with some simple examples. If you are using OpenLDAP, a simple example looks like the following (note that the bindRequiresDn option is important if you are not using AD): $options = array( 'host' => 's0.foo.net', 'username' => 'CN=user1,DC=foo,DC=net', 'password' => 'pass1', 'bindRequiresDn' => true, 'accountDomainName' => 'foo.net', 'baseDn' => 'OU=Sales,DC=foo,DC=net', ); $ldap = new Zend_Ldap($options); $acctname = $ldap->getCanonicalAccountName('abaker', Zend_Ldap::ACCTNAME_FORM_DN); echo "$acctname\n"; If you are using Microsoft AD a simple example is: $options = array( 'host' 'useStartTls' 'username' 'password' 'accountDomainName' 'accountDomainNameShort' 'baseDn' );
719
Zend_Ldap
$ldap = new Zend_Ldap($options); $acctname = $ldap->getCanonicalAccountName('bcarter', Zend_Ldap::ACCTNAME_FORM_DN); echo "$acctname\n"; Note that we use the getCanonicalAccountName() method to retrieve the account DN here only because that is what exercises the most of what little code is currently present in this class.
720
Zend_Ldap
The default canonicalization depends on what account domain name options were supplied. If accountDomainNameShort was supplied, the default accountCanonicalForm value is ACCTNAME_FORM_BACKSLASH. Otherwise, if accountDomainName was supplied, the default is ACCTNAME_FORM_PRINCIPAL. Account name canonicalization ensures that the string used to identify an account is consistent regardless of what was supplied to bind(). For example, if the user supplies an account name of abaker@example.com or just abaker and the accountCanonicalForm is set to 3, the resulting canonicalized name would be EXAMPLE\abaker.
721
Zend_Ldap
$ldap->bind($acctname, $password); $acctname = $ldap->getCanonicalAccountName($acctname); echo "SUCCESS: authenticated $acctname\n"; return; } catch (Zend_Ldap_Exception $zle) { echo ' ' . $zle->getMessage() . "\n"; if ($zle->getCode() === Zend_Ldap_Exception::LDAP_X_DOMAIN_MISMATCH) { continue; } } } If the bind fails for any reason, the next set of server options is tried. The getCanonicalAccountName() call gets the canonical account name that the application would presumably use to associate data with such as preferences. The accountCanonicalForm = 4 in all server options ensures that the canonical form is consistent regardless of which server was ultimately used. The special LDAP_X_DOMAIN_MISMATCH exception occurs when an account name with a domain component was supplied (e.g., abaker@foo.net or FOO\abaker and not just abaker) but the domain component did not match either domain in the currently selected server options. This exception indicates that the server is not an authority for the account. In this case, the bind will not be performed, thereby eliminating unnecessary communication with the server. Note that the continue instruction has no effect in this example, but in practice for error handling and debugging purposes, you will probably want to check for LDAP_X_DOMAIN_MISMATCH as well as LDAP_NO_SUCH_OBJECT and LDAP_INVALID_CREDENTIALS. The above code is very similar to code used within Zend_Auth_Adapter_Ldap. In fact, we recommend that you simply use that authentication adapter for multi-domain + failover LDAP based authentication (or copy the code).
API overview
Configuration / options
The Zend_Ldap component accepts an array of options either supplied to the constructor or through the setOptions() method. The permitted options are as follows:
port useStartTls
722
Zend_Ldap
Name useSsl
Description Whether or not the LDAP client should use SSL encrypted transport. The useSsl and useStartTls options are mutually exclusive. The default credentials username. Some servers require that this be in DN form. This must be given in DN form if the LDAP server requires a DN to bind and binding should be possible with simple usernames. The default credentials password (used only with username above). If TRUE, this instructs Zend_Ldap to retrieve the DN for the account used to bind if the username is not already in DN form. The default value is FALSE. The default base DN used for searching (e.g., for accounts). This option is required for most account related operations and should indicate the DN under which accounts are located. A small integer indicating the form to which account names should be canonicalized. See the Account Name Canonicalization section below. The FQDN domain for which the target LDAP server is an authority (e.g., example.com). The 'short' domain for which the target LDAP server is an authority. This is usually used to specify the NetBIOS domain name for Windows networks but may also be used by non-AD servers. The LDAP search filter used to search for accounts. This string is a sprintf() [http://php.net/sprintf] style expression that must contain one '%s' to accommodate the username. The default value is '(&(objectClass=user)(sAMAccountName=%s))' unless bindRequiresDn is set to TRUE, in which case the default is '(&(objectClass=posixAccount)(uid=%s))'. Users of custom schemas may need to change this option. Some LDAP servers can be configured to accept an empty string password as an anonymous bind. This behavior is almost always undesirable. For this reason, empty passwords are explicitly disallowed. Set this value to TRUE to allow an empty string password to be submitted during the bind. If set to TRUE, this option indicates to the LDAP client that referrals should be followed. The default value is FALSE. If set to FALSE, this option indicates that the given username should not be split at the first @ or \ character to separate the username from the domain during the binding-procedure. This allows the user to use usernames that contain an @ or \ character that do not inherit some domain-information, e.g. using email-addresses for binding. The default value is TRUE.
username
password bindRequiresDn
baseDn
accountCanonicalForm
accountDomainName accountDomainNameShort
accountFilterFormat
allowEmptyPassword
optReferrals tryUsernameSplit
723
Zend_Ldap
API Reference
Nota
Method names in italics are static methods.
Zend_Ldap
Zend_Ldap is the base interface into a LDAP server. It provides connection and binding methods as well as methods to operate on the LDAP tree.
boolean explodeDn($dn, array &$keys = Checks if a given DN $dn is malformed. If $keys or null, array &$vals = null) $keys and $vals are given, these arrays will be filled with the appropriate DN keys and values. This method is deprecated, please use Zend_Ldap_Dn::checkDn() instead. __construct($options) Constructor. The $options parameter is optional and can be set to an array or a Zend_Config instance. If no options are provided at instantiation, the connection parameters must be passed to the instance using Zend_Ldap::setOptions(). The allowed options are specified in Zend_Ldap Options Returns the raw LDAP extension (ext/ldap) resource. Returns the LDAP error number of the last LDAP command. & Returns the LDAP error message of the last LDAP command. The optional $errorCode parameter is set to the LDAP error number when given. The optional $errorMessages array will be filled with the raw error messages when given. The various LDAP error retrieval functions can return different things, so they are all collected if $errorMessages is given. Sets the LDAP connection and binding parameters. $options can be an array or an instance of Zend_Config. The allowed options are specified in Zend_Ldap Options Returns the current connection and binding parameters. Returns the base DN this LDAP connection is bound to.
Zend_Ldap setOptions($options)
string getCanonicalAccountName(string Returns the canonical account name of the given account $acctname, integer $form) name $acctname. $form specifies the format into which the account name is canonicalized. See Account Name Canonicalization for more details.
724
Zend_Ldap
Zend_Ldap connect(string $host, integer Connects the Zend_Ldap instance to the given LDAP $port, boolean $useSsl, boolean server. All parameters are optional and will be taken $useStartTls) from the LDAP connection and binding parameters passed to the instance via the construtor or via Zend_Ldap::setOptions() when set to NULL. Zend_Ldap bind(string $username, string Authenticates $username with $password at the $password) LDAP server. If both paramaters are omitted the binding will be carried out with the credentials given in the connection and binding parameters. If no credentials are given in the connection and binding parameters an anonymous bind will be performed. Note that this requires anonymous binds to be allowed on the LDAP server. An empty string '' can be passed as $password together with a username if, and only if, allowEmptyPassword is set to TRUE in the connection and binding parameters. Zend_Ldap_Collection search(string| Zend_Ldap_Filter_Abstract $filter, string|Zend_Ldap_Dn $basedn, integer $scope, array $attributes, string $sort, string $collectionClass) Searches the LDAP tree with the given $filter and the given search parameters.
string| The filter string Zend_Ldap_Filter_Abstract to be used in $filter the search, e.g. (objectClass=posixAccount string|Zend_Ldap_Dn $basedn The search base for the search. If omitted or NULL, the baseDn from the connection and binding parameters is used.
integer $scope
The search scope. Zend_Ldap::SEARCH_SCOPE_S searches the complete subtree including the $baseDn node. Zend_Ldap::SEARCH_SCOPE_O restricts search to one level below $baseDn. Zend_Ldap::SEARCH_SCOPE_B restricts search to the $baseDn itself; this can be used to efficiently retrieve a single entry
725
Zend_Ldap
Method
Description
by its DN. The default value is Zend_Ldap::SEARCH_SCOPE_S array $attributes Specifies the attributes contained in the returned entries. To include all possible attributes (ACL restrictions can disallow certain attribute to be retrieved by a given user) pass either an empty array array() or array('*') to the method. On some LDAP servers you can retrieve special internal attributes by passing array('*', '+') to the method. If given the result collection will be sorted after the attribute $sort. Results can only be sorted after one single attribute as this parameter uses the ext/ldap function ldap_sort(). If given the result will be wrapped in an object of type $collectionClass. By default an object of type Zend_Ldap_Collection will be returned. The custom class must extend Zend_Ldap_Collection and will be passed a
string $sort
string $collectionClass
726
Zend_Ldap
Method
Description
Zend_Ldap_Collection_Iter on instantiation. integer count(string| Counts the elements returned by the given search Zend_Ldap_Filter_Abstract $filter, parameters. See Zend_Ldap::search() for a string|Zend_Ldap_Dn $basedn, integer detailed description of the method parameters. $scope) integer countChildren(string| Counts the direct descendants (children) of the entry Zend_Ldap_Dn $dn) identified by the given $dn. boolean $dn) exists(string|Zend_Ldap_Dn Checks whether the entry identified by the given $dn exists. Performs a search operation and returns the result as an PHP array. This is essentially the same method as Zend_Ldap::search() except for the return type. See Zend_Ldap::search() for a detailed description of the method parameters.
array searchEntries(string| Zend_Ldap_Filter_Abstract $filter, string|Zend_Ldap_Dn $basedn, integer $scope, array $attributes, string $sort)
array getEntry(string|Zend_Ldap_Dn Retrieves the LDAP entry identified by $dn $dn, array $attributes, boolean with the attributes specified in $attributes. If $throwOnNotFound) $attributes is ommitted, all attributes (array()) are included in the result. $throwOnNotFound is FALSE by default, so the method will return NULL if the specified entry cannot be found. If set to TRUE, a Zend_Ldap_Exception will be thrown instead. void prepareLdapEntryArray(array $entry) & Prepare an array for the use in LDAP modification operations. This method does not need to be called by the end-user as it's implicitly called on every data modification method.
Zend_Ldap add(string|Zend_Ldap_Dn $dn, Adds the entry identified by $dn with its array $entry) attributes $entry to the LDAP tree. Throws a Zend_Ldap_Exception if the entry could not be added. Zend_Ldap update(string|Zend_Ldap_Dn Updates the entry identified by $dn with its $dn, array $entry) attributes $entry to the LDAP tree. Throws a Zend_Ldap_Exception if the entry could not be modified. Zend_Ldap save(string|Zend_Ldap_Dn Saves the entry identified by $dn with its $dn, array $entry) attributes $entry to the LDAP tree. Throws a Zend_Ldap_Exception if the entry could not be saved. This method decides by querying the LDAP tree if the entry will be added or updated. Zend_Ldap delete(string|Zend_Ldap_Dn Deletes the entry identified by $dn from the LDAP tree. $dn, boolean $recursively) Throws a Zend_Ldap_Exception if the entry could not be deleted. $recursively is FALSE by default. If set to TRUE the deletion will be carried out recursively and will effectively delete a complete subtree. Deletion will fail if $recursively is FALSE and the entry $dn is not a leaf entry. Zend_Ldap Zend_Ldap_Dn moveToSubtree(string| Moves the entry identified by $from to a location below $from, string| $to keeping its RDN unchanged. $recursively
727
Zend_Ldap
Method Description Zend_Ldap_Dn $to, boolean $recursively, specifies if the operation will be carried out recursively boolean $alwaysEmulate) (FALSE by default) so that the entry $from and all its descendants will be moved. Moving will fail if $recursively is FALSE and the entry $from is not a leaf entry. $alwaysEmulate controls whether the ext/ldap function ldap_rename() should be used if available. This can only work for leaf entries and for servers and for ext/ldap supporting this function. Set to TRUE to always use an emulated rename operation.
Nota
All move-operations are carried out by copying and then deleting the corresponding entries in the LDAP tree. These operations are not atomic so that failures during the operation will result in an inconsistent state on the LDAP server. The same is true for all recursive operations. They also are by no means atomic. Please keep this in mind. Zend_Ldap move(string|Zend_Ldap_Dn This is an alias for Zend_Ldap::rename(). $from, string|Zend_Ldap_Dn $to, boolean $recursively, boolean $alwaysEmulate) Zend_Ldap rename(string|Zend_Ldap_Dn Renames the entry identified by $from to $to. $from, string|Zend_Ldap_Dn $to, boolean $recursively specifies if the operation will be carried $recursively, boolean $alwaysEmulate) out recursively (FALSE by default) so that the entry $from and all its descendants will be moved. Moving will fail if $recursively is FALSE and the entry $from is not a leaf entry. $alwaysEmulate controls whether the ext/ldap function ldap_rename() should be used if available. This can only work for leaf entries and for servers and for ext/ldap supporting this function. Set to TRUE to always use an emulated rename operation. Zend_Ldap copyToSubtree(string| Copies the entry identified by $from to a location below Zend_Ldap_Dn $from, string| $to keeping its RDN unchanged. $recursively Zend_Ldap_Dn $to, boolean $recursively) specifies if the operation will be carried out recursively (FALSE by default) so that the entry $from and all its descendants will be copied. Copying will fail if $recursively is FALSE and the entry $from is not a leaf entry. Zend_Ldap copy(string|Zend_Ldap_Dn Copies the entry identified by $from to $to. $from, string|Zend_Ldap_Dn $to, boolean $recursively specifies if the operation will be carried $recursively) out recursively (FALSE by default) so that the entry $from and all its descendants will be copied. Copying will fail if $recursively is FALSE and the entry $from is not a leaf entry. Zend_Ldap_Node Zend_Ldap_Dn $dn) getNode(string| Returns the entry $dn wrapped in a Zend_Ldap_Node. Returns the entry for the base DN $baseDn wrapped in a Zend_Ldap_Node.
Zend_Ldap_Node getBaseNode()
728
Zend_Ldap
Description Returns the RootDSE for the current server. Returns the LDAP schema for the current server.
Zend_Ldap_Collection
Zend_Ldap_Collection implements Iterator to allow for item traversal using foreach() and Countable to be able to respond to count(). With its protected _createEntry() method it provides a simple extension point for developers needing custom result objects.
__construct(Zend_Ldap_Collection_Iterator_Interface Constructor. The constrcutor must be provided by a $iterator) Zend_Ldap_Collection_Iterator_Interface which does the real result iteration. Zend_Ldap_Collection_Iterator_Default is the default implementation for iterating ext/ldap results. boolean close() array toArray() array getFirst() Closes the internal iterator. This is also called in the destructor. Returns all entries as an array. Returns the first entry in the collection or NULL if the collection is empty.
Zend_Ldap_Attribute
Zend_Ldap_Attribute is a helper class providing only static methods to manipulate arrays suitable to the structure used in Zend_Ldap data modification methods and to the data format required by the LDAP server. PHP data types are converted the following way: string integer and float boolean object and array resource No conversion will be done. The value will be converted to a string. TRUE will be converted to 'TRUE' and FALSE to 'FALSE' The value will be converted to a string by using serialize(). If a stream resource is stream_get_contents(). given, the data will be fetched by calling
others
On reading attribute values the following conversion will take place: 'TRUE' 'FALSE' others Converted to TRUE. Converted to FALSE. All other strings won't be automatically converted and are passed as they are.
729
Zend_Ldap
void setAttribute(array &$data, string Sets the attribute $attribName in $data to the value $attribName, mixed $value, boolean $value. If $append is TRUE (FALSE by default) $append) $value will be appended to the attribute. $value can be a scalar value or an array of scalar values. Conversion will take place. array|mixed getAttribute(array $data, Returns the attribute $attribName from $data. If string $attribName, integer|null $index is NULL (default) an array will be returned $index) containing all the values for the given attribute. An empty array will be returned if the attribute does not exist in the given array. If an integer index is specified the corresponding value at the given index will be returned. If the index is out of bounds, NULL will be returned. Conversion will take place. boolean attributeHasValue(array & Checks if the attribute $attribName in $data has $data, string $attribName, mixed|array the value(s) given in $value. The method returns TRUE $value) only if all values in $value are present in the attribute. Comparison is done strictly (respecting the data type). void removeDuplicatesFromAttribute(array $data, string $attribName) Removes all duplicates from the attribute $attribName & in $data.
void removeFromAttribute(array &$data, Removes the value(s) given in $value from the attribute string $attribName, mixed|array $value) $attribName in $data. string|null $value) mixed $value) convertToLdapValue(mixed Converts a PHP data type into its LDAP representation. See introduction for details. convertFromLdapValue(string Converts an LDAP value into its PHP data type. See introduction for details. Converts a timestamp into its LDAP date/time representation. If $utc is TRUE (FALSE by default) the resulting LDAP date/time string will be in UTC, otherwise a local date/time string will be returned. Converts LDAP date/time representation into a timestamp. The method returns NULL if $value can not be converted back into a PHP timestamp.
void setPassword(array &$data, string Sets a LDAP password for the attribute $password, string $hashType, string $attribName in $data. $attribName defaults to $attribName) 'userPassword' which is the standard password attribute. The password hash can be specified with $hashType. The default value here is Zend_Ldap_Attribute::PASSWORD_HASH_MD5 with Zend_Ldap_Attribute::PASSWORD_HASH_SHA as the other possibilty. string createPassword(string Creates a LDAP password. The password hash can be $password, string $hashType) specified with $hashType. The default value here is Zend_Ldap_Attribute::PASSWORD_HASH_MD5 with
730
Zend_Ldap
Method
Description Zend_Ldap_Attribute::PASSWORD_HASH_SHA as the other possibilty. Sets the attribute $attribName in $data to the date/time value $value. If $append is TRUE (FALSE by default) $value will be appended to the attribute. $value can be an integer value or an array of integers. Date-time-conversion according to Zend_Ldap_Attribute::convertToLdapDateTimeValue() will take place.
void setDateTimeAttribute(array & $data, string $attribName, integer| array $value, boolean $utc, boolean $append)
Returns the date/time attribute $attribName from $data. If $index is NULL (default) an array will be returned containing all the date/time values for the given attribute. An empty array will be returned if the attribute does not exist in the given array. If an integer index is specified the corresponding date/ time value at the given index will be returned. If the index is out of bounds, NULL will be returned. Date-time-conversion according to Zend_Ldap_Attribute::convertFromLdapDateTimeValue() will take place.
Zend_Ldap_Dn
Zend_Ldap_Dn provides an object-oriented interface to manipulating LDAP distinguished names (DN). The parameter $caseFold that is used in several methods determines the way DN attributes are handled regarding their case. Allowed values for this paraneter are: Zend_Ldap_Dn::ATTR_CASEFOLD_NONE No case-folding will be done. Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER All attributes will be converted to upper-case. Zend_Ldap_Dn::ATTR_CASEFOLD_LOWER All attributes will be converted to lower-case. The default case-folding is Zend_Ldap_Dn::ATTR_CASEFOLD_NONE and can be set with Zend_Ldap_Dn::setDefaultCaseFold(). Each instance of Zend_Ldap_Dn can have its own case-foldingsetting. If the $caseFold parameter is ommitted in method-calls it defaults to the instance's case-folding setting. The class implements ArrayAccess to allow indexer-access to the different parts of the DN. The ArrayAccess-methods proxy to Zend_Ldap_Dn::get($offset, 1, null) for offsetGet(integer $offset), to Zend_Ldap_Dn::set($offset, $value) for offsetSet() and to Zend_Ldap_Dn::remove($offset, 1) for offsetUnset(). offsetExists() simply checks if the index is within the bounds.
731
Zend_Ldap
Description $dn, Creates a Zend_Ldap_Dn instance from a string. $dn, Creates a Zend_Ldap_Dn instance from an array. The array must conform to the array structure detailed under Zend_Ldap_Dn::implodeDn(). Gets the RDN of the current DN. The return value is an array with the RDN attribute names its keys and the RDN attribute values.
getRdnString(string|null Gets the RDN of the current DN. The return value is a string. getParentDn(integer Gets the DN of the current DN's ancestor $levelUp levels up the tree. $levelUp defaults to 1.
array get(integer $index, integer Returns a slice of the current DN determined by $index $length, string|null $caseFold) and $length. $index starts with 0 on the DN part from the left. Zend_Ldap_Dn set(integer $index, array Replaces a DN part in the current DN. This operation $value) manipulates the current instance. Zend_Ldap_Dn remove(integer integer $length) $index, Removes a DN part from the current DN. This operation manipulates the current instance. $length defaults to 1 Appends a DN part to the current DN. This operation manipulates the current instance. Prepends a DN part to the current DN. This operation manipulates the current instance.
Zend_Ldap_Dn append(array $value) Zend_Ldap_Dn prepend(array $value) Zend_Ldap_Dn insert(integer array $value) void $caseFold)
$index, Inserts a DN part after the index $index to the current DN. This operation manipulates the current instance.
setCaseFold(string|null Sets the case-folding option to the current DN instance. If $caseFold is null the default case-folding setting (Zend_Ldap_Dn::ATTR_CASEFOLD_NONE by default or set via Zend_Ldap_Dn::setDefaultCaseFold() will be set for the current instance. Returns DN as an array. Returns DN as a string proxies Zend_Ldap_Dn::toString(null). to
string toString(string|null $caseFold) Returns DN as a string. array toArray(string|null $caseFold) string __toString() void $caseFold) array $values) array $values)
setDefaultCaseFold(string Sets the default case-folding option used by all instances on creation by default. Already existing instances are not affected by this setting. escapeValue(string|array Escapes a DN value according to RFC 2253. unescapeValue(string|array Undoes the conversion done Zend_Ldap_Dn::escapeValue(). by
$dn, array Explodes the DN $dn into an array containing all parts string|null of the given DN. $keys optinally receive DN keys (e.g.
732
Zend_Ldap
Method
Description CN, OU, DC, ...). $vals optionally receive DN values. The resulting array will be of type
for a DN of cn=name1+uid=user,cn=name2,dc=example,dc=org. boolean checkDn(string &$keys, array &$vals, $caseFold) $dn, array Checks if a given DN $dn is malformed. If $keys or string|null $keys and $vals are given, these arrays will be filled with the appropriate DN keys and values.
string implodeRdn(array $part, string| Returns a DN part in the form $attribute=$value null $caseFold) string implodeDn(array string|null $caseFold, $separator) $dnArray, Implodes an array in the form delivered by string Zend_Ldap_Dn::explodeDn() to a DN string. $separator defaults to ',' but some LDAP servers also understand ';'. $dnArray must of type
boolean isChildOf(string|Zend_Ldap_Dn Checks if given $childDn is beneath $parentDn $childDn, string|Zend_Ldap_Dn subtree. $parentDn)
Zend_Ldap_Filter
Tabla 29.7. Zend_Ldap_Filter API
Method Description Zend_Ldap_Filter equals(string $attr, Creates an 'equals' filter: (attr=value). string $value) Zend_Ldap_Filter begins(string $attr, Creates an 'begins with' filter: (attr=value*). string $value) Zend_Ldap_Filter string $value) ends(string $attr, Creates an 'ends with' filter: (attr=*value).
733
Zend_Ldap
Method
Description
Zend_Ldap_Filter greaterOrEqual(string Creates an 'greater or equal' filter: (attr>=value). $attr, string $value) Zend_Ldap_Filter string $value) less(string $attr, Creates an 'less' filter: (attr<value).
Zend_Ldap_Filter lessOrEqual(string Creates an 'less or equal' filter: (attr<=value). $attr, string $value) Zend_Ldap_Filter approx(string $attr, Creates an 'approx' filter: (attr~=value). string $value) Zend_Ldap_Filter any(string $attr) Zend_Ldap_Filter $filter) Creates an 'any' filter: (attr=*). string(string Creates a simple custom string filter. The user is responsible for all value-escaping as the filter is used as is. $mask, Creates a filter from a string mask. All $value parameters will be escaped and substituted into $mask by using sprintf() [http://php.net/sprintf] Creates an 'and' filter from all arguments given.
__construct(string $attr, string Constructor. Creates an arbitrary filter according to $value, string $filtertype, string|null the parameters supplied. The resulting filter will be $prepend, string|null $append) a concatenation $attr . $filtertype . $prepend . $value . $append. Normally this constructor is not needed as all filters can be created by using the apprpriate factory methods. string toString() string __toString() Zend_Ldap_Filter_Abstract negate() Zend_Ldap_Filter_Abstract addAnd(Zend_Ldap_Filter_Abstract $filter,...) Zend_Ldap_Filter_Abstract addOr(Zend_Ldap_Filter_Abstract $filter,...) string|array $values) Returns a string representation of the filter. Returns a string representation of the filter. Proxies to Zend_Ldap_Filter::toString(). Negates the current filter. Creates an 'and' filter from the current filter and all filters passed in as the arguments. Creates an 'or' filter from the current filter and all filters passed in as the arguments.
escapeValue(string|array Escapes the given $values according to RFC 2254 so that they can be safely used in LDAP filters. If a single string is given, a string is returned - otherwise an array is returned. Any control characters with an ASCII code < 32 as well as the characters with special meaning in LDAP filters "*", "(", ")", and "\" (the backslash) are converted into the representation of a backslash followed by two hex digits representing the hexadecimal value of the character. unescapeValue(string| Undoes the conversion done by Zend_Ldap_Filter::escapeValue(). Converts
734
Zend_Ldap
Method
Description any sequences of a backslash followed by two hex digits into the corresponding character.
Zend_Ldap_Node
Zend_Ldap_Node includes the magic propery accessors __set(), __get(), __unset() and __isset() to access the attributes by their name. They proxy to Zend_Ldap_Node::setAttribute(), Zend_Ldap_Node::getAttribute(), Zend_Ldap_Node::deleteAttribute() and Zend_Ldap_Node::existsAttribute() respectively. Furthermore the class implements ArrayAccess for array-style-access to the attributes. Zend_Ldap_Node also implements Iterator and RecursiveIterato to allow for recursive tree-traversal.
Zend_Ldap_Node $ldap)
attachLdap(Zend_Ldap Attach the current node to the $ldap Zend_Ldap instance. Throws Zend_Ldap_Exception if $ldap is not responsible for the current node (node is not a child of the $ldap base DN). Detach node from LDAP connection. Checks if the current node is attached to a LDAP connection.
Zend_Ldap_Node create(string|array| Factory method to create a new detached Zend_Ldap_Dn $dn, array $objectClass) Zend_Ldap_Node for a given DN. Creates a new Zend_Ldap_Node with the DN $dn and the objectclasses $objectClass. Zend_Ldap_Node fromLdap(string|array| Factory method to create an attached Zend_Ldap_Node Zend_Ldap_Dn $dn, Zend_Ldap $ldap) for a given DN. Loads an existing Zend_Ldap_Node with the DN $dn from the LDAP connection $ldap. Zend_Ldap_Node fromArray((array $data, Factory method to create a detached Zend_Ldap_Node boolean $fromDataSource) from array data $data. If $fromDataSource is TRUE (FALSE by default), the data is treated as beeing present in a LDAP tree. boolean isNew() Tells if the node is consiedered as new on the server). Please note, that this if the node is really present on the Zend_Ldap_Node::exists() to see already there. (not present doesn't tell server. Use if a node is
Tells if this node is going to be deleted once Zend_Ldap_Node::update() is called. Marks this node as to be deleted. Node will be deleted on calling Zend_Ldap_Node::update() if Zend_Ldap_Node::willBeDeleted() is true. Tells if this node is going to be moved once Zend_Ldap_Node::update() is called.
boolean willBeMoved()
735
Zend_Ldap
Method
Description
Zend_Ldap_Node update(Zend_Ldap $ldap) Sends all pending changes to the LDAP server. If $ldap is omitted the current LDAP connection is used. If the current node is detached from a LDAP connection a Zend_Ldap_Exception will be thrown. If $ldap is provided the current node will be attached to the given LDAP connection. Zend_Ldap_Dn getCurrentDn() Gets the current DN of the current node as a Zend_Ldap_Dn. This does not reflect possible renameoperations. Gets the original DN of the current node as a Zend_Ldap_Dn. This reflects possible rename-operations. Gets the original DN of the current node as a string. This reflects possible rename-operations. Gets the original DN of the current node as an array. This reflects possible rename-operations. Gets the RDN of the current node as a string. This reflects possible rename-operations. Gets the RDN of the current node as an array. This reflects possible rename-operations.
Zend_Ldap_Dn getDn() string getDnString(string $caseFold) array getDnArray(string $caseFold) string getRdnString(string $caseFold) array getRdnArray(string $caseFold)
Zend_Ldap_Node setDn(Zend_Ldap_Dn| Sets the new DN for this node effectively moving the node string|array $newDn) once Zend_Ldap_Node::update() is called. Zend_Ldap_Node move(Zend_Ldap_Dn| This is an alias for Zend_Ldap_Node::setDn(). string|array $newDn) Zend_Ldap_Node rename(Zend_Ldap_Dn| This is an alias for Zend_Ldap_Node::setDn(). string|array $newDn) array getObjectClass() Zend_Ldap_Node string $value) Returns the objectClass of the node. setObjectClass(array| Sets the objectClass attribute.
Zend_Ldap_Node Appends to the objectClass attribute. appendObjectClass(array|string $value) string toLdif(array $options) Returns a LDIF representation of the current node. $options will be passed to the Zend_Ldap_Ldif_Encoder. Gets changed node data. The array contains all changed attributes. This format can be used in Zend_Ldap::add() and Zend_Ldap::update(). Returns all changes made. Returns the DN of the current node - proxies to Zend_Ldap_Dn::getDnString(). Casts to string representation Zend_Ldap_Dn::toString(). proxies to
array getChangedData()
array toArray(boolean Returns an array representation of the $includeSystemAttributes) current node. If $includeSystemAttributes is FALSE (defaults to TRUE) the system
736
Zend_Ldap
Method
Description specific attributes are stripped from the array. Unlike Zend_Ldap_Node::getAttributes() the resulting array contains the DN with key 'dn'.
string toJson(boolean Returns a JSON representation of the current node using $includeSystemAttributes) Zend_Ldap_Node::toArray(). array getData(boolean Returns the node's attributes. The array contains all $includeSystemAttributes) attributes in its internal format (no conversion). boolean existsAttribute(string $name, Checks whether a given attribute exists. If boolean $emptyExists) $emptyExists is FALSE empty attributes (containing only array()) are treated as non-existent returning FALSE. If $emptyExists is true empty attributes are treated as existent returning TRUE. In this case teh method returns FALSE only if the attribute name is missing in the keycollection. boolean attributeHasValue(string Checks if the given value(s) exist in the attribute. The $name, mixed|array $value) method returns TRUE only if all values in $value are present in the attribute. Comparison is done strictly (respecting the data type). integer count() mixed getAttribute(string integer|null $index) Returns the number of attributes in the node. Implements Countable. $name, Gets a LDAP attribute. Data conversion is applied using Zend_Ldap_Attribute::getAttribute().
array getAttributes(boolean Gets all attributes of node. If $includeSystemAttributes) $includeSystemAttributes is FALSE (defaults to TRUE) the system specific attributes are stripped from the array. Zend_Ldap_Node setAttribute(string Sets a LDAP attribute. Data conversion is applied using $name, mixed $value) Zend_Ldap_Attribute::setAttribute(). Zend_Ldap_Node Appends to a LDAP attribute. Data conversion is applied appendToAttribute(string $name, mixed using $value) Zend_Ldap_Attribute::setAttribute(). array|integer getDateTimeAttribute(string integer|null $index) Gets a LDAP date/time attribute. $name, Data conversion is applied using Zend_Ldap_Attribute::getDateTimeAttribute().
Zend_Ldap_Node Sets a LDAP date/time attribute. setDateTimeAttribute(string $name, Data conversion is applied using integer|array $value, boolean $utc) Zend_Ldap_Attribute::setDateTimeAttribute(). Zend_Ldap_Node Appends to a LDAP date/time attribute. appendToDateTimeAttribute(string Data conversion is applied using $name, integer|array $value, boolean Zend_Ldap_Attribute::setDateTimeAttribute(). $utc) Zend_Ldap_Node Sets a LDAP password on $attribName setPasswordAttribute(string $password, (defaults to 'userPassword') to $password string $hashType, string $attribName) with the hash type $hashType (defaults to Zend_Ldap_Attribute::PASSWORD_HASH_MD5). Zend_Ldap_Node $name) deleteAttribute(string Deletes a LDAP attribute.
737
Zend_Ldap
void removeFromAttribute(string Removes the given values from a LDAP attribute. $attribName, mixed|array $value) boolean exists(Zend_Ldap $ldap) Checks if the current node exists on the given LDAP server (current server is used if NULL is passed).
Zend_Ldap_Node reload(Zend_Ldap $ldap) Reloads the current node's attributes from the given LDAP server (current server is used if NULL is passed). Zend_Ldap_Node_Collection Searches the nodes's subtree with the given searchSubtree(string| $filter and the given search parameters. See Zend_Ldap_Filter_Abstract $filter, Zend_Ldap::search() for details on the parameters integer $scope, string $sort) $scope and $sort. integer countSubtree(string| Count the nodes's subtree items matching the Zend_Ldap_Filter_Abstract $filter, given $filter and the given search scope. See integer $scope) Zend_Ldap::search() for details on the $scope parameter. integer countChildren() Zend_Ldap_Node_Collection searchChildren(string| Zend_Ldap_Filter_Abstract string $sort) boolean hasChildren() Zend_Ldap_Node_ChildrenIterator getChildren() Zend_Ldap_Node $ldap) Count the nodes's children. Searches the nodes's children matching the given $filter. See Zend_Ldap::search() for details on $filter, the $sort parameter. Returns whether the current node has children. Returns all children of the current node.
getParent(Zend_Ldap Returns the parent of the current node using the LDAP connection $ldap (uses the current LDAP connection if omitted).
Zend_Ldap_Node_RootDse
The following methods are available on all vendor-specific subclasses. Zend_Ldap_Node_RootDse includes the magic propery accessors __get() and __isset() to access the attributes by their name. They proxy to Zend_Ldap_Node_RootDse::getAttribute() and Zend_Ldap_Node_RootDse::existsAttribute() respectively. __set() and __unset() are also implemented but they throw a BadMethodCallException as modifications are not allowed on RootDSE nodes. Furthermore the class implements ArrayAccess for array-style-access to the attributes. offsetSet() and offsetUnset() also throw a BadMethodCallException due ro obvious reasons.
738
Zend_Ldap
Method array getRdnArray(string $caseFold) array getObjectClass() string toString() string __toString()
Description Gets the RDN of the current node as an array. Returns the objectClass of the node. Returns the DN of the current node - proxies to Zend_Ldap_Dn::getDnString(). Casts to string representation Zend_Ldap_Dn::toString(). proxies to
array toArray(boolean Returns an array representation of the current $includeSystemAttributes) node. If $includeSystemAttributes is FALSE (defaults to TRUE) the system specific attributes are stripped from the array. Unlike Zend_Ldap_Node_RootDse::getAttributes() the resulting array contains the DN with key 'dn'. string toJson(boolean Returns a JSON representation of the current node using $includeSystemAttributes) Zend_Ldap_Node_RootDse::toArray(). array getData(boolean Returns the node's attributes. The array contains all $includeSystemAttributes) attributes in its internal format (no conversion). boolean existsAttribute(string $name, Checks whether a given attribute exists. If boolean $emptyExists) $emptyExists is FALSE empty attributes (containing only array()) are treated as non-existent returning FALSE. If $emptyExists is true empty attributes are treated as existent returning TRUE. In this case teh method returns FALSE only if the attribute name is missing in the keycollection. boolean attributeHasValue(string Checks if the given value(s) exist in the attribute. The $name, mixed|array $value) method returns TRUE only if all values in $value are present in the attribute. Comparison is done strictly (respecting the data type). integer count() mixed getAttribute(string integer|null $index) Returns the number of attributes in the node. Implements Countable. $name, Gets a LDAP attribute. Data conversion is applied using Zend_Ldap_Attribute::getAttribute().
array getAttributes(boolean Gets all attributes of node. If $includeSystemAttributes) $includeSystemAttributes is FALSE (defaults to TRUE) the system specific attributes are stripped from the array. array|integer getDateTimeAttribute(string integer|null $index) Zend_Ldap_Node_RootDse reload(Zend_Ldap $ldap) Zend_Ldap_Node_RootDse create(Zend_Ldap $ldap) array getNamingContexts() string|null getSubschemaSubentry() Gets a LDAP date/time attribute. $name, Data conversion is applied using Zend_Ldap_Attribute::getDateTimeAttribute(). Reloads the current node's attributes from the given LDAP server. Factory method to create the RootDSE. Gets the namingContexts. Gets the subschemaSubentry.
739
Zend_Ldap
Method
Description
boolean supportsVersion(string|int| Determines if the LDAP version is supported. array $versions) boolean supportsSaslMechanism(string| Determines if the sasl mechanism is supported. array $mechlist) integer getServerType() Gets the server type. Returns Zend_Ldap_Node_RootDse::SERVER_TYPE_GENERIC for unknown LDAP servers Zend_Ldap_Node_RootDse::SERVER_TYPE_OPENLDAP for OpenLDAP servers
Zend_Ldap_Node_RootDse::SERVER_TYPE_ACTIVEDIRECTORY for Microsoft ActiveDirectory servers Zend_Ldap_Node_RootDse::SERVER_TYPE_EDIRECTORY For Novell eDirectory servers Zend_Ldap_Dn getSchemaDn() Returns the schema DN.
OpenLDAP
Additionally the common methods above apply to instances of Zend_Ldap_Node_RootDse_OpenLdap.
Nota
Refer to LDAP Operational Attributes and Objects [http://www.zytrax.com/books/ldap/ch3/#operational]for information on the attributes of OpenLDAP RootDSE.
boolean supportsExtension(string|array Determines if the extension is supported. $oids) boolean $oids) supportsFeature(string|array Determines if the feature is supported.
ActiveDirectory
Additionally the common methods Zend_Ldap_Node_RootDse_ActiveDirectory. above apply to instances of
740
Zend_Ldap
Nota
Refer to RootDSE [http://msdn.microsoft.com/en-us/library/ms684291(VS.85).aspx]for information on the attributes of Microsoft ActiveDirectory RootDSE.
Gets the server type. Returns Zend_Ldap_Node_RootDse::SERVER_TYPE_ACTIVEDIRECTORY Gets the configurationNamingContext. Gets the currentTime. Gets the defaultNamingContext. Gets the dnsHostName. Gets the domainControllerFunctionality. Gets the domainFunctionality. Gets the dsServiceName. Gets the forestFunctionality. Gets the highestCommittedUSN. Gets the isGlobalCatalogReady. Gets the isSynchronized. Gets the ldapServiceName. Gets the rootDomainNamingContext. Gets the schemaNamingContext. Gets the serverName.
boolean supportsCapability(string| Determines if the capability is supported. array $oids) boolean $oids) supportsControl(string|array Determines if the control is supported.
eDirectory
Additionally the common methods above apply to instances of Zend_Ldap_Node_RootDse_eDirectory.
Nota
Refer to Getting Information about the LDAP Server [http://www.novell.com/documentation/edir88/ edir88/index.html?page=/documentation/edir88/edir88/data/ah59jqq.html]for information on the attributes of Novell eDirectory RootDSE.
741
Zend_Ldap
boolean supportsExtension(string|array Determines if the extension is supported. $oids) string|null getVendorName() string|null getVendorVersion() string|null getDsaName() string|null getStatisticsErrors() string|null getStatisticsSecurityErrors() string|null getStatisticsChainings() string|null getStatisticsReferralsReturned() Gets the vendorName. Gets the vendorVersion. Gets the dsaName. Gets the server statistics "errors". Gets the server statistics "securityErrors". Gets the server statistics "chainings". Gets the server statistics "referralsReturned".
string|null getStatisticsExtendedOps() Gets the server statistics "extendedOps". string|null getStatisticsAbandonOps() string|null getStatisticsWholeSubtreeSearchOps() Gets the server statistics "abandonOps". Gets the server statistics "wholeSubtreeSearchOps".
Zend_Ldap_Node_Schema
The following methods are available on all vendor-specific subclasses. Zend_Ldap_Node_Schema includes the magic propery accessors __get() and __isset() to access the attributes by their name. They proxy to Zend_Ldap_Node_Schema::getAttribute() and Zend_Ldap_Node_Schema::existsAttribute() respectively. __set() and __unset() are also implemented but they throw a BadMethodCallException as modifications are not allowed on RootDSE nodes. Furthermore the class implements ArrayAccess for array-style-access to the attributes. offsetSet() and offsetUnset() also throw a BadMethodCallException due ro obvious reasons.
742
Zend_Ldap
Method
Description false (defaults to true) the system specific attributes are stripped from the array. Unlike Zend_Ldap_Node_Schema::getAttributes() the resulting array contains the DN with key 'dn'.
string toJson(boolean Returns a JSON representation of the current node using $includeSystemAttributes) Zend_Ldap_Node_Schema::toArray(). array getData(boolean Returns the node's attributes. The array contains all $includeSystemAttributes) attributes in its internal format (no conversion). boolean existsAttribute(string $name, Checks whether a given attribute exists. If boolean $emptyExists) $emptyExists is false empty attributes (containing only array()) are treated as non-existent returning false. If $emptyExists is true empty attributes are treated as existent returning true. In this case teh method returns false only if the attribute name is missing in the keycollection. boolean attributeHasValue(string Checks if the given value(s) exist in the attribute. The $name, mixed|array $value) method returns true only if all values in $value are present in the attribute. Comparison is done strictly (respecting the data type). integer count() mixed getAttribute(string integer|null $index) Returns the number of attributes in the node. Implements Countable. $name, Gets a LDAP attribute. Data conversion is applied using Zend_Ldap_Attribute::getAttribute().
array getAttributes(boolean Gets all attributes of node. If $includeSystemAttributes) $includeSystemAttributes is false (defaults to true) the system specific attributes are stripped from the array. array|integer getDateTimeAttribute(string integer|null $index) Gets a LDAP date/time attribute. $name, Data conversion is applied using Zend_Ldap_Attribute::getDateTimeAttribute().
Zend_Ldap_Node_Schema reload(Zend_Ldap Reloads the current node's attributes from the given LDAP $ldap) server. Zend_Ldap_Node_Schema create(Zend_Ldap Factory method to create the Schema node. $ldap) array getAttributeTypes() array getObjectClasses() Gets the attribute types as an array of . Gets the object classes as an array of Zend_Ldap_Node_Schema_ObjectClass_Interface.
743
Zend_Ldap
Classes representing attribute types and object classes extend Zend_Ldap_Node_Schema_Item which provides some core methods to access arbitrary attributes on the underlying LDAP node. Zend_Ldap_Node_Schema_Item includes the magic propery accessors __get() and __isset() to access the attributes by their name. Furthermore the class implements ArrayAccess for array-style-access to the attributes. offsetSet() and offsetUnset() throw a BadMethodCallException as modifications are not allowed on schema information nodes.
OpenLDAP
Additionally the common methods above apply to instances of Zend_Ldap_Node_Schema_OpenLDAP.
744
Zend_Ldap
Zend_Ldap_Node_Schema_AttributeType_OpenLdap| Returns the parent attribute type in the inhertitance tree if null getParent() one exists.
ActiveDirectory
Zend_Ldif_Encoder
Tabla 29.22. Zend_Ldif_Encoder API
Method array decode(string $string) Description Decodes the string $string into an array of LDIF items.
string encode(scalar|array| Encode $value into a LDIF representation. $options Zend_Ldap_Node $value, array $options) is an array that may contain the following keys: 'sort' Sort the given attributes with dn following objectClass and following all other attributes sorted alphabetically. TRUE by default. The LDIF format version. 1 by default.
'version'
745
Zend_Ldap
Method
Description 'wrap'
Usage Scenarios
Authentication scenarios
OpenLDAP ActiveDirectory
746
Zend_Ldap
'cn=Hugo Mller,ou=People,dc=my,dc=local');
747
Zend_Ldap
Extended operations
Copy and move entries in the LDAP
Ejemplo 29.8. Copy a LDAP entry recursively with all its descendants
$options = array(/* ... */); $ldap = new Zend_Ldap($options); $ldap->bind(); $ldap->copy('cn=Hugo Mller,ou=People,dc=my,dc=local', 'cn=Hans Meier,ou=People,dc=my,dc=local', true);
Ejemplo 29.9. Move a LDAP entry recursively with all its descendants to a different subtree
$options = array(/* ... */); $ldap = new Zend_Ldap($options); $ldap->bind(); $ldap->moveToSubtree('cn=Hugo Mller,ou=People,dc=my,dc=local', 'ou=Dismissed,dc=my,dc=local', true);
Tools
Creation and modification of DN strings Using the filter API to create search filters
Ejemplo 29.10. Create simple LDAP filters
$f1 $f2 $f3 $f4 $f5 $f6 $f7 $f8 $f9 $f10 = = = = = = = = = = Zend_Ldap_Filter::equals('name', 'value'); Zend_Ldap_Filter::begins('name', 'value'); Zend_Ldap_Filter::ends('name', 'value'); Zend_Ldap_Filter::contains('name', 'value'); Zend_Ldap_Filter::greater('name', 'value'); Zend_Ldap_Filter::greaterOrEqual('name', 'value'); Zend_Ldap_Filter::less('name', 'value'); Zend_Ldap_Filter::lessOrEqual('name', 'value'); Zend_Ldap_Filter::approx('name', 'value'); Zend_Ldap_Filter::any('name'); // // // // // // // // // // (name=value) (name=value*) (name=*value) (name=*value*) (name>value) (name>=value) (name<value) (name<=value) (name~=value) (name=*)
748
Zend_Ldap
$f3 = Zend_Ldap_Filter::begins('name', 'value'); $f4 = Zend_Ldap_Filter::ends('name', 'value'); // (&(name=value)(name=value*)(name=*value)) $f5 = Zend_Ldap_Filter::andFilter($f2, $f3, $f4); // (|(name=value)(name=value*)(name=*value)) $f6 = Zend_Ldap_Filter::orFilter($f2, $f3, $f4);
Adding a new node to the LDAP Deleting a node from the LDAP Updating a node on the LDAP
Extended operations
Copy and move nodes in the LDAP
Tree traversal
Ejemplo 29.12. Traverse LDAP tree recursively
$options = array(/* ... */); $ldap = new Zend_Ldap($options); $ldap->bind(); $ri = new RecursiveIteratorIterator($ldap->getBaseNode(), RecursiveIteratorIterator::SELF_FIRST); foreach ($ri as $rdn => $n) {
749
Zend_Ldap
var_dump($n); }
Schema Browsing
Ejemplo 29.14. Getting hands on the server schema
$options = array(/* ... */); $ldap = new Zend_Ldap($options); $schema = $ldap->getSchema(); $classes = $schema->getObjectClasses();
OpenLDAP ActiveDirectory
Schema browsing on ActiveDirectory servers
Due to restrictions on Microsoft ActiveDirectory servers regarding the number of entries returned by generic search routines and due to the structure of the ActiveDirectory schema repository, schema browsing is currently not available for Microsoft ActiveDirectory servers.
750
Zend_Ldap
=> 'uid=rogasawara,ou=###,o=Airius', => array('top', 'person', 'organizationalPerson', 'inetOrgPerson'), 'uid' => array('rogasawara'), 'mail' => array('rogasawara@airius.co.jp'), 'givenname;lang-ja' => array('####'), 'sn;lang-ja' => array('###'), 'cn;lang-ja' => array('### ####'), 'title;lang-ja' => array('### ##'), 'preferredlanguage' => array('ja'), 'givenname' => array('####'), 'sn' => array('###'), 'cn' => array('### ####'), 'title' => array('### ##'), 'givenname;lang-ja;phonetic' => array('####'), 'sn;lang-ja;phonetic' => array('#####'), 'cn;lang-ja;phonetic' => array('##### ####'), 'title;lang-ja;phonetic' => array('###### ####'), 'givenname;lang-en' => array('Rodney'), 'sn;lang-en' => array('Ogasawara'), 'cn;lang-en' => array('Rodney Ogasawara'), 'title;lang-en' => array('Sales, Director'),
); $ldif = Zend_Ldap_Ldif_Encoder::encode($data, array('sort' => false, 'version' => null)); /* $ldif contains: dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson uid: rogasawara mail: rogasawara@airius.co.jp givenname;lang-ja:: 44Ot44OJ44OL44O8 sn;lang-ja:: 5bCP56yg5Y6f cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA== title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw== preferredlanguage: ja givenname:: 44Ot44OJ44OL44O8 sn:: 5bCP56yg5Y6f cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA== title:: 5Za25qWt6YOoIOmDqOmVtw== givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8 sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA== title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg== givenname;lang-en: Rodney sn;lang-en: Ogasawara cn;lang-en: Rodney Ogasawara title;lang-en: Sales, Director
751
Zend_Ldap
*/
752
Zend_Ldap
753
754
Cargando Archivos
El mtodo esttico Zend_Loader::loadFile() carga un archivo PHP. El archivo cargado puede contener cualquier cdigo PHP. El mtodo se comporta como un envoltorio para la funcin PHP include() [http://php.net/ include]. Este mtodo devuelve un booleano false en caso de fallo, por ejemplo, si el archivo especificado no existe.
Cargando Clases
El mtodo esttico Zend_Loader::loadClass($class, $dirs) carga un archivo PHP y comprueba la existencia de la clase.
755
Zend_Loader
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 aadiendo '.php'. En el ejemplo de arriba, 'Container_Tree' se convierte en 'Container\\Tree.php' en Windows. Si $dirs es una cadena o un array, Zend_Loader::loadClass() busca las carpetas en el orden suministrado. El primer archivo encontrado es cargado. Si el archivo no existe en el $dirs especificado, entonces se busca en el include_path del entorno PHP. Si el archivo no es encontrado o la clase no existe despus de la carga, Zend_Loader::loadClass() lanza una Zend_Exception. Zend_Loader::loadFile() se usa para cargar, as que el nombre de la clase puede contener nicamente caracteres alfanumricos, guiones ('-'), barras bajas ('_'), y puntos ('.').
Usando el Autoloader
La clase Zend_Loader contiene un mtodo que se puede registrar con PHP SPL autoloader. Zend_Loader::autoload() es el mtodo callback. Por comodidad, Zend_Loader permite a la funcin registerAutoload() registrar su mtodo autoload(). Si la extensin spl_autoload no est presente en el entorno PHP, entonces el mtodo registerAutoload() lanza una Zend_Exception.
Ejemplo 30.5. Ejemplo de registro del mtodo de callback autoload desde una clase extendida
Debido a la semntica de referencia de funciones estticas en PHP, se debe implementar cdigo tanto para la clase loadClass() como autoload(), y autoload() debe llamar a self::loadClass(). Si su mtodo autoload() delega en su padre la llamada a self::loadClass(), entonces llamar al mtodo con ese nombre en la clase padre, no la subclase.
756
Zend_Loader
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'); Se puede eliminar un callback de autoload. registerAutoload() tiene un segundo parmetro opcional, que es true por defecto. Si este parmetro es false, el callback de autoload ser borrado de la pila de autoload SPL.
The Autoloader
Zend_Loader_Autoloader introduces a comprehensive autoloading solution for Zend Framework. It has been designed with several goals in mind: Provide a true namespace autoloader. (Previous incarnations intercepted all userland namespaces.) Allow registering arbitrary callbacks as autoloaders, and manage them as a stack. (At the time of this writing, this overcomes some issues with spl_autoload, which does not allow re-registering a callback that utilizes an instance method.) Allow optimistic matching of namespaces to provide faster class resolution. Zend_Loader_Autoloader implements a singleton, making it unversally accessible. This provides the ability to register additional autoloaders from anywhere in your code as necessary.
$autoloader = Zend_Loader_Autoloader::getInstance(); By default, the autoloader is configured to match the "Zend_" and "ZendX_" namespaces. If you have your own library code that uses your own namespace, you may register it with the autoloader using the registerNamespace() method. For instance, if your library code is prefixed with "My_", you could do so as follows:
$autoloader->registerNamespace('My_');
757
Zend_Loader
Namespace Prefixes
You'll note that the previous example uses "My_" and not "My". This is because Zend_Loader_Autoloader is intended as a general purpose autoloader, and does not make the assumption that a given class prefix namespace includes an underscore. If your class namespace does include one, you should include it when registering your namespace. You can also register arbitrary autoloader callbacks, optionally with a specific namespace (or group of namespaces). Zend_Loader_Autoloader will attempt to match these first before using its internal autoloading mechanism. As an example, you may want to utilize one or more eZcomponents components with your Zend Framework application. To use its autoloading capabilities, push it onto the autoloader stack using pushAutoloader(): $autoloader->pushAutoloader(array('ezcBase', 'autoload'), 'ezc'); This tells the autoloader to use the eZcomponents autoloader for classes beginning with "ezc". You can use the unshiftAutoloader() method to add the autoloader to the beginning of the autoloader chain. By default, Zend_Loader_Autoloader does no error suppression when using its internal autoloader, which utilizes Zend_Loader::loadClass(). Most of the time, this is exactly what you want. However, there may be cases where you want to suppress them. You can do this using suppressNotFoundWarnings(): $autoloader->suppressNotFoundWarnings(true); Finally, there may be times when you want the autoloader to load any namespace. For instance, PEAR libraries do not share a common namespace, making specifying individual namespaces difficult when many PEAR components are in use. You can use the setFallbackAutoloader() method to have the autoloader act as a catch-all: $autoloader->setFallbackAutoloader(true);
758
Zend_Loader
ZendFramework/ |-- 1.9.2/ | |-- library/ |-- ZendFramework-1.9.1-minimal/ | |-- library/ |-- 1.8.4PL1/ | |-- library/ |-- 1.8.4/ | |-- library/ |-- ZendFramework-1.8.3/ | |-- library/ |-- 1.7.8/ | |-- library/ |-- 1.7.7/ | |-- library/ |-- 1.7.6/ | |-- library/ (where path points to the directory "ZendFramework" in the above example) Note that each subdirectory should contain the directory library, which contains the actual Zend Framework library code. The individual subdirectory names may be version numbers, or simply be the untarred contents of a standard Zend Framework distribution tarball/zipfile. Now, let's address the use cases. In the first use case, in development, we want to track the latest source install. We can do that by passing "latest" as the version: $autoloader->setZfPath($path, 'latest'); In the example from above, this will map to the directory ZendFramework/1.9.2/library/; you can verify this by checking the return value of getZfPath(). In the second situation, for quality assurance, let's say we want to pin to the 1.8 minor release, using the latest install you have for that release. You can do so as follows: $autoloader->setZfPath($path, '1.8'); In this case, it will find the directory ZendFramework/1.8.4PL1/library/. In the final case, for production, we'll pin to a specific version -- 1.7.7, since that was what was available when Quality Assurance tested prior to our release. $autoloader->setZfPath($path, '1.7.7'); Predictably, it finds the directory ZendFramework/1.7.7/library/. You can also specify these values in the configuration file you use with Zend_Application. To do so, you'd specify the following information: [production] autoloaderZfPath = "path/to/ZendFramework" autoloaderZfVersion = "1.7.7" [qa]
759
Zend_Loader
autoloaderZfVersion = "1.8" [development] autoloaderZfVersion = "latest" Note the different environment sections, and the different version specified in each environment; these factors will allow Zend_Application to configure the autoloader appropriately.
Performance implications
For best performance, either do not use this feature, or specify a specific Zend Framework version (i.e., not "latest", a major revision such as "1", or a minor revision such as "1.8"). Otherwise, the autoloader will need to scan the provided path for directories matching the criteria -- a somewhat expensive operation to perform on each request.
Autoloader Reference
Below, please find a guide to the methods available in Zend_Loader_Autoloader.
resetInstance()
void
N/A
760
Zend_Loader
Method autoload($class)
Parameters
Description
$class, required. A Attempt to resolve a class string class name to load. name to a file and load it. Specify an alternate PHP callback to use for the default autoloader implementation. Retrieve the default autoloader implementation; by default, this is Zend_Loader::loadClass(). Set a list of concrete autoloaders to use in the autoloader stack. Each item in the autoloaders array must be a PHP callback. Retrieve the autoloader stack. internal
getDefaultAutoloader() callback
N/A
getAutoloaders()
Array
N/A
getNamespaceAutoloaders($namespace) Array
$namespace, required Fetch all autoloaders that have registered to load a specific namespace.
registerNamespace($namespace) Zend_Loader_Autoloader $namespace, required. Register one or more namespaces with the default autoloader. If $namespace is a string, it registers that namespace; if it's an array of strings, registers each as a namespace. unregisterNamespace($namespace) Zend_Loader_Autoloader $namespace, required. Unregister one or more namespaces from the default autoloader. If $namespace is a string, it unregisters that namespace; if it's an array of strings, unregisters each as a namespace. getRegisteredNamespace() Array N/A Returns an array of all namespaces registered with the default autoloader. Set or retrieve the value of the flag used to indicate whether the default autoloader implementation should suppress "file not found" warnings. If no arguments or a null value is passed, returns a boolean indicating the status of the flag; if a boolean is passed,
761
Zend_Loader
Method
Return Value
Parameters
Description the flag is set to that value and the autoloader instance is returned (to allow method chaining). Set the value of the flag used to indicate whether or not the default autoloader should be used as a fallback or catch-all autoloader for all namespaces. Retrieve the value of the flag used to indicate whether or not the default autoloader should be used as a fallback or catch-all autoloader for all namespaces. By default, this is false. Get the list of namespaced autoloaders that could potentially match the provided class. If none match, all global (nonnamespaced) autoloaders are returned.
isFallbackAutoloader() Boolean
N/A
getClassAutoloaders($class) Array
$class, required.
unshiftAutoloader($callback, Zend_Loader_Autoloader $callback, required. Add a concrete autoloader $namespace = '') A valid PHP callback implementation to the beginning of the internal $namespace, optional. autoloader stack. If a A string representing a namespace is provided, that class prefix namespace. namespace will be used to match optimistically; otherwise, the autoloader will be considered a global autoloader. pushAutoloader($callback, Zend_Loader_Autoloader $callback, required. Add a concrete autoloader $namespace = '') A valid PHP callback implementation to the end of the internal $namespace, optional. autoloader stack. If a A string representing a namespace is provided, that class prefix namespace. namespace will be used to match optimistically; otherwise, the autoloader will be considered a global autoloader. removeAutoloader($callback, Zend_Loader_Autoloader $callback, required. Remove a concrete $namespace = '') A valid PHP callback autoloader implementation from the internal autoloader $namespace, optional. stack. If a namespace or A string representing a namespaces are provided, class prefix namespace, the callback will be removed
762
Zend_Loader
Method
Return Value
Parameters Description or an array of namespace from that namespace or strings. namespaces only.
Resource Autoloaders
Resource autoloaders are intended to manage namespaced library code that follow Zend Framework coding standard guidelines, but which do not have a 1:1 mapping between the class name and the directory structure. Their primary purpose is to facilitate autoloading application resource code, such as application-specific models, forms, and ACLs. Resource autoloaders register with the autoloader on instantiation, with the namespace to which they are associated. This allows you to easily namespace code in specific directories, and still reap the benefits of autoloading.
path/to/some/directory/ acls/ Site.php forms/ Login.php models/ User.php Within this directory, all code is prefixed with the namespace "My_". Within the "acls" subdirectory, the component prefix "Acl_" is added, giving a final class name of "My_Acl_Site". Similarly, the "forms" subdirectory maps to "Form_", giving "My_Form_Login". The "models" subdirectory has no component namespace, giving "My_User". You can use a resource autoloader to autoload these classes. To instantiate the resource autoloader, you are required to pass at the minimum the base path and namespace for the resources it will be responsible for: $resourceLoader = new Zend_Loader_Autoloader_Resource(array( 'basePath' => 'path/to/some/directory', 'namespace' => 'My', ));
Base namespace
In Zend_Loader_Autoloader, you are expected to provide the trailing underscore ("_") in your namespace if your autoloader will use it to match the namespace. Zend_Loader_Autoloader_Resource makes the assumption that all code you are autoloading will use an underscore separator between namespaces, components, and classes. As a result, you do not need to use the trailing underscore when registering a resource autoloader. Now that we have setup the base resource autoloader, we can add some components to it to autoload. This is done using the addResourceType() method, which accepts three arguments: a resource "type", used internally as a reference name; the subdirectory path underneath the base path in which these resources live; and the component namespace to append to the base namespace. As an example, let's add each of our resource types.
763
Zend_Loader
->addResourceType('form', 'forms/', 'Form') ->addResourceType('model', 'models/'); Alternately, you could pass these as an array to addResourceTypes(); the following is equivalent to the above:
$resourceLoader->addResourceTypes(array( 'acl' => array( 'path' => 'acls/', 'namespace' => 'Acl', ), 'form' => array( 'path' => 'forms/', 'namespace' => 'Form', ), 'model' => array( 'path' => 'models/', ), )); Finally, you can specify all of this when instantiating the object, by simply specifying a "resourceTypes" key in the options passed and a structure like that above:
$resourceLoader = new Zend_Loader_Autoloader_Resource(array( 'basePath' => 'path/to/some/directory', 'namespace' => 'My', 'resourceTypes' => array( 'acl' => array( 'path' => 'acls/', 'namespace' => 'Acl', ), 'form' => array( 'path' => 'forms/', 'namespace' => 'Form', ), 'model' => array( 'path' => 'models/', ), ), ));
764
Zend_Loader
As an example, if you have a module with the prefix of "Blog_", and attempted to instantiate the class "Blog_Form_Entry", it would look in the resource directory's "forms/" subdirectory for a file named "Entry.php". When using module bootstraps with Zend_Application, an instance of Zend_Application_Module_Autoloader will be created by default for each discrete module, allowing you to autoload module resources.
Loading Plugins
A number of Zend Framework components are pluggable, and allow loading of dynamic functionality by specifying a class prefix and path to class files that are not necessarily on the include_path or do not necessarily follow traditional naming conventions. Zend_Loader_PluginLoader provides common functionality for this process. The basic usage of the PluginLoader follows Zend Framework naming conventions of one class per file, using the underscore as a directory separator when resolving paths. It allows passing an optional class prefix to prepend when determining if a particular plugin class is loaded. Additionally, paths are searched in LIFO order. Due to the LIFO search and the class prefixes, this allows you to define namespaces for your plugins, and thus override plugins from paths registered earlier.
application/ modules/ foo/ views/ helpers/ FormLabel.php FormSubmit.php bar/ views/ helpers/ FormSubmit.php library/ Zend/ View/ Helper/ FormLabel.php FormSubmit.php FormText.php Now, let's create a plugin loader to address the various view helper repositories available:
765
Zend_Loader
$loader = new Zend_Loader_PluginLoader(); $loader->addPrefixPath('Zend_View_Helper', 'Zend/View/Helper/') ->addPrefixPath('Foo_View_Helper', 'application/modules/foo/views/helpers') ->addPrefixPath('Bar_View_Helper', 'application/modules/bar/views/helpers'); We can then load a given view helper using just the portion of the class name following the prefixes as defined when adding the paths:
// load 'FormText' helper: $formTextClass = $loader->load('FormText'); // 'Zend_View_Helper_FormText'; // load 'FormLabel' helper: $formLabelClass = $loader->load('FormLabel'); // 'Foo_View_Helper_FormLabel' // load 'FormSubmit' helper: $formSubmitClass = $loader->load('FormSubmit'); // 'Bar_View_Helper_FormSubmit' Once the class is loaded, we can now instantiate it.
Nota
In some cases, you may use the same prefix for multiple paths. Zend_Loader_PluginLoader actually registers an array of paths for each given prefix; the last one registered will be the first one checked. This is particularly useful if you are utilizing incubator components.
$loader = new Zend_Loader_PluginLoader(array( 'Zend_View_Helper' => 'Zend/View/Helper/', 'Foo_View_Helper' => 'application/modules/foo/views/helpers', 'Bar_View_Helper' => 'application/modules/bar/views/helpers' )); Zend_Loader_PluginLoader also optionally allows you to share plugins across plugin-aware objects, without needing to utilize a singleton instance. It does so via a static registry. Indicate the registry name at instantiation as the second parameter to the constructor:
// Store plugins in static registry 'foobar': $loader = new Zend_Loader_PluginLoader(array(), 'foobar'); Other components that instantiate the PluginLoader using the same registry name will then have access to already loaded paths and plugins.
766
Zend_Loader
getPaths($prefix = null) returns all paths as prefix / path pairs if no $prefix is provided, or just the paths registered for a given prefix if a $prefix is present. clearPaths($prefix = null) will clear all registered paths by default, or only those associated with a given prefix, if the $prefix is provided and present in the stack. removePrefixPath($prefix, $path = null) allows you to selectively remove a specific path associated with a given prefix. If no $path is provided, all paths for that prefix are removed. If a $path is provided and exists for that prefix, only that path will be removed.
$classFileIncCache = APPLICATION_PATH . '/../data/pluginLoaderCache.php'; if (file_exists($classFileIncCache)) { include_once $classFileIncCache; } Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache); Obviously, the path and filename will vary based on your needs. This code should come as early as possible, to ensure that plugin-based components can make use of it. During development, you may wish to disable the cache. One method for doing so is to use a configuration key for determining whether or not the plugin loader should cache.
767
Zend_Loader
include_once $classFileIncCache; } if ($config->enablePluginLoaderCache) { Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache); } This technique allows you to keep your modifications to your configuration file rather than code.
768
What is Localization
Localization means that an application (or homepage) can be used from different users which speak different languages. But as you already have expected Localization means more than only translating strings. It includes Zend_Locale - Backend support of locales available for localization support within other Zend Framework components. Zend_Translate - Translating of strings. Zend_Date - Localization of dates, times. Zend_Calendar - Localization of calendars (support for non-Gregorian calendar systems) Zend_Currency - Localization of currencies. Zend_Locale_Format - Parsing and generating localized numbers. Zend_Locale_Data - Retrieve localized standard strings as country names, language names and more from the CLDR [http://unicode.org/cldr/] . TODO - Localization of collations
769
Zend_Locale
What is a Locale?
Each computer user makes use of Locales, even when they don't know it. Applications lacking localization support, normally have implicit support for one particular locale (the locale of the author). When a class or function makes use of localization, we say it is locale-aware. How does the code know which localization the user is expecting? A locale string or object identifying a supported locale gives Zend_Locale and its subclasses access to information about the language and region expected by the user. Correct formatting, normalization, and conversions are made based on this information.
Nota
Be aware that there exist not only locales with 2 characters as most people think. Also there are languages and regions which are not only abbreviated with 2 characters. Therefor you should NOT strip the region and language yourself, but use Zend_Locale when you want to strip language or region from a locale string. Otherwise you could have unexpected behaviour within your code when you do this yourself. A user from USA would expect the language English and the region USA, yielding the locale identifier "en_US". A user in Germany would expect the language German and the region Germany, yielding the locale identifier "de_DE". See the list of pre-defined locale and region combinations [http://unicode.org/cldr/data/diff/supplemental/ languages_and_territories.html], if you need to select a specific locale within Zend Framework.
770
Zend_Locale
Zend_Locale(Zend_Locale::ENVIRONMENT) is used, then preference will be given to using the host server's environment configuration, as described below.
// default behavior, same as above $locale1 = new Zend_Locale(Zend_Locale::BROWSER); // prefer settings on host server $locale2 = new Zend_Locale(Zend_Locale::ENVIRONMENT); // perfer framework app default settings $locale3 = new Zend_Locale(Zend_Locale::FRAMEWORK); The search algorithm used by Zend_Locale for automatic selection of a locale uses three sources of information: 1. const Zend_Locale::BROWSER - The user's Web browser provides information with each request, which is published by PHP in the global variable HTTP_ACCEPT_LANGUAGE. If no matching locale can be found, then preference is given to ENVIRONMENT and lastly FRAMEWORK. 2. const Zend_Locale::ENVIRONMENT - PHP publishes the host server's locale via the PHP internal function setlocale(). If no matching locale can be found, then preference is given to FRAMEWORK and lastly BROWSER. 3. const Zend_Locale::FRAMEWORK - When Zend Framework has a standardized way of specifying component defaults (planned, but not yet available), then using this constant during instantiation will give preference to choosing a locale based on these defaults. If no matching locale can be found, then preference is given to ENVIRONMENT and lastly BROWSER.
771
Zend_Locale
If no locale can be detected, it will throw an exception and tell you that the automatic detection has been failed.
772
Zend_Locale
ZF Locale-Aware Classes
In the Zend Framework, locale-aware classes rely on Zend_Locale to automatically select a locale, as explained above. For example, in a Zend Framework web application, constructing a date using Zend_Date without specifying a locale results in an object with a locale based on information provided by the current user's web browser.
773
Zend_Locale
echo $date->getDate();
Zend_Locale_Format::setOptions(array $options)
The 'precision' option of a value is used to truncate or stretch extra digits. A value of '-1' disables modification of the number of digits in the fractional part of the value. The 'locale' option helps when parsing numbers and dates using separators and month names. The date format 'format_type' option selects between CLDR/ISO date format specifier tokens and PHP's date() tokens. The 'fix_date' option enables or disables heuristics that attempt to correct invalid dates. The 'number_format' option specifies a default number format for use with toNumber() (see the section called Number localization ). The 'date_format' option can be used to specify a default date format string, but beware of using getDate(), checkdateFormat() and getTime() after using setOptions() with a 'date_format'. To use these four methods with the default date format for a locale, use array('date_format' => null, 'locale' => $locale) for their options.
774
Zend_Locale
Using Zend_Locale
Zend_Locale also provides localized information about locales for each locale, including localized names for other locales, days of the week, month names, etc.
Equality
Zend_Locale also provides a convenience function to compare two locales. All locale-aware classes should provide a similar equality check.
Default locales
The method getDefault() returns an array of relevant locales using information from the user's web browser (if available), information from the environment of the host server, and Zend Framework settings. As with the constructor for Zend_Locale, the first parameter selects a preference of which information to consider (BROWSER, ENVIRONMENT, or FRAMEWORK) first. The second parameter toggles between returning all matching locales or only
775
Zend_Locale
the first/best match. Locale-aware components normally use only the first locale. A quality rating is included, when available.
776
Zend_Locale
Tabla 31.1. Details for getTranslationList($type = null, $locale = null, $value = null)
Type Language Script Territory Description Returns a localized list of all languages. The language part of the locale is returned as key and the translation as value Returns a localized list of all scripts. The script is returned as key and the translation as value Returns a localized list of all territories. This contains countries, continents and territories. To get only territories and continents use '1' as value. To get only countries use '2' as value. The country part of the locale is used as key where applicable. In the other case the official ISO code for this territory is used. The translated territory is returned as value. When you omit the value you will get a list with both. Returns a localized list of known variants of scripts. The variant is returned as key and the translation as value Returns a localized list of known keys. This keys are generic values used in translation. These are normally calendar, collation and currency. The key is returned as array key and the translation as value
Variant Key
777
Zend_Locale
Type Type
Description Returns a localized list of known types of keys. These are variants of types of calendar representations and types of collations. When you use 'collation' as value you will get all types of collations returned. When you use 'calendar' as value you will get all types of calendars returned. When you omit the value you will get a list all both returned. The type is used as key and the translation as value Returns a list of rules which describes how to format special text parts Returns a list of allowed characters within this locale Returns a list of allowed quoting characters for this locale Returns a list of known measurement values. This list is depreciated Returns a list of all month representations within this locale. There are several different representations which are all returned as sub array. If you omit the value you will get a list of all months from the 'gregorian' calendar returned. You can give any known calendar as value to get a list of months from this calendar returned. Use Zend_Date for simplicity Returns a localized list of all month names for this locale. If you omit the value you will get the normally used gregorian full name of the months where each month number is used as key and the translated month is returned as value. You can get the months for different calendars and formats if you give an array as value. The first array entry has to be the calendar, the second the used context and the third the width to return. Use Zend_Date for simplicity Returns a list of all day representations within this locale. There are several different representations which are all returned as sub array. If you omit the value you will get a list of all days from the 'gregorian' calendar returned. You can give any known calendar as value to get a list of days from this calendar returned. Use Zend_Date for simplicity Returns a localized list of all day names for this locale. If you omit the value you will get the normally used gregorian full name of the days where the english day abbreviation is used as key and the translated day is returned as value. You can get the days for different calendars and formats if you give an array as value. The first array entry has to be the calendar, the second the used context and the third the width to return. Use Zend_Date for simplicity Returns a list of values used for proper week calculations within a locale. Use Zend_Date for simplicity Returns a list of all quarter representations within this locale. There are several different representations which
Month
Days
Day
Week Quarters
778
Zend_Locale
Type
Description are all returned as sub array. If you omit the value you will get a list of all quarters from the 'gregorian' calendar returned. You can give any known calendar as value to get a list of quarters from this calendar returned Returns a localized list of all quarter names for this locale. If you omit the value you will get the normally used gregorian full name of the quarters where each quarter number is used as key and the translated quarter is returned as value. You can get the quarters for different calendars and formats if you give an array as value. The first array entry has to be the calendar, the second the used context and the third the width to return Returns a list of all era representations within this locale. If you omit the value you will get a list of all eras from the 'gregorian' calendar returned. You can give any known calendar as value to get a list of eras from this calendar returned Returns a localized list of all era names for this locale. If you omit the value you will get the normally used gregorian full name of the eras where each era number is used as key and the translated era is returned as value. You can get the eras for different calendars and formats if you give an array as value. The first array entry has to be the calendar and the second the width to return Returns a localized list of all date formats for this locale. The name of the dateformat is used as key and the format itself as value.If you omit the value you will get the date formats for the gregorian calendar returned. You can get the date formats for different calendars if you give the wished calendar as string. Use Zend_Date for simplicity Returns a localized list of all time formats for this locale. The name of the timeformat is used as key and the format itself as value. If you omit the value you will get the time formats for the gregorian calendar returned. You can get the time formats for different calendars if you give the wished calendar as string. Use Zend_Date for simplicity Returns a localized list of all known date-time formats for this locale. The name of the date-time format is used as key and the format itself as value. If you omit the value you will get the date-time formats for the gregorian calendar returned. You can get the date-time formats for different calendars if you give the wished calendar as string. Use Zend_Date for simplicity Returns a list of default formats for given date or time items Returns a list of date or time formats which are used when you want to display intervals. The list is a multidimentional array where the first dimension is the
Quarter
Eras
Era
Date
Time
DateTime
DateItem DateInterval
779
Zend_Locale
Type
Description interval format, and the second dimension is the token with the greatest difference. Returns a localized list of date fields which can be used to display calendars or date strings like 'month' or 'year' in a wished language. If you omit the value you will get this list for the gregorian calendar returned. You can get the list for different calendars if you give the wished calendar as string Returns a localized list of relative dates which can be used to display textual relative dates like 'yesterday' or 'tomorrow' in a wished language. If you omit the value you will get this list for the gregorian calendar returned. You can get the list for different calendars if you give the wished calendar as string Returns a localized list of characters used for number representations Returns a localized list of names for currencies. The currency is used as key and the translated name as value. Use Zend_Currency for simplicity Returns a list of currencies for localized names. The translated name is used as key and the currency as value. Use Zend_Currency for simplicity Returns a list of known localized currency symbols for currencies. The currency is used as key and the symbol as value. Use Zend_Currency for simplicity Returns a list of localized strings for acceptance ('yes') and negotation ('no'). Use Zend_Locale's getQuestion method for simplicity Returns a list of fractions for currency values. The currency is used as key and the fraction as integer value. Use Zend_Currency for simplicity Returns a list of how to round which currency. The currency is used as key and the rounding as integer value. Use Zend_Currency for simplicity Returns a list of currencies which are known to be used within a region. The ISO3166 value ('region') is used as array key and the ISO4217 value ('currency') as array value. Use Zend_Currency for simplicity Returns a list of regions where a currency is used . The ISO4217 value ('currency') is used as array key and the ISO3166 value ('region') as array value. When a currency is used in several regions these regions are separated with a whitespace. Use Zend_Currency for simplicity Returns a list of territories with the countries or sub territories which are included within that territory. The ISO territory code ('territory') is used as array key and the ISO3166 value ('region') as array value. When a territory
Field
Relative
Symbols NameToCurrency
CurrencyToName
CurrencySymbol
Question
CurrencyFraction
CurrencyRounding
CurrencyToRegion
RegionToCurrency
RegionToTerritory
780
Zend_Locale
Type
Description contains several regions these regions are separated with a whitespace Returns a list of regions and the territories where these regions are located. The ISO3166 code ('region') is used as array key and the ISO territory code ('territory') as array value. When a region is located in several territories these territories are separated with a whitespace Returns a list of scripts which are used within a language. The language code is used as array key and the script code as array value. When a language contains several scripts these scripts are separated with a whitespace Returns a list of languages which are using a script. The script code is used as array key and the language code as array value. When a script is used in several languages these languages are separated with a whitespace Returns a list of countries which are using a language. The country code is used as array key and the language code as array value. When a language is used in several countries these countries are separated with a whitespace Returns a list of countries and the languages spoken within these countries. The country code is used as array key and the language code as array value. When a territory is using several languages these languages are separated with a whitespace Returns a list of windows timezones and the related ISO timezone. The windows timezone is used as array key and the ISO timezone as array value Returns a list of ISO timezones and the related windows timezone. The ISO timezone is used as array key and the windows timezone as array value Returns a list of regions or territories and the related ISO timezone. The ISO timezone is used as array key and the territory code as array value Returns a list of timezones and the related region or territory code. The region or territory code is used as array key and the ISO timezone as array value Returns a localized list of cities which can be used as translation for a related timezone. Not for all timezones is a translation available, but for a user is the real city written in his languages more accurate than the ISO name of this timezone. The ISO timezone is used as array key and the translated city as array value Returns a list of timezones for localized city names. The localized city is used as array key and the ISO timezone name as array value
TerritoryToRegion
ScriptToLanguage
LanguageToScript
TerritoryToLanguage
LanguageToTerritory
TimezoneToWindows
WindowsToTimezone
TerritoryToTimezone
TimezoneToTerritory
CityToTimezone
TimezoneToCity
781
Zend_Locale
Type PhoneToTerritory
Description Returns a list of phone codes which are known to be used within a territory. The territory (region) is used as array key and the telephone code as array value Returns a list of territories where a phone is used . The phone code is used as array key and the territory (region) as array value. When a phone code is used in several territories these territories are separated with a whitespace Returns a list of 3 digit number codes for territories. The territory (region) is used as array key and the 3 digit number code as array value Returns a list of territories with their 3 digit number code. The 3 digit number code is used as array key and the territory (region) as array value Returns a list of 3 sign character codes for territories. The territory (region) is used as array key and the 3 sign character code as array value Returns a list of territories with their 3 sign character code. The 3 sign character code is used as array key and the territory (region) as array value Returns a list of territories with a regex for postal codes which are included within that territory. The ISO territory code ('territory') is used as array key and the regex as array value. Returns a list of scripts with the notation for digits used within the script Returns a list of replacement characters for often used unicode characters. This can be used to replace "" with "(C)" for example Returns a list of unicode characters for often used replacement characters. This can be used to replace "(C)" with "" for example Returns a list of locale dependencies which can be used to upgrade a language to a full qualified locale Returns a list of localized calendar units. This can be used to translate the strings "day", "month" and so on automatically
TerritoryToPhone
NumericToTerritory
TerritoryToNumeric
Alpha3ToTerritory
TerritoryToAlpha3
PostalToTerritory
NumberingSystem FallbackToChar
CharToFallback
LocaleUpgrade Unit
If you are in need of a single translated value, you can use the getTranslation() method. It returns always a string but it accepts some different types than the getTranslationList() method. Also value is the same as before with one difference. You have to give the detail you want to get returned as additional value.
Nota
Because you have almost always give a value as detail this parameter has to be given as first parameter. This differs from the getTranslationList() method. See the following table for detailed information:
782
Zend_Locale
Tabla 31.2. Details for getTranslation($value = null, $type = null, $locale = null)
Type Language Script Territory or Country Description Returns a translation for a language. To select the wished translation you must give the language code as value Returns a translation for a script. To select the wished translation you must give the script code as value Returns a translation for a territory. This can be countries, continents and territories. To select the wished variant you must give the territory code as value Returns a translation for a script variant. To select the wished variant you must give the variant code as value Returns translation for a known keys. This keys are generic values used in translation. These are normally calendar, collation and currency. To select the wished key you must give the key code as value Returns the default calendar for the given locale. For most locales this will be 'gregorian'. Use Zend_Date for simplicity Returns the default context for months which is used within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity Returns the default format for months which is used within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity Returns a translation for a month. You have to give the number of the month as integer value. It has to be between 1 and 12. If you want to receive data for other calendars, contexts or formats, then you must give an array instead of an integer with the expected values. The array has to look like this: array( 'calendar', 'context', 'format', 'month number'). If you give only an integer then the default values are the 'gregorian' calendar, the context 'format' and the format 'wide'. Use Zend_Date for simplicity Returns the default context for days which is used within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity Returns the default format for days which is used within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity Returns a translation for a day. You have to give the english abbreviation of the day as string value ('sun', 'mon', etc.). If you want to receive data for other calendars, contexts or format, then you must give an array instead of an integer with the expected values. The array has to look like this: array('calendar', 'context', 'format', 'day abbreviation'). If you give
Variant Key
DefaultCalendar
MonthContext
DefaultMonth
Month
DayContext
DefaultDay
Day
783
Zend_Locale
Type
Description only an string then the default values are the 'gregorian' calendar, the context 'format' and the format 'wide'. Use Zend_Date for simplicity Returns a translation for a quarter. You have to give the number of the quarter as integer and it has to be between 1 and 4. If you want to receive data for other calendars, contexts or formats, then you must give an array instead of an integer with the expected values. The array has to look like this: array('calendar', 'context', 'format', 'quarter number'). If you give only an string then the default values are the 'gregorian' calendar, the context 'format' and the format 'wide' Returns a translation for 'AM' in a expected locale. If you want to receive data for other calendars an string with the expected calendar. If you omit the value then the 'gregorian' calendar will be used. Use Zend_Date for simplicity Returns a translation for 'PM' in a expected locale. If you want to receive data for other calendars an string with the expected calendar. If you omit the value then the 'gregorian' calendar will be used. Use Zend_Date for simplicity Returns a translation for an era within a locale. You have to give the era number as string or integer. If you want to receive data for other calendars or formats, then you must give an array instead of the era number with the expected values. The array has to look like this: array('calendar', 'format', 'era number'). If you give only an string then the default values are the 'gregorian' calendar and the 'abbr' format Returns the default date format which is used within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity Returns the date format for an given calendar or format within a locale. If you omit the value then the 'gregorian' calendar will be used with the 'medium' format. If you give a string then the 'gregorian' calendar will be used with the given format. Or you can also give an array which will have to look like this: array('calendar', 'format'). Use Zend_Date for simplicity Returns the default time format which is used within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity Returns the time format for an given calendar or format within a locale. If you omit the value then the 'gregorian' calendar will be used with the 'medium' format. If you give a string then the 'gregorian' calendar will be used with the given format. Or you can also give an array which
Quarter
Am
Pm
Era
DefaultDate
Date
DefaultTime
Time
784
Zend_Locale
Type
Description will have to look like this: array('calendar', 'format'). Use Zend_Date for simplicity Returns the datetime format for the given locale which indicates how to display date with times in the same string within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity Returns the default format for a given date or time item Returns the interval format for a given date or time format. The first value is the calendar format, normally 'gregorian'. The second value is the interval format and the third value the token with the greatest difference. For example: array('gregorian', 'yMMMM', 'y') returns the interval format for the date format 'yMMMM' where 'y' has the greatest difference. Returns a translated date field which can be used to display calendars or date strings like 'month' or 'year' in a wished language. You must give the field which has to be returned as string. In this case the 'gregorian' calendar will be used. You can get the field for other calendar formats if you give an array which has to look like this: array('calendar', 'date field') Returns a translated date which is relative to today which can include date strings like 'yesterday' or 'tomorrow' in a wished language. You have to give the number of days relative to tomorrow to receive the expected string. Yesterday would be '-1', tomorrow '1' and so on. This will use the 'gregorian' calendar. If you want to get relative dates for other calendars you will have to give an array which has to look like this: array('calendar', 'relative days'). Use Zend_Date for simplicity Returns the format for decimal numbers within a given locale. Use Zend_Locale_Format for simplicity Returns the format for scientific numbers within a given locale Returns the format for percentage numbers within a given locale Returns the format for displaying currency numbers within a given locale. Use Zend_Currency for simplicity Returns the translated name for a given currency. The currency has to be given in ISO format which is for example 'EUR' for the currency 'euro'. Use Zend_Currency for simplicity Returns a currency for a given localized name. Use Zend_Currency for simplicity
DateTime
DateItem DateInterval
Field
Relative
CurrencyToName
785
Zend_Locale
Type CurrencySymbol
Description Returns the used symbol for a currency within a given locale. Not for all currencies exists a symbol. Use Zend_Currency for simplicity Returns a localized string for acceptance ('yes') and negotation ('no'). You have to give either 'yes' or 'no' as value to receive the expected string. Use Zend_Locale's getQuestion method for simplicity Returns the fraction to use for a given currency. You must give the currency as ISO value. Use Zend_Currency for simplicity Returns how to round a given currency. You must give the currency as ISO value. If you omit the currency then the 'DEFAULT' rounding will be returned. Use Zend_Currency for simplicity Returns the currency for a given region. The region code has to be given as ISO3166 string for example 'AT' for austria. Use Zend_Currency for simplicity Returns the regions where a currency is used. The currency has to be given as ISO4217 code for example 'EUR' for euro. When a currency is used in multiple regions, these regions are separated with a whitespace character. Use Zend_Currency for simplicity Returns the regions for a given territory. The territory has to be given as ISO4217 string for example '001' for world. The regions within this territory are separated with a whitespace character Returns the territories where a given region is located. The region has to be given in ISO3166 string for example 'AT' for austria. When a region is located in multiple territories then these territories are separated with a whitespace character Returns the scripts which are used within a given language. The language has to be given as ISO language code for example 'en' for english. When multiple scripts are used within a language then these scripts are separated with a whitespace character Returns the languages which are used within a given script. The script has to be given as ISO script code for example 'Latn' for latin. When a script is used in multiple languages then these languages are separated with a whitespace character Returns the territories where a given language is used. The language has to be given as ISO language code for example 'en' for english. When multiple territories exist where this language is used then these territories are separated with a whitespace character Returns the languages which are used within a given territory. The territory has to be given as ISO3166 code
Question
CurrencyFraction
CurrencyRounding
CurrencyToRegion
RegionToCurrency
RegionToTerritory
TerritoryToRegion
ScriptToLanguage
LanguageToScript
TerritoryToLanguage
LanguageToTerritory
786
Zend_Locale
Type
Description for example 'IT' for italia. When a language is used in multiple territories then these territories are separated with a whitespace character Returns a ISO timezone for a given windows timezone Returns a windows timezone for a given ISO timezone Returns the territory for a given ISO timezone Returns the ISO timezone for a given territory Returns the localized city for a given ISO timezone. Not for all timezones does a city translation exist Returns the ISO timezone for a given localized city name. Not for all cities does a timezone exist Returns the telephone code for a given territory (region). The territory code has to be given as ISO3166 string for example 'AT' for austria Returns the territory (region) where a telephone code is used. The telephone code has to be given as plain integer code for example '43' for +43. When a telephone code is used in multiple territories (regions), these territories are separated with a whitespace character Returns the 3 digit number code for a given territory (region). The territory code has to be given as ISO3166 string for example 'AT' for austria Returns the territory (region) for a 3 digit number code. The 3 digit number code has to be given as plain integer code for example '43' Returns the 3 sign character code for a given territory (region). The territory code has to be given as ISO3166 string for example 'AT' for austria Returns the territory (region) for a 3 sign character code Returns the a regex for postal codes for a given territory. The territory has to be given as ISO4217 string for example '001' for world Returns a scripts with the notation for digits used within this script Returns a replacement character for a often used unicode character. This can be used to replace "" with "(C)" for example Returns a unicode character for a often used replacement character. This can be used to replace "(C)" with "" for example Returns a locale dependencies for a given language which can be used to upgrade this language to a full qualified locale Returns a localized calendar unit. This can be used to translate the strings "day", "month" and so on
TerritoryToPhone
NumericToTerritory
TerritoryToNumeric
Alpha3ToTerritory
TerritoryToAlpha3 PostalToTerritory
NumberingSystem FallbackToChar
CharToFallback
LocaleUpgrade
Unit
787
Zend_Locale
Type
Description automatically. The first parameter has to be the type, and the second parameter has to be the count
Nota
With Zend Framework 1.5 several old types have been renamed. This has to be done because of several new types, some misspelling and to increase the usability. See this table for a list of old to new types:
The example below demonstrates how to obtain the names of things in different languages.
788
Zend_Locale
To generate a list of all languages known by Zend_Locale, with each language name shown in its own language, try the example below in a web page. Similarly, getCountryTranslationList() and getCountryTranslation() could be used to create a table mapping your native language names for regions to the names of the regions shown in another language. Use a try .. catch block to handle exceptions that occur when using a locale that does not exist. Not all languages are also locales. In the example, below exceptions are ignored to prevent early termination.
789
Zend_Locale
( [0] => ja [1] => j ) [noarray] => Array ( [0] => nein [1] => n ) [yesexpr] => ^([jJ][aA]?)|([jJ]?) [noexpr] => ^([nN]([eE][iI][nN])?)|([nN]?) )
Nota
Until 1.0.3 yesabbr from the underlaying locale data was also available. Since 1.5 this information is no longer standalone available, but you will find the information from it within yesarray.
Nota
Note that the locales are returned as key of the array you will receive. The value is always a boolean true.
Detecting locales
When you want to detect if a given input, regardless of its source, is a locale you should use the static isLocale() method. The first parameter of this method is the string which you want to check.
790
Zend_Locale
You should also note that any given locale string will automatically be degraded if the region part does not exist for this locale. In our previous example the language 'to' does not exist in the region 'RU', but you will still get true returned as Zend_Locale can work with the given input. Still it's sometimes usefull to prevent this automatic degrading, and this is where the second parameter of isLocale() comes in place. The strict parameter defaults to FALSE and can be used to prevent degrading when set to TRUE.
791
Zend_Locale
The following example shows how these checks and the above code can be simplified with one single call:
792
Zend_Locale
Also, the precision of the resulting decimal representation can be rounded to a desired length with getNumber() with the option 'precision'. If no precision is given, no rounding occurs. Use only PHP integers to specify the precision. If the resulting decimal representation should be truncated to a desired length instead of rounded the option 'number_format' can be used instead. Define the length of the decimal representation with the desired length of zeros. The result will then not be rounded. So if the defined precision within number_format is zero the value "1.6" will return "1", not "2. See the example nearby:
Number localization
toNumber($value, array $options = array()) can localize numbers to the following supported locales . This function will return a localized string of the given number in a conventional format for a specific locale. The 'number_format' option explicitly specifies a non-default number format for use with toNumber().
Unlimited length
toNumber() can localize numbers with unlimited length. It is not related to integer or float limitations. The same way as within getNumber(), toNumber() handles precision. If no precision is given, the complete localized number will be returned.
793
Zend_Locale
'locale' => $locale)); // will return 13.547,37 print $number; Using the option 'number_format' a self defined format for generating a number can be defined. The format itself has to be given in CLDR format as described below. The locale is used to get separation, precision and other number formatting signs from it. German for example defines ',' as precision separation and in English the '.' sign is used.
#,##,##0
12,34,567
. 0
1234567.1234 1234567.12
Number testing
isNumber($value, array $options = array()) checks if a given string is a number and returns true or false.
794
Zend_Locale
$locale = new Zend_Locale(); if (Zend_Locale_Format::isNumber('13.445,36', array('locale' => 'de_AT')) { print "Number"; } else { print "not a Number"; }
795
Zend_Locale
796
Zend_Locale
unsupported numeral system will result in an exception, to avoid accidentally performing an incorrect conversion due to a spelling error. All characters in the input, which are not numerals for the selected numeral system, are copied to the output with no conversion provided for unit separator characters. Zend_Locale* components rely on the data provided by CLDR (see their list of scripts grouped by language [http://unicode.org/cldr/data/diff/supplemental/ languages_and_scripts.html?sortby=date]). In CLDR and hereafter, the Europena/Latin numerals will be referred to as "Latin" or by the assigned 4-letter code "Latn". Also, the CLDR refers to this numeral systems as "scripts". Suppose a web form collected a numeric input expressed using Eastern Arabic digits "####". Most software and PHP functions expect input using Arabic numerals. Fortunately, converting this input to its equivalent Latin numerals "100" requires little effort using convertNumerals($inputNumeralString, $sourceNumeralSystem, $destNumeralSystem) , which returns the $input with numerals in the script $sourceNumeralSystem converted to the script $destNumeralSystem.
Ejemplo 31.39. Converting numerals from Eastern Arabic scripts to European/Latin scripts
$arabicScript = "####"; // Arabic for "100" (one hundred) $latinScript = Zend_Locale_Format::convertNumerals($arabicScript, 'Arab', 'Latn'); print "\nOriginal: " . $arabicScript; print "\nNormalized: " . $latinScript; Similarly, any of the supported numeral systems may be converted to any other supported numeral system.
Ejemplo 31.40. Converting numerals from Latin script to Eastern Arabic script
$latinScript = '123'; $arabicScript = Zend_Locale_Format::convertNumerals($latinScript, 'Latn', 'Arab'); print "\nOriginal: " . $latinScript; print "\nLocalized: " . $arabicScript;
Ejemplo 31.41. Getting 4 letter CLDR script code using a native-language name of the script
function getScriptCode($scriptName, $locale) { $scripts2names = Zend_Locale_Data::getList($locale, 'script'); $names2scripts = array_flip($scripts2names); return $names2scripts[$scriptName]; } echo getScriptCode('Latin', 'en'); // outputs "Latn" echo getScriptCode('Tamil', 'en'); // outputs "Taml" echo getScriptCode('tamoul', 'fr'); // outputs "Taml" For a list of supported numeral Zend_Locale::getTranslationList('numberingsystem', 'en'). systems call
797
Zend_Locale
For those needing to specify explicitly the format of the date string, the following format token specifiers are supported. If an invalid format specifier is used, such as the PHP 'i' specifier when in ISO format mode, then an error will be thrown by the methods in Zend_Locale_Format that support user-defined formats. These specifiers (below) are a small subset of the full "ISO" set supported by Zend_Date's toString(). If you need to use PHP date() compatible format specifiers, then first call setOptions(array('format_type' => 'php')). And if you want to convert only one special format string from PHP date() compatible format to "ISO" format use convertPhpToIsoFormat(). Currently, the only practical difference relates to the specifier for minutes ('m' using the ISO default, and 'i' using the PHP date format).
798
Zend_Locale
getDate() character h m s
Minimum 0 0 0
Maximum PHP maximum PHP maximum PHP maximum integer's integer's integer's
799
Zend_Locale
value for 'date_format' to prevent the use of a class-wide default date format set using setOptions(). This forces getDate to use the default date format for $locale.
800
Zend_Locale
Testing Dates
Use checkDateFormat($inputString, array('date_format' => $format, $locale)) to check if a given string contains all expected date parts. The checkDateFormat() method uses getDate(), but without the option 'fixdate' to avoid returning true when the input fails to conform to the date format. If errors are detected in the input, such as swapped values for months and days, the option 'fixdate' method will apply heuristics to "correct" dates before determining their validity.
801
Zend_Locale
// using the default date format for 'de_AT', is this a valid date? if (Zend_Locale_Format::checkDateFormat('13.Apr.2006', array('date_format' => Zend_Locale_Format::STANDARD, $locale) ) { print "date"; } else { print "not a date"; }
Normalizing a Time
Normally, a time will be returned with a date, if the input contains both. If the proper format is not known, but the locale relevant to the user input is known, then getTime() should be used, because it uses the default time format for the selected locale.
Testing Times
Use checkDateFormat() to check if a given string contains a proper time. The usage is exact the same as with checking Dates, only date_format should contain the parts which you expect to have.
Supported locales
Zend_Locale provides information on several locales. The following table shows all languages and their related locales, sorted by language:
802
Zend_Locale
803
Zend_Locale
Language Bengali
Region --Bangladesh India --China India --Bosnia and Herzegovina --Eritrea --Spain --Nigeria ----Czech Republic --United Kingdom --Denmark --Austria Belgium Switzerland Germany Liechtenstein Luxembourg --Maldives --Bhutan --Ghana Togo --Cyprus Greece
Tibetan
bo_CN bn_IN bs bs_BA byn byn_ER ca ca_ES cch cch_NG cop cs cs_CZ cy cy_GB da da_DK de de_AT de_BE
German
Divehi Dzongkha
Ewe
Greek
el_CY el_GR
804
Zend_Locale
Language
Locale en en_AS en_AU en_BE en_BW en_BZ en_CA en_GB en_GU en_HK en_IE en_IN en_JM
Region --American Samoa Australia Belgium Botswana Belize Canada United Kingdom Guam Hong Kong Ireland India Jamaica Marshall Islands Northern Mariana Islands Malta Namibia New Zealand Philippines Pakistan Singapore Trinidad and Tobago United States Minor Outlying Islands United States U.S. Virgin Islands South Africa Zimbabwe ----Argentina Bolivia Chile Colombia Costa Rica Dominican Republic Ecuador Spain Guatemala
English
en_MH en_MP en_MT en_NA en_NZ en_PH en_PK en_SG en_TT en_UM en_US en_VI en_ZA en_ZW
Esperanto
Spanish
805
Zend_Locale
Language
Locale es_HN es_MX es_NI es_PA es_PE es_PR es_PY es_SV es_US es_UY es_VE et et_EE eu eu_ES fa fa_AF fa_IR fi fi_FI fil fil_PH fo fo_FO fr fr_BE fr_CA fr_CH fr_FR fr_LU fr_MC fr_SN fur fur_IT ga ga_IE gaa gaa_GH
Region Honduras Mexico Nicaragua Panama Peru Puerto Rico Paraguay El Salvador United States Uruguay Venezuela --Estonia --Spain --Afghanistan Iran --Finland --Philippines --Faroe Islands --Belgium Canada Switzerland France Luxembourg Monaco Senegal --Italy --Ireland --Ghana
Estonian Basque
Persian
French
Friulian Irish Ga
806
Zend_Locale
Language Geez
Locale gez gez_ER gez_ET gl gl_ES gsw gsw_CH gu gu_IN gv gv_GB ha ha_GH
Region --Eritrea Ethiopia --Spain --Swiss --India --United Kingdom --Ghana Niger Nigeria Sudan --United States --Israel --India --Croatia --Hungary ------Indonesia --Nigeria --China ----Iceland ---
Hausa
ha_NE ha_NG ha_SD haw haw_US he he_IL hi hi_IN hr hr_HR hu hu_HU hy ia id id_ID ig ig_NG ii ii_CN in is is_IS it
Hawaiian Hebrew Hindi Croatian Hungarian Armenian Interlingua Indonesian Igbo Sichuan Yi Indonesian Icelandic Italian
807
Zend_Locale
Language
Region Switzerland Italy ------Japan --Georgia --Nigeria --Kenya --Nigeria --Ivory Coast --Kazakhstan --Greenland --Cambodia --India --South Korea --India --Guinea Liberia --Iraq
Inuktitut Hebrew Japanese Georgian Jju Kamba Tyap Koro Kazakh Kalaallisut Khmer Kannada Korean Konkani
iu iw ja ja_JP ka ka_GE kaj kaj_NG kam kam_KE kcg kcg_NG kfo kfo_CI kk kk_KZ kl kl_GL km km_KH kn kn_IN ko ko_KR kok kok_IN kpe kpe_GN kpe_LR ku ku_IQ Iran Syria Turkey kw kw_GB
Kpelle
--United Kingdom
808
Zend_Locale
Language Kirghiz
Locale ky ky_KG ln ln_CD ln_CG lo lo_LA lt lt_LT lv lv_LV mk mk_MK ml ml_IN mn mn_CN mn_MN mo mr mr_IN ms ms_BN ms_MY mt mt_MT my my_MM nb nb_NO nds nds_DE ne ne_IN ne_NP nl
Region --Kyrgyzstan --Congo - Kinshasa Congo - Brazzaville --Laos --Lithuania --Latvia --Macedonia --India --China Mongolia ----India --Brunei Malaysia --Malta --Myanmar --Norway --Germany --India Nepal --Belgium Netherlands
Lingala
Malay
Nepali
Dutch
nl_BE nl_NL
809
Zend_Locale
Language Norwegian Nynorsk Norwegian South Ndebele Northern Sotho Nyanja Occitan
Locale nn nn_NO no nr nr_ZA nso nso_ZA ny ny_MW oc oc_FR om om_ET om_KE or or_IN pa pa_IN pa_PK pl pl_PL ps ps_AF pt pt_BR pt_PT ro
Region --Norway ----South Africa --South Africa --Malawi --France --Ethiopia Kenya --India --India Pakistan --Poland --Afghanistan --Brazil Portugal --Moldova Romania --Russia Ukraine --Rwanda --India --Finland
Oromo
Oriya
Punjabi
Polish Pashto
Portuguese
Romanian
ro_MD ro_RO ru
Russian
Kinyarwanda Sanskrit
Northern Sami
810
Zend_Locale
Language
Locale se_NO sh sh_BA sh_CS sh_YU si si_LK sid sid_ET sk sk_SK sl sl_SI so so_DJ
Region Norway --Bosnia and Herzegovina Serbia and Montenegro Serbia --Sri Lanka --Ethiopia --Slovakia --Slovenia --Djibouti Ethiopia Kenya Somalia --Albania --Bosnia and Herzegovina Serbia and Montenegro Montenegro Serbia Serbia --Swaziland South Africa --Lesotho South Africa --Finland Sweden --Kenya Tanzania
Serbo-Croatian
Somali
Albanian
Serbian
Swati
ss_SZ ss_ZA st
Southern Sotho
st_LS st_ZA sv
Swedish
sv_FI sv_SE sw
Swahili
sw_KE sw_TZ
811
Zend_Locale
Locale syr syr_SY ta ta_IN te te_IN tg tg_TJ th th_TH ti ti_ER ti_ET tig tig_ER tl tn tn_ZA to to_TO tr tr_TR trv trv_TW ts ts_ZA tt tt_RU ug ug_CN uk uk_UA ur ur_IN ur_PK uz
Region --Syria --India --India --Tajikistan --Thailand --Eritrea Ethiopia --Eritrea ----South Africa --Tonga --Turkey --Taiwan --South Africa --Russia --China --Ukraine --India Pakistan --Afghanistan Uzbekistan
Tigrinya
Tigre Tagalog Tswana Tonga Turkish Taroko Tsonga Tatar Uighur Ukrainian
Urdu
Uzbek
uz_AF uz_UZ
812
Zend_Locale
Locale ve ve_ZA vi vi_VN wal wal_ET wo wo_SN xh xh_ZA yo yo_NG zh zh_CN zh_HK zh_MO zh_SG zh_TW zu zu_ZA
Region --South Africa --Vietnam --Ethiopia --Senegal --South Africa --Nigeria --China Hong Kong Macau Singapore Taiwan --South Africa
Chinese
Zulu
813
814
Creating a Log
To get started logging, instantiate a Writer and then pass it to a Log instance:
$logger = new Zend_Log(); $writer = new Zend_Log_Writer_Stream('php://output'); $logger->addWriter($writer); It is important to note that the Log must have at least one Writer. You can add any number of Writers using the Log's addWriter() method. Alternatively, you can pass a Writer directly to constructor of Log as a shortcut:
$writer = new Zend_Log_Writer_Stream('php://output'); $logger = new Zend_Log($writer); The Log is now ready to use.
Logging Messages
To log a message, call the log() method of a Log instance and pass it the message with a corresponding priority:
$logger->log('Informational message', Zend_Log::INFO); The first parameter of the log() method is a string message and the second parameter is an integer priority. The priority must be one of the priorities recognized by the Log instance. This is explained in the next section. A shortcut is also available. Instead of calling the log() method, you can call a method by the same name as the priority:
815
Zend_Log
$logger->log('Informational message', Zend_Log::INFO); $logger->info('Informational message'); $logger->log('Emergency message', Zend_Log::EMERG); $logger->emerg('Emergency message');
Destroying a Log
If the Log object is no longer needed, set the variable containing it to NULL to destroy it. This will automatically call the shutdown() instance method of each attached Writer before the Log object is destroyed:
$logger = null; Explicitly destroying the log in this way is optional and is performed automatically at PHP shutdown.
= = = = = = = =
0; 1; 2; 3; 4; 5; 6; 7;
// // // // // // // //
Emergency: system is unusable Alert: action must be taken immediately Critical: critical conditions Error: error conditions Warning: warning conditions Notice: normal but significant condition Informational: informational messages Debug: debug messages
These priorities are always available, and a convenience method of the same name is available for each one. The priorities are not arbitrary. They come from the BSD syslog protocol, which is described in RFC-3164 [http:// tools.ietf.org/html/rfc3164]. The names and corresponding priority numbers are also compatible with another PHP logging system, PEAR Log [http://pear.php.net/package/log], which perhaps promotes interoperability between it and Zend_Log. Priority numbers descend in order of importance. EMERG (0) is the most important priority. DEBUG (7) is the least important priority of the built-in priorities. You may define priorities of lower importance than DEBUG. When selecting the priority for your log message, be aware of this priority hierarchy and choose appropriately.
$logger->addPriority('FOO', 8); The snippet above creates a new priority, FOO, whose value is 8. The new priority is then available for logging:
816
Zend_Log
$logger->setEventItem('pid', getmypid()); The example above sets a new item named pid and populates it with the PID of the current process. Once a new item has been set, it is available automatically to all writers along with all of the other data event data during logging. An item can be overwritten at any time by calling the setEventItem() method again. Setting a new event item with setEventItem() causes the new item to be sent to all writers of the logger. However, this does not guarantee that the writers actually record the item. This is because the writers won't know what to do with it unless a formatter object is informed of the new item. Please see the section on Formatters to learn more.
Writers
A Writer is an object that inherits from Zend_Log_Writer_Abstract. A Writer's responsibility is to record log data to a storage backend.
Writing to Streams
Zend_Log_Writer_Stream sends log data to a PHP stream [http://www.php.net/stream]. To write log data to the PHP output buffer, use the URL php://output. Alternatively, you can send log data directly to a stream like STDERR (php://stderr).
$writer = new Zend_Log_Writer_Stream('php://output'); $logger = new Zend_Log($writer); $logger->info('Informational message'); To write data to a file, use one of the Filesystem URLs [http://www.php.net/manual/en/wrappers.php#wrappers.file]:
$writer = new Zend_Log_Writer_Stream('/path/to/logfile'); $logger = new Zend_Log($writer); $logger->info('Informational message'); By default, the stream opens in the append mode ("a"). To open it with a different mode, the Zend_Log_Writer_Stream constructor accepts an optional second parameter for the mode. The constructor of Zend_Log_Writer_Stream also accepts an existing stream resource:
817
Zend_Log
$stream = @fopen('/path/to/logfile', 'a', false); if (! $stream) { throw new Exception('Failed to open stream'); } $writer = new Zend_Log_Writer_Stream($stream); $logger = new Zend_Log($writer); $logger->info('Informational message'); You cannot specify the mode for existing stream resources. Doing so causes a Zend_Log_Exception to be thrown.
Writing to Databases
Zend_Log_Writer_Db writes log information to a database table using Zend_Db. The constructor of Zend_Log_Writer_Db receives a Zend_Db_Adapter instance, a table name, and a mapping of database columns to event data items:
$params = array ('host' => '127.0.0.1', 'username' => 'malory', 'password' => '******', 'dbname' => 'camelot'); $db = Zend_Db::factory('PDO_MYSQL', $params); $columnMapping = array('lvl' => 'priority', 'msg' => 'message'); $writer = new Zend_Log_Writer_Db($db, 'log_table_name', $columnMapping); $logger = new Zend_Log($writer); $logger->info('Informational message'); The example above writes a single row of log data to the database table named log_table_name table. The database column named lvl receives the priority number and the column named msg receives the log message.
Writing to Firebug
Zend_Log_Writer_Firebug sends log data to the Firebug [http://www.getfirebug.com/] Console [http:// getfirebug.com/logging.html].
818
Zend_Log
All data is sent via the Zend_Wildfire_Channel_HttpHeaders component which uses HTTP headers to ensure the page content is not disturbed. Debugging AJAX requests that require clean JSON and XML responses is possible with this approach. Requirements: Firefox Browser ideally version 3 but version 2 is also supported. Firebug Firefox Extension which you can download from https://addons.mozilla.org/en-US/firefox/addon/1843. FirePHP Firefox Extension which you can download from https://addons.mozilla.org/en-US/firefox/addon/6149.
$logger->addPriority('FOO', 8); $writer->setPriorityStyle(8, 'TRACE'); $logger->foo('Foo Message'); The default style for user-defined priorities can be set with the setDefaultPriorityStyle() method.
819
Zend_Log
Exception Logging
To log a Zend_Exception simply pass the exception object to the logger. It does not matter which priority or style you have set as the exception is automatically recognized.
Tabla Logging
You can also log data and format it in a table style. Columns are automatically recognized and the first row of data automatically becomes the header.
$writer->setPriorityStyle(8, 'TABLE'); $logger->addPriority('TABLE', 8); $table = array('Summary line for the table', array( array('Column 1', 'Column 2'), array('Row 1 c 1',' Row 1 c 2'), array('Row 2 c 1',' Row 2 c 2') ) ); $logger->table($table);
820
Zend_Log
Writing to Email
Zend_Log_Writer_Mail writes log entries in an email message by using Zend_Mail. The Zend_Log_Writer_Mail constructor takes a Zend_Mail object, and an optional Zend_Layout object. The primary use case for Zend_Log_Writer_Mail is notifying developers, systems administrators, or any concerned parties of errors that might be occurring with PHP-based scripts. Zend_Log_Writer_Mail was born out of the idea that if something is broken, a human being needs to be alerted of it immediately so they can take corrective action. Basic usage is outlined below:
$mail = new Zend_Mail(); $mail->setFrom('errors@example.org') ->addTo('project_developers@example.org'); $writer = new Zend_Log_Writer_Mail($mail); // Set subject text for use; summary of number of errors is appended to the // subject line before sending the message. $writer->setSubjectPrependText('Errors with script foo.php'); // Only email warning level entries and higher. $writer->addFilter(Zend_Log::WARN); $log = new Zend_Log(); $log->addWriter($writer); // Something bad happened! $log->error('unable to connect to database'); // On writer shutdown, Zend_Mail::send() is triggered to send an email with // all log entries at or above the Zend_Log filter level. Zend_Log_Writer_Mail will render the email body as plain text by default. One email is sent containing all log entries at or above the filter level. For example, if warning-level entries an up are to be emailed, and two warnings and five errors occur, the resulting email will contain a total of seven log entries.
Zend_Layout Usage
A Zend_Layout instance may be used to generate the HTML portion of a multipart email. If a Zend_Layout instance is in use, Zend_Log_Writer_Mail assumes that it is being used to render HTML and sets the body HTML for the message as the Zend_Layout-rendered value. When using Zend_Log_Writer_Mail with a Zend_Layout instance, you have the option to set a custom formatter by using the setLayoutFormatter() method. If no Zend_Layout-specific entry formatter was specified, the formatter currently in use will be used. Full usage of Zend_Layout with a custom formatter is outlined below.
821
Zend_Log
->addTo('project_developers@example.org'); // Note that a subject line is not being set on the Zend_Mail instance! // Use a simple Zend_Layout instance with its defaults. $layout = new Zend_Layout(); // Create a formatter that wraps the entry in a listitem tag. $layoutFormatter = new Zend_Log_Formatter_Simple( '<li>' . Zend_Log_Formatter_Simple::DEFAULT_FORMAT . '</li>' ); $writer = new Zend_Log_Writer_Mail($mail, $layout); // Apply the formatter for entries as rendered with Zend_Layout. $writer->setLayoutFormatter($layoutFormatter); $writer->setSubjectPrependText('Errors with script foo.php'); $writer->addFilter(Zend_Log::WARN); $log = new Zend_Log(); $log->addWriter($writer); // Something bad happened! $log->error('unable to connect to database'); // On writer shutdown, Zend_Mail::send() is triggered to send an email with // all log entries at or above the Zend_Log filter level. The email will // contain both plain text and HTML parts.
Caveats
Sending log entries via email can be dangerous. If error conditions are being improperly handled by your script, or if you're misusing the error levels, you might find yourself in a situation where you are sending hundreds or thousands of emails to the recipients depending on the frequency of your errors. At this time, Zend_Log_Writer_Mail does not provide any mechanism for throttling or otherwise batching up the messages. Such functionality should be implemented by the consumer if necessary. Again, Zend_Log_Writer_Mail's primary goal is to proactively notify a human being of error conditions. If those errors are being handled in a timely fashion, and safeguards are being put in place to prevent those circumstances in the future, then email-based notification of errors can be a valuable tool.
822
Zend_Log
One useful case for Zend_Log_Writer_Syslog is for aggregating logs from clustered machines via the system log functionality. Many systems allow remote logging of system events, which allows system administrators to monitor a cluster of machines from a single log file. By default, all syslog messages generated are prefixed with the string "Zend_Log". You may specify a different "application" name by which to identify such log messages by either passing the application name to the constructor or the application accessor:
// At instantiation, pass the "application" key in the options: $writer = new Zend_Log_Writer_Syslog(array('application' => 'FooBar')); // Any other time: $writer->setApplicationName('BarBaz'); The system log also allows you to identify the "facility," or application type, logging the message; many system loggers will actually generate different log files per facility, which again aids administrators monitoring server activity. You may specify the log facility either in the constructor or via an accessor. It should be one of the openlog() constants defined on the openlog() manual page [http://php.net/openlog].
// At instantiation, pass the "facility" key in the options: $writer = new Zend_Log_Writer_Syslog(array('facility' => LOG_AUTH)); // Any other time: $writer->setFacility(LOG_USER); When logging, you may continue to use the default Zend_Log priority constants; internally, they are mapped to the appropriate syslog() priority constants.
$writer = new Zend_Log_Writer_Null; $logger = new Zend_Log($writer); // goes nowhere $logger->info('Informational message');
823
Zend_Log
// Array // ( // [timestamp] => 2007-04-06T07:16:37-07:00 // [message] => Informational message // [priority] => 6 // [priorityName] => INFO // ) To clear the events logged by the mock, simply set $mock->events = array().
Compositing Writers
There is no composite Writer object. However, a Log instance can write to any number of Writers. To do this, use the addWriter() method:
$writer1 = new Zend_Log_Writer_Stream('/path/to/first/logfile'); $writer2 = new Zend_Log_Writer_Stream('/path/to/second/logfile'); $logger = new Zend_Log(); $logger->addWriter($writer1); $logger->addWriter($writer2); // goes to both writers $logger->info('Informational message');
Formatters
A Formatter is an object that is responsible for taking an event array describing a log event and outputting a string with a formatted log line. Some Writers are not line-oriented and cannot use a Formatter. An example is the Database Writer, which inserts the event items directly into database columns. For Writers that cannot support a Formatter, an exception is thrown if you attempt to set a Formatter.
Simple Formatting
Zend_Log_Formatter_Simple is the default formatter. It is configured automatically when you specify no formatter. The default configuration is equivalent to the following:
$format = '%timestamp% %priorityName% (%priority%): %message%' . PHP_EOL; $formatter = new Zend_Log_Formatter_Simple($format); A formatter is set on an individual Writer object using the Writer's setFormatter() method:
$writer = new Zend_Log_Writer_Stream('php://output'); $formatter = new Zend_Log_Formatter_Simple('hello %message%' . PHP_EOL); $writer->setFormatter($formatter); $logger = new Zend_Log();
824
Zend_Log
$logger->addWriter($writer); $logger->info('there'); // outputs "hello there" The constructor of Zend_Log_Formatter_Simple accepts a single parameter: the format string. This string contains keys surrounded by percent signs (e.g. %message%). The format string may contain any key from the event data array. You can retrieve the default keys by using the DEFAULT_FORMAT constant from Zend_Log_Formatter_Simple.
Formatting to XML
Zend_Log_Formatter_Xml formats log data into XML strings. By default, it automatically logs all items in the event data array:
$writer = new Zend_Log_Writer_Stream('php://output'); $formatter = new Zend_Log_Formatter_Xml(); $writer->setFormatter($formatter); $logger = new Zend_Log(); $logger->addWriter($writer); $logger->info('informational message'); The code above outputs the following XML (space added for clarity):
<logEntry> <timestamp>2007-04-06T07:24:37-07:00</timestamp> <message>informational message</message> <priority>6</priority> <priorityName>INFO</priorityName> </logEntry> It's possible to customize the root element as well as specify a mapping of XML elements to the items in the event data array. The constructor of Zend_Log_Formatter_Xml accepts a string with the name of the root element as the first parameter and an associative array with the element mapping as the second parameter:
$writer = new Zend_Log_Writer_Stream('php://output'); $formatter = new Zend_Log_Formatter_Xml('log', array('msg' => 'message', 'level' => 'priorityName') ); $writer->setFormatter($formatter); $logger = new Zend_Log(); $logger->addWriter($writer); $logger->info('informational message'); The code above changes the root element from its default of logEntry to log. It also maps the element msg to the event data item message. This results in the following output:
825
Zend_Log
Filters
A Filter object blocks a message from being written to the log.
$logger = new Zend_Log(); $writer = new Zend_Log_Writer_Stream('php://output'); $logger->addWriter($writer); $filter = new Zend_Log_Filter_Priority(Zend_Log::CRIT); $logger->addFilter($filter); // blocked $logger->info('Informational message'); // logged $logger->emerg('Emergency message'); When you add one or more Filters to the Log object, the message must pass through all of the Filters before any Writers receives it.
$logger = new Zend_Log(); $writer1 = new Zend_Log_Writer_Stream('/path/to/first/logfile'); $logger->addWriter($writer1); $writer2 = new Zend_Log_Writer_Stream('/path/to/second/logfile'); $logger->addWriter($writer2); // add a filter only to writer2 $filter = new Zend_Log_Filter_Priority(Zend_Log::CRIT); $writer2->addFilter($filter); // logged to writer1, blocked from writer2 $logger->info('Informational message'); // logged by both writers
826
Zend_Log
$logger->emerg('Emergency message');
827
828
$mail = new Zend_Mail(); $mail->setBodyText('This is the text of the mail.'); $mail->setFrom('somebody@example.com', 'Some Sender'); $mail->addTo('somebody_else@example.com', 'Some Recipient'); $mail->setSubject('TestSubject'); $mail->send();
Minimum definitions
In order to send an e-mail with Zend_Mail you have to specify at least one recipient, a sender (e.g., with setFrom()), and a message body (text and/or HTML). For most mail attributes there are "get" methods to read the information stored in the mail object. For further details, please refer to the API documentation. A special one is getRecipients(). It returns an array with all recipient email addresses that were added prior to the method call. For security reasons, Zend_Mail filters all header fields to prevent header injection with newline (\n) characters. Double quotation is changed to single quotation and angle brackets to square brackets in the name of sender and recipients. If the marks are in email address, the marks will be removed. You also can use most methods of the Zend_Mail object with a convenient fluent interface.
$mail = new Zend_Mail(); $mail->setBodyText('This is the text of the mail.') ->setFrom('somebody@example.com', 'Some Sender') ->addTo('somebody_else@example.com', 'Some Recipient') ->setSubject('TestSubject') ->send();
829
Zend_Mail
new transport instance can then act as the default Zend_Mail transport, or it can be passed to the send() method of Zend_Mail.
830
Zend_Mail
831
Zend_Mail
Additional transports
Additional transports can be written by implementing Zend_Mail_Transport_Interface.
HTML E-Mail
To send an e-mail in HTML format, set the body using the method setBodyHTML() instead of setBodyText(). The MIME content type will automatically be set to text/html then. If you use both HTML and Text bodies, a multipart/alternative MIME message will automatically be generated:
Attachments
Files can be attached to an e-mail using the createAttachment() method. The default behavior of Zend_Mail is to assume the attachment is a binary object (application/octet-stream), that it should be transferred with base64 encoding, and that it is handled as an attachment. These assumptions can be overridden by passing more parameters to createAttachment():
832
Zend_Mail
$mail->createAttachment($someBinaryString); $mail->createAttachment($myImage, 'image/gif', Zend_Mime::DISPOSITION_INLINE, Zend_Mime::ENCODING_8BIT); If you want more control over the MIME part generated for this attachment you can use the return value of createAttachment() to modify its attributes. The createAttachment() method returns a Zend_Mime_Part object:
$mail = new Zend_Mail(); $at = $mail->createAttachment($myImage); $at->type = 'image/gif'; $at->disposition = Zend_Mime::DISPOSITION_INLINE; $at->encoding = Zend_Mime::ENCODING_8BIT; $at->filename = 'test.gif'; $mail->send(); An alternative is to create an instance of Zend_Mime_Part and add it with addAttachment():
$mail = new Zend_Mail(); $at = new Zend_Mime_Part($myImage); $at->type = 'image/gif'; $at->disposition = Zend_Mime::DISPOSITION_INLINE; $at->encoding = Zend_Mime::ENCODING_8BIT; $at->filename = 'test.gif'; $mail->addAttachment($at); $mail->send();
Adding Recipients
Recipients can be added in three ways: addTo(): Adds a recipient to the mail with a "To" header addCc(): Adds a recipient to the mail with a "Cc" header addBcc(): Adds a recipient to the mail not visible in the header getRecipients() serves list of the recipients. clearRecipients() clears the list.
Additional parameter
addTo() and addCc() accept a second optional parameter that is used as a human-readable name of the recipient for the header. Double quotation is changed to single quotation and angle brackets to square brackets in the parameter.
833
Zend_Mail
Additional Headers
Arbitrary mail headers can be set by using the addHeader() method. It requires two parameters containing the name and the value of the header field. A third optional parameter determines if the header should have only one or multiple values:
Character Sets
Zend_Mail does not check for the correct character set of the mail parts. When instantiating Zend_Mail, a charset for the e-mail itself may be given. It defaults to iso-8859-1. The application has to make sure that all parts added to that mail object have their content encoded in the correct character set. When creating a new mail part, a different charset can be given for each part.
Encoding
Text and HTML message bodies are encoded with the quotedprintable mechanism by default. Message headers are also encoded with the quotedprintable mechanism if you do not specify base64 in setHeaderEncoding(). All other attachments are encoded via base64 if no other encoding is given in the addAttachment() call or assigned to the MIME part object later. 7Bit and 8Bit encoding currently only pass on the binary content data. Header Encoding, especially the encoding of the subject, is a tricky topic. Zend_Mime currently implements its own algorithm to encode quoted printable headers according to RFC-2045. This due to the problems of
834
Zend_Mail
iconv_mime_encode and mb_encode_mimeheader with regards to certain charsets. This algorithm only breaks the header at spaces, which might lead to headers that far exceed the suggested length of 76 chars. For this cases it is suggested to switch to BASE64 header encoding as the following example describes:
// By default Zend_Mime::ENCODING_QUOTEDPRINTABLE $mail = new Zend_Mail('UTF-8'); // Reset to Base64 Encoding. $mail->setHeaderEncoding(Zend_Mime::ENCODING_BASE64); Zend_Mail_Transport_Smtp encodes lines starting with one dot or two dots so that the mail does not violate the SMTP protocol.
SMTP Authentication
Zend_Mail supports the use of SMTP authentication, which can be enabled be passing the 'auth' parameter to the configuration array in the Zend_Mail_Transport_Smtp constructor. The available built-in authentication methods are PLAIN, LOGIN and CRAM-MD5 which all expect a 'username' and 'password' value in the configuration array.
Authentication types
The authentication type is case-insensitive but has no punctuation. E.g. to use CRAM-MD5 you would pass 'auth' => 'crammd5' in the Zend_Mail_Transport_Smtp constructor.
835
Zend_Mail
'port' => 25); // Optional port number supplied $transport = new Zend_Mail_Transport_Smtp('mail.server.com', $config); $mail = new Zend_Mail(); $mail->setBodyText('This is the text of the mail.'); $mail->setFrom('sender@test.com', 'Some Sender'); $mail->addTo('recipient@test.com', 'Some Recipient'); $mail->setSubject('TestSubject'); $mail->send($transport);
Create message/folder No
836
Zend_Mail
$mail = new Zend_Mail_Storage_Maildir(array('dirname' => '/home/test/mail/')); Both constructors throw a Zend_Mail_Exception if the storage can't be read.
// connecting with Pop3 $mail = new Zend_Mail_Storage_Pop3(array('host' => 'example.com', 'user' => 'test', 'password' => 'test')); // connecting with Imap $mail = new Zend_Mail_Storage_Imap(array('host' => 'example.com', 'user' => 'test', 'password' => 'test')); // example for a none standard port $mail = new Zend_Mail_Storage_Pop3(array('host' 'port' 'user' 'password'
For both storages SSL and TLS are supported. If you use SSL the default port changes as given in the RFC.
// examples for Zend_Mail_Storage_Pop3, same works for Zend_Mail_Storage_Imap // use SSL on different port (default is 995 for Pop3 and 993 for Imap) $mail = new Zend_Mail_Storage_Pop3(array('host' => 'example.com', 'user' => 'test', 'password' => 'test', 'ssl' => 'SSL')); // use TLS $mail = new Zend_Mail_Storage_Pop3(array('host' 'user' 'password' 'ssl'
Both constructors can throw Zend_Mail_Exception or Zend_Mail_Protocol_Exception (extends Zend_Mail_Exception), depending on the type of error.
837
Zend_Mail
$message = $mail->getMessage($messageNum); Array access is also supported, but this access method won't supported any additional parameters that could be added to getMessage(). As long as you don't mind, and can live with the default values, you may use:
$message = $mail[$messageNum]; For iterating over all messages the Iterator interface is implemented:
foreach ($mail as $messageNum => $message) { // do stuff ... } To count the messages in the storage, you can either use the method countMessages() or use array access:
// method $maxMessage = $mail->countMessages(); // array access $maxMessage = count($mail); To remove a mail, you use the method removeMessage() or again array access:
// get the message object $message = $mail->getMessage(1); // output subject of message echo $message->subject . "\n"; // get content-type header $type = $message->contentType; // check if CC isset: if( isset($message->cc) ) { // or $message->headerExists('cc');
838
Zend_Mail
$cc = $message->cc; } If you have multiple headers with the same name- i.e. the Received headers- you might want an array instead of a string. In this case, use the getHeader() method.
// get header as property - the result is always a string, // with new lines between the single occurrences in the message $received = $message->received; // the same via getHeader() method $received = $message->getHeader('received', 'string'); // better an array with a single entry for every occurrences $received = $message->getHeader('received', 'array'); foreach ($received as $line) { // do stuff } // if you don't define a format you'll get the internal representation // (string for single headers, array for multiple) $received = $message->getHeader('received'); if (is_string($received)) { // only one received header found in message } The method getHeaders() returns all headers as array with the lower-cased name as key and the value as and array for multiple headers or as string for single headers.
// dump all headers foreach ($message->getHeaders() as $name => $value) { if (is_string($value)) { echo "$name: $value\n"; continue; } foreach ($value as $entry) { echo "$name: $entry\n"; } } If you don't have a multipart message, fetching the content is easily done via getContent(). Unlike the headers, the content is only fetched when needed (aka late-fetch).
// output message content for HTML echo '<pre>'; echo $message->getContent(); echo '</pre>'; Checking for multipart messages is done with the method isMultipart(). If you have multipart message you can get an instance of Zend_Mail_Part with the method getPart(). Zend_Mail_Part is the base class of Zend_Mail_Message, so you have the same methods: getHeader(), getHeaders(), getContent(), getPart(), isMultipart and the properties for headers.
839
Zend_Mail
// get the first none multipart part $part = $message; while ($part->isMultipart()) { $part = $message->getPart(1); } echo 'Type of this part is ' . strtok($part->contentType, ';') . "\n"; echo "Content:\n"; echo $part->getContent(); Zend_Mail_Part also implements RecursiveIterator, which makes it easy to scan through all parts. And for easy output, it also implements the magic method __toString(), which returns the content.
// output first text/plain part $foundPart = null; foreach (new RecursiveIteratorIterator($mail->getMessage(1)) as $part) { try { if (strtok($part->contentType, ';') == 'text/plain') { $foundPart = $part; break; } } catch (Zend_Mail_Exception $e) { // ignore } } if (!$foundPart) { echo 'no plain text part found'; } else { echo "plain text part: \n" . $foundPart; }
// find unread messages echo "Unread mails:\n"; foreach ($mail as $message) { if ($message->hasFlag(Zend_Mail_Storage::FLAG_SEEN)) { continue; } // mark recent/new mails if ($message->hasFlag(Zend_Mail_Storage::FLAG_RECENT)) { echo '! '; } else { echo ' '; } echo $message->subject . "\n"; }
840
Zend_Mail
// check for known flags $flags = $message->getFlags(); echo "Message is flagged as: "; foreach ($flags as $flag) { switch ($flag) { case Zend_Mail_Storage::FLAG_ANSWERED: echo 'Answered '; break; case Zend_Mail_Storage::FLAG_FLAGGED: echo 'Flagged '; break; // ... // check for other flags // ... default: echo $flag . '(unknown flag) '; } } As IMAP allows user or client defined flags, you could get flags that don't have a constant in Zend_Mail_Storage. Instead, they are returned as strings and can be checked the same way with hasFlag().
// check message for client defined flags $IsSpam, $SpamTested if (!$message->hasFlag('$SpamTested')) { echo 'message has not been tested for spam'; } else if ($message->hasFlag('$IsSpam')) { echo 'this message is spam'; } else { echo 'this message is ham'; }
Using folders
All storages, except Pop3, support folders, also called mailboxes. The interface implemented by all storages supporting folders is called Zend_Mail_Storage_Folder_Interface. Also all of these classes have an additional optional parameter called folder, which is the folder selected after login, in the constructor. For the local storages you need to use separate classes called Zend_Mail_Storage_Folder_Mbox or Zend_Mail_Storage_Folder_Maildir. Both need one parameter called dirname with the name of the base dir. The format for maildir is as defined in maildir++ (with a dot as default delimiter), Mbox is a directory hierarchy with Mbox files. If you don't have a Mbox file called INBOX in your Mbox base dir you need to set another folder in the constructor. Zend_Mail_Storage_Imap already supports folders by default. Ejemplos for opening these storages:
// mbox with folders $mail = new Zend_Mail_Storage_Folder_Mbox(array('dirname' => '/home/test/mail/')); // mbox with a default folder not called INBOX, also works
841
Zend_Mail
// with Zend_Mail_Storage_Folder_Maildir and Zend_Mail_Storage_Imap $mail = new Zend_Mail_Storage_Folder_Mbox(array('dirname' => '/home/test/mail/', 'folder' => 'Archive')); // maildir with folders $mail = new Zend_Mail_Storage_Folder_Maildir(array('dirname' => '/home/test/mail/')); // maildir with colon as delimiter, as suggested in Maildir++ $mail = new Zend_Mail_Storage_Folder_Maildir(array('dirname' => '/home/test/mail/', 'delim' => ':')); // imap is the same with and without folders $mail = new Zend_Mail_Storage_Imap(array('host' => 'example.com', 'user' => 'test', 'password' => 'test')); With the method getFolders($root = null) you can get the folder hierarchy starting with the root folder or the given folder. It's returned as an instance of Zend_Mail_Storage_Folder, which implements RecursiveIterator and all children are also instances of Zend_Mail_Storage_Folder. Each of these instances has a local and a global name returned by the methods getLocalName() and getGlobalName(). The global name is the absolute name from the root folder (including delimiters), the local name is the name in the parent folder.
If you use the iterator, the key of the current element is the local name. The global name is also returned by the magic method __toString(). Some folders may not be selectable, which means they can't store messages and selecting them results in an error. This can be checked with the method isSelectable(). So it's very easy to output the whole tree in a view:
$folders = new RecursiveIteratorIterator($this->mail->getFolders(), RecursiveIteratorIterator::SELF_FIRST); echo '<select name="folder">'; foreach ($folders as $localName => $folder) { $localName = str_pad('', $folders->getDepth(), '-', STR_PAD_LEFT) . $localName; echo '<option'; if (!$folder->isSelectable()) { echo ' disabled="disabled"'; } echo ' value="' . htmlspecialchars($folder) . '">' . htmlspecialchars($localName) . '</option>'; } echo '</select>';
842
Zend_Mail
The current selected folder is returned by the method getSelectedFolder(). Changing the folder is done with the method selectFolder(), which needs the global name as parameter. If you want to avoid to write delimiters you can also use the properties of a Zend_Mail_Storage_Folder instance:
// depending on your mail storage and its settings $rootFolder->Archive->2005 // is the same as: // /Archive/2005 // Archive:2005 // INBOX.Archive.2005 // ... $folder = $mail->getFolders()->Archive->2005; echo 'Last folder was ' . $mail->getSelectedFolder() . "new folder is $folder\n"; $mail->selectFolder($folder);
Advanced Use
Using NOOP
If you're using a remote storage and have some long tasks you might need to keep the connection alive via noop:
foreach ($mail as $message) { // do some calculations ... $mail->noop(); // keep alive // do something else ... $mail->noop(); // keep alive }
Caching instances
Zend_Mail_Storage_Mbox, Zend_Mail_Storage_Folder_Mbox, Zend_Mail_Storage_Maildir and Zend_Mail_Storage_Folder_Maildir implement the magic methods __sleep() and __wakeup(), which means they are serializable. This avoids parsing the files or directory tree more than once. The disadvantage is that your Mbox or Maildir storage should not change. Some easy checks may be done, like reparsing the current Mbox file if the modification time changes, or reparsing the folder structure if a folder has vanished (which still results in an error, but you can search for another folder afterwards). It's better if you have something like a signal file for changes and check it before using the cached instance.
// there's no specific cache handler/class used here, // change the code to match your cache handler $signal_file = '/home/test/.mail.last_change'; $mbox_basedir = '/home/test/mail/'; $cache_id = 'example mail cache ' . $mbox_basedir . $signal_file; $cache = new Your_Cache_Class(); if (!$cache->isCached($cache_id) ||
843
Zend_Mail
filemtime($signal_file) > $cache->getMTime($cache_id)) { $mail = new Zend_Mail_Storage_Folder_Pop3(array('dirname' => $mbox_basedir)); } else { $mail = $cache->get($cache_id); } // do stuff ... $cache->set($cache_id, $mail);
class Ejemplo_Mail_Exception extends Zend_Mail_Exception { } class Ejemplo_Mail_Protocol_Exception extends Zend_Mail_Protocol_Exception { } class Ejemplo_Mail_Protocol_Pop3_Knock extends Zend_Mail_Protocol_Pop3 { private $host, $port; public function __construct($host, $port = null) { // no auto connect in this class $this->host = $host; $this->port = $port; } public function knock($port) { $sock = @fsockopen($this->host, $port); if ($sock) { fclose($sock); } } public function connect($host = null, $port = null, $ssl = false) { if ($host === null) { $host = $this->host; } if ($port === null) {
844
Zend_Mail
$port = $this->port; } parent::connect($host, $port); } } class Ejemplo_Mail_Pop3_Knock extends Zend_Mail_Storage_Pop3 { public function __construct(array $params) { // ... check $params here! ... $protocol = new Ejemplo_Mail_Protocol_Pop3_Knock($params['host']); // do our "special" thing foreach ((array)$params['knock_ports'] as $port) { $protocol->knock($port); } // get to correct state $protocol->connect($params['host'], $params['port']); $protocol->login($params['user'], $params['password']); // initialize parent parent::__construct($protocol); } } $mail = new Ejemplo_Mail_Pop3_Knock(array('host' => 'localhost', 'user' => 'test', 'password' => 'test', 'knock_ports' => array(1101, 1105, 1111))); As you see, we always assume we're connected, logged in and, if supported, a folder is selected in the constructor of the main class. Thus if you assign your own protocol class, you always need to make sure that's done or the next method will fail if the server doesn't allow it in the current state.
845
Zend_Mail
$quota = $mail->checkQuota(true); echo 'You are ', $quota['over_quota'] ? 'over quota' : 'not over quota', "\n"; echo 'You have ', $quota['count'], ' of ', $quota['quota']['count'], ' messages and use '; echo $quota['size'], ' of ', $quota['quota']['size'], ' octets'; If you want to specify your own quota instead of using the one specified in the maildirsize file you can do with setQuota():
// message count and octet size supported, order does matter $quota = $mail->setQuota(array('size' => 10000, 'count' => 100)); To add your own quota checks use single letters as keys, and they will be preserved (but obviously not checked). It's also possible to extend Zend_Mail_Storage_Writable_Maildir to define your own quota only if the maildirsize file is missing (which can happen in Maildir++):
class Ejemplo_Mail_Storage_Maildir extends Zend_Mail_Storage_Writable_Maildir { // getQuota is called with $fromStorage = true by quota checks public function getQuota($fromStorage = false) { try { return parent::getQuota($fromStorage); } catch (Zend_Mail_Storage_Exception $e) { if (!$fromStorage) { // unknown error: throw $e; } // maildirsize file must be missing list($count, $size) = get_quota_from_somewhere_else(); return array('count' => $count, 'size' => $size); } } }
846
Creation of Measurements
When creating a measurement object, Zend_Measure_* methods expect the input/original measurement data value as the first parameter. This can be a numeric argument , a String without units, or a localized string with unit(s) specified. The second parameter defines the type of the measurement. Both parameters are mandatory. The language may optionally be specified as the third parameter.
847
Zend_Measure
848
Zend_Measure
// in your bootstrap file $locale = new Zend_Locale('de_AT'); Zend_Registry::set('Zend_Locale', $locale); // somewhere in your application $length = new Zend_Measure_Length(Zend_Measure_Length::METER();
Outputting measurements
Measurements can be output in a number of different ways. Automatic output Outputting values Output with unit of measurement Output as localized string
Automatic output
Zend_Measure supports outputting of strings automatically.
849
Zend_Measure
echo $unit;
Measurement output
Output can be achieved simply by using echo [http://php.net/echo] or print [http://php.net/print] .
Outputting values
The value of a measurement can be output using getValue().
Manipulating Measurements
Parsing and normalization of input, combined with output to localized notations makes data accessible to users in different locales. Many additional methods exist in Zend_Measure_* components to manipulate and work with this data, after it has been normalized.
850
Zend_Measure
Convert Add and subtract Compare to boolean Compare to greater/smaller Manually change values Manually change types
Convert
Probably the most important feature is the conversion into different units of measurement. The conversion of a unit can be done any number of times using the method convertTo(). Units of measurement can only be converted to other units of the same type (class). Therefore, it is not possible to convert (e.g.) a length into a weight, which would might encourage poor programming practices and allow errors to propagate without exceptions. The convertTo method accepts an optional parameter. With this parameter you can define an precision for the returned output. The standard precision is '2'.
851
Zend_Measure
Automatic conversion
Adding one object to another will automatically convert it to the correct unit. It is not necessary to call convertTo() before adding different units.
// Define objects $unit = new Zend_Measure_Length(200, Zend_Measure_Length::CENTIMETER); $unit2 = new Zend_Measure_Length(1, Zend_Measure_Length::METER); // Subtract $unit2 from $unit $sum = $unit->sub($unit2); echo $sum;
Compare
Measurements can also be compared, but without automatic unit conversion. Thus, equals() returns TRUE, only if both the value and the unit of measure are identical.
852
Zend_Measure
Compare
To determine if a measurement is less than or greater than another, use compare(), which returns 0, -1 or 1 depending on the difference between the two objects. Identical measurements will return 0. Lesser ones will return a negative, greater ones a positive value.
853
Zend_Measure
Types of measurements
All supported measurement types are listed below, each with an example of the standard usage for such measurements.
Zend_Measure_AccelerationMeter per square second | Zend_Measure_Acceleration m/s covers the physical factor of acceleration. Zend_Measure_Angle Zend_Measure_Area Zend_Measure_Binary Radiant | rad Square meter | m Byte | b Zend_Measure_Angle covers angular dimensions. Zend_Measure_Area covers square measures. Zend_Measure_Binary covers binary conversions. Zend_Measure_Capacitance covers physical factor of capacitance. Zend_Measure_Cooking_Volume covers volumes which are used for cooking or written in cookbooks. Zend_Measure_Cooking_Weight covers the weights which are used for cooking or written in cookbooks. Zend_Measure_Current covers the physical factor of current.
Zend_Measure_Capacitance Farad | F
Cooking volumes
Cooking weights
Zend_Measure_Cooking_Weight Gram | g
Current
Zend_Measure_Current
Ampere | A
Density
Zend_Measure_Density
Kilogram per cubic meter | Zend_Measure_Density kg/m covers the physical factor of density. Joule | J Zend_Measure_Energy covers the physical factor of energy. Zend_Measure_Force covers the physical factor of force.
Energy
Zend_Measure_Energy
Force
Zend_Measure_Force
Newton | N
Flow (mass)
Zend_Measure_Flow_Mass Kilogram per second | kg/s Zend_Measure_Flow_Mass covers the physical factor of flow rate. The weight of the flowing mass is used as reference point within this class. Zend_Measure_Flow_Mole Mole per second | mol/s Zend_Measure_Flow_Mole covers the physical factor of flow rate. The density of
Flow (mole)
854
Zend_Measure
Typ
Class
Standardunit
Description the flowing mass is used as reference point within this class.
Flow (volume)
Zend_Measure_Flow_Volume Cubic meter per second | Zend_Measure_Flow_Volume m/s covers the physical factor of flow rate. The volume of the flowing mass is used as reference point within this class. Zend_Measure_Frequency Hertz | Hz Zend_Measure_Frequency covers the physical factor of frequency. Zend_Measure_Illumination covers the physical factor of light density. Zend_Measure_Length covers the physical factor of length.
Frequency
Illumination
Zend_Measure_Illumination Lux | lx
Length
Zend_Measure_Length
Meter | m
Lightness
Zend_Measure_Lightness
Candela per square meter | Zend_Measure_Ligntness cd/m covers the physical factor of light energy. Decimal | (10) Zend_Measure_Number converts between number formats. Zend_Measure_Power covers the physical factor of power.
Number
Zend_Measure_Number
Power
Zend_Measure_Power
Watt | W
Pressure
Zend_Measure_Pressure
Newton per square meter | Zend_Measure_Pressure N/m covers the physical factor of pressure. Meter per second | m/s Zend_Measure_Speed covers the physical factor of speed. Zend_Measure_Temperature covers the physical factor of temperature. Zend_Measure_Time covers the physical factor of time. Zend_Measure_Torque covers the physical factor of torque.
Speed
Zend_Measure_Speed
Temperature
Zend_Measure_TemperatureKelvin | K
Time
Zend_Measure_Time
Second | s
Torque
Zend_Measure_Torque
Newton meter | Nm
Viscosity (dynamic)
Zend_Measure_Viscosity_Dynamic Kilogram per meter second | Zend_Measure_Viscosity_Dynamic kg/ms covers the physical factor of viscosity. The weight of the fluid is used as reference point within this class.
855
Zend_Measure
Class
Standardunit
Description
Zend_Measure_Viscosity_Kinematic Square meter per second | Zend_Measure_Viscosity_Kinematic m/s covers the physical factor of viscosity. The distance of the flown fluid is used as reference point within this class. Zend_Measure_Volume Cubic meter | m Zend_Measure_Volume covers the physical factor of volume (content). Zend_Measure_Weight covers the physical factor of weight.
Volume
Weight
Zend_Measure_Weight
Kilogram | kg
Roman numbers
For the roman number system digits greater 4000 are supported. In reality these digits are shown with a crossbeam on top of the digit. As the crossbeam can not be shown within the computer, an underline has to be used instead of it.
$great = '_X'; $locale = new Zend_Locale('en'); $unit = new Zend_Measure_Number($great,Zend_Measure_Number::ROMAN, $locale); // convert to the decimal system echo $unit->convertTo(Zend_Measure_Number::DECIMAL);
856
$backendOptions = array( 'cache_dir' => './tmp/' // Directory where to put the swapped memory blocks ); $memoryManager = Zend_Memory::factory('File', $backendOptions); $loadedFiles = array(); for ($count = 0; $count < 10000; $count++) { $f = fopen($fileNames[$count], 'rb'); $data = fread($f, filesize($fileNames[$count])); $fclose($f); $loadedFiles[] = $memoryManager->create($data); } echo $loadedFiles[$index1]->value; $loadedFiles[$index2]->value = $newValue; $loadedFiles[$index3]->value[$charIndex] = '_';
Theory of Operation
Zend_Memory component operates with the following concepts: Memory manager Memory container
857
Zend_Memory
Memory manager
The memory manager generates memory objects (locked or movable) by request of user application and returns them wrapped into a memory container object.
Memory container
The memory container has a virtual or actual value attribute of string type. This attribute contains the data value specified at memory object creation time. You can operate with this value attribute as an object property:
$memObject = $memoryManager->create($data); echo $memObject->value; $memObject->value = $newValue; $memObject->value[$index] = '_'; echo ord($memObject->value[$index1]); $memObject->value = substr($memObject->value, $start, $length);
Nota
If you are using a PHP version earlier than 5.2, use the getRef() method instead of accessing the value property directly.
Locked memory
Locked memory objects are always stored in memory. Data stored in locked memory are never swapped to the cache backend.
Movable memory
Movable memory objects are transparently swapped and loaded to/from the cache backend by Zend_Memory when it's necessary. The memory manager doesn't swap objects with size less than the specified minimum, due to performance considerations. See the section called MinSize for more details.
Memory Manager
Creating a Memory Manager
You can create new a memory manager (Zend_Memory_Manager Zend_Memory::factory($backendName [, $backendOprions]) method. object) using the
858
Zend_Memory
The first argument $backendName is a string that names one of the backend implementations supported by Zend_Cache. The second argument $backendOptions is an optional backend options array.
$backendOptions = array( 'cache_dir' => './tmp/' // Directory where to put the swapped memory blocks ); $memoryManager = Zend_Memory::factory('File', $backendOptions); Zend_Memory uses Zend_Cache backends as storage providers. You may use the special name 'None' as a backend name, in addition to standard Zend_Cache backends.
$memoryManager = Zend_Memory::factory('None'); If you use 'None' as the backend name, then the memory manager never swaps memory blocks. This is useful if you know that memory is not limited or the overall size of objects never reaches the memory limit. The 'None' backend doesn't need any option specified.
$memObject = $memoryManager->create($data); The $data argument is optional and used to initialize the object value. If the $data argument is omitted, the value is an empty string.
$memObject = $memoryManager->createLocked($data); The $data argument is optional and used to initialize the object value. If the $data argument is omitted, the value is an empty string.
Destroying Objects
Memory objects are automatically destroyed and removed from memory when they go out of scope:
859
Zend_Memory
function foo() { global $memoryManager, $memList; ... $memObject1 = $memoryManager->create($data1); $memObject2 = $memoryManager->create($data2); $memObject3 = $memoryManager->create($data3); ... $memList[] = $memObject3; ... unset($memObject2); // $memObject2 is destroyed here ... // $memObject1 is destroyed here // but $memObject3 object is still referenced by $memList // and is not destroyed } This applies to both movable and locked objects.
$oldLimit = $memoryManager->getMemoryLimit(); $memoryManager->setMemoryLimit($newLimit); A negative value for memory limit means 'no limit'.
The default value is two-thirds of the value of 'memory_limit' in php.ini or 'no limit' (-1) if 'memory_limit' is not set in php.ini.
MinSize
MinSize is a minimal size of memory objects, which may be swapped by memory manager. The memory manager does not swap objects that are smaller than this value. This reduces the number of swap/load operations. You can retrieve or set the minimum size using the getMinSize() and setMinSize($newSize) methods:
860
Zend_Memory
$oldMinSize = $memoryManager->getMinSize(); $memoryManager->setMinSize($newSize); The default minimum size value is 16KB (16384 bytes).
Memory Objects
Movable
Create movable memory objects using the create([$data]) method of the memory manager:
$memObject = $memoryManager->create($data); "Movable" means that such objects may be swapped and unloaded from memory and then loaded when application code accesses the object.
Locked
Create locked memory objects using the createLocked([$data]) method of the memory manager:
$memObject = $memoryManager->createLocked($data); "Locked" means that such objects are never swapped and unloaded from memory. Locked objects provides the same interface as movable objects (Zend_Memory_Container_Interface). So locked object can be used in any place instead of movable objects. It's useful if an application or developer can decide, that some objects should never be swapped, based on performance considerations. Access to locked objects is faster, because the memory manager doesn't need to track changes for these objects. The locked objects class (Zend_Memory_Container_Locked) guarantees virtually the same performance as working with a string variable. The overhead is a single dereference to get the class property.
$memObject = $memoryManager->create($data); echo $memObject->value; $memObject->value = $newValue; $memObject->value[$index] = '_'; echo ord($memObject->value[$index1]); $memObject->value = substr($memObject->value, $start, $length);
861
Zend_Memory
An alternative way to access memory object data is to use the getRef() method. This method must be used for PHP versions before 5.2. It also may have to be used in some other cases for performance reasons.
getRef() method
public function &getRef(); The getRef() method returns reference to the object value. Movable objects are loaded from the cache at this moment if the object is not already in memory. If the object is loaded from the cache, this might cause swapping of other objects if the memory limit would be exceeded by having all the managed objects in memory. The getRef() method must be used to access memory object data for PHP versions before 5.2. Tracking changes to data needs additional resources. The getRef() method returns reference to string, which is changed directly by user application. So, it's a good idea to use the getRef() method for value data processing:
$memObject = $memoryManager->create($data); $value = &$memObject->getRef(); for ($count = 0; $count < strlen($value); $count++) { $char = $value[$count]; ... }
touch() method
public function touch(); The touch() method should be used in common with getRef(). It signals that object value has been changed:
$memObject = $memoryManager->create($data); ... $value = &$memObject->getRef(); for ($count = 0; $count < strlen($value); $count++) { ... if ($condition) { $value[$count] = $char; } ... } $memObject->touch();
862
Zend_Memory
lock() method
public function lock(); The lock() methods locks object in memory. It should be used to prevent swapping of some objects you choose. Normally, this is not necessary, because the memory manager uses an intelligent algorithm to choose candidates for swapping. But if you exactly know, that at this part of code some objects should not be swapped, you may lock them. Locking objects in memory also guarantees that reference returned by the getRef() method is valid until you unlock the object:
$memObject1 = $memoryManager->create($data1); $memObject2 = $memoryManager->create($data2); ... $memObject1->lock(); $memObject2->lock(); $value1 = &$memObject1->getRef(); $value2 = &$memObject2->getRef(); for ($count = 0; $count < strlen($value2); $count++) { $value1 .= $value2[$count]; } $memObject1->touch(); $memObject1->unlock(); $memObject2->unlock();
unlock() method
public function unlock(); unlock() method unlocks object when it's no longer necessary to be locked. See the example above.
isLocked() method
public function isLocked(); The isLocked() method can be used to check if object is locked. It returns TRUE if the object is locked, or FALSE if it is not locked. This is always TRUE for "locked" objects, and may be either TRUE or FALSE for "movable" objects.
863
864
Instantiating Zend_Mime
When Instantiating a Zend_Mime Object, a MIME boundary is stored that is used for all subsequent non-static method calls on that object. If the constructor is called with a string parameter, this value is used as a MIME boundary. If not, a random MIME boundary is generated during construction time. A Zend_Mime object has the following Methods: boundary(): Returns the MIME boundary string. boundaryLine(): Returns the complete MIME boundary line.
865
Zend_Mime
Zend_Mime_Message
Introduction
Zend_Mime_Message represents a MIME compliant message that can contain one or more separate Parts (Represented as Zend_Mime_Part objects). With Zend_Mime_Message, MIME compliant multipart messages can be generated from Zend_Mime_Part objects. Encoding and Boundary handling are handled transparently by the class. Zend_Mime_Message objects can also be reconstructed from given strings (experimental). Used by Zend_Mail.
Instantiation
There is no explicit constructor for Zend_Mime_Message.
Boundary handling
Zend_Mime_Message usually creates and uses its own Zend_Mime Object to generate a boundary. If you need to define the boundary or want to change the behaviour of the Zend_Mime object used by Zend_Mime_Message, you can instantiate the Zend_Mime object yourself and then register it to Zend_Mime_Message. Usually you will not need to do this. ->setMime(Zend_Mime $mime) sets a special instance of Zend_Mime to be used by this Zend_Mime_Message ->getMime() returns the instance of Zend_Mime that will be used to render the message when generateMessage() is called. ->generateMessage() renders the Zend_Mime_Message content to a string.
866
Zend_Mime
Zend_Mime_Part
Introduction
This class represents a single part of a MIME message. It contains the actual content of the message part plus information about its encoding, content type and original filename. It provides a method for generating a string from the stored data. Zend_Mime_Part objects can be added to Zend_Mime_Message to assemble a complete multipart message.
Instantiation
Zend_Mime_Part is instantiated with a string that represents the content of the new part. The type is assumed to be OCTET-STREAM, encoding is 8Bit. After instantiating a Zend_Mime_Part, meta information can be set by accessing its attributes directly:
public public public public public public public public public public
$type = Zend_Mime::TYPE_OCTETSTREAM; $encoding = Zend_Mime::ENCODING_8BIT; $id; $disposition; $filename; $description; $charset; $boundary; $location; $language;
867
868
Pages
A page (Zend_Navigation_Page) in Zend_Navigation in its most basic form is an object that holds a pointer to a web page. In addition to the pointer itself, the page object contains a number of other properties that are typically relevant for navigation, such as label, title, etc. Read more about pages in the pages section.
Containers
A navigation container (Zend_Navigation_Container) is a container class for pages. It has methods for adding, retrieving, deleting and iterating pages. It implements the SPL [http://php.net/spl] interfaces RecursiveIterator and Countable, and can thus be iterated with SPL iterators such as RecursiveIteratorIterator. Read more about containers in the containers section.
Nota
Zend_Navigation_Page extends Zend_Navigation_Container, which means that a page can have sub pages.
Pages
Zend_Navigation ships with two page types: MVC pages using the class Zend_Navigation_Page_Mvc URI pages using the class Zend_Navigation_Page_Uri MVC pages are link to on-site web pages, and are defined using MVC parameters (action, controller, module, route, params). URI pages are defined by a single property uri, which give you the full flexibility to link off-site pages or do other things with the generated links (e.g. an URI that turns into <a href="#">foo<a>).
869
Zend_Navigation
class
String
NULL
title
String
NULL
target
String
NULL
rel
Array
array()
870
Zend_Navigation
Key rev
Type Array
Default array()
Description Specifies reverse relations for the page. Works exactly like rel. Works like order for elements in Zend_Form. If specified, the page will be iterated in a specific order, meaning you can force a page to be iterated before others by setting the order attribute to a low number, e.g. -100. If a String is given, it must parse to a valid int. If NULL is given, it will be reset, meaning the order in which the page was added to the container will be used. ACL resource to associate with the page. Read more in the section on ACL integration in view helpers.. ACL privilege to associate with the page. Read more in the section on ACL integration in view helpers.. Whether the page should be considered active for the current request. If active is FALSE or not given, MVC pages will check its properties against the request object upon calling $page->isActive(). Whether page should be visible for the user, or just be a part of the structure. Invisible pages are skipped by view helpers. Child pages of the page. This could be an Array or Zend_Config object containing either page options that can be passed to the factory() method, or actual Zend_Navigation_Page instances, or a mixture of both.
order
NULL
resource
privilege
active
bool
FALSE
visible
bool
TRUE
pages
871
Zend_Navigation
Custom properties
All pages support setting and getting of custom properties by use of the magic methods __set($name, $value), __get($name), __isset($name) and __unset($name). Custom properties may have any value, and will be included in the array that is returned from $page->toArray(), which means that pages can be serialized/deserialized successfully even if the pages contains properties that are not native in the page class. Both native and custom properties can be set using $page->set($name, $value) and retrieved using $page->get($name), or by using magic methods.
Zend_Navigation_Page_Mvc
MVC pages are defined using MVC parameters known from the Zend_Controller component. An MVC page will use Zend_Controller_Action_Helper_Url internally in the getHref() method to generate hrefs, and the isActive() method will intersect the Zend_Controller_Request_Abstract params with the page's params to determine if the page is active.
Nota
The three examples below assume a default MVC setup with the default route in place.
872
Zend_Navigation
The URI returned is relative to the baseUrl in Zend_Controller_Front. In the examples, the baseUrl is '/' for simplicity.
// getHref() returns / $page = new Zend_Navigation_Page_Mvc(array( 'action' => 'index', 'controller' => 'index' )); // getHref() returns /blog/post/view $page = new Zend_Navigation_Page_Mvc(array( 'action' => 'view', 'controller' => 'post', 'module' => 'blog' )); // getHref() returns /blog/post/view/id/1337 $page = new Zend_Navigation_Page_Mvc(array( 'action' => 'view', 'controller' => 'post', 'module' => 'blog', 'params' => array('id' => 1337) ));
/* * Dispatched request: * - module: default * - controller: index * - action: index */ $page1 = new Zend_Navigation_Page_Mvc(array( 'action' => 'index', 'controller' => 'index' )); $page2 = new Zend_Navigation_Page_Mvc(array( 'action' => 'bar', 'controller' => 'index' )); $page1->isActive(); // returns true $page2->isActive(); // returns false
873
Zend_Navigation
/* * Dispatched request: * - module: blog * - controller: post * - action: view * - id: 1337 */ $page = new Zend_Navigation_Page_Mvc(array( 'action' => 'view', 'controller' => 'post', 'module' => 'blog' )); // returns true, because request has the same module, controller and action $page->isActive(); /* * Dispatched request: * - module: blog * - controller: post * - action: view */ $page = new Zend_Navigation_Page_Mvc(array( 'action' => 'view', 'controller' => 'post', 'module' => 'blog', 'params' => array('id' => null) )); // returns false, because page requires the id param to be set in the request $page->isActive(); // returns false
Nota
Note that when using the route property in a page, you should also specify the default params that the route defines (module, controller, action, etc.), otherwise the isActive() method will not be able to determine if the page is active. The reason for this is that there is currently no way to get the default params from a Zend_Controller_Router_Route_Interface object, nor to retrieve the current route from a Zend_Controller_Router_Interface object.
// the following route is added to the ZF router Zend_Controller_Front::getInstance()->getRouter()->addRoute( 'article_view', // route name new Zend_Controller_Router_Route( 'a/:id', array( 'module' => 'news', 'controller' => 'article',
874
Zend_Navigation
'action' 'id' ) ) );
// a page is created with a 'route' option $page = new Zend_Navigation_Page_Mvc(array( 'label' => 'A news article', 'route' => 'article_view', 'module' => 'news', // required for isActive(), see note above 'controller' => 'article', // required for isActive(), see note above 'action' => 'view', // required for isActive(), see note above 'params' => array('id' => 42) )); // returns: /a/42 $page->getHref();
Zend_Navigation_Page_Uri
Pages of type Zend_Navigation_Page_Uri can be used to link to pages on other domains or sites, or to implement custom logic for the page. URI pages are simple; in addition to the common page options, a URI page takes only one option uri. The uri will be returned when calling $page->getHref(), and may be a String or NULL.
Nota
Zend_Navigation_Page_Uri will not try to determine whether it should be active when calling $page->isActive(). It merely returns what currently is set, so to make a URI page active you have to manually call $page->setActive() or specifying active as a page option when constructing.
875
Zend_Navigation
class My_Navigation_Page extends Zend_Navigation_Page { private $_foo; private $_fooBar; public function setFoo($foo) { $this->_foo = $foo; } public function getFoo() { return $this->_foo; } public function setFooBar($fooBar) { $this->_fooBar = $fooBar; } public function getFooBar() { return $this->_fooBar; } public function getHref() { return $this->foo . '/' . $this->fooBar; } } // can now construct using $page = new My_Navigation_Page(array( 'label' => 'Property names are mapped to setters', 'foo' => 'bar', 'foo_bar' => 'baz' )); // ...or $page = Zend_Navigation_Page::factory(array( 'type' => 'My_Navigation_Page', 'label' => 'Property names are mapped to setters', 'foo' => 'bar',
876
Zend_Navigation
877
Zend_Navigation
)); $page = Zend_Navigation_Page::factory(array( 'label' => 'My URI page', 'uri' => '#' )); $page = Zend_Navigation_Page::factory(array( 'type' => 'uri', 'label' => 'My URI page' ));
Ejemplo 37.9. Creating a custom page type using the page factory
To create a custom page type using the factory, use the option type to specify a class name to instantiate. class My_Navigation_Page extends Zend_Navigation_Page { protected $_fooBar = 'ok'; public function setFooBar($fooBar) { $this->_fooBar = $fooBar; } } $page = Zend_Navigation_Page::factory(array( 'type' => 'My_Navigation_Page', 'label' => 'My custom page', 'foo_bar' => 'foo bar' ));
Containers
Containers have methods for adding, retrieving, deleting and iterating pages. Containers implement the SPL [http:// php.net/spl] interfaces RecursiveIterator and Countable, meaning that a container can be iterated using the SPL RecursiveIteratorIterator class.
Creating containers
Zend_Navigation_Container is abstract, and can not be instantiated directly. Use Zend_Navigation if you want to instantiate a container. Zend_Navigation can be constructed entirely empty, or take an array or a Zend_Config object with pages to put in the container. Each page in the given array/config will eventually be passed to the addPage() method of the container class, which means that each element in the array/config can be an array or a config object, or a Zend_Navigation_Page instance.
878
Zend_Navigation
* * Each element in the array will be passed to * Zend_Navigation_Page::factory() when constructing. */ $container = new Zend_Navigation(array( array( 'label' => 'Page 1', 'id' => 'home-link', 'uri' => '/' ), array( 'label' => 'Zend', 'uri' => 'http://www.zend-project.com/', 'order' => 100 ), array( 'label' => 'Page 2', 'controller' => 'page2', 'pages' => array( array( 'label' => 'Page 2.1', 'action' => 'page2_1', 'controller' => 'page2', 'class' => 'special-one', 'title' => 'This element has a special class', 'active' => true ), array( 'label' => 'Page 2.2', 'action' => 'page2_2', 'controller' => 'page2', 'class' => 'special-two', 'title' => 'This element has a special class too' ) ) ), array( 'label' => 'Page 2 with params', 'action' => 'index', 'controller' => 'page2', // specify a param or two 'params' => array( 'format' => 'json', 'foo' => 'bar' ) ), array( 'label' => 'Page 2 with params and a route', 'action' => 'index', 'controller' => 'page2', // specify a route name and a param for the route 'route' => 'nav-route-example', 'params' => array( 'format' => 'json'
879
Zend_Navigation
) ), array( 'label' => 'Page 3', 'action' => 'index', 'controller' => 'index', 'module' => 'mymodule', 'reset_params' => false ), array( 'label' => 'Page 4', 'uri' => '#', 'pages' => array( array( 'label' => 'Page 4.1', 'uri' => '/page4', 'title' => 'Page 4 using uri', 'pages' => array( array( 'label' => 'Page 4.1.1', 'title' => 'Page 4 using mvc params', 'action' => 'index', 'controller' => 'page4', // let's say this page is active 'active' => '1' ) ) ) ) ), array( 'label' => 'Page 0?', 'uri' => '/setting/the/order/option', // setting order to -1 should make it appear first 'order' => -1 ), array( 'label' => 'Page 5', 'uri' => '/', // this page should not be visible 'visible' => false, 'pages' => array( array( 'label' => 'Page 5.1', 'uri' => '#', 'pages' => array( array( 'label' => 'Page 5.1.1', 'uri' => '#', 'pages' => array( array( 'label' => 'Page 5.1.2', 'uri' => '#', // let's say this page is active
880
Zend_Navigation
'active' => true ) ) ) ) ) ) ), array( 'label' => 'ACL page 1 (guest)', 'uri' => '#acl-guest', 'resource' => 'nav-guest', 'pages' => array( array( 'label' => 'ACL page 1.1 (foo)', 'uri' => '#acl-foo', 'resource' => 'nav-foo' ), array( 'label' => 'ACL page 1.2 (bar)', 'uri' => '#acl-bar', 'resource' => 'nav-bar' ), array( 'label' => 'ACL page 1.3 (baz)', 'uri' => '#acl-baz', 'resource' => 'nav-baz' ), array( 'label' => 'ACL page 1.4 (bat)', 'uri' => '#acl-bat', 'resource' => 'nav-bat' ) ) ), array( 'label' => 'ACL page 2 (member)', 'uri' => '#acl-member', 'resource' => 'nav-member' ), array( 'label' => 'ACL page 3 (admin', 'uri' => '#acl-admin', 'resource' => 'nav-admin', 'pages' => array( array( 'label' => 'ACL page 3.1 (nothing)', 'uri' => '#acl-nada' ) ) ), array( 'label' => 'Zend Framework', 'route' => 'zf-route'
881
Zend_Navigation
) ));
882
Zend_Navigation
</page2_2_2> </pages> </page2_2> <page2_3> <label>Page 2.3</label> <uri>page2/page2_3</uri> <pages> <page2_3_1> <label>Page 2.3.1</label> <uri>page2/page2_3/page2_3_1</uri> </page2_3_1> <page2_3_2> <label>Page 2.3.2</label> <uri>page2/page2_3/page2_3_2</uri> <visible>0</visible> <pages> <page2_3_2_1> <label>Page 2.3.2.1</label> <uri>page2/page2_3/page2_3_2/1</uri> <active>1</active> </page2_3_2_1> <page2_3_2_2> <label>Page 2.3.2.2</label> <uri>page2/page2_3/page2_3_2/2</uri> <active>1</active> <pages> <page_2_3_2_2_1> <label>Ignore</label> <uri>#</uri> <active>1</active> </page_2_3_2_2_1> </pages> </page2_3_2_2> </pages> </page2_3_2> <page2_3_3> <label>Page 2.3.3</label> <uri>page2/page2_3/page2_3_3</uri> <resource>admin</resource> <pages> <page2_3_3_1> <label>Page 2.3.3.1</label> <uri>page2/page2_3/page2_3_3/1</uri> <active>1</active>
883
Zend_Navigation
</page2_3_3_1> <page2_3_3_2> <label>Page 2.3.3.2</label> <uri>page2/page2_3/page2_3_3/2</uri> <resource>guest</resource> <active>1</active> </page2_3_3_2> </pages> </page2_3_3> </pages> </page2_3> </pages> </page2> <page3> <label>Page 3</label> <uri>page3</uri> <pages> <page3_1> <label>Page 3.1</label> <uri>page3/page3_1</uri> <resource>guest</resource> </page3_1> <page3_2> <label>Page 3.2</label> <uri>page3/page3_2</uri> <resource>member</resource> <pages> <page3_2_1> <label>Page 3.2.1</label> <uri>page3/page3_2/page3_2_1</uri> </page3_2_1> <page3_2_2> <label>Page 3.2.2</label> <uri>page3/page3_2/page3_2_2</uri> <resource>admin</resource> </page3_2_2> </pages> </page3_2> <page3_3> <label>Page 3.3</label> <uri>page3/page3_3</uri> <resource>special</resource> <pages>
884
Zend_Navigation
<page3_3_1> <label>Page 3.3.1</label> <uri>page3/page3_3/page3_3_1</uri> <visible>0</visible> </page3_3_1> <page3_3_2> <label>Page 3.3.2</label> <uri>page3/page3_3/page3_3_2</uri> <resource>admin</resource> </page3_3_2> </pages> </page3_3> </pages> </page3> <home> <label>Home</label> <order>-100</order> <module>default</module> <controller>index</controller> <action>index</action> </home> </nav> </config> */ $config = new Zend_Config_Xml('/path/to/navigation.xml', 'nav'); $container = new Zend_Navigation($config);
Adding pages
Adding pages to a container can be done with the methods addPage(), addPages(), or setPages(). See examples below for explanation.
885
Zend_Navigation
// add page by giving a config object $container->addPage(new Zend_Config(array( 'uri' => 'http://www.example.com/' ))) $pages = array( array( 'label' => 'action' => ), array( 'label' => 'action' => ) );
'Save' 'save',
'Delete', 'delete'
// add two pages $container->addPages($pages); // remove existing pages and add the given pages $container->setPages($pages);
Removing pages
Removing pages can be done with removePage() or removePages(). The first method accepts a an instance of a page, or an integer. The integer corresponds to the order a page has. The latter method will remove all pages in the container.
// remove page by implicit page order $container->removePage(0); // removes Page 1 // remove page by instance $page3 = $container->findOneByAction('Page 3'); $container->removePage($page3); // removes Page 3
886
Zend_Navigation
// remove page by explicit page order $container->removePage(200); // removes Page 2 // remove all pages $container->removePages();
Finding pages
Containers have finder methods for retrieving pages. They are findOneBy($property, $value), findAllBy($property, $value), and findBy($property, $value, $all = false). Those methods will recursively search the container for pages matching the given $page->$property == $value. The first method, findOneBy(), will return a single page matching the property with the given value, or null if it cannot be found. The second method will return all pages with a property matching the given value. The third method will call one of the two former methods depending on the $all flag. The finder methods can also be used magically by appending the property name to findBy, findOneBy, or findAllBy, e.g. findOneByLabel('Home') to return the first matching page with label Home. Other combinations are findByLabel(...), findOnyByTitle(...), findAllByController(...), etc. Finder methods also work on custom properties, such as findByFoo('bar').
887
Zend_Navigation
=> 'page1'
// The 'id' is not required to be unique, but be aware that // having two pages with the same id will render the same id // in menus and breadcrumbs. $found = $container->findBy('id', 'page_2_and_3'); // returns $found = $container->findOneBy('id', 'page_2_and_3'); // returns $found = $container->findBy('id', 'page_2_and_3', true); // returns $found = $container->findById('page_2_and_3'); // returns $found = $container->findOneById('page_2_and_3'); // returns $found = $container->findAllById('page_2_and_3'); // returns // Find all matching CSS class my-class $found = $container->findAllBy('class', 'my-class'); $found = $container->findAllByClass('my-class'); // Find first matching CSS class my-class $found = $container->findOneByClass('my-class');
attribute
Page 2 Page 2
// returns Page 1.2 and Page 2 // returns Page 1.2 and Page 2
// Find all matching CSS class non-existant $found = $container->findAllByClass('non-existant'); // returns array() // Find first matching CSS class non-existant $found = $container->findOneByClass('non-existant'); // returns null // Find all pages with custom property 'foo' = 'bar' $found = $container->findAllBy('foo', 'bar'); // returns Page 1 and Page 1.1 // To achieve the same magically, 'foo' must be in lowercase. // This is because 'foo' is a custom property, and thus the // property name is not normalized to 'Foo' $found = $container->findAllByfoo('bar'); // Find all with controller = 'index' $found = $container->findAllByController('index'); // returns Page 2 and Page 3
Iterating containers
Zend_Navigation_Container implements RecursiveIteratorIterator, and can be iterated using any Iterator class. To iterate a container recursively, use the RecursiveIteratorIterator class.
888
Zend_Navigation
Other operations
The method hasPage(Zend_Navigation_Page $page) checks if the container has the given page. The method hasPages() checks if there are any pages in the container, and is equivalent to count($container) > 1. The toArray() method converts the container and the pages in it to an array. This can be useful for serializing and debugging.
889
Zend_Navigation
890
Zend_Navigation
["rel"]=> array(0) { } ["rev"]=> array(0) { } ["order"]=> NULL ["resource"]=> NULL ["privilege"]=> NULL ["active"]=> bool(false) ["visible"]=> bool(true) ["type"]=> string(23) "Zend_Navigation_Page_Uri" ["pages"]=> array(2) { [0]=> array(15) { ["label"]=> string(8) "Page 2.1" ["id"]=> NULL ["class"]=> NULL ["title"]=> NULL ["target"]=> NULL ["rel"]=> array(0) { } ["rev"]=> array(0) { } ["order"]=> NULL ["resource"]=> NULL ["privilege"]=> NULL ["active"]=> bool(false) ["visible"]=> bool(true) ["type"]=> string(23) "Zend_Navigation_Page_Uri" ["pages"]=> array(0) { } ["uri"]=> string(1) "#" } [1]=> array(15) { ["label"]=> string(8) "Page 2.2" ["id"]=> NULL ["class"]=> NULL ["title"]=> NULL ["target"]=> NULL ["rel"]=> array(0) { } ["rev"]=> array(0) { } ["order"]=> NULL ["resource"]=> NULL ["privilege"]=> NULL ["active"]=> bool(false) ["visible"]=> bool(true) ["type"]=> string(23) "Zend_Navigation_Page_Uri" ["pages"]=> array(0) { } ["uri"]=> string(1) "#" } } ["uri"]=> string(1) "#"
891
Zend_Navigation
} } */
892
What is OpenID?
OpenID is a set of protocols for user-centric digital identities. These protocols allows users to create an identity online, using an identity provider. This identity can be used on any site that supports OpenID. Using OpenID-enabled sites, users do not need to remember traditional authentication tokens such as usernames and passwords for each site. All OpenID-enabled sites accept a single OpenID identity. This identity is typically a URL. It may be the URL of the user's personal page, blog or other resource that may provide additional information about them. That mean a user needs just one identifier for all sites he or she uses. services. OpenID is an open, decentralized, and free user-centric solution. Users may choose which OpenID provider to use, or even create their own personal identity server. No central authority is required to approve or register OpenID-enabled sites or identity providers. For more information about OpenID visit the OpenID official site [http://www.openid.net/].
1. Authentication is initiated by the end user, who passes their OpenID identifier to the OpenID consumer through a User-Agent. 2. The OpenID consumer performs normalization and discovery on the user-supplied identifier. Through this process, the consumer obtains the claimed identifier, the URL of the OpenID provider and an OpenID protocol version. 3. The OpenID consumer establishes an optional association with the provider using Diffie-Hellman keys. As a result, both parties have a common "shared secret" that is used for signing and verification of the subsequent messages. 4. The OpenID consumer redirects the User-Agent to the URL of the OpenID provider with an OpenID authentication request. 5. The OpenID provider checks if the User-Agent is already authenticated and, if not, offers to do so. 6. The end user enters the required password. 7. The OpenID provider checks if it is allowed to pass the user identity to the given consumer, and asks the user if necessary.
893
Zend_OpenId
8. The user allows or disallows passing his identity. 9. The OpenID Provider redirects the User-Agent back to the OpenID consumer with an "authentication approved" or "failed" request. 10.The OpenID consumer verifies the information received from the provider by using the shared secret it got in step 3 or by sending an additional direct request to the OpenID provider.
Zend_OpenId Structure
Zend_OpenId consists of two sub-packages. The first one is Zend_OpenId_Consumer for developing OpenIDenabled sites, and the second is Zend_OpenId_Provider for developing OpenID servers. They are completely independent of each other and may be used separately. The only common code used by these sub-packages are the OpenID Simple Registration Extension implemented by Zend_OpenId_Extension_Sreg class and a set of utility functions implemented by the Zend_OpenId class.
Nota
Zend_OpenId takes advantage of the GMP extension [http://php.net/gmp], where available. Consider enabling the GMP extension for enhanced performance when using Zend_OpenId.
Zend_OpenId_Consumer Basics
Zend_OpenId_Consumer can be used to implement OpenID authentication for web sites.
OpenID Authentication
From a web site developer's point of view, the OpenID authentication process consists of three steps: 1. Show OpenID authentication form 2. Accept OpenID identity and pass it to the OpenID provider 3. Verify response from the OpenID provider The OpenID authentication protocol actually requires more steps, but many of them are encapsulated inside Zend_OpenId_Consumer and are therefore transparent to the developer. The end user initiates the OpenID authentication process by submitting his or her identification credentials with the appropriate form. The following example shows a simple form that accepts an OpenID identifier. Note that the example only demonstrates a login.
894
Zend_OpenId
895
Zend_OpenId
Consumer Realm
When an OpenID-enabled site passes authentication requests to a provider, it identifies itself with a realm URL. This URL may be considered a root of a trusted site. If the user trusts the realm URL, he or she should also trust matched and subsequent URLs.
896
Zend_OpenId
By default, the realm URL is automatically set to the URL of the directory in which the login script resides. This default value is useful for most, but not all, cases. Sometimes an entire domain, and not a directory should be trusted. Or even a combination of several servers in one domain. To override the default value, developers may pass the realm URL as a third argument to the Zend_OpenId_Consumer::login method. In the following example, a single interaction asks for trusted access to all php.net sites.
Immediate Check
In some cases, an application need only check if a user is already logged in to a trusted OpenID server without any interaction with the user. The Zend_OpenId_Consumer::check method does precisely that. It is executed with the same arguments as Zend_OpenId_Consumer::login, but it doesn't display any OpenID server pages to the user. From the users point of view this process is transparent, and it appears as though they never left the site. The third step succeeds if the user is already logged in and trusted by the site, otherwise it will fail.
Zend_OpenId_Consumer_Storage
There are three steps in the OpenID authentication procedure, and each step is performed by a separate HTTP request. To store information between requests, Zend_OpenId_Consumer uses internal storage. Developers do not necessarily have to be aware of this storage because by default Zend_OpenId_Consumer uses file-based storage under the temporary directory- similar to PHP sessions. However, this storage may be not suitable in all cases. Some developers may want to store information in a database, while others may need to use common storage suitable for server farms. Fortunately, developers may easily replace the default storage with their own. To specify a custom storage mechanism, one need only extend the Zend_OpenId_Consumer_Storage class and pass this subclass to the Zend_OpenId_Consumer constructor in the first argument. The following example demonstrates a simple storage mechanism that uses Zend_Db as its backend and exposes three groups of functions. The first group contains functions for working with associations, while the second group
897
Zend_OpenId
caches discovery information, and the third group can be used to check whether a response is unique. This class can easily be used with existing or new databases; if the required tables don't exist, it will create them.
898
Zend_OpenId
" nonce varchar(256) not null primary key," . " created timestamp default current_timestamp" . ")"); } } public function addAssociation($url, $handle, $macFunc, $secret, $expires) { $table = $this->_association_table; $secret = base64_encode($secret); $this->_db ->query('insert into ' . $table (url, handle, macFunc, secret, expires) " . "values ('$url', '$handle', '$macFunc', " . "'$secret', $expires)"); return true; } public function getAssociation($url, &$handle, &$macFunc, &$secret, &$expires) { $table = $this->_association_table; $this->_db->query("delete from $table where expires < " . time()); $res = $this->_db->fetchRow('select handle, macFunc, secret, expires ' . "from $table where url = '$url'"); if (is_array($res)) { $handle = $res['handle']; $macFunc = $res['macFunc']; $secret = base64_decode($res['secret']); $expires = $res['expires']; return true; } return false; } public function getAssociationByHandle($handle, &$url, &$macFunc, &$secret, &$expires) { $table = $this->_association_table; $this->_db->query("delete from $table where expires < " . time()); $res = $this->_db ->fetchRow('select url, macFunc, secret, expires ' . "from $table where handle = '$handle'"); if (is_array($res)) {
899
Zend_OpenId
$url = $res['url']; $macFunc = $res['macFunc']; $secret = base64_decode($res['secret']); $expires = $res['expires']; return true; } return false; } public function delAssociation($url) { $table = $this->_association_table; $this->_db->query("delete from $table where url = '$url'"); return true; } public function addDiscoveryInfo($id, $realId, $server, $version, $expires) { $table = $this->_discovery_table; $this->_db ->query("insert into $table " . "(id, realId, server, version, expires) " . "values " . "('$id', '$realId', '$server', $version, $expires)"); return true; } public function getDiscoveryInfo($id, &$realId, &$server, &$version, &$expires) { $table = $this->_discovery_table; $this->_db->query("delete from $table where expires < " . time()); $res = $this->_db ->fetchRow('select realId, server, version, expires ' . "from $table where id = '$id'"); if (is_array($res)) { $realId = $res['realId']; $server = $res['server']; $version = $res['version']; $expires = $res['expires']; return true; } return false; } public function delDiscoveryInfo($id) {
900
Zend_OpenId
$table = $this->_discovery_table; $this->_db->query("delete from $table where id = '$id'"); return true; } public function isUniqueNonce($nonce) { $table = $this->_nonce_table; try { $ret = $this->_db ->query("insert into $table (nonce) values ('$nonce')"); } catch (Zend_Db_Statement_Exception $e) { return false; } return true; } public function purgeNonces($date=null) { } } $db = Zend_Db::factory('Pdo_Sqlite', array('dbname'=>'/tmp/openid_consumer.db')); $storage = new DbStorage($db); $consumer = new Zend_OpenId_Consumer($storage); This example doesn't list the OpenID authentication code itself, but this code would be the same as that for other examples in this chapter. examples.
901
Zend_OpenId
language - the user's preferred language as specified by ISO639 timezone - an ASCII string from a TimeZone database. For example, "Europe/Paris" or "America/Los_Angeles". An OpenID-enabled web site may ask for any combination of these fields. It may also strictly require some information and allow users to provide or hide additional information. The following example instantiates the Zend_OpenId_Extension_Sreg class, requiring a nickname and optionally requests an email and a fullname.
902
Zend_OpenId
echo "INVALID " . htmlspecialchars($id); } If the Zend_OpenId_Extension_Sreg object was created without any arguments, the user code should check for the existence of the required data itself. However, if the object is created with the same list of required fields as on the second step, it will automatically check for the existence of required data. In this case, Zend_OpenId_Consumer::verify will return false if any of the required fields are missing. Zend_OpenId_Extension_Sreg uses version 1.0 by default, because the specification for version 1.1 is not yet finalized. However, some libraries don't fully support version 1.0. For example, www.myopenid.com requires an SREG namespace in requests which is only available in 1.1. To work with such a server, you must explicitly set the version to 1.1 in the Zend_OpenId_Extension_Sreg constructor. The second argument of the Zend_OpenId_Extension_Sreg constructor is a policy URL, that should be provided to the user by the identity provider.
903
Zend_OpenId
} return new Zend_Auth_Result($ret, $id, array($msg)); } } $status = ""; $auth = Zend_Auth::getInstance(); if ((isset($_POST['openid_action']) && $_POST['openid_action'] == "login" && !empty($_POST['openid_identifier'])) || isset($_GET['openid_mode'])) { $adapter = new OpenIdAdapter(@$_POST['openid_identifier']); $result = $auth->authenticate($adapter); if ($result->isValid()) { Zend_OpenId::redirect(Zend_OpenId::selfURL()); } else { $auth->clearIdentity(); foreach ($result->getMessages() as $message) { $status .= "$message<br>\n"; } } } else if ($auth->hasIdentity()) { if (isset($_POST['openid_action']) && $_POST['openid_action'] == "logout") { $auth->clearIdentity(); } else { $status = "You are logged in as " . $auth->getIdentity() . "<br>\n"; } } ?> <html><body> <?php echo htmlspecialchars($status);?> <form method="post"><fieldset> <legend>OpenID Login</legend> <input type="text" name="openid_identifier" value=""> <input type="submit" name="openid_action" value="login"> <input type="submit" name="openid_action" value="logout"> </fieldset></form></body></html> With Zend_Auth the end-user's identity is saved in the session's data. It may be checked with Zend_Auth::hasIdentity and Zend_Auth::getIdentity.
904
Zend_OpenId
Zend_OpenId_Provider
Zend_OpenId_Provider can be used to implement OpenID servers. This chapter provides examples that demonstrate how to build a very basic server. However, for implementation of a production OpenID server (such as www.myopenid.com [http://www.myopenid.com]) you may have to deal with more complex issues.
Quick Start
The following example includes code for creating a user account using Zend_OpenId_Provider::register. The link element with rel="openid.server" points to our own server script. If you submit this identity to an OpenID-enabled site, it will perform authentication on this server. The code before the <html> tag is just a trick that automatically creates a user account. You won't need such code when using real identities.
905
Zend_OpenId
echo 'Forbidden'; }
Nota
It is a good idea to use a secure connection (HTTPS) for these scripts- especially for the following interactive scripts- to prevent password disclosure. The following script implements a login screen for an identity server using Zend_OpenId_Provider and redirects to this page when a required user has not yet logged in. On this page, a user will enter his password to login. You should use the password "123" that was used in the identity script above. On submit, the script calls Zend_OpenId_Provider::login with the accepted user's identity and password, then redirects back to the main identity provider's script. On success, the Zend_OpenId_Provider::login establishes a session between the user and the identity provider and stores the information about the user, who is now logged in. All following requests from the same user won't require a login procedure- even if they come from another OpenID enabled web site.
Nota
Note that this session is between end-user and identity provider only. OpenID enabled sites know nothing about it.
906
Zend_OpenId
<td>Password:</td> <td> <input type="text" name="openid_password" value=""> </td> </tr> <tr> <td> </td> <td> <input type="submit" name="openid_action" value="login"> </td> </tr> </table> </fieldset> </form> </body> </html> The fact that the user is now logged in doesn't mean that the authentication must necessarily succeed. The user may decide not to trust particular OpenID enabled sites. The following trust screen allows the end user to make that choice. This choice may either be made only for current requests or forever. In the second case, information about trusted/ untrusted sites is stored in an internal database, and all following authentication requests from this site will be handled automatically without user interaction.
907
Zend_OpenId
<a href="<?php echo htmlspecialchars($server->getSiteRoot($_GET));?>"> <?php echo htmlspecialchars($server->getSiteRoot($_GET));?> </a> has asked us for confirmation that <a href="<?php echo htmlspecialchars($server->getLoggedInUser());?>"> <?php echo htmlspecialchars($server->getLoggedInUser());?> </a> is your identity URL. </p> <form method="post"> <input type="checkbox" name="forever"> <label for="forever">forever</label><br> <input type="hidden" name="openid_action" value="trust"> <input type="submit" name="allow" value="Allow"> <input type="submit" name="deny" value="Deny"> </form> </body> </html> Production OpenID servers usually support the Simple Registration Extension that allows consumers to request some information about the user from the provider. In this case, the trust page can be extended to allow entering requested fields or selecting a specific user profile.
Nota
The following example is not complete. It doesn't provide GUI code for the user, instead performing an automatic login and trust relationship instead. This is done just to simplify the example; a production server should include some code from previous examples.
908
Zend_OpenId
} else { $ret = $server->handle(); if (is_string($ret)) { echo $ret; } else if ($ret !== true) { header('HTTP/1.0 403 Forbidden'); echo 'Forbidden'; } } If you compare this example with previous examples split in to separate pages, you will see only the one difference besides the dispatch code: unset($_GET['openid_action']). This call to unset is necessary to route the next request to main handler.
909
Zend_OpenId
trust was established by calling the Zend_OpenId_Provider::allowSite() method in the identity script. The same method associates the profile with the trusted URL. This profile will be returned automatically for a request from the trusted URL. To make Simple Registration Extension work, you must simply pass an instance of Zend_OpenId_Extension_Sreg as the second argument to the Zend_OpenId_Provider::handle() method.
Anything Else?
Building OpenID providers is much less common than building OpenID-enabled sites, so this manual doesn't cover all Zend_OpenId_Provider features exhaustively, as was done for Zend_OpenId_Consumer. To summamize, Zend_OpenId_Provider contains: A set of methods to build an end-user GUI that allows users to register and manage their trusted sites and profiles An abstract storage layer to store information about users, their sites and their profiles. It also stores associations between the provider and OpenID-enabled sites. This layer is very similar to that of the Zend_OpenId_Consumer class. It also uses file storage by default, but may used with another backend. An abstract user-association layer that may associate a user's web browser with a logged-in identity The Zend_OpenId_Provider class doesn't attempt to cover all possible features that can be implemented by OpenID servers, e.g. digital certificates, but it can be extended easily using Zend_OpenId_Extensions or by standard object-oriented extension.
910
Usage
Paginating data collections
In order to paginate items into pages, Zend_Paginator must have a generic way of accessing that data. For that reason, all data access takes place through data source adapters. Several adapters ship with Zend Framework by default:
Iterator Null
Nota
Instead of selecting every matching row of a given query, the DbSelect and DbTableSelect adapters retrieve only the smallest amount of data necessary for displaying the current page. Because of this, a second query is dynamically generated to determine the total number of matching rows. However, it is possible to directly supply a count or count query yourself. See the setRowCount() method in the DbSelect adapter for more information. To create an instance of Zend_Paginator, you must supply an adapter to the constructor:
911
Zend_Paginator
$paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($array)); For convenience, you may take advantage of the static factory() method for the adapters packaged with Zend Framework: $paginator = Zend_Paginator::factory($array);
Nota
In the case of the Null adapter, in lieu of a data collection you must supply an item count to its constructor. Although the instance is technically usable in this state, in your controller action you'll need to tell the paginator what page number the user requested. This allows him to advance through the paginated data. $paginator->setCurrentPageNumber($page); The simplest way to keep track of this value is through a URL. Although we recommend using a Zend_Controller_Router_Interface-compatible router to handle this, it is not a requirement. The following is an example route you might use in an INI configuration file: routes.example.route = articles/:articleName/:page routes.example.defaults.controller = articles routes.example.defaults.action = view routes.example.defaults.page = 1 routes.example.reqs.articleName = \w+ routes.example.reqs.page = \d+ With the above route (and using Zend Framework MVC components), you might set the current page number like this: $paginator->setCurrentPageNumber($this->_getParam('page')); There are other options available; see Configuration for more on them. Finally, you'll need to assign the paginator instance to your view. If you're using Zend_View with the ViewRenderer action helper, the following will work: $this->view->paginator = $paginator;
912
Zend_Paginator
The database adapters will try and build the most efficient query that will execute on pretty much all modern databases. However, depending on your database or even your own schema setup, there might be more efficient ways to get a rowcount. For this scenario the database adapters allow you to set a custom COUNT query. For example, if you keep track of the count of blog posts in a separate table, you could achieve a faster count query with the following setup: $adapter = new Zend_Paginator_Adapter_DbSelect($db->select()->from('posts')); $adapter->setRowCount( $db->select() ->from( 'item_counts', array( Zend_Paginator_Adapter_DbSelect::ROW_COUNT_COLUMN => 'post_count' ) ) ); $paginator = new Zend_Paginator($adapter); This approach will probably not give you a huge performance gain on small collections and/or simple select queries. However, with complex queries and large collections, a similar approach could give you a significant performance boost.
913
Zend_Paginator
What happens when the user clicks the "next" link a few times? Well, any number of things could happen. The current page number could stay in the middle as you click through (as it does on Yahoo!), or it could advance to the end of the page range and then appear again on the left when the user clicks "next" one more time. The page numbers might even expand and contract as the user advances (or "scrolls") through them (as they do on Google). There are four scrolling styles packaged with Zend Framework:
Elastic Jumping
Sliding
The fourth and final parameter is reserved for an optional associative array of additional variables that you want available in your view partial (available via $this). For instance, these values could include extra URL parameters for pagination links. By setting the default view partial, default scrolling style, and view instance, you can eliminate the calls to PaginationControl completely:
Zend_Paginator::setDefaultScrollingStyle('Sliding'); Zend_View_Helper_PaginationControl::setDefaultViewPartial( 'my_pagination_control.phtml' ); $paginator->setView($view); When all of these values are set, you can render the pagination control inside your view script with a simple echo statement:
Nota
Of course, it's possible to use Zend_Paginator with other template engines. For example, with Smarty you might do the following:
914
Zend_Paginator
$smarty->assign('pages', $paginator->getPages()); You could then access paginator values from a template like so:
{$pages->pageCount}
<!-See http://developer.yahoo.com/ypatterns/pattern.php?pattern=searchpagination --> <?php if ($this->pageCount): ?> <div class="paginationControl"> <!-- Previous page link --> <?php if (isset($this->previous)): ?> <a href="<?php echo $this->url(array('page' => $this->previous)); ?>"> < Previous </a> | <?php else: ?> <span class="disabled">< Previous</span> | <?php endif; ?> <!-- Numbered page links --> <?php foreach ($this->pagesInRange as $page): ?> <?php if ($page != $this->current): ?> <a href="<?php echo $this->url(array('page' => $page)); ?>"> <?php echo $page; ?> </a> | <?php else: ?> <?php echo $page; ?> | <?php endif; ?> <?php endforeach; ?> <!-- Next page link --> <?php if (isset($this->next)): ?> <a href="<?php echo $this->url(array('page' => $this->next)); ?>"> Next > </a> <?php else: ?> <span class="disabled">Next ></span> <?php endif; ?> </div> <?php endif; ?> Item pagination:
<!--
915
Zend_Paginator
See http://developer.yahoo.com/ypatterns/pattern.php?pattern=itempagination --> <?php if ($this->pageCount): ?> <div class="paginationControl"> <?php echo $this->firstItemNumber; ?> - <?php echo $this->lastItemNumber; ?> of <?php echo $this->totalItemCount; ?> <!-- First page link --> <?php if (isset($this->previous)): ?> <a href="<?php echo $this->url(array('page' => $this->first)); ?>"> First </a> | <?php else: ?> <span class="disabled">First</span> | <?php endif; ?> <!-- Previous page link --> <?php if (isset($this->previous)): ?> <a href="<?php echo $this->url(array('page' => $this->previous)); ?>"> < Previous </a> | <?php else: ?> <span class="disabled">< Previous</span> | <?php endif; ?> <!-- Next page link --> <?php if (isset($this->next)): ?> <a href="<?php echo $this->url(array('page' => $this->next)); ?>"> Next > </a> | <?php else: ?> <span class="disabled">Next ></span> | <?php endif; ?> <!-- Last page link --> <?php if (isset($this->next)): ?> <a href="<?php echo $this->url(array('page' => $this->last)); ?>"> Last </a> <?php else: ?> <span class="disabled">Last</span> <?php endif; ?> </div> <?php endif; ?> Dropdown pagination:
<?php if ($this->pageCount): ?> <select id="paginationControl" size="1"> <?php foreach ($this->pagesInRange as $page): ?> <?php $selected = ($page == $this->current) ? ' selected="selected"' : ''; ?>
916
Zend_Paginator
<option value="<?php echo $this->url(array('page' => $page));?>"<?php echo $selected ?>> <?php echo $page; ?> </option> <?php endforeach; ?> </select> <?php endif; ?> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js"> </script> <script type="text/javascript"> $('paginationControl').observe('change', function() { window.location = this.options[this.selectedIndex].value; }) </script>
Listing of properties
The following options are available to pagination control view partials:
Configuration
Zend_Paginator has several configuration methods that can be called:
917
Zend_Paginator
setView
Advanced usage
Custom data source adapters
At some point you may run across a data type that is not covered by the packaged adapters. In this case, you will need to write your own. To do so, you must implement Zend_Paginator_Adapter_Interface. There are two methods required to do this: count() getItems($offset, $itemCountPerPage) Additionally, you'll want to implement a constructor that takes your data source as a parameter and stores it as a protected or private property. How you wish to go about doing this specifically is up to you. If you've ever used the SPL interface Countable [http://www.php.net/~helly/php/ext/spl/interfaceCountable.html], you're familiar with count(). As used with Zend_Paginator, this is the total number of items in the data collection. Additionally, the Zend_Paginator instance provides a method countAllItems() that proxies to the adapter count() method. The getItems() method is only slightly more complicated. For this, your adapter is supplied with an offset and the number of items to display per page. You must return the appropriate slice of data. For an array, that would be:
return array_slice($this->_array, $offset, $itemCountPerPage); Take a look at the packaged adapters (all of which implement the Zend_Paginator_Adapter_Interface) for ideas of how you might go about implementing your own.
918
Zend_Paginator
This method should calculate a lower and upper bound for page numbers within the range of so-called "local" pages (that is, pages that are nearby the current page). Unless it extends another scrolling style (see Zend_Paginator_ScrollingStyle_Elastic for an example), your custom scrolling style will inevitably end with something similar to the following line of code: return $paginator->getPagesInRange($lowerBound, $upperBound); There's nothing special about this call; it's merely a convenience method to check the validity of the lower and upper bound and return an array of the range to the paginator. When you're ready to use your new scrolling style, you'll need to tell Zend_Paginator what directory to look in. To do that, do the following: $prefix = 'My_Paginator_ScrollingStyle'; $path = 'My/Paginator/ScrollingStyle/'; Zend_Paginator::addScrollingStylePrefixPath($prefix, $path);
Caching features
Zend_Paginator can be told to cache the data it has already passed on, preventing the adapter from fetching them each time they are used. To tell paginator to automatically cache the adapter's data, just pass to its setCache() method a Zend_Cache_Core instance. $paginator = Zend_Paginator::factory($someData); $fO = array('lifetime' => 3600, 'automatic_serialization' => true); $bO = array('cache_dir'=>'/tmp'); $cache = Zend_cache::factory('Core', 'File', $fO, $bO); Zend_Paginator::setCache($cache); As far as Zend_Paginator has got a Zend_Cache_Core instance, data will be cached. Sometimes you would like not to cache data even if you already passed a cache instance. You should then use setCacheEnable() for that. $paginator = Zend_Paginator::factory($someData); // $cache is a Zend_Cache_Core instance Zend_Paginator::setCache($cache); // ... later on the script $paginator->setCacheEnable(false); // cache is now disabled When a cache is set, data are automatically stored in it and pulled out from it. It then can be useful to empty the cache manually. You can get this done by calling clearPageItemCache($pageNumber). If you don't pass any parameter, the whole cache will be empty. You can optionally pass a parameter representing the page number to empty in the cache: $paginator = Zend_Paginator::factory($someData); Zend_Paginator::setCache($cache); $items = $paginator->getCurrentItems(); // page 1 is now in cache $page3Items = $paginator->getItemsByPage(3); // page 3 is now in cache
919
Zend_Paginator
// clear the cache of the results for page 3 $paginator->clearPageItemCache(3); // clear all the cache data $paginator->clearPageItemCache(); Changing the item count per page will empty the whole cache as it would have become invalid: $paginator = Zend_Paginator::factory($someData); Zend_Paginator::setCache($cache); // fetch some items $items = $paginator->getCurrentItems(); // all the cache data will be flushed: $paginator->setItemCountPerPage(2); It is also possible to see the data in cache and ask for them directly. getPageItemCache() can be used for that: $paginator = Zend_Paginator::factory($someData); $paginator->setItemCountPerPage(3); Zend_Paginator::setCache($cache); // fetch some items $items = $paginator->getCurrentItems(); $otherItems = $paginator->getItemsPerPage(4); // see the cached items as a two-dimension array: var_dump($paginator->getPageItemCache());
Zend_Paginator_AdapterAggregate Interface
Depending on your application you might want to paginate objects, whose internal data-structure is equal to existing adapters, but you don't want to break up your encapsulation to allow access to this data. In other cases an object might be in a "has-an adapter" relationship, rather than the "is-an adapter" relationsship that Zend_Paginator_Adapter_Abstract promotes. For this cases you can use the Zend_Paginator_AdapterAggregate interface that behaves much like the IteratorAggregate interface of the PHP SPL extension. interface Zend_Paginator_AdapterAggregate { /** * Return a fully configured Paginator Adapter from this method. * * @return Zend_Paginator_Adapter_Abstract */ public function getPaginatorAdapter(); } The interface is fairly small and only expects you to return an instance of Zend_Paginator_Adapter_Abstract. An Adapter Aggregate instance is then recognized by both Zend_Paginator::factory and the constructor of Zend_Paginator and handled accordingly.
920
921
Zend_Pdf
El formato de archivos PDF soporta la actualizacin incremental del documento. As, cada vez que un documento es actualizado, entonces se crea una nueva revisin del documento. El componente Zend_Pdf soporta la recuperacin de una revisin especificada. Una revisin puede especificarse como un segundo parmetro a los mtodos Zend_Pdf::load() y Zend_Pdf::parse() o requerirlo llamando al mtodo Zend_Pdf::rollback(). 3 call.
El mtodo Zend_Pdf::rollback() debe ser invocado antes de aplicar cualquier cambio al documento, de lo contrario el comportamiento no est definido.
922
Zend_Pdf
Clonado de Pfinas.
La pgina PDF existente puede ser clonada creando un nuevo objeto Zend_Pdf_Page con una pgina existente como parmetro:
4
Es una limitacin de la versin actual de ZF. Ser eliminada en futuras versiones. Pero las pginas no agregadas siempre dan mejor resultado (ms ptimo) para compartir pginas entre los documentos.
923
Zend_Pdf
Caution
Importante! La pgina clonada comparte algunos recursos de PDF con una pgina plantilla, la que puede ser utilizada slo en el mismo documento como una pgina plantilla. El documento modificado pueden guardarse como uno nuevo.
Dibujo
Geometra
PDF utiliza la misma geometra que PostScript. Se inicia desde la parte inferior izquierda de la pgina y por defecto se mide en puntos (1/72 de pulgada). El tamao de la pgina se puede recuperar desde un objeto pgina:
Colores
PDF tiene una poderosa capacidad de representacin de colores. El mdulo Zend_Pdf soporta la Escala de Grises, y los espacios de color RGB y CMYK. Cualquiera de ellos puede ser usado en cualquier lugar, donde el objeto Zend_Pdf_Color sea requerido. Las clases Zend_Pdf_Color_GrayScale, Zend_Pdf_Color_Rgb y Zend_Pdf_Color_Cmyk proporcionan esta funcionalidad:
// $grayLevel (float number). 0.0 (black) - 1.0 (white) $color1 = new Zend_Pdf_Color_GrayScale($grayLevel);
924
Zend_Pdf
// $r, $g, $b (float numbers). 0.0 (min intensity) - 1.0 (max intensity) $color2 = new Zend_Pdf_Color_Rgb($r, $g, $b); // $c, $m, $y, $k (float numbers). 0.0 (min intensity) - 1.0 (max intensity) $color3 = new Zend_Pdf_Color_Cmyk($c, $m, $y, $k); Los estilos de colores HTML tambin se proporcionan con la clase Zend_Pdf_Color_Html: $color1 = new Zend_Pdf_Color_Html('#3366FF'); $color2 = new Zend_Pdf_Color_Html('silver'); $color3 = new Zend_Pdf_Color_Html('forestgreen');
Dibujo de Formas
Todas las operaciones de dibujo se puede hacer en un contexto de pgina PDF. La clase Zend_Pdf_Page proporciona un conjunto de primitivas de dibujo: /** * Dibujar una lnea desde x1,y1 hasta x2,y2. * * @param float $x1 * @param float $y1 * @param float $x2 * @param float $y2 * @return Zend_Pdf_Page */ public function drawLine($x1, $y1, $x2, $y2);
/** * Dibujar un rectngulo. * * Rellenar los tipos: * Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE - rellenar el rectngulo * y delinearlo (por defecto) * Zend_Pdf_Page::SHAPE_DRAW_STROKE - delinear el rectngulo * Zend_Pdf_Page::SHAPE_DRAW_FILL - rellenar el rectngulo * * @param float $x1 * @param float $y1 * @param float $x2 * @param float $y2 * @param integer $fillType * @return Zend_Pdf_Page */ public function drawRectangle($x1, $y1, $x2, $y2, $fillType = Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE);
925
Zend_Pdf
* * Si $fillType es Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE o * Zend_Pdf_Page::SHAPE_DRAW_FILL, entonces el polgono se cierra automticamente. * Vase la descripcin detallada de estos mtodos en la documentacin de PDF * (seccin 4.4.2 Path painting Operators, Filling) * * @param array $x - array de float (la coordenada X de los vrtices) * @param array $y - array de float (la coordenada Y de los vrtices) * @param integer $fillType * @param integer $fillMethod * @return Zend_Pdf_Page */ public function drawPolygon($x, $y, $fillType = Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE, $fillMethod = Zend_Pdf_Page::FILL_METHOD_NON_ZERO_WINDING);
/** * Dibujar un crculo centrado en X, y con un radio de radius. * * Los ngulos estn especificados en radianes. * * Firmas del Mtodo:: * drawCircle($x, $y, $radius); * drawCircle($x, $y, $radius, $fillType); * drawCircle($x, $y, $radius, $startAngle, $endAngle); * drawCircle($x, $y, $radius, $startAngle, $endAngle, $fillType); * * * No es un crculo de verdad, porque PDF slo admite curvas cbicss de Bezier, * pero con muy buena aproximacin. * Se distingue de un verdadero crculo en un mximo de 0.00026 radios (en PI/8, * 3*PI/8, 5*PI/8, 7*PI/8, 9*PI/8, 11*PI/8, 13*PI/8 y 15*PI/8 ngulos). * A 0, PI/4, PI/2, 3*PI/4, PI, 5*PI/4, 3*PI/2 y 7*PI/4 es exactamente * la tangente a un crculo. * * @param float $x * @param float $y * @param float $radius * @param mixed $param4 * @param mixed $param5 * @param mixed $param6 * @return Zend_Pdf_Page */ public function drawCircle($x, $y, $radius, $param4 = null, $param5 = null, $param6 = null);
926
Zend_Pdf
/** * Dibujar una elipse dentro del rectngulo especificado. * * Firmas del mtodo: * drawEllipse($x1, $y1, $x2, $y2); * drawEllipse($x1, $y1, $x2, $y2, $fillType); * drawEllipse($x1, $y1, $x2, $y2, $startAngle, $endAngle); * drawEllipse($x1, $y1, $x2, $y2, $startAngle, $endAngle, $fillType); * * Los ngulos se especifican en radianes * * @param float $x1 * @param float $y1 * @param float $x2 * @param float $y2 * @param mixed $param5 * @param mixed $param6 * @param mixed $param7 * @return Zend_Pdf_Page */ public function drawEllipse($x1, $y1, $x2, $y2, $param5 = null, $param6 = null, $param7 = null);
Dibujo de Texto
Las operaciones de dibujo de texto tambin existen en el contexto de una pgina PDF. Puede dibujar una sola lnea de texto en cualquier posicin en la pgina mediante el suministro de las coordenadas X e Y de la base de referencia. La fuente y tamao actual de la letra se utilizan para operaciones de dibujo de texto (ver descripcin detallada ms abajo). /** * Dibujar una lnea de texto en una posicin especfica. * * @param string $text * @param float $x * @param float $y * @param string $charEncoding (opcional) Codificacin de caracteres del texto * fuente. El valor por defecto es la codificacin actual y local. * @throws Zend_Pdf_Exception * @return Zend_Pdf_Page */ public function drawText($text, $x, $y, $charEncoding = '');
927
Zend_Pdf
Por defecto, los strings de texto se interpretan usando el mtodo de codificacin de la localizacin actual. Si tiene un string que utiliza un mtodo de codificacin diferente (como un string UTF-8 a leer desde un archivo en disco, o un string MacRoman obtenido a partir del legado de una base de datos), puede indicar la codificacin de caracteres a llamar en tiempo de dibujo y Zend_Pdf se encargar de la conversin. Puede proporcionar la fuente de cualquier mtodo de codificacin de strings soportados por la funcin de PHP iconv() [http://www.php.net/manual/ function.iconv.php] :
Uso de Fuentes
Zend_Pdf_Page::drawText() utiliza la fuente y el tamao actual de la fuente de la pgina, que se establece con el mtodo Zend_Pdf_Page::setFont():
/** * Establecer la fuente actual. * * @param Zend_Pdf_Resource_Font $font * @param float $fontSize * @return Zend_Pdf_Page */ public function setFont(Zend_Pdf_Resource_Font $font, $fontSize); Los documentos PDF soportan fuentes PostScript Type 1 y TrueType, as como dos tipos especializados de PDF, Type 3 y fuentes compuestas. Tambin hay 14 fuentes estndar Tipo 1 incorporadas para cada visor PDF: Courier (4 estilos), Helvetica (4 estilos), Times (4 estilos), Symbol y Zapf Dingbats. Zend_Pdf actualmente soporta el estndar de 14 fuentes PDF, as como sus propias fuentes personalizadas TrueType. Los objetos Font se obtienen a travs de una de los dos mtodos de fbrica: Zend_Pdf_Font::fontWithName($fontName) para las 14 fuentes estndar PDF o Zend_Pdf_Font::fontWithPath($filePath) para fuentes personalizadas.
928
Zend_Pdf
Zend_Pdf_Font::FONT_COURIER Zend_Pdf_Font::FONT_COURIER_BOLD Zend_Pdf_Font::FONT_COURIER_ITALIC Zend_Pdf_Font::FONT_COURIER_BOLD_ITALIC Zend_Pdf_Font::FONT_TIMES Zend_Pdf_Font::FONT_TIMES_BOLD Zend_Pdf_Font::FONT_TIMES_ITALIC Zend_Pdf_Font::FONT_TIMES_BOLD_ITALIC Zend_Pdf_Font::FONT_HELVETICA Zend_Pdf_Font::FONT_HELVETICA_BOLD Zend_Pdf_Font::FONT_HELVETICA_ITALIC Zend_Pdf_Font::FONT_HELVETICA_BOLD_ITALIC Zend_Pdf_Font::FONT_SYMBOL Zend_Pdf_Font::FONT_ZAPFDINGBATS Tambin puede utilizar cualquier fuente individual TrueType (que generalmente tiene una extensin '.ttf') o bien una fuente OpenType (con la extensin '.otf') si contiene esquemas TrueType. Actualmente no estn soportadas, pero est previsto para una versin futura archivos de fuentes .dfont de Mac OS X y de Microsoft TrueType Collection(extensin '.ttc'). Para utilizar una fuente TrueType, debe proporcionar toda la ruta del archivo a la fuente del programa. Si la fuente no se puede leer por alguna razn, o si no es una fuente TrueType, el mtodo de fbrica arrojar una excepcin:
Ejemplo 40.10. Crear una fuente TrueType, pero no incluirla en el documento PDF.
929
Zend_Pdf
... // Crear una nueva fuente $goodDogCoolFont = Zend_Pdf_Font::fontWithPath('/path/to/GOODDC__.TTF', Zend_Pdf_Font::EMBED_DONT_EMBED); // Aplicar la fuente $pdfPage->setFont($goodDogCoolFont, 36); ... Si el programa no es de fuentes incrustadas, pero el destinatario del archivo PDF tiene instalada la fuente en su sistema, va a ver el documento como estaba previsto. Si no tiene la fuente correcta instalada, la aplicacin del visor de PDF har todo lo posible para sintetizar un sustituto. Algunas fuentes tienen normas especficas de concesin de licencias que les impiden ser tenidas en cuenta en documentos PDF. As que no son capturados con la "guardia baja" por la presente, si intenta utilizar una fuente que no puede ser incorporada, el mtodo de fbrica lanzar una excepcin. Puede seguir utilizando esas fuentes, pero debe pasar el flag de no incluir como se ha descripto anteriormente, o simplemente puede suprimir la excepcin:
Ejemplo 40.11. No arrojar una excepcin para las fuentes que no puedan ser incorporadas.
... $font = Zend_Pdf_Font::fontWithPath( '/path/to/unEmbeddableFont.ttf', Zend_Pdf_Font::EMBED_SUPPRESS_EMBED_EXCEPTION ); ... Esta tcnica de supresin se prefiere si va a permitir a un usuario final a elegir sus propios tipos de letra. Las fuentes que puedan ser embebidas en el documento PDF, lo harn, aquellos que no puedan, no. Los de programas de fuentes pueden ser bastante grandes, algunas llegan a decenas de megabytes. Por defecto, todas las fuentes incorporadas son comprimidas utilizando el esquema de compresin Flate, lo que resulta en un ahorro de espacio del 50% en promedio. Si, por alguna razn, no desea comprimir la fuente del programa, se puede desactivar con una opcin:
930
Zend_Pdf
... $pdf = Zend_Pdf::load($documentPath); ... // Obtener todas las fuentes del documento $fontList = $pdf->extractFonts(); $pdf->pages[] = ($page = $pdf->newPage(Zend_Pdf_Page::SIZE_A4)); $yPosition = 700; foreach ($fontList as $font) { $page->setFont($font, 15); $fontName = $font->getFontName(Zend_Pdf_Font::NAME_POSTSCRIPT, 'en', 'UTF-8'); $page->drawText($fontName . ': The quick brown fox jumps over the lazy dog', 100,
931
Zend_Pdf
$yPosition, 'UTF-8'); $yPosition -= 30; } ... // Obtener las fuentes referenciadas dentro de la primera pgina del documento $firstPage = reset($pdf->pages); $firstPageFonts = $firstPage->extractFonts(); ...
... $pdf = new Zend_Pdf(); ... $pdf->pages[] = ($page = $pdf->newPage(Zend_Pdf_Page::SIZE_A4)); $font = Zend_Pdf_Font::fontWithPath($fontPath); $page->setFont($font, $fontSize); $page->drawText($text, $x, $y); ... // Este nombre de fuente debe ser almacenado en algn lugar... $fontName = $font->getFontName(Zend_Pdf_Font::NAME_POSTSCRIPT, 'en', 'UTF-8'); ... $pdf->save($docPath); ...
... $pdf = Zend_Pdf::load($docPath); ... $pdf->pages[] = ($page = $pdf->newPage(Zend_Pdf_Page::SIZE_A4)); /* $srcPage->extractFont($fontName) tambin se puede usar aqu */ $font = $pdf->extractFont($fontName); $page->setFont($font, $fontSize); $page->drawText($text, $x, $y); ... $pdf->save($docPath, true /* modo de actualizacin incremental */); ... Las fuentes extradas pueden ser utilizadas en el lugar de cualquier otra fuente con las siguientes limitaciones: La fuente extrada puede ser usada slo en el contexto del documento del que se ha extrado. Posiblemente, el programa no extraiga realmente la fuente incrustada. As que las fuentes extradas no pueden proporcionar mtricas correctas y la fuente original tiene que ser utilizada para los clculos de ancho de texto:
932
Zend_Pdf
... $font = $pdf->extractFont($fontName); $originalFont = Zend_Pdf_Font::fontWithPath($fontPath); $page->setFont($font /* usar la fuente extrada para dibujar */, $fontSize); $xPosition = $x; for ($charIndex = 0; $charIndex < strlen($text); $charIndex++) { $page->drawText($text[$charIndex], xPosition, $y); // Usar la fuente original para calcular el ancho del texto $width = $originalFont->widthForGlyph( $originalFont->glyphNumberForCharacter($text[$charIndex]) ); $xPosition += $width/$originalFont->getUnitsPerEm()*$fontSize; } ...
Dibujo de Imgenes
La clase Zend_Pdf_Page proporciona el mtodo drawImage() para dibujar la imagen: /** * Dibujar una imagen en una posicin especfica de la pgina. * * @param Zend_Pdf_Resource_Image $image * @param float $x1 * @param float $y1 * @param float $x2 * @param float $y2 * @return Zend_Pdf_Page */ public function drawImage(Zend_Pdf_Resource_Image $image, $x1, $y1, $x2, $y2); Los objetos imagen deben ser creados con el mtodo Zend_Pdf_Image::imageWithPath($filePath) (imgenes JPG, PNG y TIFF ahora son soportadas):
933
Zend_Pdf
/** Establecer el color de la lnea. */ public function setLineColor(Zend_Pdf_Color $color); /** Establecer el ancho de la lnea. */ public function setLineWidth(float $width); /** * Establecer el patrn de lneas de guiones. * * El patrn es una array de nmeros de punto flotante: * array(on_length, off_length, on_length, off_length, ...) * La fase est desplazada lateralmente desde el comienzo de la lnea. * * @param array $pattern * @param array $phase * @return Zend_Pdf_Page */ public function setLineDashingPattern($pattern, $phase = 0);
Estilo Relleno
Los mtodos Zend_Pdf_Page::drawRectangle(), Zend_Pdf_Page::drawPolygon(), Zend_Pdf_Page::drawCircle() y Zend_Pdf_Page::drawEllipse() toman el argumento $fillType como un parmetro opcional. Puede ser: Zend_Pdf_Page::SHAPE_DRAW_STROKE - forma del trazo Zend_Pdf_Page::SHAPE_DRAW_FILL - slo llenar la forma Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE - llenar y trazar (comportamiento por defecto) El mtodo Zend_Pdf_Page::drawPolygon() tambin tiene un parmetro adicional $fillMethod: Zend_Pdf_Page::FILL_METHOD_NON_ZERO_WINDING (comportamiento por defecto) PDF reference esta norma se describe como sigue: La tortuosa regla del nmero distinto de cero determina si un punto est dentro de un camino de un rayo conceptual dibujado a partir de ese punto hasta el infinito en cualquier direccin y luego de examinar los lugares en los que un segmento de la ruta atraviesa el rayo. A partir de la cuenta de 0, la norma agrega 1 cada vez que un segmento de ruta atraviesa el rayo de izquierda a derecha y resta 1 cada vez que un segmento cruza de derecha a izquierda. Despus de contar todos los cruces, si el resultado es 0, entonces el punto est fuera del camino; otra cosa es el interior. Nota: El mtodo que acabamos de describir no especifica qu hacer si un segmento de ruta coincide con o es tangente al rayo elegido. Dado que la direccin de los rayos es arbitraria, la regla simplemente elige un rayo que no encuentre problemas con las intersecciones. Por simples caminos convexos, la regla del tortuoso nmero distinto de cero define el dentro y afuera como uno lo espera intuitivamente. Los casos ms interesantes son aquellos que involucran la complejidad o
934
Zend_Pdf
las rutas auto-intersectadas como las que se muestran en la Figura 4.10 (en un PDF de referencia). Para un camino que consiste en una estrella de cinco puntas, dibujado con cinco segmentos conectados de lneas rectas intersectndose entre s, la regla considera que el interior ser toda el rea delimitada por la estrella, incluido el pentgono en el centro. Para un camino compuesto por dos crculos concntricos, las reas de ambos crculos cerrados se consideran que estn adentro, siempre que ambas se hayan dibujado en la misma direccin. Si los crculos son dibujados en direcciones opuestas, slo la forma de "doughnut" (rosquilla) formada entre ellos es el interior, de acuerdo a la norma, el "agujero de la rosquilla" est afuera. Zend_Pdf_Page::FILL_METHOD_EVEN_ODD PDF reference describe esta norma como sigue: Una alternativa al tortuoso nmero distinto de cero es la regla par-impar. Esta norma determina la "interioridad" de un punto por el dibujo de un rayo desde ese punto en cualquier direccin y simplemente contando el nmero de segmentos de ruta que atraviesan los rayos, independientemente de la direccin. Si este nmero es impar, el punto est adentro, si es par, el punto est afuera. Esto produce los mismos resultados que la regla del tortuoso nmero distinto de cero para caminos con formas simples, pero produce resultados diferentes para formas ms complejas. La Figura 4.11 (en un PDF de referencia) muestra los efectos de la aplicacin de la regla par-impar a las rutas complejss. Para la estrella de cinco puntas, la regla considera que los puntos del tringulo estn dentro de la ruta, pero no el pentgono en el centro. Para los dos crculos concntricos, slo la forma de la "rosquilla" entre los dos crculo est considerada adentro, independientemente de las direcciones en las que se dibujen los crculos.
Transformaciones Lineales
Rotaciones.
La pgina PDF se puede rotar antes de aplicar cualquier operacin de dibujo. Se puede hacer con el mtodo Zend_Pdf_Page::rotate():
/** * Rotar la pgina. * * @param float $x - la coordenada X del punto de rotacin * @param float $y - la coordenada Y del punto de rotacin * @param float $angle - ngulo de rotacin * @return Zend_Pdf_Page */ public function rotate($x, $y, $angle);
/** * Establecer la escala al sistema de coordenadas. * * @param float $xScale - factor de escala de la dimensin X * @param float $yScale - factor de escala de la dimensin Y * @return Zend_Pdf_Page
935
Zend_Pdf
/** * Traducir sistema de coordenadas. * * @param float $xShift - desplazamiento de la coordenada X * @param float $yShift - desplazamiento de la coordenada Y * @return Zend_Pdf_Page */ public function translate($xShift, $yShift);
/** * Traducir sistema de coordenadas. * * @param float $x - la coordenada X del eje del punto de sesgo * @param float $y - la coordenada Y del eje del punto de sesgo * @param float $xAngle - ngulo de sesgo en el eje X * @param float $yAngle - ngulo de sesgo en el eje Y * @return Zend_Pdf_Page */ public function skew($x, $y, $xAngle, $yAngle);
/** * Salva el estado de los grficos de esta pgina. * Esta toma una instantnea del estilo aplicado actualmente, posicin, * rea de recorte y cualquier rotacin/traduccin/escalado que ha sido * aplicada. * * @return Zend_Pdf_Page */ public function saveGS(); /** * Restablecer los grficos que se guardaron con la ltima llamada a
936
Zend_Pdf
/** * Intersectar el rea actual de recorte con un rectngulo. * * @param float $x1 * @param float $y1 * @param float $x2 * @param float $y2 * @return Zend_Pdf_Page */ public function clipRectangle($x1, $y1, $x2, $y2);
/** * Intersectar el rea actual de recorte con un polgono. * * @param array $x - array de float (la coordenada X de los vrtices) * @param array $y - array de float (la coordenada Y de los vrtices) * @param integer $fillMethod * @return Zend_Pdf_Page */ public function clipPolygon($x, $y, $fillMethod = Zend_Pdf_Page::FILL_METHOD_NON_ZERO_WINDING);
/** * Intersectar el rea actual de recorte con un crculo. * * @param float $x * @param float $y * @param float $radius * @param float $startAngle * @param float $endAngle * @return Zend_Pdf_Page */ public function clipCircle($x, $y, $radius, $startAngle = null,
937
Zend_Pdf
$endAngle = null);
/** * Intersectar el rea actual de recorte con una elipse. * * Firmas del mtodo: * drawEllipse($x1, $y1, $x2, $y2); * drawEllipse($x1, $y1, $x2, $y2, $startAngle, $endAngle); * * @todo process special cases with $x2-$x1 == 0 or $y2-$y1 == 0 * * @param float $x1 * @param float $y1 * @param float $x2 * @param float $y2 * @param float $startAngle * @param float $endAngle * @return Zend_Pdf_Page */ public function clipEllipse($x1, $y1, $x2, $y2, $startAngle = null, $endAngle = null);
Estilos
La clase Zend_Pdf_Style proporciona la funcionalidad de los estilos. Los estilos se pueden utilizar para almacenar un conjunto de parmetros de estado del grfico y aplicarlo a un pgina PDF por una operacin:
/** * Establecer el estilo a utilizar para futuras operaciones de dibujo sobre esta pgina * * @param Zend_Pdf_Style $style * @return Zend_Pdf_Page */ public function setStyle(Zend_Pdf_Style $style); /** * Regresar el estilo aplicado a la pgina. * * @return Zend_Pdf_Style|null */ public function getStyle(); La clase Zend_Pdf_Style proporciona un conjunto de mtodos para obtener o configurar diferentes parmetros de estado de los grficos:
938
Zend_Pdf
/** * Establecer el color de la lnea. * * @param Zend_Pdf_Color $color * @return Zend_Pdf_Page */ public function setLineColor(Zend_Pdf_Color $color);
/** * Establecer el ancho de la lnea. * * @param float $width * @return Zend_Pdf_Page */ public function setLineWidth($width);
/** * Establecer el patrn de la lnea de guiones * * @param array $pattern * @param float $phase * @return Zend_Pdf_Page */ public function setLineDashingPattern($pattern, $phase = 0);
/** * Obtener el patrn de la lnea de guiones * * @return array */ public function getLineDashingPattern();
939
Zend_Pdf
/** * Establecer el color de relleno. * * @param Zend_Pdf_Color $color * @return Zend_Pdf_Page */ public function setFillColor(Zend_Pdf_Color $color);
/** * Establecer la fuente actual. * * @param Zend_Pdf_Resource_Font $font * @param float $fontSize * @return Zend_Pdf_Page */ public function setFont(Zend_Pdf_Resource_Font $font, $fontSize);
/** * Modificar el tamao de la fuente actual. * * @param float $fontSize * @return Zend_Pdf_Page */ public function setFontSize($fontSize);
/** * Obtener la fuente actual. * * @return Zend_Pdf_Resource_Font $font */ public function getFont();
/** * Obtener el tamao de la fuente actual. * * @return float $fontSize */ public function getFontSize();
940
Zend_Pdf
Transparencia
El mdulo Zend_Pdf soporta el manejo de la transparencia. La transparencia puede ser el mtodo Zend_Pdf_Page::setAlpha():
/** * Establecer la transparencia. * * $alpha == 0 - transparente * $alpha == 1 - opaco * * Modos de transparencia soportados por PDF: * Normal (por defecto), Multiply, Screen, Overlay, Darken, Lighten, * ColorDodge, ColorBurn, HardLight, SoftLight, Difference, Exclusion * * @param float $alpha * @param string $mode * @throws Zend_Pdf_Exception * @return Zend_Pdf_Page */ public function setAlpha($alpha, $mode = 'Normal');
Interactive Features
Destinations
A destination defines a particular view of a document, consisting of the following items: The page of the document to be displayed. The location of the document window on that page. The magnification (zoom) factor to use when displaying the page. Destinations may be associated with outline items (Document Outline (bookmarks)), annotations (Annotations), or actions (Actions). In each case, the destination specifies the view of the document to be presented when the outline item or annotation is opened or the action is performed. In addition, the optional document open action can be specified.
Zend_Pdf_Destination_Zoom
Display the specified page, with the coordinates (left, top) positioned at the upper-left corner of the window and the contents of the page magnified by the factor zoom. Destination object may be created using Zend_Pdf_Destination_Zoom::create($page, $left = null, $top = null, $zoom = null) method.
941
Zend_Pdf
Where: $page is a destination page (a Zend_Pdf_Page object or a page number). $left is a left edge of the displayed page (float). $top is a top edge of the displayed page (float). $zoom is a zoom factor (float). NULL, specified for $left, $top or $zoom parameter means "current viewer application value". Zend_Pdf_Destination_Zoom class also provides the following methods: FloatgetLeftEdge(); setLeftEdge(float $left); FloatgetTopEdge(); setTopEdge(float $top); FloatgetZoomFactor(); setZoomFactor(float $zoom);
Zend_Pdf_Destination_Fit
Display the specified page, with the coordinates (left, top) positioned at the upper-left corner of the window and the contents of the page magnified by the factor zoom. Display the specified page, with its contents magnified just enough to fit the entire page within the window both horizontally and vertically. If the required horizontal and vertical magnification factors are different, use the smaller of the two, centering the page within the window in the other dimension. Destination object may be created using Zend_Pdf_Destination_Fit::create($page) method. Where $page is a destination page (a Zend_Pdf_Page object or a page number).
Zend_Pdf_Destination_FitHorizontally
Display the specified page, with the vertical coordinate top positioned at the top edge of the window and the contents of the page magnified just enough to fit the entire width of the page within the window. Destination object may be created using Zend_Pdf_Destination_FitHorizontally::create($page, $top) method. Where: $page is a destination page (a Zend_Pdf_Page object or a page number). $top is a top edge of the displayed page (float). Zend_Pdf_Destination_FitHorizontally class also provides the following methods: FloatgetTopEdge(); setTopEdge(float $top);
942
Zend_Pdf
Zend_Pdf_Destination_FitVertically
Display the specified page, with the horizontal coordinate left positioned at the left edge of the window and the contents of the page magnified just enough to fit the entire height of the page within the window. Destination object may be created using Zend_Pdf_Destination_FitVertically::create($page, $left) method. Where: $page is a destination page (a Zend_Pdf_Page object or a page number). $left is a left edge of the displayed page (float). Zend_Pdf_Destination_FitVertically class also provides the following methods: FloatgetLeftEdge(); setLeftEdge(float $left);
Zend_Pdf_Destination_FitRectangle
Display the specified page, with its contents magnified just enough to fit the rectangle specified by the coordinates left, bottom, right, and top entirely within the window both horizontally and vertically. If the required horizontal and vertical magnification factors are different, use the smaller of the two, centering the rectangle within the window in the other dimension. Destination object may be created using Zend_Pdf_Destination_FitRectangle::create($page, $left, $bottom, $right, $top) method. Where: $page is a destination page (a Zend_Pdf_Page object or a page number). $left is a left edge of the displayed page (float). $bottom is a bottom edge of the displayed page (float). $right is a right edge of the displayed page (float). $top is a top edge of the displayed page (float). Zend_Pdf_Destination_FitRectangle class also provides the following methods: FloatgetLeftEdge(); setLeftEdge(float $left); FloatgetBottomEdge(); setBottomEdge(float $bottom); FloatgetRightEdge(); setRightEdge(float $right); FloatgetTopEdge(); setTopEdge(float $top);
943
Zend_Pdf
Zend_Pdf_Destination_FitBoundingBox
Display the specified page, with its contents magnified just enough to fit its bounding box entirely within the window both horizontally and vertically. If the required horizontal and vertical magnification factors are different, use the smaller of the two, centering the bounding box within the window in the other dimension. Destination object may be created using Zend_Pdf_Destination_FitBoundingBox::create($page, $left, $bottom, $right, $top) method. Where $page is a destination page (a Zend_Pdf_Page object or a page number).
Zend_Pdf_Destination_FitBoundingBoxHorizontally
Display the specified page, with the vertical coordinate top positioned at the top edge of the window and the contents of the page magnified just enough to fit the entire width of its bounding box within the window. Destination object may be created using Zend_Pdf_Destination_FitBoundingBoxHorizontally::create($page, $top) method. Where $page is a destination page (a Zend_Pdf_Page object or a page number). $top is a top edge of the displayed page (float). Zend_Pdf_Destination_FitBoundingBoxHorizontally class also provides the following methods: FloatgetTopEdge(); setTopEdge(float $top);
Zend_Pdf_Destination_FitBoundingBoxVertically
Display the specified page, with the horizontal coordinate left positioned at the left edge of the window and the contents of the page magnified just enough to fit the entire height of its bounding box within the window. Destination object may be created using Zend_Pdf_Destination_FitBoundingBoxVertically::create($page, $left) method. Where $page is a destination page (a Zend_Pdf_Page object or a page number). $left is a left edge of the displayed page (float). Zend_Pdf_Destination_FitBoundingBoxVertically class also provides the following methods: FloatgetLeftEdge(); setLeftEdge(float $left);
Zend_Pdf_Destination_Named
All destinations listed above are "Explicit Destinations". In addition to this, PDF document may contain a dictionary of such destinations which may be used to reference from outside the PDF (e.g. 'http://www.mycompany.com/document.pdf#chapter3').
944
Zend_Pdf
Zend_Pdf_Destination_Named objects allow to refer destinations from the document named destinations dictionary. Named destination object may be created using Zend_Pdf_Destination_Named::create(string $name) method. Zend_Pdf_Destination_Named class provides the only one additional method: StringgetName();
PDF document named destinations dictionary may be updated with Zend_Pdf::setNamedDestination(string $name, $destination) method, where $destination is either an explicit destination (any destination except Zend_Pdf_Destination_Named) or a GoTo action. If NULL is specified in place of $destination, then specified named destination is removed.
Nota
Unresolvable named destinations are automatically removed from a document while document saving.
945
Zend_Pdf
// Returns $page2 object $page = $pdf->resolveDestination($destination1); // Returns null, page 3 is not included into document yet $page = $pdf->resolveDestination($destination2); $pdf->setNamedDestination('Page2', $destination1); $pdf->setNamedDestination('Page3', $destination2); // Returns $destination2 $destination = $pdf->getNamedDestination('Page3'); // Returns $destination1 $pdf->resolveDestination(Zend_Pdf_Destination_Named::create('Page2')); // Returns null, page 3 is not included into document yet $pdf->resolveDestination(Zend_Pdf_Destination_Named::create('Page3'));
Actions
Instead of simply jumping to a destination in the document, an annotation or outline item can specify an action for the viewer application to perform, such as launching an application, playing a sound, or changing an annotation's appearance state.
946
Zend_Pdf
Zend_Pdf_Action_SubmitForm - send data to a uniform resource locator. Zend_Pdf_Action_ResetForm - set fields to their default values. Zend_Pdf_Action_ImportData - import field values from a file. Zend_Pdf_Action_JavaScript - execute a JavaScript script. Zend_Pdf_Action_SetOCGState - set the state of one or more optional content groups. Zend_Pdf_Action_Rendition - control the playing of multimedia content (begin, stop, pause, or resume a playing rendition). Zend_Pdf_Action_Trans - update the display of a document, using a transition dictionary. Zend_Pdf_Action_GoTo3DView - set the current view of a 3D annotation. Only Zend_Pdf_Action_GoTo actions can be created by user now. It can be done using Zend_Pdf_Action_GoTo::create($destination) method, where $destination is a Zend_Pdf_Destination object or string which can be used to identify named destination. It also supports the following methods:
Actions chaining
Actions objects can be chained using Zend_Pdf_Action::$next public property. It's an array of Zend_Pdf_Action objects, which also may have their sub-actions. Zend_Pdf_Action class supports RecursiveIterator interface, so child actions may be iterated recursively:
$pdf = new Zend_Pdf(); $page1 = $pdf->newPage(Zend_Pdf_Page::SIZE_A4); $page2 = $pdf->newPage(Zend_Pdf_Page::SIZE_A4); // Page created, but not included into pages list $page3 = $pdf->newPage(Zend_Pdf_Page::SIZE_A4); $pdf->pages[] = $page1; $pdf->pages[] = $page2; $action1 = Zend_Pdf_Action_GoTo::create( Zend_Pdf_Destination_Fit::create($page2)); $action2 = Zend_Pdf_Action_GoTo::create( Zend_Pdf_Destination_Fit::create($page3)); $action3 = Zend_Pdf_Action_GoTo::create( Zend_Pdf_Destination_Named::create('Captulo1')); $action4 = Zend_Pdf_Action_GoTo::create( Zend_Pdf_Destination_Named::create('Captulo5')); $action2->next[] = $action3; $action2->next[] = $action4; $action1->next[] = $action2; $actionsCount = 1; // Note! Iteration doesn't include top level action and
947
Zend_Pdf
// walks through children only $iterator = new RecursiveIteratorIterator( $action1, RecursiveIteratorIterator::SELF_FIRST); foreach ($iterator as $chainedAction) { $actionsCount++; } printf("Actions in a tree: %d\n", $actionsCount++); // Prints 'Actions in a tree: 4'
$pdf = Zend_Pdf::load($path); // Remove outline item unset($pdf->outlines[0]->childOutlines[1]); // Set Outline to be displayed in bold $pdf->outlines[0]->childOutlines[3]->setIsBold(true); // Add outline entry $pdf->outlines[0]->childOutlines[5]->childOutlines[] = Zend_Pdf_Outline::create('Captulo 2', 'chapter_2'); $pdf->save($path, true); Outline attributes may be retrieved or set using the following methods: string getTitle() - get outline item title. setTitle(string $title) - set outline item title. boolean isOpen() - true if outline is open by default.
948
Zend_Pdf
setIsOpen(boolean $isOpen) - set isOpen state. boolean isItalic() - true if outline item is displayed in italic. setIsItalic(boolean $isItalic) - set isItalic state. boolean isBold() - true if outline item is displayed in bold. setIsBold(boolean $isBold) - set isBold state. Zend_Pdf_Color_Rgb getColor() - get outline text color (null means black). setColor(Zend_Pdf_Color_Rgb $color) - set outline text color (null means black). Zend_Pdf_Target getTarget() - get outline target (action or explicit or named destination object). setTarget(Zend_Pdf_Target|string $target) - set outline target (action or destination). String may be used to identify named destination. Null means 'no target'. array getOptions() - get outline attributes as an array. setOptions(array $options) - set outline options. The following options are recognized: 'title', 'open', 'color', 'italic', 'bold', and 'target'. New outline may be created in two ways: Zend_Pdf_Outline::create(string $title[, Zend_Pdf_Target|string $target]) Zend_Pdf_Outline::create(array $options) Each outline object may have child outline items listed in Zend_Pdf_Outline::$childOutlines public property. It's an array of Zend_Pdf_Outline objects, so outlines are organized in a tree. Zend_Pdf_Outline class implements RecursiveArray interface, so child outlines may be recursively iterated using RecursiveIteratorIterator:
$pdf = Zend_Pdf::load($path); foreach ($pdf->outlines as $documentRootOutlineEntry) { $iterator = new RecursiveIteratorIterator($documentRootOutlineEntry, RecursiveIteratorIterator::SELF_FIRST); foreach ($iterator as $childOutlineItem) { $OutlineItemTarget = $childOutlineItem->getTarget(); if ($OutlineItemTarget instanceof Zend_Pdf_Destination) { if ($pdf->resolveDestination($OutlineItemTarget) === null) { // Mark Outline item with unresolvable destination using RED color $childOutlineItem->setColor(new Zend_Pdf_Color_Rgb(1, 0, 0)); } } else if ($OutlineItemTarget instanceof Zend_Pdf_Action_GoTo) { if ($pdf->resolveDestination($OutlineItemTarget->setDestination()) === null) { // Mark Outline item with unresolvable destination using RED color $childOutlineItem->setColor(new Zend_Pdf_Color_Rgb(1, 0, 0)); } } }
949
Zend_Pdf
} $pdf->save($path, true);
Nota
All outline items with unresolved destinations (or destinations of GoTo actions) are updated while document saving by setting their targets to null. So document will not be corrupted by removing pages referenced by outlines.
Annotations
An annotation associates an object such as a note, sound, or movie with a location on a page of a PDF document, or provides a way to interact with the user by means of the mouse and keyboard. All annotations are represented by Zend_Pdf_Annotation abstract class. Annotation may be attached to a page Zend_Pdf_Page::attachAnnotation(Zend_Pdf_Annotation $annotation) method. Three types of annotations may be created by user now: Zend_Pdf_Annotation_Link::create($x1, $y1, $x2, $y2, $target) where $target is an action object or a destination or string (which may be used in place of named destination object). Zend_Pdf_Annotation_Text::create($x1, $y1, $x2, $y2, $text) Zend_Pdf_Annotation_FileAttachment::create($x1, $fileSpecification) $y1, $x2, $y2, using
A link annotation represents either a hypertext link to a destination elsewhere in the document or an action to be performed. A text annotation represents a "sticky note" attached to a point in the PDF document. A file attachment annotation contains a reference to a file. The following methods are shared between all annotation types: setLeft(float $left) float getLeft() setRight(float $right) float getRight() setTop(float $top) float getTop() setBottom(float $bottom) float getBottom() setText(string $text)
950
Zend_Pdf
string getText() Text annotation property is a text to be displayed for the annotation or, if this type of annotation does not display text, an alternate description of the annotation's contents in human-readable form. Link annotation objects also provide two additional methods: setDestination(Zend_Pdf_Target|string $target) Zend_Pdf_Target getDestination()
$pdf = Zend_Pdf::load($pdfPath); echo $pdf->properties['Title'] . "\n"; echo $pdf->properties['Author'] . "\n"; $pdf->properties['Title'] = 'New Title.'; $pdf->save($pdfPath); Las siguientes claves estn definidas por v1.4 PDF (Acrobat 5) estndar: Title - string, opcional, el ttulo del documento. Author - string, opcional, el nombre de la persona que cre el documento. Subject - string, opcional, el tema del documento. Keywords - string, opcional, las palabras clave asociadas con el documento. Creator - string, opcional, si el documento se convirti desde otro formato a PDF, el nombre de la aplicacin (por ejemplo, Adobe FrameMaker ) que cre el documento original a partir del cual se convirti. Producer - string, opcional, si el documento se convirti desde otro formato a PDF, el nombre de la aplicacin (por ejemplo, Acrobat Distiller), que lo convirti a PDF. CreationDate - string, opcional, la fecha y la hora en que el documento fue creado, en la forma siguiente: "D:YYYYMMDDHHmmSSOHH'mm'", en la que: YYYY es el ao. MM es el mes. DD es el da (0131). HH es la hora (0023). mm es el minuto (0059).
951
Zend_Pdf
SS es el segundo (0059). O es la relacin de la hora local a la hora universal (UT), identificado por uno de los caracteres +, -, o Z (vase ms adelante). HH seguido de ' es el valor absoluto de la posicin de la UT en horas (00-23). mm seguido de ' es el valor absoluto de la posicin de la UT en minutos (00-59). El carcter apstrofe (') despus de HH mm es parte de la sintaxis. Todos los campos despus del ao son opcionales. (El prefijo D:, aunque tambin opcional, se recomienda fuertemente.) Los valores por defecto para MM y DD son 01, y todos los dems valores numricos de los campos son cero por defecto. Un signo ms (+) como el valor del campo O significa que la hora local es ms tarde que la UT, un signo menos (-) que la hora local es anterior a la UT, y la letra Z que la hora local es igual a la UT. Si no se especifica la informacin UT, la relacin del tiempo especificado para UT se considera desconocida. Ya sea que la zona horaria se conozca o no, el resto de la fecha debe estar especificada en la hora local. Por ejemplo, el 23 de diciembre de 1998, a las 7:52 PM, hora estndar del Pacfico de EE.UU., est representado por el string "D:199812231952-08'00'". ModDate - string, opcional, la fecha y la hora en que el documento fue modificado mas recientemente, de la misma forma que CreationDate. Trapped - booleano, opcional, indica si el documento ha sido modificado para incluir la captura de informacin. true - El documento ha sido capturado; no se necesitan ms capturas. false - El documento an no ha sido capturado; cualquier captura todava debe ser hecha. null - O bien se desconoce si el documento ha sido capturado o que lo ha sido en parte pero no completamente capturado, y alguna captura adicional puede ser necesaria. Desde PDF v 1.6 los metadatos se pueden almacenar en el documento XML especial adjunto al PDF (XMP - Extensible Metadata Platform [http://www.adobe.com/products/xmp/]). Este documento XML se pueden recuperar y adjuntar al PDF con los mtodos Zend_Pdf::getMetadata() y Zend_Pdf::setMetadata($metadata):
$pdf = Zend_Pdf::load($pdfPath); $metadata = $pdf->getMetadata(); $metadataDOM = new DOMDocument(); $metadataDOM->loadXML($metadata); $xpath = new DOMXPath($metadataDOM); $pdfPreffixNamespaceURI = $xpath->query('/rdf:RDF/rdf:Description') ->item(0) ->lookupNamespaceURI('pdf'); $xpath->registerNamespace('pdf', $pdfPreffixNamespaceURI); $titleNode = $xpath->query('/rdf:RDF/rdf:Description/pdf:Title')->item(0); $title = $titleNode->nodeValue; ... $titleNode->nodeValue = 'New title'; $pdf->setMetadata($metadataDOM->saveXML());
952
Zend_Pdf
$pdf->save($pdfPath); Las propiedades comunes del documento se duplican en la estructura de Info y el documento Metadata (si se presentan). Ahora es responsabilidad del usuario la aplicacin para mantenerlos sincronizados.
953
Zend_Pdf
$fontH = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_HELVETICA_BOLD); $style->setFont($fontH, 32); try { // Crear un nuevo objeto imagen $imageFile = dirname(__FILE__) . '/stamp.jpg'; $stampImage = Zend_Pdf_Image::imageWithPath($imageFile); } catch (Zend_Pdf_Exception $e) { // Ejemplo de operacin con excepciones de carga de imgenes. if ($e->getMessage() != 'Extensin de imagen no est instalada.' && $e->getMessage() != 'El soporte a JPG no est configurado correctamente.') { throw $e; } $stampImage = null; } // Marcar la pgina como modificada foreach ($pdf->pages as $page){ $page->saveGS() ->setAlpha(0.25) ->setStyle($style) ->rotate(0, 0, M_PI_2/3); $page->saveGS(); $page->clipCircle(550, -10, 50); if ($stampImage != null) { $page->drawImage($stampImage, 500, -60, 600, 40); } $page->restoreGS(); $page->drawText('Modificado por Zend Framework!', 150, 0) ->restoreGS(); } // Agregar una nueva pgina generada por el objeto Zend_Pdf // (la pgina es agregada al documento especificado) $pdf->pages[] = ($page1 = $pdf->newPage('A4')); // Agregar una nueva pgina generada por el objeto Zend_Pdf_Page // (la pgina no es agregada al documento) $page2 = new Zend_Pdf_Page(Zend_Pdf_Page::SIZE_LETTER_LANDSCAPE); $pdf->pages[] = $page2; // Crear una fuente nueva $font = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_HELVETICA); // Aplicar la fuente y dibujar el texto $page1->setFont($font, 36) ->setFillColor(Zend_Pdf_Color_Html::color('#9999cc')) ->drawText('Helvetica 36 text string', 60, 500); // Usar el objeto fuente para otra pgina $page2->setFont($font, 24) ->drawText('Helvetica 24 text string', 60, 500);
954
Zend_Pdf
// Usar otra fuente $fontT = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_TIMES); $page2->setFont($fontT, 32) ->drawText('Times-Roman 32 text string', 60, 450); // Dibujar un rectngulo $page2->setFillColor(new Zend_Pdf_Color_GrayScale(0.8)) ->setLineColor(new Zend_Pdf_Color_GrayScale(0.2)) ->setLineDashingPattern(array(3, 2, 3, 4), 1.6) ->drawRectangle(60, 400, 400, 350); // Dibujar un crculo $page2->setLineDashingPattern(Zend_Pdf_Page::LINE_DASHING_SOLID) ->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 0)) ->drawCircle(85, 375, 25); // Dibujar sectores $page2->drawCircle(200, 375, 25, 2*M_PI/3, -M_PI/6) ->setFillColor(new Zend_Pdf_Color_Cmyk(1, 0, 0, 0)) ->drawCircle(200, 375, 25, M_PI/6, 2*M_PI/3) ->setFillColor(new Zend_Pdf_Color_Rgb(1, 1, 0)) ->drawCircle(200, 375, 25, -M_PI/6, M_PI/6); // Dibujar una elipse $page2->setFillColor(new ->drawEllipse(250, ->setFillColor(new ->drawEllipse(250, ->setFillColor(new ->drawEllipse(250,
Zend_Pdf_Color_Rgb(1, 0, 0)) 400, 400, 350) Zend_Pdf_Color_Cmyk(1, 0, 0, 0)) 400, 400, 350, M_PI/6, 2*M_PI/3) Zend_Pdf_Color_Rgb(1, 1, 0)) 400, 400, 350, -M_PI/6, M_PI/6);
// Dibujar y rellenar un polgono $page2->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 1)); $x = array(); $y = array(); for ($count = 0; $count < 8; $count++) { $x[] = 140 + 25*cos(3*M_PI_4*$count); $y[] = 375 + 25*sin(3*M_PI_4*$count); } $page2->drawPolygon($x, $y, Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE, Zend_Pdf_Page::FILL_METHOD_EVEN_ODD); // ----------- Draw figures in modified coordination system -------------// Movimineto del sistema de coordenadas $page2->saveGS(); $page2->translate(60, 250); // Despalazamiento del sistema de coordenadas // Dibujar un rectngulo $page2->setFillColor(new Zend_Pdf_Color_GrayScale(0.8)) ->setLineColor(new Zend_Pdf_Color_GrayScale(0.2)) ->setLineDashingPattern(array(3, 2, 3, 4), 1.6)
955
Zend_Pdf
->drawRectangle(0, 50, 340, 0); // Dibujar un crculo $page2->setLineDashingPattern(Zend_Pdf_Page::LINE_DASHING_SOLID) ->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 0)) ->drawCircle(25, 25, 25); // Dibujar sectores $page2->drawCircle(140, 25, 25, 2*M_PI/3, -M_PI/6) ->setFillColor(new Zend_Pdf_Color_Cmyk(1, 0, 0, 0)) ->drawCircle(140, 25, 25, M_PI/6, 2*M_PI/3) ->setFillColor(new Zend_Pdf_Color_Rgb(1, 1, 0)) ->drawCircle(140, 25, 25, -M_PI/6, M_PI/6); // Dibujar una elipse $page2->setFillColor(new ->drawEllipse(190, ->setFillColor(new ->drawEllipse(190, ->setFillColor(new ->drawEllipse(190,
Zend_Pdf_Color_Rgb(1, 0, 0)) 50, 340, 0) Zend_Pdf_Color_Cmyk(1, 0, 0, 0)) 50, 340, 0, M_PI/6, 2*M_PI/3) Zend_Pdf_Color_Rgb(1, 1, 0)) 50, 340, 0, -M_PI/6, M_PI/6);
// Dibujar y rellenar un polgono $page2->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 1)); $x = array(); $y = array(); for ($count = 0; $count < 8; $count++) { $x[] = 80 + 25*cos(3*M_PI_4*$count); $y[] = 25 + 25*sin(3*M_PI_4*$count); } $page2->drawPolygon($x, $y, Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE, Zend_Pdf_Page::FILL_METHOD_EVEN_ODD); // Dibujar una lnea $page2->setLineWidth(0.5) ->drawLine(0, 25, 340, 25); $page2->restoreGS();
// Movimineto del sistema de coordenadas, sesgado y escalado $page2->saveGS(); $page2->translate(60, 150) // Despalazamiento del sistema de coordenadas ->skew(0, 0, 0, -M_PI/9) // Sesgar el sistema de coordenadas ->scale(0.9, 0.9); // Escalar el sistema de coordenadas // Dibujar un rectngulo $page2->setFillColor(new Zend_Pdf_Color_GrayScale(0.8)) ->setLineColor(new Zend_Pdf_Color_GrayScale(0.2)) ->setLineDashingPattern(array(3, 2, 3, 4), 1.6) ->drawRectangle(0, 50, 340, 0); // Dibujar un crculo
956
Zend_Pdf
$page2->setLineDashingPattern(Zend_Pdf_Page::LINE_DASHING_SOLID) ->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 0)) ->drawCircle(25, 25, 25); // Dibujar sectores $page2->drawCircle(140, 25, 25, 2*M_PI/3, -M_PI/6) ->setFillColor(new Zend_Pdf_Color_Cmyk(1, 0, 0, 0)) ->drawCircle(140, 25, 25, M_PI/6, 2*M_PI/3) ->setFillColor(new Zend_Pdf_Color_Rgb(1, 1, 0)) ->drawCircle(140, 25, 25, -M_PI/6, M_PI/6); // Dibujar una elipse $page2->setFillColor(new ->drawEllipse(190, ->setFillColor(new ->drawEllipse(190, ->setFillColor(new ->drawEllipse(190,
Zend_Pdf_Color_Rgb(1, 0, 0)) 50, 340, 0) Zend_Pdf_Color_Cmyk(1, 0, 0, 0)) 50, 340, 0, M_PI/6, 2*M_PI/3) Zend_Pdf_Color_Rgb(1, 1, 0)) 50, 340, 0, -M_PI/6, M_PI/6);
// Dibujar y rellenar un polgono $page2->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 1)); $x = array(); $y = array(); for ($count = 0; $count < 8; $count++) { $x[] = 80 + 25*cos(3*M_PI_4*$count); $y[] = 25 + 25*sin(3*M_PI_4*$count); } $page2->drawPolygon($x, $y, Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE, Zend_Pdf_Page::FILL_METHOD_EVEN_ODD); // Dibujar una lnea $page2->setLineWidth(0.5) ->drawLine(0, 25, 340, 25); $page2->restoreGS(); //-----------------------------------------------------------------------if (isset($argv[2])) { $pdf->save($argv[2]); } else { $pdf->save($argv[1], true /* update */); }
957
958
$progressBar = new Zend_ProgressBar($adapter, 0, $fileSize); while (!feof($fp)) { // Do something $progressBar->update($currentByteCount); } $progressBar->finish(); In the first step, an instance of Zend_ProgressBar is created, with a specific adapter, a min-value of 0 and a maxvalue of the total filesize. Then a file is processed and in every loop the progressbar is updated with the current byte count. At the end of the loop, the progressbar status is set to finished. You can also call the update() method of Zend_ProgressBar without arguments, which just recalculates ETA and notifies the adapter. This is useful when there is no data update but you want the progressbar to be updated.
Persistent progress
If you want the progressbar to be persistent over multiple requests, you can give the name of a session namespace as fourth argument to the constructor. In that case, the progressbar will not notify the adapter within the constructor, but only when you call update() or finish(). Also the current value, the status text and the start time for ETA calculation will be fetched in the next request run again.
Standard adapters
Zend_ProgressBar comes with the following three adapters: the section called Zend_ProgressBar_Adapter_Console the section called Zend_ProgressBar_Adapter_JsPush the section called Zend_ProgressBar_Adapter_JsPull
959
Zend_ProgressBar
Zend_ProgressBar_Adapter_Console
Zend_ProgressBar_Adapter_Console is a text-based adapter for terminals. It can automatically detect terminal widths but supports custom widths as well. You can define which elements are displayed with the progressbar and as well customize the order of them. You can also define the style of the progressbar itself.
Zend_ProgressBar_Adapter_JsPush
Zend_ProgressBar_Adapter_JsPush is an adapter which let's you update a progressbar in a browser via Javascript Push. This means that no second connection is required to gather the status about a running process, but that the process itself sends its status directly to the browser. You can set the adapter options either via the set* methods or give an array or a Zend_Config instance with options as first parameter to the constructor. The available options are: updateMethodName: The javascript method which should be called on every update. Default value is Zend_ProgressBar_Update. finishMethodName: The javascript method which should be called after finish status was set. Default value is NULL, which means nothing is done.
960
Zend_ProgressBar
The usage of this adapter is quite simple. First you create a progressbar in your browser, either with JavaScript or previously created with plain HTML. Then you define the update method and optionally the finish method in JavaScript, both taking a json object as single argument. Then you call a webpage with the long-running process in a hidden iframe or object tag. While the process is running, the adapter will call the update method on every update with a json object, containing the following parameters: current: The current absolute value max: The max absolute value percent: The calculated percentage timeTaken: The time how long the process ran yet timeRemaining: The expected time for the process to finish text: The optional status message, if given
#long-running-process { position: absolute; left: -100px; top: -100px; width: 1px; height: 1px; } #zend-progressbar-container { width: 100px; height: 30px; border: 1px solid #000000; background-color: #ffffff; } #zend-progressbar-done { width: 0; height: 30px; background-color: #000000; }
961
Zend_ProgressBar
function Zend_ProgressBar_Update(data) { document.getElementById('zend-progressbar-done').style.width = data.percent + '%'; } This will create a simple container with a black border and a block which indicates the current process. You should not hide the iframe or object by display: none;, as some browsers like Safari 2 will not load the actual content then. Instead of creating your custom progressbar, you may want to use one of the available JavaScript libraries like Dojo, jQuery etc. For example, there are: Dojo: http://dojotoolkit.org/book/dojo-book-0-9/part-2-dijit/user-assistance-and-feedback/progress-bar jQuery: http://t.wits.sg/2008/06/20/jquery-progress-bar-11/ MooTools: http://davidwalsh.name/dw-content/progress-bar.php Prototype: http://livepipe.net/control/progressbar
Interval of updates
You should take care of not sending too many updates, as every update has a min-size of 1kb. This is a requirement for the Safari browser to actually render and execute the function call. Internet Explorer has a similar limitation of 256 bytes.
Zend_ProgressBar_Adapter_JsPull
Zend_ProgressBar_Adapter_JsPull is the opposite of jsPush, as it requires to pull for new updates, instead of pushing updates out to the browsers. Generally you should use the adapter with the persistence option of the Zend_ProgressBar. On notify, the adapter sends a JSON string to the browser, which looks exactly like the JSON string which is send by the jsPush adapter. The only difference is, that it contains an additional parameter, finished, which is either FALSE when update() is called or TRUE, when finish() is called. You can set the adapter options either via the set* methods or give an array or a Zend_Config instance with options as first parameter to the constructor. The available options are: exitAfterSend: Exits the current request after the data were send to the browser. Default is TRUE.
962
<resume> <name>John Smith</name> <location> <city>San Francisco</city> <state>California</state> <zip>00001</zip> </location> <skills> <programming>PHP</programming> <programming>Perl</programming> </skills> </resume> The recipient or consumer of the queue would pick up the message and process the resume. There are many messaging patterns that can be applied to queues to abstract the flow of control from the code and provide metrics, transformations, and monitoring of messages queues. A good book on messaging patterns is Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions (Addison-Wesley Signature Series) [http://www.amazon.com/Enterprise-Integration-Patterns-Designing-AddisonWesley/dp/0321200683] (ISBN-10 0321127420; ISBN-13 978-0321127426).
Ejemplo usage
The below example of Zend_Queue shows a variety of features, including queue creation, queue retrieval, message retrieval, message deletion, and sending messages.
// For configuration options // @see Zend_Queue_Adapater::__construct() $options = array( 'name' => 'queue1', ); // Create an array queue $queue = new Zend_Queue('Array', $options);
963
Zend_Queue
// Get list of queues foreach ($queue->getQueues() as $name) { echo $name, "\n"; } // Create a new queue $queue2 = $queue->createQueue('queue2'); // Get number of messages in a queue (supports Countable interface from SPL) echo count($queue); // Get up to 5 messages from a queue $messages = $queue->receive(5); foreach ($messages as $i => $message) { echo $message->body, "\n"; // We have processed the message; now we remove it from the queue. $queue->deleteMessage($message); } // Send a message to the currently active queue $queue->send('My Test Message'); // Delete a queue we created and all of it's messages $queue->deleteQueue('queue2');
Framework
The Zend_Queue is a proxy that hides the details of the queue services. The queue services are represented by Zend_Queue_Adapter_<service>. For example, Zend_Queue_Adapter_Db is a queue that will use database tables to store and retrieve messages. Below is an example for using database tables for a queuing system: $options = array( 'name' 'driverOptions' 'host' 'port' 'username' 'password' 'dbname' 'type' ) );
// Create a database queue. // Zend_Queue will prepend Zend_Queue_Adapter_ to 'Db' for the class name. $queue = Zend_Queue('Db', $options); The Zend_Queue constructor will create a Zend_Queue_Adapter_Db and initialize the adapter with the configuration settings.
964
Zend_Queue
The accepted configuration settings for each adapter are provided in the adapter notes. Zend_Queue returns messages using the class Zend_Queue_Message_Iterator, which is an implementation of SPL Iterator and Countable. Zend_Queue_Message_Iterator contains an array of Zend_Queue_Message objects. $messages = $queue->receive(5); foreach ($messages as $i => $message) { echo "$i) Message => ", $message->body, "\n"; } Any exceptions thrown are of class Zend_Queue_Exception.
Introduction
Zend_Queue is a proxy class that represents an adapter. The send(), count($queue), and receive() methods are employed by each adapter to interact with queues. The createQueue(), deleteQueue() methods are used to manage queues.
Adapters
Zend_Queue supports all queues implementing the interface Zend_Queue_Adapter_AdapterInterface. The following Message Queue services are supported:
965
Zend_Queue
Apache ActiveMQ [http://activemq.apache.org/]. A database driven queue via Zend_Db. A MemcacheQ [http://memcachedb.org/memcacheq/] queue driven via Memcache. Zend Platform's [http://www.zend.com/en/products/platform/] Job Queue. A local array. Useful for unit testing.
Limitations
Message transaction handling is not supported.
Db - Zend_Queue_Adapter_Db
Driver options are checked for a few required options such as type, host, username, password, and dbname. You may pass along additional parameters for Zend_DB::factory() as parameters in
966
Zend_Queue
$options['driverOptions']. An example of an additional option not listed here, but could be passed would be port.
$options = array( 'driverOptions' => array( 'host' => 'db1.domain.tld', 'username' => 'my_username', 'password' => 'my_password', 'dbname' => 'messaging', 'type' => 'pdo_mysql', 'port' => 3306, // optional parameter. ), 'options' => array( // use Zend_Db_Select for update, not all databases can support this // feature. Zend_Db_Select::FOR_UPDATE => true ) ); // Create a database queue. $queue = new Zend_Queue('Db', $options); $options['name'] = 'queue1'; This is the name of the queue that you wish to start using. (Required) $options['driverOptions']['type'] = 'Pdo'; type is the adapter you wish to have Zend_Db::factory() use. This is the first parameter for the Zend_Db::factory() class method call. $options['driverOptions']['host'] = 'host.domain.tld'; $options['driverOptions']['host'] = '127.0.0.1'; You may set host to an IP address or a hostname. Default setting for host is '127.0.0.1'. $options['driverOptions']['username'] = 'username'; $options['driverOptions']['password'] = 'password'; $options['driverOptions']['dbname'] = 'dbname'; The database name that you have created the required tables for. See the notes section below.
MemcacheQ - Zend_Queue_Adapter_Memcacheq
$options['name'] = 'queue1'; This is the name of the queue that you wish to start using. (Required) $options['driverOptions']['host'] = 'host.domain.tld'; $options['driverOptions']['host'] = '127.0.0.1;'
967
Zend_Queue
You may set host to an IP address or a hostname. Default setting for host is '127.0.0.1'. $options['driverOptions']['port'] = 22201; The default setting for port is 22201.
Array - Zend_Queue_Adapter_Array
$options['name'] = 'queue1'; This is the name of the queue that you wish to start using. (Required)
Apache ActiveMQ
Visibility duration for Zend_Queue_Adapter_Activemq is not available. While Apache's ActiveMQ will support multiple subscriptions, the Zend_Queue does not. You must create a new Zend_Queue object for each individual subscription. ActiveMQ queue/topic names must begin with one of: /queue/ /topic/ /temp-queue/ /temp-topic/ For example: /queue/testing The following functions are not supported: create() - create queue. Calling this function will throw an exception. delete() - delete queue. Calling this function will throw an exception. getQueues() - list queues. Calling this function will throw an exception.
968
Zend_Queue
Zend_Db
The database CREATE TABLE ( ... ) SQL statement can be found in Zend/Queue/Adapter/Db/queue.sql.
MemcacheQ
Memcache can be downloaded from http://www.danga.com/memcached/. MemcacheQ can be downloaded from http://memcachedb.org/memcacheq/. deleteMessage() - Messages are deleted upon reception from the queue. Calling this function would have no effect. Calling this function will throw an error. count() or count($adapter) - MemcacheQ does not support a method for counting the number of items in a queue. Calling this function will throw an error.
969
Zend_Queue
preserved - whether or not to retain the job within the Job Queue history. By default, off; pass a true value to retain it. user_variables - an associative array of all variables you wish to have in scope during job execution (similar to named arguments). interval - how often, in seconds, the job should run. By default, this is set to 0, indicating it should run once, and once only. end_time - an expiry time, past which the job should not run. If the job was set to run only once, and end_time has passed, then the job will not be executed. If the job was set to run on an interval, it will not execute again once end_time has passed. schedule_time - a UNIX timestamp indicating when to run the job; by default, 0, indicating the job should run as soon as possible. application_id - the application identifier of the job. By default, this is null, indicating that one will be automatically assigned by the queue, if the queue was assigned an application ID. As noted, only the script argument is required; all others are simply available to allow passing more finegrained detail on how and when to run the job. ZendApi_Job - finally, you may simply pass a ZendApi_Job instance, and it will be passed along to Platform's Job Queue. In all instances, send() returns a Zend_Queue_Message_PlatformJob object, which provides access to the ZendApi_Job object used to communicate with Job Queue. receive() - retrieves a list of active jobs from Job Queue. Each job in the returned set will be an instance of Zend_Queue_Message_PlatformJob. deleteMessage() - since this adapter only works with Job Queue, this method expects the provided $message to be a Zend_Queue_Message_PlatformJob instance, and will throw an exception otherwise.
Array (local)
The Array queue is a PHP array() in local memory. The Zend_Queue_Adapter_Array is good for unit testing.
Customizing Zend_Queue
Creating your own adapter
Zend_Queue will accept any adapter that implements Zend_Queue_Adapter_AdapterAbstract. You can create your own adapter by extending one of the existing adapters, or the abstract class Zend_Queue_Adapter_AdapterAbstract. I suggest reviewing Zend_Queue_Adapter_Array as this adapter is the easiest to conceptualize.
970
Zend_Queue
* Custom_DbForUpdate uses the SELECT ... FOR UPDATE to find it's rows. * this is more likely to produce the wanted rows than the existing code. * * However, not all databases have SELECT ... FOR UPDATE as a feature. * * Note: this was later converted to be an option for Zend_Queue_Adapter_Db * * This code still serves as a good example. */ } $options = array( 'name' 'driverOptions' 'host' 'port' 'username' 'password' 'dbname' 'type' ) );
$adapter = new Custom_DbForUpdate($options); $queue = Zend_Queue($adapter, $options); You can also change the adapter on the fly as well.
$adapter = new MyCustom_Adapter($options); $queue = Zend_Queue($options); $queue->setAdapter($adapter); echo "Adapter: ", get_class($queue->getAdapter()), "\n"; or
$options = array( 'name' => 'queue1', 'namespace' => 'Custom', 'driverOptions' => array( 'host' => '127.0.0.1', 'port' => '3306', 'username' => 'queue', 'password' => 'queue', 'dbname' => 'queue', 'type' => 'pdo_mysql' ) ); $queue = Zend_Queue('DbForUpdate', $config); // loads Custom_DbForUpdate
971
Zend_Queue
class Zend_Queue_Message { protected $_data = array(); } You can extend the existing messaging class. See the example code in tests/Zend/Queue/Custom/ Message.php.
Stomp
Zend_Queue_Stomp provides a basic client to communicate with Stomp [http://stomp.codehaus.org/] compatible servers. Some servers, such as Apache ActiveMQ and RabbitMQ, will allow you to communicate by other methods, such as HTTP, and XMPP. The Stomp protocol provides StompConnect [http://stomp.codehaus.org/StompConnect] which supports any Java Message Service (JMS) [http://java.sun.com/products/jms/] provider. Stomp is supported by Apache ActiveMQ [http://activemq.apache.org/], RabbitMQ [http://www.rabbitmq.com/], stompserver [http:// stompserver.rubyforge.org/], and Gozirra [http://www.germane-software.com/software/Java/Gozirra/].
972
Zend_Reflection Ejemplos
Ejemplo 43.1. Performing reflection on a file
$r = new Zend_Reflection_File($filename); printf( "===> The %s file\n". " has %d lines\n", $r->getFileName(), $r->getEndLine() ); $classes = $r->getClasses(); echo " It has " . count($classes) . ":\n"; foreach ($classes as $class) { echo " " . $class->getName() . "\n"; } $functions = $r->getFunctions(); echo " It has " . count($functions) . ":\n"; foreach ($functions as $function) { echo " " . $function->getName() . "\n"; }
973
Zend_Reflection
$r = new Zend_Reflection_Class($class); printf( "The class level docblock has the short description: %s\n". "The class level docblock has the long description:\n%s\n", $r->getDocblock()->getShortDescription(), $r->getDocblock()->getLongDescription(), ); // Get the declaring file reflection $file = $r->getDeclaringFile();
974
Zend_Reflection
Zend_Reflection Reference
The various classes in Zend_Reflection mimic the API of PHP's Reflection API [http://php.net/reflection] - with one important difference. PHP's Reflection API does not provide introspection into docblock annotation tags, nor into parameter variable types or return types. Zend_Reflection analyzes method docblock annotations to determine parameter variable types and the return type. Specifically, the @param and @return annotations are used. However, you can also check for any other annotation tags, as well as the standard "short" and "long" descriptions. Each reflection object in Zend_Reflection overrides the getDocblock() method to return an instance of Zend_Reflection_Docblock. This class provides introspection into the docblocks and annotation tags. Zend_Reflection_File is a new reflection class that allows introspection of PHP files. With it, you can retrieve the classes, functions, and global PHP code contained in the file. Finally, the various methods that return other reflection objects allow a second parameter, the name of the reflection class to use for the returned reflection object.
Zend_Reflection_Docblock
Zend_Reflection_Docblock is the heart of Zend_Reflection's value-add over PHP's Reflection API. It provides the following methods: getContents(): returns the full contents of the docblock. getStartLine(): returns the starting position of the docblock within the defining file. getEndLine(): get last line of docblock within the defining file. getShortDescription(): get the short, one-line description (usually the first line of the docblock). getLongDescription(): get the long description from the docblock. hasTag($name): determine if the docblock has the given annotation tag. getTag($name): Retrieve the given annotation tag reflection object, or a boolean FALSE if it's not present. getTags($filter): Retrieve all tags, or all tags matching the given $filter string. The tags returned will be an array of Zend_Reflection_Docblock_Tag objects.
Zend_Reflection_Docblock_Tag
Zend_Reflection_Docblock_Tag provides reflection for individual annotation tags. Most tags consist of only a name and a description. In the case of some special tags, the class provides a factory method for retrieving an instance of the appropriate class. The following methods are defined for Zend_Reflection_Docblock_Tag: factory($tagDocblockLine): instantiate the appropriate tag reflection class and return it. getName(): return the annotation tag name. getDescription(): return the annotation description.
975
Zend_Reflection
Zend_Reflection_Docblock_Tag_Param
Zend_Reflection_Docblock_Tag_Param is a specialized version of Zend_Reflection_Docblock_Tag. The @param annotation tag description consists of the parameter type, variable name, and variable description. It adds the following methods to Zend_Reflection_Docblock_Tag: getType(): return the parameter variable type. getVariableName(): return the parameter variable name.
Zend_Reflection_Docblock_Tag_Return
Like Zend_Reflection_Docblock_Tag_Param, Zend_Reflection_Docblock_Tag_Return is a specialized version of Zend_Reflection_Docblock_Tag. The @return annotation tag description consists of the return type and variable description. It adds the following method to Zend_Reflection_Docblock_Tag: getType(): return the return type.
Zend_Reflection_File
Zend_Reflection_File provides introspection into PHP files. With it, you can introspect the classes, functions, and bare PHP code defined in a file. It defines the following methods: getFileName(): retrieve the filename of the file being reflected. getStartLine(): retrieve the starting line of the file (always "1"). getEndLine() retrieve the last line / number of lines in the file. getDocComment($reflectionClass docblock reflection object. = 'Zend_Reflection_Docblock'): retrive the file-level
getClasses($reflectionClass = 'Zend_Reflection_Class'): retrieve an array of reflection objects, one for each class defined in the file. getFunctions($reflectionClass = 'Zend_Reflection_Function'): retrieve an array of reflection objects, one for each function defined in the file. getClass($name = null, $reflectionClass = 'Zend_Reflection_Class'): retrieve the reflection object for a single class. getContents(): retrieve the full contents of the file.
Zend_Reflection_Class
Zend_Reflection_Class extends ReflectionClass, and follows its API. It adds one additional method, getDeclaringFile(), which may be used to retrieve the Zend_Reflection_File reflection object for the defining file. Additionally, the following methods add an additional argument for specifying the reflection class to use when fetching a reflection object: getDeclaringFile($reflectionClass = 'Zend_Reflection_File') getDocblock($reflectionClass = 'Zend_Reflection_Docblock')
976
Zend_Reflection
getInterfaces($reflectionClass = 'Zend_Reflection_Class') getMethod($reflectionClass = 'Zend_Reflection_Method') getMethods($filter = -1, $reflectionClass = 'Zend_Reflection_Method') getParentClass($reflectionClass = 'Zend_Reflection_Class') getProperty($name, $reflectionClass = 'Zend_Reflection_Property') getProperties($filter = -1, $reflectionClass = 'Zend_Reflection_Property')
Zend_Reflection_Extension
Zend_Reflection_Extension extends ReflectionExtension, and follows its API. It overrides the following methods to add an additional argument for specifying the reflection class to use when fetching a reflection object: getFunctions($reflectionClass = 'Zend_Reflection_Function'): retrieve an array of reflection objects representing the functions defined by the extension. getClasses($reflectionClass = 'Zend_Reflection_Class'): retrieve an array of reflection objects representing the classes defined by the extension.
Zend_Reflection_Function
Zend_Reflection_Function adds a method for retrieving the function return type, as well as overrides several methods to allow specifying the reflection class to use for returned reflection objects. getDocblock($reflectionClass docblock reflection object. = 'Zend_Reflection_Docblock'): retrieve the function
getParameters($reflectionClass = 'Zend_Reflection_Parameter'): retrieve an array of all function parameter reflection objects. getReturn(): retrieve the return type reflection object.
Zend_Reflection_Method
Zend_Reflection_Method mirrors Zend_Reflection_Function, and only overrides one additional method: getParentClass($reflectionClass = 'Zend_Reflection_Class'): retrieve the parent class reflection object.
Zend_Reflection_Parameter
Zend_Reflection_Parameter adds a method for retrieving the parameter type, as well as overrides methods to allow specifying the reflection class to use on returned reflection objects. getDeclaringClass($reflectionClass = 'Zend_Reflection_Class'): get the declaring class of the parameter as a reflection object (if available). getClass($reflectionClass = 'Zend_Reflection_Class'): get the class of the parameter as a reflection object (if available).
977
Zend_Reflection
getDeclaringFunction($reflectionClass = function of the parameter as a reflection object (if available). getType(): get the parameter type.
Zend_Reflection_Property
Zend_Reflection_Property overrides a single method in order to allow specifying the returned reflection object class: getDeclaringClass($reflectionClass = 'Zend_Reflection_Class'): retrieve the declaring class of the property as a reflection object.
978
979
Zend_Registry
Use the traditional new operator to instantiate Zend_Registry. Instantiating Zend_Registry using its constructor also makes initializing the entries in the registry simple by taking an associative array as an argument.
Nota
You must set the ArrayObject::ARRAY_AS_PROPS option before the static registry has been accessed for the first time.
980
Zend_Registry
Zend_Registry::setInstance($registry); $registry->tree = 'apple'; . . . // in a different function, elsewhere in your application: $registry = Zend_Registry::getInstance(); echo $registry->tree; // echo's "apple" $registry->index = $value; var_dump($registry->index);
Nota
The class must be a subclass of Zend_Registry.
981
Zend_Registry
982
Zend_Rest_Client
Introduction
Using the Zend_Rest_Client is very similar to using SoapClient objects (SOAP web service extension [http:// www.php.net/soap]). You can simply call the REST service procedures as Zend_Rest_Client methods. Specify the service's full address in the Zend_Rest_Client constructor.
Differences in calling
Zend_Rest_Client attempts to make remote methods look as much like native methods as possible, the only difference being that you must follow the method call with one of either get(), post(), put() or delete(). This call may be made via method chaining or in separate method calls:
Responses
All requests made using Zend_Rest_Client return a Zend_Rest_Client_Response object. This object has many properties that make it easier to access the results. When the service is based on Zend_Rest_Server, Zend_Rest_Client can make several assumptions about the response, including response status (success or failure) and return type.
983
Zend_Rest
984
Zend_Rest
<rank>60635</rank> </weblog> <inboundblogs>44</inboundblogs> <inboundlinks>218</inboundlinks> </result> </document> </tapi> Here we are accessing the firstname and lastname properties. Even though these are not top-level elements, they are automatically returned when accessed by name.
Multiple items
If multiple items are found when accessing a value by name, an array of SimpleXMLElements will be returned; accessing via method notation will return an array of PHP values.
Request Arguments
Unless you are making a request to a Zend_Rest_Server based service, chances are you will need to send multiple arguments with your request. This is done by calling a method with the name of the argument, passing in the value as the first (and only) argument. Each of these method calls returns the object itself, allowing for chaining, or "fluent" usage. The first call, or the first argument if you pass in more than one argument, is always assumed to be the method when calling a Zend_Rest_Server service.
You will notice that the first call of $client->arg('value1'); resulted in both method=arg&arg1=value1 and arg=value1; this is so that Zend_Rest_Server can understand the request properly, rather than requiring pre-existing knowledge of the service.
Strictness of Zend_Rest_Client
Any REST service that is strict about the arguments it receives will likely fail using Zend_Rest_Client, because of the behavior described above. This is not a common practice and should not cause problems.
Zend_Rest_Server
Introduction
Zend_Rest_Server is intended as a fully-featured REST server.
985
Zend_Rest
Numeric index
Numeric arguments use a 1-based index. To call sayHello from the example above, you can use either: ?method=sayHello&who=Davey&when=Day or: ?method=sayHello&arg1=Davey&arg2=Day
986
Zend_Rest
/** * Say Hello * * @param string $who * @param string $when * @return array */ function sayHello($who, $when) { return array('msg' => "An Error Occurred", 'status' => false); } $server = new Zend_Rest_Server(); $server->addFunction('sayHello'); $server->handle();
987
988
$doc = new Zend_Search_Lucene_Document(); // Field is not tokenized, but is indexed and stored within the index. // Stored fields can be retrived from the index. $doc->addField(Zend_Search_Lucene_Field::Keyword('doctype', 'autogenerated')); // Field is not tokenized nor indexed, but is stored in the index.
989
Zend_Search_Lucene
$doc->addField(Zend_Search_Lucene_Field::UnIndexed('created', time())); // Binary String valued Field that is not tokenized nor indexed, // but is stored in the index. $doc->addField(Zend_Search_Lucene_Field::Binary('icon', $iconData)); // Field is tokenized and indexed, and is stored in the index. $doc->addField(Zend_Search_Lucene_Field::Text('annotation', 'Document annotation text')); // Field is tokenized and indexed, but is not stored in the index. $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', 'My document content')); Each of these methods (excluding the Zend_Search_Lucene_Field::Binary() method) has an optional $encoding parameter for specifying input data encoding. Encoding may differ for different documents as well as for different fields within one document: $doc = new Zend_Search_Lucene_Document(); $doc->addField(Zend_Search_Lucene_Field::Text('title', $title, 'iso-8859-1')); $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $contents, 'utf-8')); If encoding parameter is omitted, then the current locale is used at processing time. For example: setlocale(LC_ALL, 'de_DE.iso-8859-1'); ... $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $contents)); Fields are always stored and returned from the index in UTF-8 encoding. Any required conversion to UTF-8 happens automatically. Text analyzers (see below) may also convert text to some other encodings. Actually, the default analyzer converts text to 'ASCII//TRANSLIT' encoding. Be careful, however; this translation may depend on current locale. Fields' names are defined at your discretion in the addField() method. Java Lucene uses the 'contents' field as a default field to search. Zend_Search_Lucene searches through all fields by default, but the behavior is configurable. See the "Default search field" chapter for details.
990
Zend_Search_Lucene
Binary fields are not tokenized or indexed, but are stored for retrieval with search hits. They can be used to store any data encoded as a binary string, such as an image icon. Text fields are stored, indexed, and tokenized. Text fields are appropriate for storing information like subjects and titles that need to be searchable as well as returned with search results. UnStored fields are tokenized and indexed, but not stored in the index. Large amounts of text are best indexed using this type of field. Storing data creates a larger index on disk, so if you need to search but not redisplay the data, use an UnStored field. UnStored fields are practical when using a Zend_Search_Lucene index in combination with a relational database. You can index large data fields with UnStored fields for searching, and retrieve them from your relational database by using a separate field as an identifier.
HTML documents
Zend_Search_Lucene offers a HTML parsing feature. Documents can be created directly from a HTML file or string:
$doc = Zend_Search_Lucene_Document_Html::loadHTMLFile($filename); $index->addDocument($doc); ... $doc = Zend_Search_Lucene_Document_Html::loadHTML($htmlString); $index->addDocument($doc); Zend_Search_Lucene_Document_Html class uses the DOMDocument::loadHTML() and DOMDocument::loadHTMLFile() methods to parse the source HTML, so it doesn't need HTML to be well formed or to be XHTML. On the other hand, it's sensitive to the encoding specified by the "meta http-equiv" header tag. Zend_Search_Lucene_Document_Html class recognizes document title, body and document header meta tags. The 'title' field is actually the /html/head/title value. It's stored within the index, tokenized and available for search. The 'body' field is the actual body content of the HTML file or string. It doesn't include scripts, comments or attributes. The loadHTML() and loadHTMLFile() methods of Zend_Search_Lucene_Document_Html class also have second optional argument. If it's set to true, then body content is also stored within index and can be retrieved from the index. By default, the body is tokenized and indexed, but not stored. The third parameter of loadHTML() and loadHTMLFile() methods optionally specifies source HTML document encoding. It's used if encoding is not specified using Content-type HTTP-EQUIV meta tag. Other document header meta tags produce additional document fields. The field 'name' is taken from 'name' attribute, and the 'content' attribute populates the field 'value'. Both are tokenized, indexed and stored, so documents may be searched by their meta tags (for example, by keywords).
991
Zend_Search_Lucene
Parsed documents may be augmented by the programmer with any other field:
$doc = Zend_Search_Lucene_Document_Html::loadHTML($htmlString); $doc->addField(Zend_Search_Lucene_Field::UnIndexed('created', time())); $doc->addField(Zend_Search_Lucene_Field::UnIndexed('updated', time())); $doc->addField(Zend_Search_Lucene_Field::Text('annotation', 'Document annotation text')); $index->addDocument($doc); Document links are not included in the generated document, but be retrieved with the Zend_Search_Lucene_Document_Html::getLinks() Zend_Search_Lucene_Document_Html::getHeaderLinks() methods: may and
$doc = Zend_Search_Lucene_Document_Html::loadHTML($htmlString); $linksArray = $doc->getLinks(); $headerLinksArray = $doc->getHeaderLinks(); Starting from Zend Framework 1.6 it's also possible to exclude links with rel attribute set to 'nofollow'. Use Zend_Search_Lucene_Document_Html::setExcludeNoFollowLinks($true) to turn on this option. Zend_Search_Lucene_Document_Html::getExcludeNoFollowLinks() method returns current state of "Exclude nofollow links" flag.
$doc = Zend_Search_Lucene_Document_Docx::loadDocxFile($filename); $index->addDocument($doc); Zend_Search_Lucene_Document_Docx class uses the ZipArchive class and simplexml methods to parse the source document. If the ZipArchive class (from module php_zip) is not available, the Zend_Search_Lucene_Document_Docx will also not be available for use with Zend Framework. Zend_Search_Lucene_Document_Docx class recognizes document meta data and document text. Meta data consists, depending on document contents, of filename, title, subject, creator, keywords, description, lastModifiedBy, revision, modified, created. The 'filename' field is the actual Word 2007 file name. The 'title' field is the actual document title. The 'subject' field is the actual document subject. The 'creator' field is the actual document creator. The 'keywords' field contains the actual document keywords. The 'description' field is the actual document description.
992
Zend_Search_Lucene
The 'lastModifiedBy' field is the username who has last modified the actual document. The 'revision' field is the actual document revision number. The 'modified' field is the actual document last modified date / time. The 'created' field is the actual document creation date / time. The 'body' field is the actual body content of the Word 2007 document. It only includes normal text, comments and revisions are not included. The loadDocxFile() methods of Zend_Search_Lucene_Document_Docx class also have second optional argument. If it's set to true, then body content is also stored within index and can be retrieved from the index. By default, the body is tokenized and indexed, but not stored. Parsed documents may be augmented by the programmer with any other field:
$doc = Zend_Search_Lucene_Document_Docx::loadDocxFile($filename); $doc->addField(Zend_Search_Lucene_Field::UnIndexed( 'indexTime', time()) ); $doc->addField(Zend_Search_Lucene_Field::Text( 'annotation', 'Document annotation text') ); $index->addDocument($doc);
$doc = Zend_Search_Lucene_Document_Pptx::loadPptxFile($filename); $index->addDocument($doc); Zend_Search_Lucene_Document_Pptx class uses the ZipArchive class and simplexml methods to parse the source document. If the ZipArchive class (from module php_zip) is not available, the Zend_Search_Lucene_Document_Pptx will also not be available for use with Zend Framework. Zend_Search_Lucene_Document_Pptx class recognizes document meta data and document text. Meta data consists, depending on document contents, of filename, title, subject, creator, keywords, description, lastModifiedBy, revision, modified, created. The 'filename' field is the actual Powerpoint 2007 file name. The 'title' field is the actual document title. The 'subject' field is the actual document subject. The 'creator' field is the actual document creator. The 'keywords' field contains the actual document keywords. The 'description' field is the actual document description.
993
Zend_Search_Lucene
The 'lastModifiedBy' field is the username who has last modified the actual document. The 'revision' field is the actual document revision number. The 'modified' field is the actual document last modified date / time. The 'created' field is the actual document creation date / time. The 'body' field is the actual content of all slides and slide notes in the Powerpoint 2007 document. The loadPptxFile() methods of Zend_Search_Lucene_Document_Pptx class also have second optional argument. If it's set to true, then body content is also stored within index and can be retrieved from the index. By default, the body is tokenized and indexed, but not stored. Parsed documents may be augmented by the programmer with any other field: $doc = Zend_Search_Lucene_Document_Pptx::loadPptxFile($filename); $doc->addField(Zend_Search_Lucene_Field::UnIndexed( 'indexTime', time())); $doc->addField(Zend_Search_Lucene_Field::Text( 'annotation', 'Document annotation text')); $index->addDocument($doc);
994
Zend_Search_Lucene
The 'modified' field is the actual document last modified date / time. The 'created' field is the actual document creation date / time. The 'body' field is the actual content of all cells in all worksheets of the Excel 2007 document. The loadXlsxFile() methods of Zend_Search_Lucene_Document_Xlsx class also have second optional argument. If it's set to true, then body content is also stored within index and can be retrieved from the index. By default, the body is tokenized and indexed, but not stored. Parsed documents may be augmented by the programmer with any other field:
$doc = Zend_Search_Lucene_Document_Xlsx::loadXlsxFile($filename); $doc->addField(Zend_Search_Lucene_Field::UnIndexed( 'indexTime', time())); $doc->addField(Zend_Search_Lucene_Field::Text( 'annotation', 'Document annotation text')); $index->addDocument($doc);
Building Indexes
Creating a New Index
Index creation and updating capabilities are implemented within the Zend_Search_Lucene component, as well as the Java Lucene project. You can use either of these options to create indexes that Zend_Search_Lucene can search. The PHP code listing below provides an example of how to index a file using Zend_Search_Lucene indexing API:
// Create index $index = Zend_Search_Lucene::create('/data/my-index'); $doc = new Zend_Search_Lucene_Document(); // Store document URL to identify it in the search results $doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl)); // Index document contents $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $docContent)); // Add document to the index $index->addDocument($doc); Newly added documents are immediately searchable in the index.
Updating Index
The same procedure is used to update an existing index. The only difference is that the open() method is called instead of the create() method:
995
Zend_Search_Lucene
// Open existing index $index = Zend_Search_Lucene::open('/data/my-index'); $doc = new Zend_Search_Lucene_Document(); // Store document URL to identify it in search result. $doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl)); // Index document content $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $docContent)); // Add document to the index. $index->addDocument($doc);
Updating Documents
The Lucene index file format doesn't support document updating. Documents should be removed and re-added to the index to effectively update them. Zend_Search_Lucene::delete() method operates with an internal index document id. It can be retrieved from a query hit by 'id' property:
$indexSize = $index->count(); $documents = $index->numDocs(); Zend_Search_Lucene::isDeleted($id) method may be used to check if a document is deleted.
for ($count = 0; $count < $index->maxDoc(); $count++) { if ($index->isDeleted($count)) { echo "Document #$id is deleted.\n"; } } Index optimization removes deleted documents and squeezes documents' IDs in to a smaller range. A document's internal id may therefore change during index optimization.
996
Zend_Search_Lucene
Index optimization
A Lucene index consists of many segments. Each segment is a completely independent set of data. Lucene index segment files can't be updated by design. A segment update needs full segment reorganization. See Lucene index file formats for details (http://lucene.apache.org/java/2_3_0/fileformats.html) 1. New documents are added to the index by creating new segment. Increasing number of segments reduces quality of the index, but index optimization restores it. Optimization essentially merges several segments into a new one. This process also doesn't update segments. It generates one new large segment and updates segment list ('segments' file). Full index optimization can be trigger by calling the Zend_Search_Lucene::optimize() method. It merges all index segments into one new segment:
// Open existing index $index = Zend_Search_Lucene::open('/data/my-index'); // Optimize index. $index->optimize(); Automatic index optimization is performed to keep indexes in a consistent state. Automatic optimization is an iterative process managed by several index options. It merges very small segments into larger ones, then merges these larger segments into even larger segments and so on.
The currently supported Lucene index file format is version 2.3 (starting from Zend Framework 1.6).
997
Zend_Search_Lucene
values, more RAM is used during indexing, and while searches on unoptimized indices are slower, indexing is faster. Thus larger values (> 10) are best for batch index creation, and smaller values (< 10) for indices that are interactively maintained. MergeFactor is a good estimation for average number of segments merged by one auto-optimization pass. Too large values produce large number of segments while they are not merged into new one. It may be a cause of "failed to open stream: Too many open files" error message. This limitation is system dependent. MergeFactor can be retrieved or set >setMergeFactor($mergeFactor) calls. Default value is 10. Lucene Java and Luke (Lucene Index Toolbox - http://www.getopt.org/luke/) can also be used to optimize an index. Latest Luke release (v0.8) is based on Lucene v2.3 and compatible with current implementation of Zend_Search_Lucene component (Zend Framework 1.6). Earlier versions of Zend_Search_Lucene implementations need another versions of Java Lucene tools to be compatible: Zend Framework 1.5 - Java Lucene 2.1 (Luke tool v0.7.1 - http://www.getopt.org/luke/luke-0.7.1/) Zend Framework 1.0 - Java Lucene 1.4 - 2.1 (Luke tool v0.6 - http://www.getopt.org/luke/luke-0.6/) by $index->getMergeFactor() or $index-
Permissions
By default, index files are available for reading and writing by everyone. It's possible to override this with the Zend_Search_Lucene_Storage_Directory_Filesystem::setDefaultFilePermissions() method:
// Get current default file permissions $currentPermissions = Zend_Search_Lucene_Storage_Directory_Filesystem::getDefaultFilePermissions(); // Give read-writing permissions only for current user and group Zend_Search_Lucene_Storage_Directory_Filesystem::setDefaultFilePermissions(0660);
Limitations
Index size
Index size is limited by 2GB for 32-bit platforms. Use 64-bit platforms for larger indices.
Supported Filesystems
Zend_Search_Lucene uses flock() to provide concurrent searching, index updating and optimization. According to the PHP documentation [http://www.php.net/manual/en/function.flock.php], "flock() will not work on NFS and many other networked file systems". Do not use networked file systems with Zend_Search_Lucene.
998
Zend_Search_Lucene
Searching an Index
Building Queries
There are two ways to search the index. The first method uses query parser to construct a query from a string. The second is to programmatically create your own queries through the Zend_Search_Lucene API. Before choosing to use the provided query parser, please consider the following: 1. If you are programmatically creating a query string and then parsing it with the query parser then you should consider building your queries directly with the query API. Generally speaking, the query parser is designed for human-entered text, not for program-generated text. 2. Untokenized fields are best added directly to queries and not through the query parser. If a field's values are generated programmatically by the application, then the query clauses for this field should also be constructed programmatically. An analyzer, which the query parser uses, is designed to convert human-entered text to terms. Program-generated values, like dates, keywords, etc., should be added with the query API. 3. In a query form, fields that are general text should use the query parser. All others, such as date ranges, keywords, etc., are better added directly through the query API. A field with a limited set of values that can be specified with a pull-down menu should not be added to a query string that is subsequently parsed but instead should be added as a TermQuery clause. 4. Boolean queries allow the programmer to logically combine two or more queries into new one. Thus it's the best way to add additional criteria to a search defined by a query string. Both ways use the same API method to search through the index: $index = Zend_Search_Lucene::open('/data/my_index'); $index->find($query); The Zend_Search_Lucene::find() method determines the input type automatically and uses the query parser to construct an appropriate Zend_Search_Lucene_Search_Query object from an input of type string. It is important to note that the query parser uses the standard analyzer to tokenize separate parts of query string. Thus all transformations which are applied to indexed text are also applied to query strings. The standard analyzer may transform the query string to lower case for case-insensitivity, remove stop-words, and stem among other transformations. The API method doesn't transform or filter input terms in any way. It's therefore more suitable for computer generated or untokenized fields.
Query Parsing
Zend_Search_Lucene_Search_QueryParser::parse() method may be used to parse query strings into query objects. This query object may be used in query construction API methods to combine user entered queries with programmatically generated queries. Actually, in some cases it's the only way to search for values within untokenized fields:
999
Zend_Search_Lucene
$userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr); $pathTerm = new Zend_Search_Lucene_Index_Term( '/data/doc_dir/' . $filename, 'path' ); $pathQuery = new Zend_Search_Lucene_Search_Query_Term($pathTerm); $query = new Zend_Search_Lucene_Search_Query_Boolean(); $query->addSubquery($userQuery, true /* required */); $query->addSubquery($pathQuery, true /* required */); $hits = $index->find($query); Zend_Search_Lucene_Search_QueryParser::parse() method also takes an optional encoding parameter, which can specify query string encoding:
$userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr, 'iso-8859-5'); If the encoding parameter is omitted, then current locale is used. It's also possible to specify the default query string encoding Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding() method: with
Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('iso-8859-5'); ... $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr); Zend_Search_Lucene_Search_QueryParser::getDefaultEncoding() returns the current default query string encoding (the empty string means "current locale").
Search Results
The search result is an array of Zend_Search_Lucene_Search_QueryHit objects. Each of these has two properties: $hit->id is a document number within the index and $hit->score is a score of the hit in a search result. The results are ordered by score (descending from highest score). The Zend_Search_Lucene_Search_QueryHit object also exposes each field of the Zend_Search_Lucene_Document found in the search as a property of the hit. In the following example, a hit is returned with two fields from the corresponding document: title and author.
$index = Zend_Search_Lucene::open('/data/my_index'); $hits = $index->find($query); foreach ($hits as $hit) { echo $hit->score; echo $hit->title; echo $hit->author; } Stored fields are always returned in UTF-8 encoding.
1000
Zend_Search_Lucene
Optionally, the original Zend_Search_Lucene_Document object can be returned from the Zend_Search_Lucene_Search_QueryHit. You can retrieve stored parts of the document by using the getDocument() method of the index object and then get them by getFieldValue() method:
$index = Zend_Search_Lucene::open('/data/my_index'); $hits = $index->find($query); foreach ($hits as $hit) { // return Zend_Search_Lucene_Document object for this hit echo $document = $hit->getDocument(); // return a Zend_Search_Lucene_Field object // from the Zend_Search_Lucene_Document echo $document->getField('title'); // return the string value of the Zend_Search_Lucene_Field object echo $document->getFieldValue('title'); // same as getFieldValue() echo $document->title; } The fields available from the Zend_Search_Lucene_Document object are determined at the time of indexing. The document fields are either indexed, or index and stored, in the document by the indexing application (e.g. LuceneIndexCreation.jar). Note that the document identity ('path' in our example) is also stored in the index and must be retrieved from it.
$currentResultSetLimit = Zend_Search_Lucene::getResultSetLimit(); Zend_Search_Lucene::setResultSetLimit($newLimit); The default value of 0 means 'no limit'. It doesn't give the 'best N' results, but only the 'first N' 2.
Results Scoring
Zend_Search_Lucene uses the same scoring algorithms as Java Lucene. All hits in the search result are ordered by score by default. Hits with greater score come first, and documents having higher scores should match the query more precisely than documents having lower scores. Roughly speaking, search hits that contain the searched term or phrase more frequently will have a higher score.
2
Returned hits are still ordered by score or by the specified order, if given.
1001
Zend_Search_Lucene
A hit's score can be retrieved by accessing the score property of the hit:
$hits = $index->find($query); foreach ($hits as $hit) { echo $hit->id; echo $hit->score; } The Zend_Search_Lucene_Search_Similarity class is used to calculate the score for each hit. See Extensibility. Scoring Algorithms section for details.
$index->find($query [, $sortField [, $sortType [, $sortOrder]]] [, $sortField2 [, $sortType [, $sortOrder]]] ...); A name of stored field by which to sort result should be passed as the $sortField parameter. $sortType may be omitted or take the following enumerated values: SORT_REGULAR (compare items normallydefault value), SORT_NUMERIC (compare items numerically), SORT_STRING (compare items as strings). $sortOrder may be omitted or take the following enumerated values: SORT_ASC (sort in ascending order- default value), SORT_DESC (sort in descending order). Ejemplos:
$index->find($query, 'name', SORT_STRING, 'quantity', SORT_NUMERIC, SORT_DESC); Please use caution when using a non-default search order; the query needs to retrieve documents completely from an index, which may dramatically reduce search performance.
/**
1002
Zend_Search_Lucene
* Highlight text with specified color * * @param string|array $words * @param string $colour * @return string */ public function highlight($words, $colour = '#66ffff');
/** * Highlight text using specified View helper or callback function. * * @param string|array $words Words to highlight. Words could be organized using the array or string. * @param callback $callback Callback method, used to transform (highlighting) text. * @param array $params Array of additionall callback parameters passed through into it (first non-optional parameter is an HTML fragment for highlighting) * @return string * @throws Zend_Search_Lucene_Exception */ public function highlightExtended($words, $callback, $params = array()) To customize highlighting behavior use highlightExtended() method with specified callback, which takes one or more parameters3, or extend Zend_Search_Lucene_Document_Html class and redefine applyColour($stringToHighlight, $colour) method used as a default highlighting callback. 4 View helpers also can be used as callbacks in context of view script:
$doc->highlightExtended('word1 word2 word3...', array($this, 'myViewHelper')); The result of highlighting operation is retrieved by Zend_Search_Lucene_Document_Html->getHTML() method.
Nota
Highlighting is performed in terms of current analyzer. So all forms of the word(s) recognized by analyzer are highlighted. E.g. if current analyzer is case insensitive and we request to highlight 'text' word, then 'text', 'Text', 'TEXT' and other case combinations will be highlighted. In the same way, if current analyzer supports stemming and we request to highlight 'indexed', then 'index', 'indexing', 'indices' and other word forms will be highlighted. On the other hand, if word is skipped by corrent analyzer (e.g. if short words filter is applied to the analyzer), then nothing will be highlighted. The second option is to use Zend_Search_Lucene_Search_Query->highlightMatches(string $inputHTML[, $defaultEncoding = 'UTF-8'[, Zend_Search_Lucene_Search_Highlighter_Interface $highlighter]]) method:
3 4
The first is an HTML fragment for highlighting and others are callback behavior dependent. Returned value is a highlighted HTML fragment. In both cases returned HTML is automatically transformed into valid XHTML.
1003
Zend_Search_Lucene
$query = Zend_Search_Lucene_Search_QueryParser::parse($queryStr); $highlightedHTML = $query->highlightMatches($sourceHTML); Optional second parameter is a default HTML document encoding. It's used if encoding is not specified using Contenttype HTTP-EQUIV meta tag. Optional third parameter is a highlighter object which Zend_Search_Lucene_Search_Highlighter_Interface interface: has to implement
interface Zend_Search_Lucene_Search_Highlighter_Interface { /** * Set document for highlighting. * * @param Zend_Search_Lucene_Document_Html $document */ public function setDocument(Zend_Search_Lucene_Document_Html $document); /** * Get document for highlighting. * * @return Zend_Search_Lucene_Document_Html $document */ public function getDocument(); /** * Highlight specified words (method is invoked once per subquery) * * @param string|array $words Words to highlight. They could be organized using the array or string. */ public function highlight($words); } Where Zend_Search_Lucene_Document_Html object is an object constructed from the source HTML provided to the Zend_Search_Lucene_Search_Query->highlightMatches() method. If $highlighter parameter is omitted, then Zend_Search_Lucene_Search_Highlighter_Default object is instantiated and used. Highlighter highlight() method is invoked once per subquery, so it has an ability to differentiate highlighting for them. Actually, default highlighter does this walking through predefined color table. So you can implement your own highlighter or just extend the default and redefine color table. Zend_Search_Lucene_Search_Query->htmlFragmentHighlightMatches() has similar behavior. The only differenece is that it takes as an input and returns HTML fragment without <>HTML>, <HEAD>, <BODY> tags. Nevertheless, fragment is automatically transformed to valid XHTML.
Query Language
Java Lucene and Zend_Search_Lucene provide quite powerful query languages.
1004
Zend_Search_Lucene
These languages are mostly the same with some minor differences, which are mentioned below. Full Java Lucene query language syntax documentation can be found here [http://lucene.apache.org/java/2_3_0/ queryparsersyntax.html].
Terms
A query is broken up into terms and operators. There are three types of terms: Single Terms, Phrases, and Subqueries. A Single Term is a single word such as "test" or "hello". A Phrase is a group of words surrounded by double quotes such as "hello dolly". A Subquery is a query surrounded by parentheses such as "(hello dolly)". Multiple terms can be combined together with boolean operators to form complex queries (see below).
Fields
Lucene supports fields of data. When performing a search you can either specify a field, or use the default field. The field names depend on indexed data and default field is defined by current settings. The first and most significant difference from Java Lucene is that terms are searched through all fields by default. There are two static methods in the Zend_Search_Lucene class which allow the developer to configure these settings:
$defaultSearchField = Zend_Search_Lucene::getDefaultSearchField(); ... Zend_Search_Lucene::setDefaultSearchField('contents'); The NULL value indicated that the search is performed across all fields. It's the default setting. You can search specific fields by typing the field name followed by a colon ":" followed by the term you are looking for. As an example, let's assume a Lucene index contains two fields- title and text- with text as the default field. If you want to find the document entitled "The Right Way" which contains the text "don't go this way", you can enter:
title:"Do it right" AND go Because "text" is the default field, the field indicator is not required. Note: The field is only valid for the term, phrase or subquery that it directly precedes, so the query
title:Do it right Will only find "Do" in the title field. It will find "it" and "right" in the default field (if the default field is set) or in all indexed fields (if the default field is set to NULL).
1005
Zend_Search_Lucene
Wildcards
Lucene supports single and multiple character wildcard searches within single terms (but not within phrase queries). To perform a single character wildcard search use the "?" symbol. To perform a multiple character wildcard search use the "*" symbol. The single character wildcard search looks for string that match the term with the "?" replaced by any single character. For example, to search for "text" or "test" you can use the search:
te?t Multiple character wildcard searches look for 0 or more characters when matching strings against terms. For example, to search for test, tests or tester, you can use the search:
test* You can use "?", "*" or both at any place of the term:
*wr?t* It searches for "write", "wrote", "written", "rewrite", "rewrote" and so on. Starting from ZF 1.7.7 wildcard patterns need some non-wildcard prefix. Default prefix length is 3 (like in Java Lucene). So "*", "te?t", "*wr?t*" terms will cause an exception5. It can be altered using Zend_Search_Lucene_Search_Query_Wildcard::getMinPrefixLength() and Zend_Search_Lucene_Search_Query_Wildcard::setMinPrefixLength() methods.
Term Modifiers
Lucene supports modifying query terms to provide a wide range of searching options. "~" modifier can be used to specify proximity search for phrases or fuzzy search for individual terms.
Range Searches
Range queries allow the developer or user to match documents whose field(s) values are between the lower and upper bound specified by the range query. Range Queries can be inclusive or exclusive of the upper and lower bounds. Sorting is performed lexicographically.
mod_date:[20020101 TO 20030101] This will find documents whose mod_date fields have values between 20020101 and 20030101, inclusive. Note that Range Queries are not reserved for date fields. You could also use range queries with non-date fields:
title:{Aida TO Carmen}
5
Please note, that it's not a Zend_Search_Lucene_Search_QueryParserException, but a Zend_Search_Lucene_Exception. It's thrown during query rewrite (execution) operation.
1006
Zend_Search_Lucene
This will find all documents whose titles would be sorted between Aida and Carmen, but not including Aida and Carmen. Inclusive range queries are denoted by square brackets. Exclusive range queries are denoted by curly brackets. If field is not specified then Zend_Search_Lucene searches for specified interval through all fields by default.
{Aida TO Carmen}
Fuzzy Searches
Zend_Search_Lucene as well as Java Lucene supports fuzzy searches based on the Levenshtein Distance, or Edit Distance algorithm. To do a fuzzy search use the tilde, "~", symbol at the end of a Single word Term. For example to search for a term similar in spelling to "roam" use the fuzzy search:
roam~ This search will find terms like foam and roams. Additional (optional) parameter can specify the required similarity. The value is between 0 and 1, with a value closer to 1 only terms with a higher similarity will be matched. For example:
roam~0.8 The default that is used if the parameter is not given is 0.5.
Proximity Searches
Lucene supports finding words from a phrase that are within a specified word distance in a string. To do a proximity search use the tilde, "~", symbol at the end of the phrase. For example to search for a "Zend" and "Framework" within 10 words of each other in a document use the search:
"Zend Framework"~10
Boosting a Term
Java Lucene and Zend_Search_Lucene provide the relevance level of matching documents based on the terms found. To boost the relevance of a term use the caret, "^", symbol with a boost factor (a number) at the end of the term you are searching. The higher the boost factor, the more relevant the term will be. Boosting allows you to control the relevance of a document by boosting individual terms. For example, if you are searching for
1007
Zend_Search_Lucene
PHP framework and you want the term "PHP" to be more relevant boost it using the ^ symbol along with the boost factor next to the term. You would type:
PHP^4 framework This will make documents with the term PHP appear more relevant. You can also boost phrase terms and subqueries as in the example:
"PHP framework"^4 "Zend Framework" By default, the boost factor is 1. Although the boost factor must be positive, it may be less than 1 (e.g. 0.2).
Boolean Operators
Boolean operators allow terms to be combined through logic operators. Lucene supports AND, "+", OR, NOT and "-" as Boolean operators. Java Lucene requires boolean operators to be ALL CAPS. Zend_Search_Lucene does not. AND, OR, and NOT operators and "+", "-" defines two different styles to construct boolean queries. Unlike Java Lucene, Zend_Search_Lucene doesn't allow these two styles to be mixed. If the AND/OR/NOT style is used, then an AND or OR operator must be present between all query terms. Each term may also be preceded by NOT operator. The AND operator has higher precedence than the OR operator. This differs from Java Lucene behavior.
AND
The AND operator means that all terms in the "AND group" must match some part of the searched field(s). To search for documents that contain "PHP framework" and "Zend Framework" use the query:
OR
The OR operator divides the query into several optional terms. To search for documents that contain "PHP framework" or "Zend Framework" use the query:
NOT
The NOT operator excludes documents that contain the term after NOT. But an "AND group" which contains only terms with the NOT operator gives an empty result set instead of a full set of indexed documents. To search for documents that contain "PHP framework" but not "Zend Framework" use the query:
1008
Zend_Search_Lucene
+
The "+" or required operator stipulates that the term after the "+" symbol must match the document. To search for documents that must contain "Zend" and may contain "Framework" use the query: +Zend Framework
The "-" or prohibit operator excludes documents that match the term after the "-" symbol. To search for documents that contain "PHP framework" but not "Zend Framework" use the query: "PHP framework" -"Zend Framework"
No Operator
If no operator is used, then the search behavior is defined by the "default boolean operator". This is set to OR by default. That implies each term is optional by default. It may or may not be present within document, but documents with this term will receive a higher score. To search for documents that requires "PHP framework" and may contain "Zend Framework" use the query: +"PHP framework" "Zend Framework" The default boolean operator may be set or retrieved with the Zend_Search_Lucene_Search_QueryParser::setDefaultOperator($operator) and Zend_Search_Lucene_Search_QueryParser::getDefaultOperator() methods, respectively. These methods operate with the Zend_Search_Lucene_Search_QueryParser::B_AND Zend_Search_Lucene_Search_QueryParser::B_OR constants. and
Grouping
Java Lucene and Zend_Search_Lucene support using parentheses to group clauses to form sub queries. This can be useful if you want to control the precedence of boolean logic operators for a query or mix different boolean query styles: +(framework OR library) +php Zend_Search_Lucene supports subqueries nested to any level.
Field Grouping
Lucene also supports using parentheses to group multiple clauses to a single field.
1009
Zend_Search_Lucene
To search for a title that contains both the word "return" and the phrase "pink panther" use the query:
\(1\+1\)\:2
$query = Zend_Search_Lucene_Search_QueryParser::parse($queryString);
try { $query = Zend_Search_Lucene_Search_QueryParser::parse($queryString); } catch (Zend_Search_Lucene_Search_QueryParserException $e) { echo "Query syntax error: " . $e->getMessage() . "\n"; } The same technique should be used for the find() method of a Zend_Search_Lucene object. Starting in 1.5, query parsing exceptions are suppressed by default. If query doesn't conform query language, then it's tokenized using current default analyzer and all tokenized terms are used for searching. Use Zend_Search_Lucene_Search_QueryParser::dontSuppressQueryParsingExceptions() method to turn exceptions on. Zend_Search_Lucene_Search_QueryParser::suppressQueryParsingExceptions() and
1010
Zend_Search_Lucene
Term Query
Term queries can be used for searching with a single term. Query string: word1 or Query construction by API: $term = new Zend_Search_Lucene_Index_Term('word1', 'field1'); $query = new Zend_Search_Lucene_Search_Query_Term($term); $hits = $index->find($query); The term field is optional. Zend_Search_Lucene searches through all indexed fields in each document if the field is not specified: // Search for 'word1' in all indexed fields $term = new Zend_Search_Lucene_Index_Term('word1'); $query = new Zend_Search_Lucene_Search_Query_Term($term); $hits = $index->find($query);
Multi-Term Query
Multi-term queries can be used for searching with a set of terms. Each term in a set can be defined as required, prohibited, or neither. required means that documents not matching this term will not match the query; prohibited means that documents matching this term will not match the query; neither, in which case matched documents are neither prohibited from, nor required to, match the term. A document must match at least 1 term, however, to match the query. If optional terms are added to a query with required terms, both queries will have the same result set but the optional terms may affect the score of the matched documents. Both search methods can be used for multi-term queries. Query string: +word1 author:word2 -word3 '+' is used to define a required term. '-' is used to define a prohibited term. 'field:' prefix is used to indicate a document field for a search. If it's omitted, then all fields are searched.
1011
Zend_Search_Lucene
$query = new Zend_Search_Lucene_Search_Query_MultiTerm(); $query->addTerm(new Zend_Search_Lucene_Index_Term('word1'), true); $query->addTerm(new Zend_Search_Lucene_Index_Term('word2', 'author'), null); $query->addTerm(new Zend_Search_Lucene_Index_Term('word3'), false); $hits = $index->find($query);
It's also possible to specify terms list within MultiTerm query constructor:
$terms = array(new Zend_Search_Lucene_Index_Term('word1'), new Zend_Search_Lucene_Index_Term('word2', 'author'), new Zend_Search_Lucene_Index_Term('word3')); $signs = array(true, null, false); $query = new Zend_Search_Lucene_Search_Query_MultiTerm($terms, $signs); $hits = $index->find($query);
The $signs array contains information about the term type: TRUE is used to define required term. FALSE is used to define prohibited term. NULL is used to define a term that is neither required nor prohibited.
Boolean Query
Boolean queries allow to construct query using other queries and boolean operators. Each subquery in a set can be defined as required, prohibited, or optional. required means that documents not matching this subquery will not match the query; prohibited means that documents matching this subquery will not match the query; optional, in which case matched documents are neither prohibited from, nor required to, match the subquery. A document must match at least 1 subquery, however, to match the query. If optional subqueries are added to a query with required subqueries, both queries will have the same result set but the optional subqueries may affect the score of the matched documents. Both search methods can be used for boolean queries. Query string:
1012
Zend_Search_Lucene
'+' is used to define a required subquery. '-' is used to define a prohibited subquery. 'field:' prefix is used to indicate a document field for a search. If it's omitted, then all fields are searched. or Query construction by API:
$query = new Zend_Search_Lucene_Search_Query_Boolean(); $subquery1 = new Zend_Search_Lucene_Search_Query_MultiTerm(); $subquery1->addTerm(new Zend_Search_Lucene_Index_Term('word1')); $subquery1->addTerm(new Zend_Search_Lucene_Index_Term('word2')); $subquery1->addTerm(new Zend_Search_Lucene_Index_Term('word3')); $subquery2 = new Zend_Search_Lucene_Search_Query_MultiTerm(); $subquery2->addTerm(new Zend_Search_Lucene_Index_Term('word4', 'author')); $subquery2->addTerm(new Zend_Search_Lucene_Index_Term('word5', 'author')); $term6 = new Zend_Search_Lucene_Index_Term('word6'); $subquery3 = new Zend_Search_Lucene_Search_Query_Term($term6); $query->addSubquery($subquery1, true /* required */); $query->addSubquery($subquery2, null /* optional */); $query->addSubquery($subquery3, false /* prohibited */); $hits = $index->find($query);
It's also possible to specify subqueries list within Boolean query constructor:
... $subqueries = array($subquery1, $subquery2, $subquery3); $signs = array(true, null, false); $query = new Zend_Search_Lucene_Search_Query_Boolean($subqueries, $signs); $hits = $index->find($query);
The $signs array contains information about the subquery type: TRUE is used to define required subquery. FALSE is used to define prohibited subquery. NULL is used to define a subquery that is neither required nor prohibited. Each query which uses boolean operators can be rewritten using signs notation and constructed using API. For example:
word1 AND (word2 AND word3 AND NOT word4) OR word5 is equivalent to
1013
Zend_Search_Lucene
Wildcard Query
Wildcard queries can be used to search for documents containing strings matching specified patterns. The '?' symbol is used as a single character wildcard. The '*' symbol is used as a multiple character wildcard. Query string: field1:test* or Query construction by API: $pattern = new Zend_Search_Lucene_Index_Term('test*', 'field1'); $query = new Zend_Search_Lucene_Search_Query_Wildcard($pattern); $hits = $index->find($query); The term field is optional. Zend_Search_Lucene searches through all fields on each document if a field is not specified: $pattern = new Zend_Search_Lucene_Index_Term('test*'); $query = new Zend_Search_Lucene_Search_Query_Wildcard($pattern); $hits = $index->find($query);
Fuzzy Query
Fuzzy queries can be used to search for documents containing strings matching terms similar to specified term. Query string: field1:test~ This query matches documents containing 'test' 'text' 'best' words and others. or Query construction by API: $term = new Zend_Search_Lucene_Index_Term('test', 'field1'); $query = new Zend_Search_Lucene_Search_Query_Fuzzy($term); $hits = $index->find($query); Optional similarity can be specified after "~" sign. Query string:
1014
Zend_Search_Lucene
$term = new Zend_Search_Lucene_Index_Term('test', 'field1'); $query = new Zend_Search_Lucene_Search_Query_Fuzzy($term, 0.4); $hits = $index->find($query); The term field is optional. Zend_Search_Lucene searches through all fields on each document if a field is not specified:
Phrase Query
Phrase Queries can be used to search for a phrase within documents. Phrase Queries are very flexible and allow the user or developer to search for exact phrases as well as 'sloppy' phrases. Phrases can also contain gaps or terms in the same places; they can be generated by the analyzer for different purposes. For example, a term can be duplicated to increase the term its weight, or several synonyms can be placed into a single position.
$query1 = new Zend_Search_Lucene_Search_Query_Phrase(); // Add 'word1' at 0 relative position. $query1->addTerm(new Zend_Search_Lucene_Index_Term('word1')); // Add 'word2' at 1 relative position. $query1->addTerm(new Zend_Search_Lucene_Index_Term('word2')); // Add 'word3' at 3 relative position. $query1->addTerm(new Zend_Search_Lucene_Index_Term('word3'), 3); ... $query2 = new Zend_Search_Lucene_Search_Query_Phrase( array('word1', 'word2', 'word3'), array(0,1,3)); ... // Query without a gap. $query3 = new Zend_Search_Lucene_Search_Query_Phrase( array('word1', 'word2', 'word3')); ... $query4 = new Zend_Search_Lucene_Search_Query_Phrase(
1015
Zend_Search_Lucene
array('word1', 'word2'), array(0,1), 'annotation'); A phrase query can be constructed in one step with a class constructor or step by step with Zend_Search_Lucene_Search_Query_Phrase::addTerm() method calls. Zend_Search_Lucene_Search_Query_Phrase class constructor takes three optional arguments: Zend_Search_Lucene_Search_Query_Phrase( [array $terms[, array $offsets[, string $field]]] ); The $terms parameter is an array of strings that contains a set of phrase terms. If it's omitted or equal to null, then an empty query is constructed. The $offsets parameter is an array of integers that contains offsets of terms in a phrase. If it's omitted or equal to null, then the terms' positions are assumed to be sequential with no gaps. The $field parameter is a string that indicates the document field to search. If it's omitted or equal to null, then the default field is searched. Thus: $query = new Zend_Search_Lucene_Search_Query_Phrase(array('zend', 'framework')); will search for the phrase 'zend framework' in all fields. $query = new Zend_Search_Lucene_Search_Query_Phrase( array('zend', 'download'), array(0, 2) ); will search for the phrase 'zend ????? download' and match 'zend platform download', 'zend studio download', 'zend core download', 'zend framework download', and so on. $query = new Zend_Search_Lucene_Search_Query_Phrase( array('zend', 'framework'), null, 'title' ); will search for the phrase 'zend framework' in the 'title' field. Zend_Search_Lucene_Search_Query_Phrase::addTerm() takes Zend_Search_Lucene_Index_Term object and an optional position: two arguments, a required
Zend_Search_Lucene_Search_Query_Phrase::addTerm( Zend_Search_Lucene_Index_Term $term[, integer $position] ); The $term parameter describes the next term in the phrase. It must indicate the same field as previous terms, or an exception will be thrown. The $position parameter indicates the term position in the phrase. Thus:
1016
Zend_Search_Lucene
$query = new Zend_Search_Lucene_Search_Query_Phrase(); $query->addTerm(new Zend_Search_Lucene_Index_Term('zend')); $query->addTerm(new Zend_Search_Lucene_Index_Term('framework')); will search for the phrase 'zend framework'.
$query = new Zend_Search_Lucene_Search_Query_Phrase(); $query->addTerm(new Zend_Search_Lucene_Index_Term('zend'), 0); $query->addTerm(new Zend_Search_Lucene_Index_Term('framework'), 2); will search for the phrase 'zend ????? download' and match 'zend platform download', 'zend studio download', 'zend core download', 'zend framework download', and so on.
$query = new Zend_Search_Lucene_Search_Query_Phrase(); $query->addTerm(new Zend_Search_Lucene_Index_Term('zend', 'title')); $query->addTerm(new Zend_Search_Lucene_Index_Term('framework', 'title')); will search for the phrase 'zend framework' in the 'title' field. The slop factor sets the number of other words permitted between specified words in the query phrase. If set to zero, then the corresponding query is an exact phrase search. For larger values this works like the WITHIN or NEAR operators. The slop factor is in fact an edit distance, where the edits correspond to moving terms in the query phrase. For example, to switch the order of two words requires two moves (the first move places the words atop one another), so to permit re-orderings of phrases, the slop factor must be at least two. More exact matches are scored higher than sloppier matches; thus, search results are sorted by exactness. The slop is zero by default, requiring exact matches. The slop factor can be assigned after query creation:
// Query without a gap. $query = new Zend_Search_Lucene_Search_Query_Phrase(array('word1', 'word2')); // Search for 'word1 word2', 'word1 ... word2' $query->setSlop(1); $hits1 = $index->find($query); // Search for 'word1 word2', 'word1 ... word2', // 'word1 ... ... word2', 'word2 word1' $query->setSlop(2); $hits2 = $index->find($query);
Range Query
Range queries are intended for searching terms within specified interval. Query string:
mod_date:[20020101 TO 20030101]
1017
Zend_Search_Lucene
title:{Aida TO Carmen} or Query construction by API: $from = new Zend_Search_Lucene_Index_Term('20020101', 'mod_date'); $to = new Zend_Search_Lucene_Index_Term('20030101', 'mod_date'); $query = new Zend_Search_Lucene_Search_Query_Range( $from, $to, true // inclusive ); $hits = $index->find($query); Term fields are optional. Zend_Search_Lucene searches through all fields if the field is not specified: $from = new Zend_Search_Lucene_Index_Term('Aida'); $to = new Zend_Search_Lucene_Index_Term('Carmen'); $query = new Zend_Search_Lucene_Search_Query_Range( $from, $to, false // non-inclusive ); $hits = $index->find($query); Either (but not both) of the boundary terms may be set to null. Zend_Search_Lucene searches from the beginning or up to the end of the dictionary for the specified field(s) in this case: // searches for ['20020101' TO ...] $from = new Zend_Search_Lucene_Index_Term('20020101', 'mod_date'); $query = new Zend_Search_Lucene_Search_Query_Range( $from, null, true // inclusive ); $hits = $index->find($query);
Character Set
UTF-8 and single-byte character set support
Zend_Search_Lucene works with the UTF-8 charset internally. Index files store unicode data in Java's "modified UTF-8 encoding". Zend_Search_Lucene core completely supports this encoding with one exception. 6 Actual input data encoding may be specified through Zend_Search_Lucene API. Data will be automatically converted into UTF-8 encoding.
Zend_Search_Lucene supports only Basic Multilingual Plane (BMP) characters (from 0x0000 to 0xFFFF) and doesn't support "supplementary characters" (characters whose code points are greater than 0xFFFF) Java 2 represents these characters as a pair of char (16-bit) values, the first from the high-surrogates range (0xD800-0xDBFF), the second from the low-surrogates range (0xDC00-0xDFFF). Then they are encoded as usual UTF-8 characters in six bytes. Standard UTF-8 representation uses four bytes for supplementary characters.
1018
Zend_Search_Lucene
ctype_alpha() is not UTF-8 compatible, so the analyzer converts text to 'ASCII//TRANSLIT' encoding before indexing. The same processing is transparently performed during query parsing. 7 Default analyzer doesn't treats numbers as parts of terms. Use corresponding 'Num' analyzer if you don't want words to be broken by numbers.
analyzers:
1019
Zend_Search_Lucene
new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8()); ... $doc = new Zend_Search_Lucene_Document(); $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', strtolower($contents))); // Title field for search through (indexed, unstored) $doc->addField(Zend_Search_Lucene_Field::UnStored('title', strtolower($title))); // Title field for retrieving (unindexed, stored) $doc->addField(Zend_Search_Lucene_Field::UnIndexed('_title', $title));
// Searching setlocale(LC_CTYPE, 'de_DE.iso-8859-1'); ... Zend_Search_Lucene_Analysis_Analyzer::setDefault( new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8()); ... $hits = $index->find(strtolower($query));
Extensibility
Text Analysis
The Zend_Search_Lucene_Analysis_Analyzer class is used by the indexer to tokenize document text fields. The Zend_Search_Lucene_Analysis_Analyzer::getDefault() and Zend_Search_Lucene_Analysis_Analyzer::setDefault() methods are used to get and set the default analyzer. You can assign your own text analyzer or choose it from the set of predefined analyzers: Zend_Search_Lucene_Analysis_Analyzer_Common_Text and Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive (default). Both of them interpret tokens as sequences of letters. Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive converts all tokens to lower case. To switch between analyzers: Zend_Search_Lucene_Analysis_Analyzer::setDefault( new Zend_Search_Lucene_Analysis_Analyzer_Common_Text()); ... $index->addDocument($doc);
1020
Zend_Search_Lucene
The Zend_Search_Lucene_Analysis_Analyzer_Common class is designed to be an ancestor of all user defined analyzers. User should only define the reset() and nextToken() methods, which takes its string from the $_input member and returns tokens one by one (a NULL value indicates the end of the stream). The nextToken() method should call the normalize() method on each token. This will allow you to use token filters with your analyzer. Here is an example of a custom analyzer, which accepts words with digits as terms:
1021
Zend_Search_Lucene
$this->_position++; } // Empty token, end of stream. if ($this->_position == $termStartPosition) { return null; } $token = new Zend_Search_Lucene_Analysis_Token( substr($this->_input, $termStartPosition, $this->_position $termStartPosition), $termStartPosition, $this->_position); $token = $this->normalize($token); if ($token !== null) { return $token; } // Continue if token is skipped } return null; } } Zend_Search_Lucene_Analysis_Analyzer::setDefault( new My_Analyzer());
Tokens Filtering
The Zend_Search_Lucene_Analysis_Analyzer_Common analyzer also offers a token filtering mechanism. The Zend_Search_Lucene_Analysis_TokenFilter class provides an abstract interface for such filters. Your own filters should extend this class either directly or indirectly. Any custom filter must implement the normalize() method which may transform input token or signal that the current token should be skipped. There are three filters already defined in the analysis subpackage: Zend_Search_Lucene_Analysis_TokenFilter_LowerCase Zend_Search_Lucene_Analysis_TokenFilter_ShortWords Zend_Search_Lucene_Analysis_TokenFilter_StopWords The LowerCase filter is already used for Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive analyzer by default. The ShortWords and StopWords filters may be used with pre-defined or custom analyzers like this:
$stopWords = array('a', 'an', 'at', 'the', 'and', 'or', 'is', 'am'); $stopWordsFilter =
1022
Zend_Search_Lucene
$shortWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_ShortWords(); $analyzer = new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive(); $analyzer->addFilter($shortWordsFilter); Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer); The Zend_Search_Lucene_Analysis_TokenFilter_StopWords constructor takes an array of stopwords as an input. But stop-words may be also loaded from a file:
$stopWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_StopWords(); $stopWordsFilter->loadFromFile($my_stopwords_file); $analyzer = new Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive(); $analyzer->addFilter($stopWordsFilter); Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer); This file should be a common text file with one word in each line. The '#' character marks a line as a comment. The Zend_Search_Lucene_Analysis_TokenFilter_ShortWords constructor has one optional argument. This is the word length limit, set by default to 2.
Scoring Algorithms
The score of a document d for a query q is defined as follows: score(q,d) = sum( tf(t in d) * idf(t) * getBoost(t.field lengthNorm(t.field in d) ) * coord(q,d) * queryNorm(q) in d) *
tf(t in d) - Zend_Search_Lucene_Search_Similarity::tf($freq) - a score factor based on the frequency of a term or phrase in a document. idf(t) - Zend_Search_Lucene_Search_Similarity::idf($input, $reader) - a score factor for a simple term with the specified index. getBoost(t.field in d) - the boost factor for the term field. lengthNorm($term) - the normalization value for a field given the total number of terms contained in a field. This value is stored within the index. These values, together with field boosts, are stored in an index and multiplied into scores for hits on each field by the search code. Matches in longer fields are less precise, so implementations of this method usually return smaller values when numTokens is large, and larger values when numTokens is small.
1023
Zend_Search_Lucene
coord(q,d) - Zend_Search_Lucene_Search_Similarity::coord($overlap, $maxOverlap) - a score factor based on the fraction of all query terms that a document contains. The presence of a large portion of the query terms indicates a better match with the query, so implementations of this method usually return larger values when the ratio between these parameters is large and smaller values when the ratio between them is small. queryNorm(q) - the normalization value for a query given the sum of the squared weights of each of the query terms. This value is then multiplied into the weight of each query term. This does not affect ranking, but rather just attempts to make scores from different queries comparable. The scoring algorithm can be customized by defining your own Similarity class. To do this extend the Zend_Search_Lucene_Search_Similarity class as defined below, then use the Zend_Search_Lucene_Search_Similarity::setDefault($similarity); method to set it as default.
class MySimilarity extends Zend_Search_Lucene_Search_Similarity { public function lengthNorm($fieldName, $numTerms) { return 1.0/sqrt($numTerms); } public function queryNorm($sumOfSquaredWeights) { return 1.0/sqrt($sumOfSquaredWeights); } public function tf($freq) { return sqrt($freq); } /** * It's not used now. Computes the amount of a sloppy phrase match, * based on an edit distance. */ public function sloppyFreq($distance) { return 1.0; } public function idfFreq($docFreq, $numDocs) { return log($numDocs/(float)($docFreq+1)) + 1.0; } public function coord($overlap, $maxOverlap) { return $overlap/(float)$maxOverlap; } } $mySimilarity = new MySimilarity(); Zend_Search_Lucene_Search_Similarity::setDefault($mySimilarity);
Storage Containers
The abstract class Zend_Search_Lucene_Storage_Directory defines directory functionality.
1024
Zend_Search_Lucene
string
or
The Zend_Search_Lucene_Storage_Directory_Filesystem class implements directory functionality for a file system. If a string is used as an input for the Zend_Search_Lucene constructor, then the index reader (Zend_Search_Lucene object) treats it as a file system path and instantiates the Zend_Search_Lucene_Storage_Directory_Filesystem object. You can define your own directory Zend_Search_Lucene_Storage_Directory class. Zend_Search_Lucene_Storage_Directory methods: implementation by extending the
abstract class Zend_Search_Lucene_Storage_Directory { /** * Closes the store. * * @return void */ abstract function close(); /** * Creates a new, empty file in the directory with the given $filename. * * @param string $name * @return void */ abstract function createFile($filename); /** * Removes an existing $filename in the directory. * * @param string $filename * @return void */ abstract function deleteFile($filename); /** * Returns true if a file with the given $filename exists. * * @param string $filename * @return boolean */ abstract function fileExists($filename); /** * Returns the length of a $filename in the directory. * * @param string $filename * @return integer */ abstract function fileLength($filename);
1025
Zend_Search_Lucene
/** * Returns the UNIX timestamp $filename was last modified. * * @param string $filename * @return integer */ abstract function fileModified($filename); /** * Renames an existing file in the directory. * * @param string $from * @param string $to * @return void */ abstract function renameFile($from, $to); /** * Sets the modified time of $filename to now. * * @param string $filename * @return void */ abstract function touchFile($filename); /** * Returns a Zend_Search_Lucene_Storage_File object for a given * $filename in the directory. * * @param string $filename * @return Zend_Search_Lucene_Storage_File */ abstract function getFileObject($filename); } The getFileObject($filename) method of a Zend_Search_Lucene_Storage_Directory instance returns a Zend_Search_Lucene_Storage_File object. The Zend_Search_Lucene_Storage_File abstract class implements file abstraction and index file reading primitives. You must also extend Zend_Search_Lucene_Storage_File for your directory implementation. Only two methods of Zend_Search_Lucene_Storage_File must be overridden in your implementation:
class MyFile extends Zend_Search_Lucene_Storage_File { /** * Sets the file position indicator and advances the file pointer. * The new position, measured in bytes from the beginning of the file, * is obtained by adding offset to the position specified by whence, * whose values are defined as follows: * SEEK_SET - Set position equal to offset bytes.
1026
Zend_Search_Lucene
* SEEK_CUR - Set position to current location plus offset. * SEEK_END - Set position to end-of-file plus offset. (To move to * a position before the end-of-file, you need to pass a negative value * in offset.) * Upon success, returns 0; otherwise, returns -1 * * @param integer $offset * @param integer $whence * @return integer */ public function seek($offset, $whence=SEEK_SET) { ... } /** * Read a $length bytes from the file and advance the file pointer. * * @param integer $length * @return string */ protected function _fread($length=1) { ... } }
Index Directory
After index creation, the index directory will contain several files: The segments file is a list of index segments. The *.cfs files contain index segments. Note! An optimized index always has only one segment. The deletable file is a list of files that are no longer used by the index, but which could not be deleted.
The currently supported Lucene index file format version is 2.3 (starting from Zend Framework 1.6).
1027
Zend_Search_Lucene
import org.apache.lucene.index.IndexWriter; import org.apache.lucene.document.*; import java.io.* ... IndexWriter indexWriter = new IndexWriter("/data/my_index", new SimpleAnalyzer(), true); ... String filename = "/path/to/file-to-index.txt" File f = new File(filename); Document doc = new Document(); doc.add(Field.Text("path", filename)); doc.add(Field.Keyword("modified",DateField.timeToString(f.lastModified()))); doc.add(Field.Text("author", "unknown")); FileInputStream is = new FileInputStream(f); Reader reader = new BufferedReader(new InputStreamReader(is)); doc.add(Field.Text("contents", reader)); indexWriter.addDocument(doc);
Advanced
Starting from 1.6, handling index format transformations
Zend_Search_Lucene component works with Java Lucene 1.4-1.9, 2.1 and 2.3 index formats. Current index format may be requested using $index->getFormatVersion() call. It returns one of the following values: Zend_Search_Lucene::FORMAT_PRE_2_1 for Java Lucene 1.4-1.9 index format. Zend_Search_Lucene::FORMAT_2_1 for Java Lucene 2.1 index format (also used for Lucene 2.2). Zend_Search_Lucene::FORMAT_2_3 for Java Lucene 2.3 index format. Index modifications are performed only if any index update is done. That happens if a new document is added to an index or index optimization is started manually by $index->optimize() call. In a such case Zend_Search_Lucene may convert index to the higher format version. That always happens for the indices in Zend_Search_Lucene::FORMAT_PRE_2_1 format, which are automatically converted to 2.1 format. You may manage conversion process and assign target index format by $index->setFormatVersion() which takes Zend_Search_Lucene::FORMAT_2_1 or Zend_Search_Lucene::FORMAT_2_3 constant as a parameter: Zend_Search_Lucene::FORMAT_2_1 actually does nothing since pre-2.1 indices are automatically converted to 2.1 format. Zend_Search_Lucene::FORMAT_2_3 forces conversion to the 2.3 format.
1028
Zend_Search_Lucene
Important!
Once index is converted to upper version it can't be converted back. So make a backup of your index when you plan migration to upper version, but want to have possibility to go back.
class Searcher { private static $_index; public static function initIndex() { self::$_index = Zend_Search_Lucene::open('path/to/index'); } } Searcher::initIndex(); All the same, the destructor for static properties is correctly invoked at this point in the program's execution. One potential problem is exception handling. Exceptions thrown by destructors of static objects don't have context, because the destructor is executed after the script has already completed. You might see a "Fatal error: Exception thrown without a stack frame in Unknown on line 0" error message instead of exception description in such cases. Zend_Search_Lucene provides a workaround to this problem with the commit() method. It saves all unsaved changes and frees memory used for storing new segments. You are free to use the commit operation any time- or even several times- during script execution. You can still use the Zend_Search_Lucene object for searching, adding or deleting document after the commit operation. But the commit() call guarantees that if there are no document added or deleted after the call to commit(), then the Zend_Search_Lucene destructor has nothing to do and will not throw exception:
class Searcher { private static $_index; public static function initIndex() { self::$_index = Zend_Search_Lucene::open('path/to/index'); }
1029
Zend_Search_Lucene
... public static function commit() { self::$_index->commit(); } } Searcher::initIndex(); ... // Script shutdown routine ... Searcher::commit(); ...
Best Practices
Field names
There are no limitations for field names in Zend_Search_Lucene. Nevertheless it's a good idea not to use 'id' and 'score' names to avoid ambiguity in QueryHit properties names. The Zend_Search_Lucene_Search_QueryHit id and score properties always refer to internal Lucene document id and hit score. If the indexed document has the same stored fields, you have to use the getDocument() method to access them:
$hits = $index->find($query); foreach ($hits as $hit) { // Get 'title' document field $title = $hit->title; // Get 'contents' document field $contents = $hit->contents; // Get internal Lucene document id $id = $hit->id; // Get query hit score $score = $hit->score; // Get 'id' document field $docId = $hit->getDocument()->id; // Get 'score' document field $docId = $hit->getDocument()->score; // Another way to get 'title' document field $title = $hit->getDocument()->title; }
1030
Zend_Search_Lucene
Indexing performance
Indexing performance is a compromise between used resources, indexing time and index quality. Index quality is completely determined by number of index segments. Each index segment is entirely independent portion of data. So indexes containing more segments need more memory and time for searching. Index optimization is a process of merging several segments into a new one. A fully optimized index contains only one segment. Full index optimization may be performed with the optimize() method:
$index = Zend_Search_Lucene::open($indexPath); $index->optimize(); Index optimization works with data streams and doesn't take a lot of memory but does require processor resources and time. Lucene index segments are not updatable by their nature (the update operation requires the segment file to be completely rewritten). So adding new document(s) to an index always generates a new segment. This, in turn, decreases index quality. An index auto-optimization process is performed after each segment generation and consists of merging partial segments. There are three options to control the behavior of auto-optimization (see Index optimization section): MaxBufferedDocs is the number of documents that can be buffered in memory before a new segment is generated and written to the hard drive. MaxMergeDocs is the maximum number of documents merged by auto-optimization process into a new segment. MergeFactor determines how often auto-optimization is performed.
Nota
All these options are Zend_Search_Lucene object properties- not index properties. They affect only current Zend_Search_Lucene object behavior and may vary for different scripts. MaxBufferedDocs doesn't have any effect if you index only one document per script execution. On the other hand, it's very important for batch indexing. Greater values increase indexing performance, but also require more memory. There is simply no way to calculate the best value for the MaxBufferedDocs parameter because it depends on average document size, the analyzer in use and allowed memory. A good way to find the right value is to perform several tests with the largest document you expect to be added to the index 9. It's a best practice not to use more than a half of the allowed memory. MaxMergeDocs limits the segment size (in terms of documents). It therefore also limits auto-optimization time by guaranteeing that the addDocument() method is not executed more than a certain number of times. This is very important for interactive applications.
9
1031
Zend_Search_Lucene
Lowering the MaxMergeDocs parameter also may improve batch indexing performance. Index auto-optimization is an iterative process and is performed from bottom up. Small segments are merged into larger segment, which are in turn merged into even larger segments and so on. Full index optimization is achieved when only one large segment file remains. Small segments generally decrease index quality. Many small segments may also trigger the "Too many open files" error determined by OS limitations 10. in general, background index optimization should be performed for interactive indexing mode and MaxMergeDocs shouldn't be too low for batch indexing. MergeFactor affects auto-optimization frequency. Lower values increase the quality of unoptimized indexes. Larger values increase indexing performance, but also increase the number of merged segments. This again may trigger the "Too many open files" error. MergeFactor groups index segments by their size: 1. Not greater than MaxBufferedDocs. 2. Greater than MaxBufferedDocs, but not greater than MaxBufferedDocs*MergeFactor. 3. Greater than MaxBufferedDocs*MergeFactor, but not greater than MaxBufferedDocs*MergeFactor*MergeFactor. 4. ... Zend_Search_Lucene checks during each addDocument() call to see if merging any segments may move the newly created segment into the next group. If yes, then merging is performed. So an index with N groups may contain MaxBufferedDocs + (N-1)*MergeFactor segments and contains at least MaxBufferedDocs*MergeFactor(N-1) documents. This gives good approximation for the number of segments in the index: NumberOfSegments <= MaxBufferedDocs + MergeFactor*log MergeFactor (NumberOfDocuments/MaxBufferedDocs) MaxBufferedDocs is determined by allowed memory. This allows for the appropriate merge factor to get a reasonable number of segments. Tuning the MergeFactor parameter is more effective for batch indexing performance than MaxMergeDocs. But it's also more course-grained. So use the estimation above for tuning MergeFactor, then play with MaxMergeDocs to get best batch indexing performance.
Zend_Search_Lucene keeps each segment file opened to improve search performance. This also may occur if the index or QueryHit instances are referred to in some cyclical data structures, because PHP garbage collects objects with cyclic references only at the end of script execution.
1032
Zend_Search_Lucene
It doesn't prevent normal index shutdown process, but may prevent accurate error diagnostic if any error occurs during shutdown. There are two ways with which you may avoid this problem. The first is to force going out of scope:
$index = Zend_Search_Lucene::open($indexPath); ... unset($index); And the second is to perform a commit operation before the end of script execution:
$index = Zend_Search_Lucene::open($indexPath); $index->commit(); This possibility is also described in the "Advanced. Using index as static property" section.
// Retrieving documents with find() method using a query string $query = $idFieldName . ':' . $docId; $hits = $index->find($query); foreach ($hits as $hit) { $title = $hit->title; $contents = $hit->contents; ... } ... // Retrieving documents with find() method using the query API $term = new Zend_Search_Lucene_Index_Term($docId, $idFieldName); $query = new Zend_Search_Lucene_Search_Query_Term($term); $hits = $index->find($query); foreach ($hits as $hit) { $title = $hit->title; $contents = $hit->contents; ... } ... // Retrieving documents with termDocs() method
1033
Zend_Search_Lucene
$term = new Zend_Search_Lucene_Index_Term($docId, $idFieldName); $docIds = $index->termDocs($term); foreach ($docIds as $id) { $doc = $index->getDocument($id); $title = $doc->title; $contents = $doc->contents; ... }
Memory Usage
Zend_Search_Lucene is a relatively memory-intensive module. It uses memory to cache some information and optimize searching and indexing performance. The memory required differs for different modes. The terms dictionary index is loaded during the search. It's actually each 128th 12 term of the full dictionary. Thus memory usage is increased if you have a high number of unique terms. This may happen if you use untokenized phrases as a field values or index a large volume of non-text information. An unoptimized index consists of several segments. It also increases memory usage. Segments are independent, so each segment contains its own terms dictionary and terms dictionary index. If an index consists of N segments it may increase memory usage by N times in worst case. Perform index optimization to merge all segments into one to avoid such memory consumption. Indexing uses the same memory as searching plus memory for buffering documents. The amount of memory used may be managed with MaxBufferedDocs parameter. Index optimization (full or partial) uses stream-style data processing and doesn't require a lot of memory.
Encoding
Zend_Search_Lucene works with UTF-8 strings internally. So all strings returned by Zend_Search_Lucene are UTF-8 encoded. You shouldn't be concerned with encoding if you work with pure ASCII data, but you should be careful if this is not the case. Wrong encoding may cause error notices at the encoding conversion time or loss of data. Zend_Search_Lucene offers a wide range of encoding possibilities for indexed documents and parsed queries. Encoding may be explicitly specified as an optional parameter of field creation methods:
The Lucene file format allows you to configure this number, but Zend_Search_Lucene doesn't expose this in its API. Nevertheless you still have the ability to configure this value if the index is prepared with another Lucene implementation.
1034
Zend_Search_Lucene
'utf-8')); This is the best way to avoid ambiguity in the encoding used. If optional encoding parameter is omitted, then the current locale is used. The current locale may contain character encoding data in addition to the language specification:
setlocale(LC_ALL, 'fr_FR'); ... setlocale(LC_ALL, 'de_DE.iso-8859-1'); ... setlocale(LC_ALL, 'ru_RU.UTF-8'); ... The same approach is used to set query string encoding. If encoding is not specified, then the current locale is used to determine the encoding. Encoding may be passed as an optional parameter, if the query is parsed explicitly before search:
$query = Zend_Search_Lucene_Search_QueryParser::parse($queryStr, 'iso-8859-5'); $hits = $index->find($query); ... The default encoding may also be specified with setDefaultEncoding() method:
Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('iso-8859-1'); $hits = $index->find($queryStr); ... The empty string implies 'current locale'. If the correct encoding is specified it can be correctly processed by analyzer. The actual behavior depends on which analyzer is used. See the Character Set documentation section for details.
Index maintenance
It should be clear that Zend_Search_Lucene as well as any other Lucene implementation does not comprise a "database". Indexes should not be used for data storage. They do not provide partial backup/restore functionality, journaling, logging, transactions and many other features associated with database management systems. Nevertheless, Zend_Search_Lucene attempts to keep indexes in a consistent state at all times. Index backup and restoration should be performed by copying the contents of the index folder. If index corruption occurs for any reason, the corrupted index should be restored or completely rebuilt. So it's a good idea to backup large indexes and store changelogs to perform manual restoration and roll-forward operations if necessary. This practice dramatically reduces index restoration time.
1035
1036
Zend_Server_Reflection
Introduction
Zend_Server_Reflection provides a standard mechanism for performing function and class introspection for use with server classes. It is based on PHP 5's Reflection API, augmenting it with methods for retrieving parameter and return value types and descriptions, a full list of function and method prototypes (i.e., all possible valid calling combinations), and function/method descriptions. Typically, this functionality will only be used by developers of server classes for the framework.
Usage
Basic usage is simple:
$class = Zend_Server_Reflection::reflectClass('My_Class'); $function = Zend_Server_Reflection::reflectFunction('my_function'); // Get prototypes $prototypes = $reflection->getPrototypes(); // Loop through each prototype for the function foreach ($prototypes as $prototype) { // Get prototype return type echo "Return type: ", $prototype->getReturnType(), "\n"; // Get prototype parameters $parameters = $prototype->getParameters(); echo "Parameters: \n"; foreach ($parameters as $parameter) { // Get parameter type echo " ", $parameter->getType(), "\n"; } }
1037
Zend_Server
// Get namespace for a class, function, or method. // Namespaces may be set at instantiation time (second argument), or using // setNamespace() $reflection->getNamespace(); reflectFunction() returns a Zend_Server_Reflection_Function object; reflectClass returns a Zend_Server_Reflection_Class object. Please refer to the API documentation to see what methods are available to each.
1038
Zend_Service_Akismet
Introduction
Zend_Service_Akismet provides a client for the Akismet API [http://akismet.com/development/api/]. The Akismet service is used to determine if incoming data is potentially spam. It also exposes methods for submitting data as known spam or as false positives (ham). It was originally intended to help categorize and identify spam for Wordpress, but it can be used for any type of data. Akismet requires an API key for usage. You can get one by signing up for a WordPress.com [http://wordpress.com/] account. You do not need to activate a blog. Simply acquiring the account will provide you with the API key. Akismet requires that all requests contain a URL to the resource for which data is being filtered. Because of Akismet's origins in WordPress, this resource is called the blog URL. This value should be passed as the second argument to the constructor, but may be reset at any time using the setBlogUrl() method, or overridden by specifying a 'blog' key in the various method calls.
1039
Zend_Service
// Instantiate with the API key and a URL to the application or // resource being used $akismet = new Zend_Service_Akismet($apiKey, 'http://framework.zend.com/wiki/'); if ($akismet->verifyKey($apiKey) { echo "Key is valid.\n"; } else { echo "Key is not valid\n"; } If called with no arguments, verifyKey() uses the API key provided to the constructor. verifyKey() implements Akismet's verify-key REST method.
=> '111.222.111.222',
1040
Zend_Service
'user_agent'
=> 'Mozilla/5.0 ' . (Windows; U; Windows NT ' . '5.2; en-GB; rv:1.8.1) Gecko/20061010 ' . 'Firefox/2.0', 'comment_type' => 'contact', 'comment_author' => 'John Doe', 'comment_author_email' => 'nospam@myhaus.net', 'comment_content' => "I'm not a spammer, honest!" ); if ($akismet->isSpam($data)) { echo "Sorry, but we think you're a spammer."; } else { echo "Welcome to our site!"; } isSpam() implements the comment-check Akismet API method.
=> '111.222.111.222', => 'Mozilla/5.0 (Windows; U; Windows NT 5.2;' . 'en-GB; rv:1.8.1) Gecko/20061010 Firefox/2.0', 'comment_type' => 'contact', 'comment_author' => 'John Doe', 'comment_author_email' => 'nospam@myhaus.net', 'comment_content' => "I'm not a spammer, honest!"
1041
Zend_Service
=> '111.222.111.222', => 'Mozilla/5.0 (Windows; U; Windows NT 5.2;' . 'en-GB; rv:1.8.1) Gecko/20061010 Firefox/2.0', 'comment_type' => 'contact', 'comment_author' => 'John Doe', 'comment_author_email' => 'nospam@myhaus.net', 'comment_content' => "I'm not a spammer, honest!"
Zend-specific Methods
While the Akismet API only specifies four methods, Zend_Service_Akismet has several additional methods that may be used for retrieving and modifying internal properties. getBlogUrl() and setBlogUrl() allow you to retrieve and modify the blog URL used in requests. getApiKey() and setApiKey() allow you to retrieve and modify the API key used in requests. getCharset() and setCharset() allow you to retrieve and modify the character set used to make the request. getPort() and setPort() allow you to retrieve and modify the TCP port used to make the request. getUserAgent() and setUserAgent() allow you to retrieve and modify the HTTP user agent used to make the request. Note: this is not the user_agent used in data submitted to the service, but rather the value provided in the HTTP User-Agent header when making a request to the service. The value used to set the user agent should be of the form some user agent/version | Akismet/ version. The default is Zend Framework/ZF-VERSION | Akismet/1.11, where ZF-VERSION is the current Zend Framework version as stored in the Zend_Framework::VERSION constant.
Zend_Service_Amazon
Introduction
Zend_Service_Amazon is a simple API for using Amazon web services. Zend_Service_Amazon has two APIs: a more traditional one that follows Amazon's own API, and a simpler "Query API" for constructing even complex search queries easily. Zend_Service_Amazon enables developers to retrieve information appearing throughout Amazon.com web sites directly through the Amazon Web Services API. Ejemplos include: Store item information, such as images, descriptions, pricing, and more Customer and editorial reviews Similar products and accessories Amazon.com offers ListMania lists
1042
Zend_Service
In order to use Zend_Service_Amazon, you should already have an Amazon developer API key aswell as a secret key. To get a key and for more information, please visit the Amazon Web Services [http://aws.amazon.com/] web site. As of August 15th, 2009 you can only use the Amazon Product Advertising API through Zend_Service_Amazon, when specifying the additional secret key.
Attention
Your Amazon developer API and secret keys are linked to your Amazon identity, so take appropriate measures to keep them private.
$amazon = new Zend_Service_Amazon('AMAZON_API_KEY', 'US', 'AMAZON_SECRET_KEY'); $results = $amazon->itemSearch(array('SearchIndex' => 'Books', 'Keywords' => 'php')); foreach ($results as $result) { echo $result->Title . '<br />'; }
$query = new Zend_Service_Amazon_Query('AMAZON_API_KEY', 'US, 'AMAZON_SECRET_KEY'); $query->category('Books')->Keywords('PHP'); $results = $query->search(); foreach ($results as $result) { echo $result->Title . '<br />'; }
Country Codes
By default, Zend_Service_Amazon connects to the United States ("US") Amazon web service. To connect from a different country, simply specify the appropriate country code string as the second parameter to the constructor:
Country codes
Valid country codes are: CA, DE, FR, JP, UK, and US.
1043
Zend_Service
Image information
To retrieve images information for your search results, you must set ResponseGroup option to Medium or Large.
Tip
The Zend_Service_Amazon_Query class is an easy to use wrapper around this method.
1044
Zend_Service
$query = new Zend_Service_Amazon_Query('MY_API_KEY', 'US', 'AMAZON_SECRET_KEY'); $query->Category('Books')->Keywords('PHP'); $results = $query->search(); foreach ($results as $result) { echo $result->Title . '<br />'; } This sets the option Category to "Books" and Keywords to "PHP". For more information on the available options, please refer to the relevant Amazon documentation [http://www.amazon.com/gp/aws/sdk/main.html/102-9041115-9057709? s=AWSEcommerceService&v=2005-10-05&p=ApiReference/ItemSearchOperation].
Zend_Service_Amazon Classes
The following classes are all returned Zend_Service_Amazon::itemSearch(): Zend_Service_Amazon_Item Zend_Service_Amazon_Image Zend_Service_Amazon_ResultSet Zend_Service_Amazon_OfferSet Zend_Service_Amazon_Offer Zend_Service_Amazon_SimilarProduct Zend_Service_Amazon_Accessories Zend_Service_Amazon_CustomerReview Zend_Service_Amazon_EditorialReview Zend_Service_Amazon_ListMania by Zend_Service_Amazon::itemLookup() and
1045
Zend_Service
Zend_Service_Amazon_Item
Zend_Service_Amazon_Item is the class type used to represent an Amazon item returned by the web service. It encompasses all of the items attributes, including title, description, reviews, etc.
Zend_Service_Amazon_Item::asXML()
string asXML(); Return the original XML for the item
Properties
Zend_Service_Amazon_Item has a number of properties directly related to their standard Amazon API counterparts.
Zend_Service_Amazon_OfferSet Offer Summary and Offers for the Item array Customer reviews represented as an array of Zend_Service_Amazon_CustomerReview objects Editorial reviews represented as an array of Zend_Service_Amazon_EditorialReview objects Similar Products represented as an array of Zend_Service_Amazon_SimilarProduct objects Accessories for the item represented as an array of Zend_Service_Amazon_Accessories objects An array of track numbers and names for Music CDs and DVDs Item related Listmania Lists as an array of
EditorialReviews
array
SimilarProducts
array
Accessories
array
Tracks ListmaniaLists
array array
1046
Zend_Service
Name
Type
string
Zend_Service_Amazon_Image
Zend_Service_Amazon_Image represents a remote Image for a product.
Zend_Service_Amazon_ResultSet
Zend_Service_Amazon_ResultSet objects are returned by Zend_Service_Amazon::itemSearch() and allow you to easily handle the multiple results returned.
SeekableIterator
Implements the SeekableIterator for easy iteration (e.g. using foreach), as well as direct access to a specific result using seek().
Zend_Service_Amazon_ResultSet::totalResults()
int totalResults(); Returns the total number of results returned by the search Back to Class List
Zend_Service_Amazon_OfferSet
Each result returned by Zend_Service_Amazon::itemSearch() and Zend_Service_Amazon::itemLookup() contains a Zend_Service_Amazon_OfferSet object through which pricing information for the item can be retrieved.
1047
Zend_Service
Lowest Price for the item in "Used" condition The currency LowestOldPrice for the
Total number of "new" condition available for the item Total number of "used" condition available for the item Total number of "collectible" condition available for the item Total number of "refurbished" condition available for the item An array of Zend_Service_Amazon_Offer objects.
Zend_Service_Amazon_Offer
Each offer for an item is returned as an Zend_Service_Amazon_Offer object.
Zend_Service_Amazon_SimilarProduct
When searching for items, Amazon also returns a list of similar products that the searcher may find to their liking. Each of these is returned as a Zend_Service_Amazon_SimilarProduct object.
1048
Zend_Service
Each object contains the information to allow you to make sub-sequent requests to get the full information on the item.
Zend_Service_Amazon_Accessories
Accessories for the returned item are represented as Zend_Service_Amazon_Accessories objects
Zend_Service_Amazon_CustomerReview
Each Customer Review is returned as a Zend_Service_Amazon_CustomerReview object.
Zend_Service_Amazon_EditorialReview
Each items Editorial Reviews are returned as a Zend_Service_Amazon_EditorialReview object
1049
Zend_Service
Zend_Service_Amazon_Listmania
Each results List Mania List items are returned as Zend_Service_Amazon_Listmania objects.
Zend_Service_Amazon_Ec2
Introduction
Zend_Service_Amazon_Ec2 provides an interface to Amazon Elastic Clound Computing (EC2).
Static Methods
To make using the Ec2 class easier to use there are two static methods that can be invoked from any of the Ec2 Elements. The first static method is setKeys which will defind you AWS Access Keys as default keys. When you then create any new object you don't need to pass in any keys to the constructor.
1050
Zend_Service
Zend_Service_Amazon_Ec2: Instances
Instance Types
Amazon EC2 instances are grouped into two families: standard and High-CPU. Standard instances have memory to CPU ratios suitable for most general purpose applications; High-CPU instances have proportionally more CPU resources than memory (RAM) and are well suited for compute-intensive applications. When selecting instance types, you might want to use less powerful instance types for your web server instances and more powerful instance types for your database instances. Additionally, you might want to run CPU instance types for CPU-intensive data processing tasks. One of the advantages of EC2 is that you pay by the instance hour, which makes it convenient and inexpensive to test the performance of your application on different instance families and types. One good way to determine the most appropriate instance family and instance type is to launch test instances and benchmark your application.
Instance Types
The instance types are defined as constants in the code. Column eight in the table is the defined constant name
1 EC2 1.7 GB Compute Unit (1 virtual core with 1 EC2 Compute Unit) 4 EC2 7.5 GB Compute Units (2 virtual cores with 2 EC2 Compute Units each) 8 EC2 15 GB Compute Units (4 virtual cores
160 GB 32-bit instance storage (150 GB plus 10 GB root partition) 850 GB 64-bit instance storage (2 x 420 GB plus 10 GB root partition) 1,690 GB 64-bit instance storage (4 x 420 GB plus
Zend_Service_Amazon_Ec
Large
High
m1.large
Zend_Service_Amazon_Ec
Extra Large
High
m1.xlarge
Zend_Service_Amazon_Ec
1051
Zend_Service
Type
Memory
Platform
I/O
Name
Constant Name
High-CPU Medium
5 EC2 1.7 GB Compute Units (2 virtual cores with 2.5 EC2 Compute Units each) 20 EC2 7 GB Compute Units (8 virtual cores with 2.5 EC2 Compute Units each)
350 GB 32-bit instance storage (340 GB plus 10 GB root partition) 1,690 GB 64-bit instance storage (4 x 420 GB plus 10 GB root partition)
Moderate
c1.medium
Zend_Service_Amazon_Ec
High
c1.xlarge
Zend_Service_Amazon_Ec
ID of the AMI with which to launch Yes instances. Minimum number of instances to No launch. Default: 1 Maximum number of instances to No launch. Default: 1 Name of the key pair with which No to launch instances. If you do not provide a key, all instances will be inaccessible. Names of the security groups with No which to associate the instances. The user data available to the launched No instances. This should not be Base64 encoded. Specifies the instance type. Default: No m1.small
securityGroup userData
instanceType
1052
Zend_Service
Name placement
Description
Required
Specifies the availability zone in No which to launch the instance(s). By default, Amazon EC2 selects an availability zone for you. The ID of the kernel with which to No launch the instance. The ID of the RAM disk with which No to launch the instance. Specifies the virtual name to map to No the corresponding device name. For example: instancestore0 Specifies the device to which you are No mapping a virtual name. For example: sdb Turn on AWS CloudWatch Instance No Monitoring
blockDeviceName
monitor
run will return information about each instance that is starting up.
$ec2_instance = new Zend_Service_Amazon_Ec2_Instance('aws_key', 'aws_secret_key'); $return = $ec2_instance->run(array('imageId' => 'ami-509320', 'keyName' => 'myKey', 'securityGroup' => array('web', 'default')));
1053
Zend_Service
Terminated Instances
Terminated instances will remain visible after termination (approximately one hour).
Terminated Instances
Recently terminated instances might appear in the returned results. This interval is usually less than one hour. If you do not want terminated instances to be returned, pass in a second variable of boolean true to describe and the terminated instances will be ignored.
Terminated Instances
Recently terminated instances might appear in the returned results. This interval is usually less than one hour. If you do not want terminated instances to be returned, pass in a second variable of boolean true to describe and the terminated instances will be ignored.
1054
Zend_Service
consoleOutput returns an array containing the instanceId, timestamp from the last output and the output from the console.
1055
Zend_Service
As part of this service, Amazon EC2 instances can now run Microsoft Windows Server 2003. Our base Windows image provides you with most of the common functionality associated with Windows. However, if you require more than two concurrent Windows users or need to leverage applications that require LDAP, Kerberos, RADIUS, or other credential services, you must use Windows with Authentication Services. For example, Microsoft Exchange Server and Microsoft SharePoint Server require Windows with Authentication Services.
Nota
To get started using Windows instances, we recommend using the AWS Management Console. There are differences in pricing between Windows and Windows with Authentication Services instances. For information on pricing, go to the Amazon EC2 Product Page. Amazon EC2 currently provides the following Windows AMIs: Windows Authenticated (32-bit) Windows Authenticated (64-bit) Windows Anonymous (32-bit) Windows Anonymous (64-bit) The Windows public AMIs that Amazon provides are unmodified versions of Windows with the following two exceptions: we added drivers to improve the networking and disk I/O performance and we created the Amazon EC2 configuration service. The Amazon EC2 configuration service performs the following functions: Randomly sets the Administrator password on initial launch, encrypts the password with the user's SSH key, and reports it to the console. This operation happens upon initial AMI launch. If you change the password, AMIs that are created from this instance use the new password. Configures the computer name to the internal DNS name. To determine the internal DNS name, see Using Instance Addressing. Sends the last three system and application errors from the event log to the console. This helps developers to identify problems that caused an instance to crash or network connectivity to be lost.
1056
Zend_Service
1057
Zend_Service
Amazon EC2 applies the two m1.small Reserved Instances to two of the instances in Availability Zone us-east-1a. Amazon EC2 doesn't apply the two c1.medium Reserved Instances because the c1.medium instances are in a different Availability Zone and does not apply the m1.xlarge Reserved Instances because there are no running m1.xlarge instances.
1058
Zend_Service
CloudWatch Usage
Ejemplo 48.28. Listing Aviable Metrics
listMetrics() returns a list of up to 500 valid metrics for which there is recorded data available to a you and a NextToken string that can be used to query for the next set of results.
Nota
The maximum number of datapoints that the Amazon CloudWatch service will return in a single GetMetricStatistics request is 1,440. If a request is made that would generate more datapoints than this amount, Amazon CloudWatch will return an error. You can alter your request by narrowing the time range (StartTime, EndTime) or increasing the Period in your single request. You may also get all of the data at the granularity you originally asked for by making multiple requests with adjacent time ranges. getMetricStatistics() only requires two parameters but it also has four additional parameters that are optional. Required: MeasureName The measure name that corresponds to the measure for the gathered metric. Valid EC2 Values are CPUUtilization, NetworkIn, NetworkOut, DiskWriteOps DiskReadBytes, DiskReadOps, DiskWriteBytes. Valid Elastic Load Balancing Metrics are Latency, RequestCount, HealthyHostCount UnHealthyHostCount. For more information click here [http://docs.amazonwebservices.com/AmazonCloudWatch/latest/DeveloperGuide/ arch-AmazonCloudWatch-metricscollected.html] Statistics The statistics to be returned for the given metric. Valid values are Average, Maximum, Minimum, Samples, Sum. You can specify this as a string or as an array of values. If you don't specify one it will default to Average instead of failing out. If you specify an incorrect option it will just skip it. For more information click here [http://docs.amazonwebservices.com/AmazonCloudWatch/latest/DeveloperGuide/ arch-Amazon-CloudWatch-statistics.html] Optional: Dimensions Amazon CloudWatch allows you to specify one Dimension to further filter metric data on. If you don't specify a dimension, the service returns the aggregate of all the measures with the given measure name and time range. Unit The standard unit of Measurement for a given Measure. Valid Values: Seconds, Percent, Bytes, Bits, Count, Bytes/Second, Bits/Second, Count/Second, and None. Constraints: When using count/second as the unit, you should use Sum as the statistic instead of Average. Otherwise, the sample returns as equal to the number of requests instead of the number of 60-second intervals. This will cause the Average to always equals one when the unit is count/ second. StartTime The timestamp of the first datapoint to return, inclusive. For example, 2008-02-26T19:00:00+00:00. We round your value down to the nearest minute. You can set your start time for more than two weeks in the past. However, you will only get data for the past two weeks. (in ISO 8601 format). Constraints: Must be before EndTime.
1059
Zend_Service
EndTime The timestamp to use for determining the last datapoint to return. This is the last datapoint to fetch, exclusive. For example, 2008-02-26T20:00:00+00:00 (in ISO 8601 format). $ec2_ebs = new Zend_Service_Amazon_Ec2_CloudWatch('aws_key','aws_secret_key'); $return = $ec2_ebs->getMetricStatistics( array('MeasureName' => 'NetworkIn', 'Statistics' => array('Average')));
explicit
1060
Zend_Service
Name implicit
Description A user has implicit launch permissions for all AMIs he or she owns.
The list of AMIs returned can be modified by specifying AMI IDs, AMI owners, or users with launch permissions. If no options are specified, Amazon EC2 returns all AMIs for which the user has launch permissions. If you specify one or more AMI IDs, only AMIs that have the specified IDs are returned. If you specify an invalid AMI ID, a fault is returned. If you specify an AMI ID for which you do not have access, it will not be included in the returned results. If you specify one or more AMI owners, only AMIs from the specified owners and for which you have access are returned. The results can include the account IDs of the specified owners, amazon for AMIs owned by Amazon or self for AMIs that you own. If you specify a list of executable users, only users that have launch permissions for the AMIs are returned. You can specify account IDs (if you own the AMI(s)), self for AMIs for which you own or have explicit permissions, or all for public AMIs. describe returns an array for all the images that match the critera that was passed in. The array contains the imageId, imageLocation, imageState, imageOwnerId, isPublic, architecture, imageType, kernelId, ramdiskId and platform. $ec2_img = new Zend_Service_Amazon_Ec2_Image('aws_key','aws_secret_key'); $ip = $ec2_img->describe();
modifyAttribute returns boolean true or false. $ec2_img = new Zend_Service_Amazon_Ec2_Image('aws_key','aws_secret_key'); // modify the launchPermission of an AMI $return = $ec2_img->modifyAttribute('imageId', 'launchPermission', 'add',
1061
Zend_Service
'userId', 'userGroup'); // set the product code of the AMI. $return = $ec2_img->modifyAttribute('imageId', 'productCodes', 'add', null, null, 'productCode');
1062
Zend_Service
1063
Zend_Service
Forced Detach
You should only force a detach if the previous detachment attempt did not occur cleanly (logging into an instance, unmounting the volume, and detaching normally). This option can lead to data loss or a corrupted file system. Use this option only as a last resort to detach a volume from a failed instance. The instance will not have an opportunity to flush file system caches or file system meta data. If you use this option, you must perform file system check and repair procedures.
1064
Zend_Service
$ec2_eip = new Zend_Service_Amazon_Ec2_Elasticip('aws_key','aws_secret_key'); $ip = $ec2_eip->allocate(); // print out your newly allocated elastic ip address; print $ip;
1065
Zend_Service
$ec2_eip = new Zend_Service_Amazon_Ec2_Elasticip('aws_key','aws_secret_key'); // describe all $ips = $ec2_eip->describe(); // describe a subset $ips = $ec2_eip->describe(array('ip1', 'ip2', 'ip3')); // describe a single ip address $ip = $ec2_eip->describe('ip1');
Zend_Service_Amazon_Ec2: Keypairs
Keypairs are used to access instances.
1066
Zend_Service
$return = $ec2_kp->create('my-new-key');
1067
Zend_Service
$ec2_zones = new Zend_Service_Amazon_Ec2_Availabilityzones('aws_key', 'aws_secret_key'); $zones = $ec2_zones->describe(); foreach($zones as $zone) { print $zone['zoneName'] . ' -- ' . $zone['zoneState'] . '<br />'; }
1068
Zend_Service
Authorizing Access
Ejemplo 48.59. Authorizing by IP
authorizeIp Adds permissions to a security group based on an IP address, protocol type and port range. Permissions are specified by the IP protocol (TCP, UDP or ICMP), the source of the request (by IP range or an Amazon EC2 user-group pair), the source and destination port ranges (for TCP and UDP), and the ICMP codes and types (for ICMP). When authorizing ICMP, -1 can be used as a wildcard in the type and code fields. Permission changes are propagated to instances within the security group as quickly as possible. However, depending on the number of instances, a small delay might occur. authorizeIp returns boolean true or false
1069
Zend_Service
'ipRange');
Revoking Access
Ejemplo 48.61. Revoke by IP
revokeIp Revokes permissions to a security group based on an IP address, protocol type and port range. The permissions used to revoke must be specified using the same values used to grant the permissions. Permissions are specified by the IP protocol (TCP, UDP or ICMP), the source of the request (by IP range or an Amazon EC2 user-group pair), the source and destination port ranges (for TCP and UDP), and the ICMP codes and types (for ICMP). When authorizing ICMP, -1 can be used as a wildcard in the type and code fields. Permission changes are propagated to instances within the security group as quickly as possible. However, depending on the number of instances, a small delay might occur. revokeIp returns boolean true or false
$ec2_sg = new Zend_Service_Amazon_Ec2_Securitygroups('aws_key', 'aws_secret_key'); $return = $ec2_sg->revokeIp('mygroup', 'protocol', 'fromPort', 'toPort', 'ipRange');
1070
Zend_Service
Zend_Service_Amazon_S3
Introduction
Amazon S3 provides a simple web services interface that can be used to store and retrieve any amount of data, at any time, from anywhere on the web. It gives any developer access to the same highly scalable, reliable, fast, inexpensive data storage infrastructure that Amazon uses to run its own global network of web sites. The service aims to maximize benefits of scale and to pass those benefits on to developers.
API Documentation
The Zend_Service_Amazon_S3 class provides the PHP wrapper to the Amazon S3 REST interface. Please consult the Amazon S3 documentation [http://developer.amazonwebservices.com/connect/kbcategory.jspa? categoryID=48] for detailed description of the service. You will need to be familiar with basic concepts in order to use this service.
Features
Zend_Service_Amazon_S3 provides the following functionality: A single point for configuring your amazon.s3 authentication credentials that can be used across the amazon.s3 namespaces. A proxy object that is more convenient to use than an HTTP client alone, mostly removing the need to manually construct HTTP POST requests to access the REST service. A response wrapper that parses each response body and throws an exception if an error occurred, alleviating the need to repeatedly check the success of many commands. Additional convenience methods for some of the more common operations.
Getting Started
Once you have registered with Amazon S3, you're ready to store your first data object on the S3. The objects on S3 are stored in containers, called "buckets". Bucket names are unique on S3, and each user can have no more than 100 buckets simultaneously. Each bucket can contain unlimited amount of objects, identified by name. The following example demonstrates creating a bucket, storing and retrieving the data.
1071
Zend_Service
$s3->createBucket("my-own-bucket"); $s3->putObject("my-own-bucket/myobject", "somedata"); echo $s3->getObject("my-own-bucket/myobject"); Since Zend_Service_Amazon_S3 service requires authentication, you should pass your credentials (AWS key and secret key) to the constructor. If you only use one account, you can set default credentials for the service:
Bucket operations
All objects in S3 system are stored in buckets. Bucket has to be created before any storage operation. Bucket name is unique in the system, so you can not have bucket named the same as someone else's bucket. Bucket name can contain lowercase letters, digits, periods (.), underscores (_), and dashes (-). No other symbols allowed. Bucket name should start with letter or digit, and be 3 to 255 characters long. Names looking like an IP address (e.g. "192.168.16.255") are not allowed. createBucket() creates a new bucket. cleanBucket() removes all objects that are contained in a bucket. removeBucket() removes the bucket from the system. The bucket should be empty to be removed.
1072
Zend_Service
Object operations
The object is the basic storage unit in S3. Object stores unstructured data, which can be any size up to 4 gigabytes. There's no limit on how many objects can be stored on the system. The object are contained in buckets. Object is identified by name, which can be any utf-8 string. It is common to use hierarchical names (such as Pictures/Myself/CodingInPHP.jpg) to organise object names. Object name is prefixed with bucket name when using object functions, so for object "mydata" in bucket "my-own-bucket" the name would be my-own-bucket/mydata. Objects can be replaced (by rewriting new data with the same key) or deleted, but not modified, appended, etc. Object is always stored whole. By default, all objects are private and can be accessed only by their owner. However, it is possible to specify object with public access, in which case it will be available through the URL: http://s3.amazonaws.com/[bucketname]/[object-name]. putObject($object, $data, $meta) created an object with name $object (should contain the bucket name as prefix!) having $data as its content. Optional $meta parameter is the array of metadata, which currently supports the following parameters as keys: S3_CONTENT_TYPE_HEADER MIME content type of the data. If not specified, the type will be guessed according to the file extension of the object name. The access to the item. Following access constants can be used: S3_ACL_PRIVATE S3_ACL_PUBLIC_READ Only the owner has access to the item. Anybody can read the object, but only owner can write. This is setting may be used to store publicly accessible content. Anybody can read or write the object. This policy is rarely useful.
S3_ACL_HEADER
S3_ACL_PUBLIC_WRITE
Only the owner has write access to the item, and other authenticated S3 users have read access. This is useful for sharing data between S3 accounts without exposing them to the public. By default, all the items are private. S3_ACL_AUTH_READ
1073
Zend_Service
array(Zend_Service_Amazon_S3::S3_ACL_HEADER => Zend_Service_Amazon_S3::S3_ACL_PUBLIC_READ)); echo "Go to http://s3.amazonaws.com/my-own-bucket/Pictures/Me.png getObject($object) retrieves object data from the storage by name. removeObject($object) removes the object from the storage. getInfo($object) retrieves the metadata information about the object. The function will return array with metadata information. Some of the useful keys are: type size mtime The MIME type of the item. The size of the object data. UNIX-type timestamp of the last modification for the object.
etag The ETag of the data, which is the MD5 hash of the data, surrounded by quotes ("). The function will return false if the key does not correspond to any existing object. getObjectsByBucket($bucket) returns the list of the object keys, contained in the bucket.
Stream wrapper
In addition to the interfaces described above, Zend_Service_Amazon_S3 also supports operating as a stream wrapper. For this, you need to register the client object as the stream wrapper:
1074
Zend_Service
mkdir("s3://my-own-bucket"); file_put_contents("s3://my-own-bucket/testdata", "mydata"); echo file_get_contents("s3://my-own-bucket/testdata"); Directory operations (mkdir, rmdir, opendir, etc.) will operate on buckets and thus their arguments should be of the form of s3://bucketname. File operations operate on objects. Object creation, reading, writing, deletion, stat and directory listing is supported.
Zend_Service_Amazon_Sqs
Introduction
Amazon Simple Queue Service (Amazon SQS) [http://aws.amazon.com/sqs/] offers a reliable, highly scalable, hosted queue for storing messages as they travel between computers. By using Amazon SQS, developers can simply move data between distributed components of their applications that perform different tasks, without losing messages or requiring each component to be always available. Amazon SQS makes it easy to build an automated workflow, working in close conjunction with the Amazon Elastic Compute Cloud (Amazon EC2) and the other AWS infrastructure web services. Amazon SQS works by exposing Amazon's web-scale messaging infrastructure as a web service. Any computer on the Internet can add or read messages without any installed software or special firewall configurations. Components of applications using Amazon SQS can run independently, and do not need to be on the same network, developed with the same technologies, or running at the same time.
API Documentation
The Zend_Service_Amazon_Sqs class provides the PHP wrapper to the Amazon SQS REST interface. Please consult the Amazon SQS documentation [http://developer.amazonwebservices.com/connect/kbcategory.jspa? categoryID=31] for detailed description of the service. You will need to be familiar with basic concepts in order to use this service.
Features
Zend_Service_Amazon_Sqs provides the following functionality: A single point for configuring your amazon.sqs authentication credentials that can be used across the amazon.sqs namespaces. A proxy object that is more convenient to use than an HTTP client alone, mostly removing the need to manually construct HTTP POST requests to access the REST service. A response wrapper that parses each response body and throws an exception if an error occurred, alleviating the need to repeatedly check the success of many commands. Additional convenience methods for some of the more common operations.
1075
Zend_Service
Getting Started
Once you have registered with Amazon SQS, you're ready to create your queue and store some messages on SQS. Each queue can contain unlimited amount of messages, identified by name. The following example demonstrates creating a queue, storing and retrieving messages.
Queue operations
All messages SQS are stored in queues. A queue has to be created before any message operations. Queue names must be unique under your access key and secret key. Queue names can contain lowercase letters, digits, periods (.), underscores (_), and dashes (-). No other symbols allowed. Queue names can be a maximum of 80 characters. create() creates a new queue. delete() removes all messages in the queue.
1076
Zend_Service
$count = $sqs->count($queue_url); // Returns '1' getQueues() returns the list of the names of all queues belonging to the user.
Message operations
After a queue is created, simple messages can be sent into the queue then received at a later point in time. Messages can be up to 8KB in length. If longer messages are needed please see S3 [http://framework.zend.com/manual/en/ zend.service.amazon.s3.html]. There is no limit to the number of messages a queue can contain. sent($queue_url, $message) send the $message to the $queue_url SQS queue URL.
1077
Zend_Service
Zend_Service_Audioscrobbler
Introduction
Zend_Service_Audioscrobbler is a simple API for using the Audioscrobbler REST Web Service. The Audioscrobbler Web Service provides access to its database of Users, Artists, Albums, Tracks, Tags, Groups, and Forums. The methods of the Zend_Service_Audioscrobbler class begin with one of these terms. The syntax and namespaces of the Audioscrobbler Web Service are mirrored in Zend_Service_Audioscrobbler. For more information about the Audioscrobbler REST Web Service, please visit the Audioscrobbler Web Service site [http:// www.audioscrobbler.net/data/webservices/].
Users
In order to retrieve information for a specific user, the setUser() method is first used to select the user for which data are to be retrieved. Zend_Service_Audioscrobbler provides several methods for retrieving data specific to a single user: userGetProfileInformation(): Returns a SimpleXML object containing the current user's profile information. userGetTopArtists(): Returns a SimpleXML object containing a list of the current user's most listened to artists. userGetTopAlbums(): Returns a SimpleXML object containing a list of the current user's most listened to albums. userGetTopTracks(): Returns a SimpleXML object containing a list of the current user's most listened to tracks. userGetTopTags(): Returns a SimpleXML object containing a list of tags most applied by the current user. userGetTopTagsForArtist(): Requires that an artist be set via setArtist(). Returns a SimpleXML object containing the tags most applied to the current artist by the current user. userGetTopTagsForAlbum(): Requires that an album be set via setAlbum(). Returns a SimpleXML object containing the tags most applied to the current album by the current user. userGetTopTagsForTrack(): Requires that a track be set via setTrack(). Returns a SimpleXML object containing the tags most applied to the current track by the current user. userGetFriends(): Returns a SimpleXML object containing the user names of the current user's friends. userGetNeighbours(): Returns a SimpleXML object containing the user names of people with similar listening habits to the current user. userGetRecentTracks(): Returns a SimpleXML object containing the 10 tracks most recently played by the current user. userGetRecentBannedTracks(): Returns a SimpleXML object containing a list of the 10 tracks most recently banned by the current user.
1078
Zend_Service
userGetRecentLovedTracks(): Returns a SimpleXML object containing a list of the 10 tracks most recently loved by the current user. userGetRecentJournals(): Returns a SimpleXML object containing a list of the current user's most recent journal entries. userGetWeeklyChartList(): Returns a SimpleXML object containing a list of weeks for which there exist Weekly Charts for the current user. userGetRecentWeeklyArtistChart(): Returns a SimpleXML object containing the most recent Weekly Artist Chart for the current user. userGetRecentWeeklyAlbumChart(): Returns a SimpleXML object containing the most recent Weekly Album Chart for the current user. userGetRecentWeeklyTrackChart(): Returns a SimpleXML object containing the most recent Weekly Track Chart for the current user. userGetPreviousWeeklyArtistChart($fromDate, $toDate): Returns a SimpleXML object containing the Weekly Artist Chart from $fromDate to $toDate for the current user. userGetPreviousWeeklyAlbumChart($fromDate, $toDate): Returns a SimpleXML object containing the Weekly Album Chart from $fromDate to $toDate for the current user. userGetPreviousWeeklyTrackChart($fromDate, $toDate): Returns a SimpleXML object containing the Weekly Track Chart from $fromDate to $toDate for the current user.
$as = new Zend_Service_Audioscrobbler(); // Set the user whose profile information we want to retrieve $as->setUser('BigDaddy71'); // Retrieve BigDaddy71's profile information $profileInfo = $as->userGetProfileInformation(); // Display some of it print "Information for $profileInfo->realname " . "can be found at $profileInfo->url";
1079
Zend_Service
$as->setToDate($weeks[0]); // Set the ending date $previousWeeklyArtists = $as->userGetPreviousWeeklyArtistChart(); echo 'Artist Chart For Week Of ' . date('Y-m-d h:i:s', $as->from_date) . '<br />'; foreach ($previousWeeklyArtists as $artist) { // Display the artists' names with links to their profiles print '<a href="' . $artist->url . '">' . $artist->name . '</a><br />'; }
Artists
Zend_Service_Audioscrobbler provides several methods for retrieving data about a specific artist, specified via the setArtist() method: artistGetRelatedArtists(): Returns a SimpleXML object containing a list of Artists similar to the current Artist. artistGetTopFans(): Returns a SimpleXML object containing a list of Users who listen most to the current Artist. artistGetTopTracks(): Returns a SimpleXML object containing a list of the current Artist's top-rated Tracks. artistGetTopAlbums(): Returns a SimpleXML object containing a list of the current Artist's top-rated Albums. artistGetTopTags(): Returns a SimpleXML object containing a list of the Tags most frequently applied to current Artist.
Tracks
Zend_Service_Audioscrobbler provides two methods for retrieving data specific to a single track, specified via the setTrack() method: trackGetTopFans(): Returns a SimpleXML object containing a list of Users who listen most to the current Track. trackGetTopTags(): Returns a SimpleXML object containing a list of the Tags most frequently applied to the current Track.
1080
Zend_Service
Tags
Zend_Service_Audioscrobbler provides several methods for retrieving data specific to a single tag, specified via the setTag() method: tagGetOverallTopTags(): Returns a SimpleXML object containing a list of Tags most frequently used on Audioscrobbler. tagGetTopArtists(): Returns a SimpleXML object containing a list of Artists to whom the current Tag was most frequently applied. tagGetTopAlbums(): Returns a SimpleXML object containing a list of Albums to which the current Tag was most frequently applied. tagGetTopTracks(): Returns a SimpleXML object containing a list of Tracks to which the current Tag was most frequently applied.
Groups
Zend_Service_Audioscrobbler provides several methods for retrieving data specific to a single group, specified via the setGroup() method: groupGetRecentJournals(): Returns a SimpleXML object containing a list of recent journal posts by Users in the current Group. groupGetWeeklyChart(): Returns a SimpleXML object containing a list of weeks for which there exist Weekly Charts for the current Group. groupGetRecentWeeklyArtistChart(): Returns a SimpleXML object containing the most recent Weekly Artist Chart for the current Group. groupGetRecentWeeklyAlbumChart(): Returns a SimpleXML object containing the most recent Weekly Album Chart for the current Group. groupGetRecentWeeklyTrackChart(): Returns a SimpleXML object containing the most recent Weekly Track Chart for the current Group. groupGetPreviousWeeklyArtistChart($fromDate, $toDate): Requires setFromDate() and setToDate(). Returns a SimpleXML object containing the Weekly Artist Chart from the current fromDate to the current toDate for the current Group. groupGetPreviousWeeklyAlbumChart($fromDate, $toDate): Requires setFromDate() and setToDate(). Returns a SimpleXML object containing the Weekly Album Chart from the current fromDate to the current toDate for the current Group. groupGetPreviousWeeklyTrackChart($fromDate, $toDate): Returns a SimpleXML object containing the Weekly Track Chart from the current fromDate to the current toDate for the current Group.
Forums
Zend_Service_Audioscrobbler provides a method for retrieving data specific to a single forum, specified via the setForum() method: forumGetRecentPosts(): Returns a SimpleXML object containing a list of recent posts in the current forum.
1081
Zend_Service
Zend_Service_Delicious
Introduction
Zend_Service_Delicious is simple API for using del.icio.us [http://del.icio.us] XML and JSON web services. This component gives you read-write access to posts at del.icio.us if you provide credentials. It also allows read-only access to public data of all users.
Retrieving posts
Zend_Service_Delicious provides three methods for retrieving posts: getPosts(), getRecentPosts() and getAllPosts(). All of these methods return an instance of Zend_Service_Delicious_PostList, which holds all retrieved posts. /** * Get posts matching the arguments. If no date or url is given, * most recent date will be used. * * @param string $tag Optional filtering by tag * @param Zend_Date $dt Optional filtering by date * @param string $url Optional filtering by url * @return Zend_Service_Delicious_PostList */ public function getPosts($tag = null, $dt = null, $url = null); /** * Get recent posts * * @param string $tag Optional filtering by tag * @param string $count Maximal number of posts to be returned * (default 15) * @return Zend_Service_Delicious_PostList */ public function getRecentPosts($tag = null, $count = 15); /** * Get all posts * * @param string $tag Optional filtering by tag * @return Zend_Service_Delicious_PostList
1082
Zend_Service
Zend_Service_Delicious_PostList
Instances of this class are returned by the getPosts(), getAllPosts(), getRecentPosts(), and getUserPosts() methods of Zend_Service_Delicious. For easier data access this class implements the Countable, Iterator, and ArrayAccess interfaces.
Nota
The ArrayAccess::offsetSet() and ArrayAccess::offsetUnset() methods throw exceptions in this implementation. Thus, code like unset($posts[0]); and $posts[0] = 'A'; will throw exceptions because these properties are read-only. Post list objects have two built-in filtering capabilities. Post lists may be filtered by tags and by URL.
1083
Zend_Service
$delicious = new Zend_Service_Delicious('username', 'password'); $posts = $delicious->getAllPosts(); // Print posts having "help" in the URL foreach ($posts->withUrl('/help/') as $post) { echo "Title: {$post->getTitle()}\n"; echo "Url: {$post->getUrl()}\n"; }
Editing posts
Ejemplo 48.83. Post editing
$delicious = new Zend_Service_Delicious('username', 'password'); $posts = $delicious->getPosts(); // set title $posts[0]->setTitle('New title'); // save changes $posts[0]->save();
$delicious = new Zend_Service_Delicious('username', 'password'); $posts = $delicious->getPosts(); $posts[0]->setTitle('New title') ->setNotes('New notes') ->save();
Deleting posts
There are two ways to delete a post, by specifying the post URL or by calling the delete() method upon a post object.
1084
Zend_Service
$delicious->deletePost($posts[0]->getUrl());
Tags
Ejemplo 48.87. Tags
$delicious = new Zend_Service_Delicious('username', 'password'); // get all tags print_r($delicious->getTags()); // rename tag ZF to zendFramework $delicious->renameTag('ZF', 'zendFramework');
Bundles
Ejemplo 48.88. Bundles
$delicious = new Zend_Service_Delicious('username', 'password'); // get all bundles print_r($delicious->getBundles()); // delete bundle someBundle $delicious->deleteBundle('someBundle'); // add bundle $delicious->addBundle('newBundle', array('tag1', 'tag2'));
1085
Zend_Service
Public data
The del.icio.us web API allows access to the public data of all users.
Nota
When using only these methods, a username and password combination is not required when constructing a new Zend_Service_Delicious object.
Public posts
When retrieving public posts with the getUserPosts() method, a Zend_Service_Delicious_PostList object is returned, and it contains Zend_Service_Delicious_SimplePost objects, which contain basic information about the posts, including URL, title, notes, and tags.
HTTP client
Zend_Service_Delicious uses Zend_Rest_Client for making HTTP requests to the del.icio.us web service. To change which HTTP client Zend_Service_Delicious uses, you need to change the HTTP client of Zend_Rest_Client.
1086
Zend_Service
Nota
When a Zend_Service_Delicious object is constructed, the SSL transport of Zend_Rest_Client is set to 'ssl' rather than the default of 'ssl2'. This is because del.icio.us has some problems with 'ssl2', such as requests taking a long time to complete (around 2 seconds).
Zend_Service_Flickr
Introduction
Zend_Service_Flickr is a simple API for using the Flickr REST Web Service. In order to use the Flickr web services, you must have an API key. To obtain a key and for more information about the Flickr REST Web Service, please visit the Flickr API Documentation [http://www.flickr.com/services/api/]. In the following example, we use the tagSearch() method to search for photos having "php" in the tags.
Optional parameter
tagSearch() accepts an optional second parameter as an array of options.
1087
Zend_Service
getIdByUsername(): Returns a string user ID associated with the given username string. getIdByEmail(): Returns a string user ID associated with the given email address string.
$flickr = new Zend_Service_Flickr('MY_API_KEY'); $results = $flickr->userSearch($userEmail); foreach ($results as $result) { echo $result->title . '<br />'; }
Optional parameter
groupPoolGetPhotos() accepts an optional second parameter as an array of options.
$flickr = new Zend_Service_Flickr('MY_API_KEY'); $image = $flickr->getImageDetails($imageId); echo "Image ID $imageId is $image->width x $image->height pixels.<br />\n"; echo "<a href=\"$image->clickUri\">Click for Image</a>\n";
1088
Zend_Service
Zend_Service_Flickr_ResultSet
Represents a set of Results from a Flickr search.
Nota
Implements the SeekableIterator interface for easy iteration (e.g., using foreach), as well as direct access to a specific result using seek().
Zend_Service_Flickr_ResultSet::totalResults()
int totalResults(); Returns the total number of results in this result set. Back to Class List
Zend_Service_Flickr_Result
A single Image result from a Flickr query
1089
Zend_Service
Name ispublic isfriend isfamily license dateupload datetaken ownername iconserver Square Thumbnail Small Medium Large Original Back to Class List
Type string string string string string string string string Zend_Service_Flickr_Image Zend_Service_Flickr_Image Zend_Service_Flickr_Image Zend_Service_Flickr_Image Zend_Service_Flickr_Image Zend_Service_Flickr_Image
Description The photo is public. The photo is visible to you because you are a friend of the owner. The photo is visible to you because you are family of the owner. The license the photo is available under. The date the photo was uploaded. The date the photo was taken. The screenname of the owner. The server used in assembling icon URLs. A 75x75 thumbnail of the image. A 100 pixel thumbnail of the image. A 240 pixel version of the image. A 500 pixel version of the image. A 640 pixel version of the image. The original image.
Zend_Service_Flickr_Image
Represents an Image returned by a Flickr search.
Zend_Service_Nirvanix
Introduction
Nirvanix provides an Internet Media File System (IMFS), an Internet storage service that allows applications to upload, store and organize files and subsequently access them using a standard Web Services interface. An IMFS is distributed clustered file system, accessed over the Internet, and optimized for dealing with media files (audio, video, etc). The
1090
Zend_Service
goal of an IMFS is to provide massive scalability to deal with the challenges of media storage growth, with guaranteed access and availability regardless of time and location. Finally, an IMFS gives applications the ability to access data securely, without the large fixed costs associated with acquiring and maintaining physical storage assets.
API Documentation
Access to the Nirvanix IMFS is available through both SOAP and a faster REST Zend_Service_Nirvanix provides a relatively thin PHP 5 wrapper around the REST service. service.
Zend_Service_Nirvanix aims to make using the Nirvanix REST service easier but understanding the service itself is still essential to be successful with Nirvanix. The Nirvanix API Documentation [http://developer.nirvanix.com/sitefiles/1000/API.html] provides an overview as well as detailed information using the service. Please familiarize yourself with this document and refer back to it as you use Zend_Service_Nirvanix.
Features
Nirvanix's REST service can be used effectively with PHP using the SimpleXML [http://www.php.net/simplexml] extension and Zend_Http_Client alone. However, using it this way is somewhat inconvenient due to repetitive operations like passing the session token on every request and repeatedly checking the response body for error codes. Zend_Service_Nirvanix provides the following functionality: A single point for configuring your Nirvanix authentication credentials that can be used across the Nirvanix namespaces. A proxy object that is more convenient to use than an HTTP client alone, mostly removing the need to manually construct HTTP POST requests to access the REST service. A response wrapper that parses each response body and throws an exception if an error occurred, alleviating the need to repeatedly check the success of many commands. Additional convenience methods for some of the more common operations.
Getting Started
Once you have registered with Nirvanix, you're ready to store your first file on the IMFS. The most common operations that you will need to do on the IMFS are creating a new file, downloading an existing file, and deleting a file. Zend_Service_Nirvanix provides convenience methods for these three operations.
$auth = array('username' => 'your-username', 'password' => 'your-password', 'appKey' => 'your-app-key');
1091
Zend_Service
$nirvanix = new Zend_Service_Nirvanix($auth); $imfs = $nirvanix->getService('IMFS'); $imfs->putContents('/foo.txt', 'contents to store'); echo $imfs->getContents('/foo.txt'); $imfs->unlink('/foo.txt'); The first step to using Zend_Service_Nirvanix is always to authenticate against the service. This is done by passing your credentials to the Zend_Service_Nirvanix constructor above. The associative array is passed directly to Nirvanix as POST parameters. Nirvanix divides its web services into namespaces [http://developer.nirvanix.com/sitefiles/1000/ API.html#_Toc175999879]. Each namespace encapsulates a group of related operations. After getting an instance of Zend_Service_Nirvanix, call the getService() method to create a proxy for the namespace you want to use. Above, a proxy for the IMFS namespace is created. After you have a proxy for the namespace you want to use, call methods on it. The proxy will allow you to use any command available on the REST API. The proxy may also make convenience methods available, which wrap web service commands. The example above shows using the IMFS convenience methods to create a new file, retrieve and display that file, and finally delete the file.
$auth = array('username' => 'your-username', 'password' => 'your-password', 'appKey' => 'your-app-key'); $nirvanix = new Zend_Service_Nirvanix($auth); $imfs = $nirvanix->getService('IMFS'); $result = $imfs->renameFile(array('filePath' => '/path/to/foo.txt', 'newFileName' => 'bar.txt')); Above, a proxy for the IMFS namespace is created. A method, renameFile(), is then called on the proxy. This method does not exist as a convenience method in the PHP code, so it is trapped by __call() and converted into a POST request to the REST API where the associative array is used as the POST parameters.
1092
Zend_Service
Notice in the Nirvanix API documentation that sessionToken is required for this method but we did not give it to the proxy object. It is added automatically for your convenience. The result of this operation will either be a Zend_Service_Nirvanix_Response object wrapping the XML returned by Nirvanix, or a Zend_Service_Nirvanix_Exception if an error occurred.
Examining Results
The Nirvanix REST API always returns its results in XML. Zend_Service_Nirvanix parses this XML with the SimpleXML extension and then decorates the resulting SimpleXMLElement with a Zend_Service_Nirvanix_Response object. The simplest way to examine a result from the service is to use the built-in PHP functions like print_r():
<?php $auth = array('username' => 'your-username', 'password' => 'your-password', 'appKey' => 'your-app-key'); $nirvanix = new Zend_Service_Nirvanix($auth); $imfs = $nirvanix->getService('IMFS'); $result = $imfs->putContents('/foo.txt', 'fourteen bytes'); print_r($result); ?> Zend_Service_Nirvanix_Response Object ( [_sxml:protected] => SimpleXMLElement Object ( [ResponseCode] => 0 [FilesUploaded] => 1 [BytesUploaded] => 14 ) ) You can access any property or method of the decorated SimpleXMLElement. In the above example, $result>BytesUploaded could be used to see the number of bytes received. Should you want to access the SimpleXMLElement directly, just use $result->getSxml(). The most common response from Nirvanix is success (ResponseCode of zero). It is not normally necessary to check ResponseCode because any non-zero result will throw a Zend_Service_Nirvanix_Exception. See the next section on handling errors.
Handling Errors
When using Nirvanix, it's important to anticipate errors that can be returned by the service and handle them appropriately. All operations against the REST service result in an XML return payload that contains a ResponseCode element, such as the following example:
1093
Zend_Service
<Response> <ResponseCode>0</ResponseCode> </Response> When the ResponseCode is zero such as in the example above, the operation was successful. When the operation is not successful, the ResponseCode is non-zero and an ErrorMessage element should be present. To alleviate the need to repeatedly check if the ResponseCode is non-zero, Zend_Service_Nirvanix automatically checks each response returned by Nirvanix. If the ResponseCode indicates an error, a Zend_Service_Nirvanix_Exception will be thrown.
$auth = array('username' => 'your-username', 'password' => 'your-password', 'appKey' => 'your-app-key'); $nirvanix = new Zend_Service_Nirvanix($auth); try { $imfs = $nirvanix->getService('IMFS'); $imfs->unlink('/a-nonexistant-path'); } catch (Zend_Service_Nirvanix_Exception $e) { echo $e->getMessage() . "\n"; echo $e->getCode(); } In the example above, unlink() is a convenience method that wraps the DeleteFiles command on the REST API. The filePath parameter required by the DeleteFiles [http://developer.nirvanix.com/ sitefiles/1000/API.html#_Toc175999918] command contains a path that does not exist. This will result in a Zend_Service_Nirvanix exception being thrown with the message "Invalid path" and code 70005. The Nirvanix API Documentation [http://developer.nirvanix.com/sitefiles/1000/API.html] describes the errors associated with each command. Depending on your needs, you may wrap each command in a try block or wrap many commands in the same try block for convenience.
Zend_Service_ReCaptcha
Introduction
Zend_Service_ReCaptcha provides a client for the reCAPTCHA Web Service [http://recaptcha.net/]. Per the reCAPTCHA site, "reCAPTCHA is a free CAPTCHA service that helps to digitize books." Each reCAPTCHA requires the user to input two words, the first of which is the actual CAPTCHA, and the second of which is a word from some scanned text that Optical Character Recognition (OCR) software has been unable to identify. The assumption is that if a user correctly provides the first word, the second is likely correctly entered as well, and can be used to improve OCR software for digitizing books. In order to use the reCAPTCHA service, you will need to sign up for an account [http://recaptcha.net/ whyrecaptcha.html] and register one or more domains with the service in order to generate public and private keys.
Simplest use
Instantiate a Zend_Service_ReCaptcha object, passing it your public and private keys:
1094
Zend_Service
1095
Zend_Service
$mailHide = new Zend_Service_ReCaptcha_Mailhide(); $mailHide->setPublicKey($pubKey); $mailHide->setPrivateKey($privKey); $mailHide->setEmail($mail); // Display it print($mailHide); The example above will display "m...@example.com" where "..." has a link that opens up a popup window with a reCAPTCHA challenge. The public key, private key, and the email address can also be specified in the constructor of the class. A fourth argument also exists that enables you to set some options for the component. The available options are listed in the following table:
The configuration options can be set by sending them as the fourth argument to the constructor or by calling setOptions($options), which takes an associative array or an instance of Zend_Config.
1096
Zend_Service
Zend_Service_Simpy
Introduction
Zend_Service_Simpy is a lightweight wrapper for the free REST API available for the Simpy social bookmarking service. In order to use Zend_Service_Simpy, you should already have a Simpy account. To get an account, visit the Simpy web site [http://simpy.com]. For more information on the Simpy REST API, refer to the Simpy REST API documentation [http://www.simpy.com/doc/api/rest]. The Simpy REST API allows developers to interact with specific aspects of the service that the Simpy web site offers. The sections following will outline the use of Zend_Service_Simpy for each of these areas. Links: Create, Retrieve, Update, Delete Tags: Retrieve, Delete, Rename, Merge, Split Notes: Create, Retrieve, Update, Delete Watchlists: Get, Get All
Links
When querying links, results are returned in descending order by date added. Links can be searched by title, nickname, tags, note, or even the content of the web page associated with the link. Simpy offers searching by any or all of these fields with phrases, boolean operators, and wildcards. See the search syntax [http://www.simpy.com/ faq#searchSyntax] and search fields [http://www.simpy.com/faq#searchFieldsLinks] sections of the Simpy FAQ for more information.
1097
Zend_Service
/* Search for all links with 'French' in the title and 'language' in the tags */ $linkQuery->setQueryString('+title:French +tags:language'); /* Search for all links with 'French' in the title and without 'travel' in the tags */ $linkQuery->setQueryString('+title:French -tags:travel'); /* Search for all links added on 12/9/06 */ $linkQuery->setDate('2006-12-09'); /* Search for all links added after 12/9/06 (excluding that date) */ $linkQuery->setAfterDate('2006-12-09'); /* Search for all links added before 12/9/06 (excluding that date) */ $linkQuery->setBeforeDate('2006-12-09'); /* Search for all links added between 12/1/06 and 12/9/06 (excluding those two dates) */ $linkQuery->setBeforeDate('2006-12-01'); $linkQuery->setAfterDate('2006-12-09'); Links are represented uniquely by their URLs. In other words, if an attempt is made to save a link that has the same URL as an existing link, data for the existing link will be overwritten with the data specified in the save attempt.
1098
Zend_Service
/* A really easy way to do spring cleaning on your links ;) */ $linkSet = $this->_simpy->getLinks(); foreach ($linkSet as $link) { $this->_simpy->deleteLink($link->getUrl()); }
Tags
When retrieved, tags are sorted in decreasing order (i.e. highest first) by the number of links that use the tag.
Notes
Notes can be saved, retrieved, and deleted. They are uniquely identified by a numeric ID value.
1099
Zend_Service
Watchlists
Watchlists cannot be created or removed using the API, only retrieved. Thus, you must set up a watchlist via the Simpy web site prior to attempting to access it using the API.
1100
Zend_Service
/* Get a list of all watchlists */ $watchlistSet = $simpy->getWatchlists(); /* Display data for each watchlist */ foreach ($watchlistSet as $watchlist) { echo $watchlist->getId(); echo '<br />'; echo $watchlist->getName(); echo '<br />'; echo $watchlist->getDescription(); echo '<br />'; echo $watchlist->getAddDate(); echo '<br />'; echo $watchlist->getNewLinks(); echo '<br />'; foreach ($watchlist->getUsers() as $user) { echo $user; echo '<br />'; } foreach ($watchlist->getFilters() as $filter) { echo $filter->getName(); echo '<br />'; echo $filter->getQuery(); echo '<br />'; } } /* Get an individual watchlist by its identifier */ $watchlist = $simpy->getWatchlist($watchlist->getId()); $watchlist = $simpy->getWatchlist(1);
Introduction
The Zend_Service_SlideShare component is used to interact with the slideshare.net [http:// www.slideshare.net/] web services for hosting slide shows online. With this component, you can embed slide shows which are hosted on this web site within a web site and even upload new slide shows to your account.
1101
Zend_Service
1102
Zend_Service
public function setFilename($file) { $this->_slideShowFilename = (string)$file; return $this; } /** * Retrieves the filename on the local filesystem of the slide show * which will be uploaded */ public function getFilename() { return $this->_slideShowFilename; } /** * Gets the ID for the slide show */ public function getId() { return $this->_slideShowId; } /** * Retrieves the HTML embed code for the slide show */ public function getEmbedCode() { return $this->_embedCode; } /** * Retrieves the Thumbnail URi for the slide show */ public function getThumbnailUrl() { return $this->_thumbnailUrl; } /** * Sets the title for the Slide show */ public function setTitle($title) { $this->_title = (string)$title; return $this; } /** * Retrieves the Slide show title */ public function getTitle() { return $this->_title; } /** * Sets the description for the Slide show */ public function setDescription($desc) { $this->_description = (string)$desc;
1103
Zend_Service
return $this; } /** * Gets the description of the slide show */ public function getDescription() { return $this->_description; } /** * Gets the numeric status of the slide show on the server */ public function getStatus() { return $this->_status; } /** * Gets the textual description of the status of the slide show on * the server */ public function getStatusDescription() { return $this->_statusDescription; } /** * Gets the permanent link of the slide show */ public function getPermaLink() { return $this->_permalink; } /** * Gets the number of views the slide show has received */ public function getNumViews() { return $this->_numViews; } }
Nota
The above pseudo-class only shows those methods which should be used by end-user developers. Other available methods are internal to the component. When using the Zend_Service_SlideShare component, this data class will be used frequently to browse or add new slide shows to or from the web service.
1104
Zend_Service
// Create a new instance of the component $ss = new Zend_Service_SlideShare('APIKEY', 'SHAREDSECRET', 'USERNAME', 'PASSWORD'); $slideshow = $ss->getSlideShow(123456); print "Slide Show Title: {$slideshow->getTitle()}<br/>\n"; print "Number of views: {$slideshow->getNumViews()}<br/>\n";
// Create a new instance of the component $ss = new Zend_Service_SlideShare('APIKEY', 'SHAREDSECRET', 'USERNAME', 'PASSWORD'); $starting_offset = 0; $limit = 10; // Retrieve the first 10 of each type $ss_user = $ss->getSlideShowsByUser('username', $starting_offset, $limit); $ss_tags = $ss->getSlideShowsByTag('zend', $starting_offset, $limit); $ss_group = $ss->getSlideShowsByGroup('mygroup', $starting_offset, $limit); // Iterate over the slide shows foreach($ss_user as $slideshow) { print "Slide Show Title: {$slideshow->getTitle}<br/>\n"; }
1105
Zend_Service
$frontendOptions = array( 'lifetime' => 7200, 'automatic_serialization' => true); $backendOptions = array( 'cache_dir' => '/webtmp/'); $cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions); $ss = new Zend_Service_SlideShare('APIKEY', 'SHAREDSECRET', 'USERNAME', 'PASSWORD'); $ss->setCacheObject($cache); $ss_user = $ss->getSlideShowsByUser('username', $starting_offset, $limit);
$client = new Zend_Http_Client(); $client->setConfig(array('timeout' => 5)); $ss = new Zend_Service_SlideShare('APIKEY', 'SHAREDSECRET', 'USERNAME', 'PASSWORD'); $ss->setHttpClient($client); $ss_user = $ss->getSlideShowsByUser('username', $starting_offset, $limit);
Zend_Service_StrikeIron
Zend_Service_StrikeIron provides a PHP 5 client to StrikeIron web services. See the following sections: the section called Zend_Service_StrikeIron the section called Zend_Service_StrikeIron: Bundled Services the section called Zend_Service_StrikeIron: Advanced Uses
1106
Zend_Service
Overview
StrikeIron [http://www.strikeiron.com] offers hundreds of commercial data services ("Data as a Service") such as Online Sales Tax, Currency Rates, Stock Quotes, Geocodes, Global Address Verification, Yellow/White Pages, MapQuest Driving Directions, Dun & Bradstreet Business Credit Checks, and much, much more. Each StrikeIron web service shares a standard SOAP (and REST) API, making it easy to integrate and manage multiple services. StrikeIron also manages customer billing for all services in a single account, making it perfect for solution providers. Get started with free web services at http://www.strikeiron.com/sdp. StrikeIron's services may be used through the PHP 5 SOAP extension [http://us.php.net/soap] alone. However, using StrikeIron this way does not give an ideal PHP-like interface. The Zend_Service_StrikeIron component provides a lightweight layer on top of the SOAP extension for working with StrikeIron services in a more convenient, PHP-like manner.
Nota
The PHP 5 SOAP extension must be installed and enabled to use Zend_Service_StrikeIron. The Zend_Service_StrikeIron component provides: A single point for configuring your StrikeIron authentication credentials that can be used across many StrikeIron services. A standard way of retrieving your StrikeIron subscription information such as license status and the number of hits remaining to a service. The ability to use any StrikeIron service from its WSDL without creating a PHP wrapper class, and the option of creating a wrapper for a more convenient interface. Wrappers for three popular StrikeIron services.
Getting Started
Once you have registered [http://strikeiron.com/Register.aspx] for a StrikeIron account and signed up for the Super Data Pack [http://www.strikeiron.com/ProductDetail.aspx?p=257], you're ready to start using Zend_Service_StrikeIron. StrikeIron consists of hundreds of different web services. Zend_Service_StrikeIron can be used with many of these services but provides supported wrappers for three of them: ZIP Code Information US Address Verification
1107
Zend_Service
Sales & Use Tax Basic The class Zend_Service_StrikeIron provides a simple way of specifying your StrikeIron account information and other options in its constructor. It also has a factory method that will return clients for StrikeIron services: $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username', 'password' => 'your-password')); $taxBasic = $strikeIron->getService(array('class' => 'SalesUseTaxBasic')); The getService() method will return a client for any StrikeIron service by the name of its PHP wrapper class. In this case, the name SalesUseTaxBasic refers to the wrapper class Zend_Service_StrikeIron_SalesUseTaxBasic. Wrappers are included for three services and described in Bundled Services. The getService() method can also return a client for a StrikeIron service that does not yet have a PHP wrapper. This is explained in Using Services by WSDL.
Examining Results
When learning or debugging the StrikeIron services, it's often useful to dump the result returned from a method call. The result will always be an object that is an instance of Zend_Service_StrikeIron_Decorator. This is a small decorator [http://en.wikipedia.org/wiki/Decorator_pattern] object that wraps the results from the method call. The simplest way to examine a result from the service is to use the built-in PHP functions like print_r() [http:// www.php.net/print_r]:
1108
Zend_Service
<?php $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username', 'password' => 'your-password')); $taxBasic = $strikeIron->getService(array('class' => 'SalesUseTaxBasic')); $rateInfo = $taxBasic->getTaxRateCanada(array('province' => 'ontario')); print_r($rateInfo); ?> Zend_Service_StrikeIron_Decorator Object ( [_name:protected] => GetTaxRateCanadaResult [_object:protected] => stdClass Object ( [abbreviation] => ON [province] => ONTARIO [GST] => 0.06 [PST] => 0.08 [total] => 0.14 [HST] => Y ) ) In the output above, we see that the decorator ($rateInfo) wraps an object named GetTaxRateCanadaResult, the result of the call to getTaxRateCanada(). This means that $rateInfo has public properties like abbreviation, province, and GST. These are accessed like $rateInfo->province.
Tip
StrikeIron result properties sometimes start with an uppercase letter such as Foo or Bar where most PHP object properties normally start with a lowercase letter as in foo or bar. The decorator will automatically do this inflection so you may read a property Foo as foo. If you ever need to get the original object or its name out of the decorator, use the respective methods getDecoratedObject() and getDecoratedObjectName().
Handling Errors
The previous examples are naive, i.e. no error handling was shown. It's possible that StrikeIron will return a fault during a method call. Events like bad account credentials or an expired subscription can cause StrikeIron to raise a fault. An exception will be thrown when such a fault occurs. You should anticipate and catch these exceptions when making method calls to the service: $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username', 'password' => 'your-password')); $taxBasic = $strikeIron->getService(array('class' => 'SalesUseTaxBasic')); try {
1109
Zend_Service
$taxBasic->getTaxRateCanada(array('province' => 'ontario')); } catch (Zend_Service_StrikeIron_Exception $e) { // error handling for events like connection // problems or subscription errors } The exceptions thrown will always be Zend_Service_StrikeIron_Exception. It's important to understand the difference between exceptions and normal failed method calls. Exceptions occur for exceptional conditions, such as the network going down or your subscription expiring. Failed method calls that are a common occurrence, such as getTaxRateCanada() not finding the province you supplied, will not result an in exception.
Nota
Every time you make a method call to a StrikeIron service, you should check the response object for validity and also be prepared to catch an exception.
1110
Zend_Service
$strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username', 'password' => 'your-password')); // Get a client for the Zip Code Information service $zipInfo = $strikeIron->getService(array('class' => 'ZipCodeInfo')); // Get the Zip information for 95014 $response = $zipInfo->getZipCode(array('ZipCode' => 95014)); $zips = $response->serviceResult; // Display the results if ($zips->count == 0) { echo 'No results found'; } else { // a result with one single zip code is returned as an object, // not an array with one element as one might expect. if (! is_array($zips->zipCodes)) { $zips->zipCodes = array($zips->zipCodes); } // print all of the possible results foreach ($zips->zipCodes as $z) { $info = $z->zipCodeInfo; // show all properties print_r($info); // or just the city name echo $info->preferredCityName; } } // Detailed status information // http://www.strikeiron.com/exampledata/StrikeIronZipCodeInformation_v3.pdf $status = $response->serviceStatus;
1111
Zend_Service
U.S. Address Verification Service Page [http://www.strikeiron.com/ProductDetail.aspx?p=198] U.S. Address Verification Service WSDL [http://ws.strikeiron.com/zf1.StrikeIron/USAddressVerification4_0? WSDL] The service contains a verifyAddressUSA() method that will verify an address in the United States:
$strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username', 'password' => 'your-password')); // Get a client for the Zip Code Information service $verifier = $strikeIron->getService(array('class' => 'USAddressVerification')); // Address to verify. Not all fields are required but // supply as many as possible for the best results. $address = array('firm' => 'Zend Technologies', 'addressLine1' => '19200 Stevens Creek Blvd', 'addressLine2' => '', 'city_state_zip' => 'Cupertino CA 95014'); // Verify the address $result = $verifier->verifyAddressUSA($address); // Display the results if ($result->addressErrorNumber != 0) { echo $result->addressErrorNumber; echo $result->addressErrorMessage; } else { // show all properties print_r($result); // or just the firm name echo $result->firm; // valid address? $valid = ($result->valid == 'VALID'); }
1112
Zend_Service
// Get a client for the Sales & Use Tax Basic service $taxBasic = $strikeIron->getService(array('class' => 'SalesUseTaxBasic')); // Query tax rate for Ontario, Canada $rateInfo = $taxBasic->getTaxRateCanada(array('province' => 'foo')); print_r($rateInfo); // show all properties echo $rateInfo->GST; // or just the GST (Goods & Services Tax) // Query tax rate for Cupertino, CA USA $rateInfo = $taxBasic->getTaxRateUS(array('zip_code' => 95014)); print_r($rateInfo); // show all properties echo $rateInfo->state_sales_tax; // or just the state sales tax
$strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username', 'password' => 'your-password')); // Get a generic client to the Reverse Phone Lookup service $phone = $strikeIron->getService( array('wsdl' => 'http://ws.strikeiron.com/ReversePhoneLookup?WSDL') ); $result = $phone->lookup(array('Number' => '(408) 253-8800')); echo $result->listingName; // Zend Technologies USA Inc Using StrikeIron services from the WSDL will require at least some understanding of the WSDL files. StrikeIron has many resources on its site to help with this. Also, Jan Schneider [http://janschneider.de] from the Horde project [http:// horde.org] has written a small PHP routine [http://janschneider.de/news/25/268] that will format a WSDL file into more readable HTML. Please note that only the services described in the Bundled Services section are officially supported.
1113
Zend_Service
Every StrikeIron client (subclass of Zend_Service_StrikeIron_Base) contains a getSoapClient() method to return the underlying instance of SOAPClient used to communicate with StrikeIron. PHP's SOAPClient [http://www.php.net/manual/en/function.soap-soapclient-construct.php] has a trace option that causes it to remember the XML exchanged during the last transaction. Zend_Service_StrikeIron does not enable the trace option by default but this can easily by changed by specifying the options that will be passed to the SOAPClient constructor. To view a SOAP transaction, call the getSoapClient() method to get the SOAPClient instance and then call the appropriate methods like __getLastRequest() [http://www.php.net/manual/ en/function.soap-soapclient-getlastrequest.php] and __getLastRequest() [http://www.php.net/manual/en/ function.soap-soapclient-getlastresponse.php]: $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username', 'password' => 'your-password', 'options' => array('trace' => true))); // Get a client for the Sales & Use Tax Basic service $taxBasic = $strikeIron->getService(array('class' => 'SalesUseTaxBasic')); // Perform a method call $taxBasic->getTaxRateCanada(array('province' => 'ontario')); // Get SOAPClient instance and view XML $soapClient = $taxBasic->getSoapClient(); echo $soapClient->__getLastRequest(); echo $soapClient->__getLastResponse();
Zend_Service_Technorati
Introduction
Zend_Service_Technorati provides an easy, intuitive and object-oriented interface for using the Technorati API. It provides access to all available Technorati API queries [http://technorati.com/developers/api/] and returns the original XML response as a friendly PHP object. Technorati [http://technorati.com/] is one of the most popular blog search engines. The API interface enables developers to retrieve information about a specific blog, search blogs matching a single tag or phrase and get information about a specific author (blogger). For a full list of available queries please see the Technorati API documentation [http://technorati.com/developers/api/] or the Available Technorati queries section of this document.
Getting Started
Technorati requires a valid API key for usage. To get your own API Key you first need to create a new Technorati account [http://technorati.com/signup/], then visit the API Key section [http://technorati.com/developers/apikey.html].
1114
Zend_Service
Ejemplo 48.109. Sending multiple queries with the same Zend_Service_Technorati instance
// create a new Zend_Service_Technorati // with a valid API_KEY $technorati = new Zend_Service_Technorati('VALID_API_KEY'); // search Technorati for PHP keyword $search = $technorati->search('PHP'); // get top tags indexed by Technorati $topTags = $technorati->topTags();
Consuming Results
You can get one of two types of result object in response to a query. The first group is represented by Zend_Service_Technorati_*ResultSet objects. A result set object is basically a collection of result objects. It extends the basic Zend_Service_Technorati_ResultSet class and
1115
Zend_Service
implements the SeekableIterator PHP interface. The best way to consume a result set object is to loop over it with the PHP foreach statement.
Nota
SeekableIterator works as an array and counts positions starting from index 0. Fetching position number 1 means getting the second result in the collection. The second group is represented by special standalone result objects. Zend_Service_Technorati_GetInfoResult, Zend_Service_Technorati_BlogInfoResult and Zend_Service_Technorati_KeyInfoResult act as wrappers for additional objects, such as Zend_Service_Technorati_Author and Zend_Service_Technorati_Weblog.
1116
Zend_Service
// get info about weppos author $result = $technorati->getInfo('weppos'); $author = $result->getAuthor(); echo '<h2>Blogs authored by ' . $author->getFirstName() . " " . $author->getLastName() . '</h2>'; echo '<ol>'; foreach ($result->getWeblogs() as $weblog) { echo '<li>' . $weblog->getName() . '</li>'; } echo "</ol>"; Please read the Zend_Service_Technorati Classes section for further details about response classes.
Handling Errors
Each Zend_Service_Technorati query method throws a Zend_Service_Technorati_Exception exception on failure with a meaningful error message. There are several reasons that may cause a Zend_Service_Technorati query to fail. Zend_Service_Technorati validates all parameters for any query request. If a parameter is invalid or it contains an invalid value, a new Zend_Service_Technorati_Exception exception is thrown. Additionally, the Technorati API interface could be temporally unavailable, or it could return a response that is not well formed. You should always wrap a Technorati query with a try...catch block.
1117
Zend_Service
Technorati Cosmos
Cosmos [http://technorati.com/developers/api/cosmos.html] query lets you see what blogs are linking to a given URL. It returns a Zend_Service_Technorati_CosmosResultSet object. For full details please see Zend_Service_Technorati::cosmos() in the API reference guide [http://framework.zend.com/apidoc/core/ ].
Technorati Search
The Search [http://technorati.com/developers/api/search.html] query lets you see what blogs contain a given search string. It returns a Zend_Service_Technorati_SearchResultSet object. For full details please see Zend_Service_Technorati::search() in the API reference guide [http://framework.zend.com/apidoc/core/ ].
1118
Zend_Service
echo "<p>Reading " . $resultSet->totalResults() . " of " . $resultSet->totalResultsAvailable() . " available results</p>"; echo "<ol>"; foreach ($resultSet as $result) { echo "<li>" . $result->getWeblog()->getName() . "</li>"; } echo "</ol>";
Technorati Tag
The Tag [http://technorati.com/developers/api/tag.html] query lets you see what posts are associated with a given tag. It returns a Zend_Service_Technorati_TagResultSet object. For full details please see Zend_Service_Technorati::tag() in the API reference guide [http://framework.zend.com/apidoc/core/].
Technorati DailyCounts
The DailyCounts [http://technorati.com/developers/api/dailycounts.html] query provides daily counts of posts containing the queried keyword. It returns a Zend_Service_Technorati_DailyCountsResultSet object. For full details please see Zend_Service_Technorati::dailyCounts() in the API reference guide [http:// framework.zend.com/apidoc/core/].
Technorati TopTags
The TopTags [http://technorati.com/developers/api/toptags.html] query provides information on top tags indexed by Technorati. It returns a Zend_Service_Technorati_TagsResultSet object. For full details please see
1119
Zend_Service
Technorati BlogInfo
The BlogInfo [http://technorati.com/developers/api/bloginfo.html] query provides information on what blog, if any, is associated with a given URL. It returns a Zend_Service_Technorati_BlogInfoResult object. For full details please see Zend_Service_Technorati::blogInfo() in the API reference guide [http:// framework.zend.com/apidoc/core/].
Technorati BlogPostTags
The BlogPostTags [http://technorati.com/developers/api/blogposttags.html] query provides information on the top tags used by a specific blog. It returns a Zend_Service_Technorati_TagsResultSet object. For full details please see Zend_Service_Technorati::blogPostTags() in the API reference guide [http:// framework.zend.com/apidoc/core/].
1120
Zend_Service
Technorati GetInfo
The GetInfo [http://technorati.com/developers/api/getinfo.html] query tells you things that Technorati knows about a member. It returns a Zend_Service_Technorati_GetInfoResult object. For full details please see Zend_Service_Technorati::getInfo() in the API reference guide [http://framework.zend.com/apidoc/ core/].
Technorati KeyInfo
The KeyInfo query provides information on daily usage of an API key. It returns a Zend_Service_Technorati_KeyInfoResult object. For full details please see Zend_Service_Technorati::keyInfo() in the API reference guide [http://framework.zend.com/apidoc/ core/].
Zend_Service_Technorati Classes
The following classes are returned by the various Technorati queries. Each Zend_Service_Technorati_*ResultSet class holds a type-specific result set which can be easily iterated, with each result being contained in a type result object. All result set classes extend Zend_Service_Technorati_ResultSet class and implement the SeekableIterator interface, allowing for easy iteration and seeking to a specific result. Zend_Service_Technorati_ResultSet Zend_Service_Technorati_CosmosResultSet Zend_Service_Technorati_SearchResultSet Zend_Service_Technorati_TagResultSet Zend_Service_Technorati_DailyCountsResultSet Zend_Service_Technorati_TagsResultSet Zend_Service_Technorati_Result Zend_Service_Technorati_CosmosResult Zend_Service_Technorati_SearchResult Zend_Service_Technorati_TagResult
1121
Zend_Service
Nota
Zend_Service_Technorati_GetInfoResult, Zend_Service_Technorati_BlogInfoResult and Zend_Service_Technorati_KeyInfoResult represent exceptions to the above because they don't belong to a result set and they don't implement any interface. They represent a single response object and they act as a wrapper for additional Zend_Service_Technorati objects, such as Zend_Service_Technorati_Author and Zend_Service_Technorati_Weblog. The Zend_Service_Technorati library includes additional convenient classes representing specific response objects. Zend_Service_Technorati_Author represents a single Technorati account, also known as a blog author or blogger. Zend_Service_Technorati_Weblog represents a single weblog object, along with all specific weblog properties such as feed URLs or blog name. For full details please see Zend_Service_Technorati in the API reference guide [http://framework.zend.com/apidoc/core/].
Zend_Service_Technorati_ResultSet
Zend_Service_Technorati_ResultSet is the most essential result set. The scope of this class is to be extended by a query-specific child result set class, and it should never be used to initialize a standalone object. Each of the specific result sets represents a collection of query-specific Zend_Service_Technorati_Result objects. Zend_Service_Technorati_ResultSet implements the PHP SeekableIterator interface, and you can iterate all result objects via the PHP foreach statement.
Zend_Service_Technorati_CosmosResultSet
Zend_Service_Technorati_CosmosResultSet represents a Technorati Cosmos query result set.
Nota
Zend_Service_Technorati_CosmosResultSet extends Zend_Service_Technorati_ResultSet.
1122
Zend_Service
Zend_Service_Technorati_SearchResultSet
Zend_Service_Technorati_SearchResultSet represents a Technorati Search query result set.
Nota
Zend_Service_Technorati_SearchResultSet extends Zend_Service_Technorati_ResultSet.
Zend_Service_Technorati_TagResultSet
Zend_Service_Technorati_TagResultSet represents a Technorati Tag query result set.
Nota
Zend_Service_Technorati_TagResultSet extends Zend_Service_Technorati_ResultSet.
Zend_Service_Technorati_DailyCountsResultSet
Zend_Service_Technorati_DailyCountsResultSet represents a Technorati DailyCounts query result set.
Nota
Zend_Service_Technorati_DailyCountsResultSet Zend_Service_Technorati_ResultSet. extends
Zend_Service_Technorati_TagsResultSet
Zend_Service_Technorati_TagsResultSet represents a Technorati TopTags or BlogPostTags queries result set.
Nota
Zend_Service_Technorati_TagsResultSet extends Zend_Service_Technorati_ResultSet.
Zend_Service_Technorati_Result
Zend_Service_Technorati_Result is the most essential result object. The scope of this class is to be extended by a query specific child result class, and it should never be used to initialize a standalone object.
Zend_Service_Technorati_CosmosResult
Zend_Service_Technorati_CosmosResult represents a single Technorati Cosmos query result object. It is never returned as a standalone object, but it always belongs to a valid Zend_Service_Technorati_CosmosResultSet object.
Nota
Zend_Service_Technorati_CosmosResult extends Zend_Service_Technorati_Result.
Zend_Service_Technorati_SearchResult
Zend_Service_Technorati_SearchResult represents a single Technorati Search query result object. It is never returned as a standalone object, but it always belongs to a valid Zend_Service_Technorati_SearchResultSet object.
1123
Zend_Service
Nota
Zend_Service_Technorati_SearchResult extends Zend_Service_Technorati_Result.
Zend_Service_Technorati_TagResult
Zend_Service_Technorati_TagResult represents a single Technorati Tag query result object. It is never returned as a standalone object, but it always belongs to a valid Zend_Service_Technorati_TagResultSet object.
Nota
Zend_Service_Technorati_TagResult extends Zend_Service_Technorati_Result.
Zend_Service_Technorati_DailyCountsResult
Zend_Service_Technorati_DailyCountsResult represents a single Technorati DailyCounts query result object. It is never returned as a standalone object, but it always belongs to a valid Zend_Service_Technorati_DailyCountsResultSet object.
Nota
Zend_Service_Technorati_DailyCountsResult extends Zend_Service_Technorati_Result.
Zend_Service_Technorati_TagsResult
Zend_Service_Technorati_TagsResult represents a single Technorati TopTags or BlogPostTags query result object. It is never returned as a standalone object, but it always belongs to a valid Zend_Service_Technorati_TagsResultSet object.
Nota
Zend_Service_Technorati_TagsResult extends Zend_Service_Technorati_Result.
Zend_Service_Technorati_GetInfoResult
Zend_Service_Technorati_GetInfoResult represents a single Technorati GetInfo query result object.
Zend_Service_Technorati_BlogInfoResult
Zend_Service_Technorati_BlogInfoResult represents a single Technorati BlogInfo query result object.
Zend_Service_Technorati_KeyInfoResult
Zend_Service_Technorati_KeyInfoResult represents a single Technorati KeyInfo query result object. It provides information about your Technorati API Key daily usage.
Zend_Service_Twitter
Introduction
Zend_Service_Twitter provides a client for the Twitter REST API [http://apiwiki.twitter.com/Twitter-APIDocumentation]. Zend_Service_Twitter allows you to query the public timeline. If you provide a username
1124
Zend_Service
and password for Twitter, it will allow you to get and update your status, reply to friends, direct message friends, mark tweets as favorite, and much more. Zend_Service_Twitter is implementing a REST service, and all methods return an instance of Zend_Rest_Client_Result. Zend_Service_Twitter is broken up into subsections so you can easily identify which type of call is being requested. account makes sure that your account credentials are valid, checks your API rate limit, and ends the current session for the authenticated user. status retrieves the public and user timelines and shows, updates, destroys, and retrieves replies for the authenticated user. user retrieves friends and followers for the authenticated user and returns extended information about a passed user. directMessage retrieves the authenticated user's received direct messages, deletes direct messages, and sends new direct messages. friendship creates and removes friendships for the authenticated user. favorite lists, creates, and removes favorite tweets. block blocks and unblocks users from following you.
Authentication
With the exception of fetching the public timeline, Zend_Service_Twitter requires authentication to work. Twitter currently uses HTTP Basic Authentication [http://en.wikipedia.org/wiki/Basic_authentication_scheme]. You can pass in your username or registered email along with your password for Twitter to login.
$twitter = new Zend_Service_Twitter('myusername', 'mysecretpassword'); // verify your credentials with Twitter $response = $twitter->account->verifyCredentials(); You can also pass in an array that contains the username and password as the first argument.
$userInfo $twitter
Account Methods
verifyCredentials() tests if supplied user credentials are valid with minimal overhead.
1125
Zend_Service
rateLimitStatus() returns the remaining number of API requests available to the authenticating user before the API limit is reached for the current hour.
Status Methods
publicTimeline() returns the 20 most recent statuses from non-protected users with a custom user icon. The public timeline is cached by Twitter for 60 seconds.
friendsTimeline() returns the 20 most recent statuses posted by the authenticating user and that user's friends.
The friendsTimeline() method accepts an array of optional parameters to modify the query. since narrows the returned results to just those statuses created after the specified date/time (up to 24 hours old). page specifies which page you want to return. userTimeline() returns the 20 most recent statuses posted from the authenticating user.
1126
Zend_Service
$response
= $twitter->status->userTimeline();
The userTimeline() method accepts an array of optional parameters to modify the query. id specifies the ID or screen name of the user for whom to return the friends_timeline. since narrows the returned results to just those statuses created after the specified date/time (up to 24 hours old). page specifies which page you want to return. count specifies the number of statuses to retrieve. May not be greater than 200. show() returns a single status, specified by the id parameter below. The status' author will be returned inline.
update() updates the authenticating user's status. This method requires that you pass in the status update that you want to post to Twitter.
The update() method accepts a second additional parameter. in_reply_to_status_id specifies the ID of an existing status that the status to be posted is in reply to. replies() returns the 20 most recent @replies (status updates prefixed with @username) for the authenticating user.
The replies() method accepts an array of optional parameters to modify the query. since narrows the returned results to just those statuses created after the specified date/time (up to 24 hours old). page specifies which page you want to return. since_id returns only statuses with an ID greater than (that is, more recent than) the specified ID. destroy() destroys the status specified by the required id parameter.
Zend_Service
$response
= $twitter->status->destroy(12345);
User Methods
friends()r eturns up to 100 of the authenticating user's friends who have most recently updated, each with current status inline.
The friends() method accepts an array of optional parameters to modify the query. id specifies the ID or screen name of the user for whom to return a list of friends. since narrows the returned results to just those statuses created after the specified date/time (up to 24 hours old). page specifies which page you want to return. followers() returns the authenticating user's followers, each with current status inline.
The followers() method accepts an array of optional parameters to modify the query. id specifies the ID or screen name of the user for whom to return a list of followers. page specifies which page you want to return. show() returns extended information of a given user, specified by ID or screen name as per the required id parameter below.
The message() method accepts an array of optional parameters to modify the query.
1128
Zend_Service
since_id returns only direct messages with an ID greater than (that is, more recent than) the specified ID. since narrows the returned results to just those statuses created after the specified date/time (up to 24 hours old). page specifies which page you want to return. sent() returns a list of the 20 most recent direct messages sent by the authenticating user.
The sent() method accepts an array of optional parameters to modify the query. since_id returns only direct messages with an ID greater than (that is, more recent than) the specified ID. since narrows the returned results to just those statuses created after the specified date/time (up to 24 hours old). page specifies which page you want to return. new() sends a new direct message to the specified user from the authenticating user. Requires both the user and text parameters below.
destroy() destroys the direct message specified in the required id parameter. The authenticating user must be the recipient of the specified direct message.
Friendship Methods
create() befriends the user specified in the id parameter with the authenticating user.
destroy() discontinues friendship with the user specified in the id parameter and the authenticating user.
1129
Zend_Service
$twitter $response
exists() tests if a friendship exists between the user specified in the id parameter and the authenticating user.
Favorite Methods
favorites() returns the 20 most recent favorite statuses for the authenticating user or user specified by the id parameter.
The favorites() method accepts an array of optional parameters to modify the query. id specifies the ID or screen name of the user for whom to request a list of favorite statuses. page specifies which page you want to return. create() favorites the status specified in the id parameter as the authenticating user.
destroy() un-favorites the status specified in the id parameter as the authenticating user.
Block Methods
exists() checks if the authenticating user is blocking a target user and can optionally return the blocked user's object if a block does exists.
1130
Zend_Service
// returns true or false $response = $twitter->block->exists('blockeduser'); // returns the blocked user's info if the user is blocked $response2 = $twitter->block->exists('blockeduser', true); The favorites() method accepts a second optional parameter. returnResult specifies whether or not return the user object instead of just true or false. create() blocks the user specified in the id parameter as the authenticating user and destroys a friendship to the blocked user if one exists. Returns the blocked user in the requested format when successful.
destroy() un-blocks the user specified in the id parameter for the authenticating user. Returns the un-blocked user in the requested format when successful.
blocking() returns an array of user objects that the authenticating user is blocking.
Zend_Service_Twitter_Search
Introduction
Zend_Service_Twitter_Search provides a client for the Twitter Search API [http://apiwiki.twitter.com/ Search+API+Documentation]. The Twitter Search service is use to search Twitter. Currently, it only returns data in Atom or JSON format, but a full REST service is in the future, which will support XML responses.
1131
Zend_Service
Twitter Trends
Returns the top ten queries that are currently trending on Twitter. The response includes the time of the request, the name of each trending topic, and the url to the Twitter Search results page for that topic. Currently the search API for trends only supports a JSON return so the function returns an array.
$twitterSearch $twitterTrends
foreach ($twitterTrends as $trend) { print $trend['name'] . ' - ' . $trend['url'] . PHP_EOL } The return array has two values in it: name is the name of trend. url is the URL to see the tweets for that trend.
Searching Twitter
Using the search method returns tweets that match a specific query. There are a number of Search Operators [http:// search.twitter.com/operators] that you can use to query with. The search method can accept six different optional URL parameters passed in as an array: lang restricts the tweets to a given language. lang must be given by an ISO 639-1 code [http://en.wikipedia.org/ wiki/ISO_639-1]. rpp is the number of tweets to return per page, up to a maximum of 100. page specifies the page number to return, up to a maximum of roughly 1500 results (based on rpp * page). since_id returns tweets with status IDs greater than the given ID. show_user specifies whether to add ">user<:" to the beginning of the tweet. This is useful for readers that do not display Atom's author field. The default is "false". geocode returns tweets by users located within a given radius of the given latitude/longitude, where the user's location is taken from their Twitter profile. The parameter value is specified by "latitude,longitude,radius", where radius units must be specified as either "mi" (miles) or "km" (kilometers).
$twitterSearch $searchResults
1132
Zend_Service
$twitterSearch $searchResults
Zend_Service_Yahoo
Introduction
Zend_Service_Yahoo is a simple API for using many of the Yahoo! REST APIs. Zend_Service_Yahoo allows you to search Yahoo! Web search, Yahoo! News, Yahoo! Local, Yahoo! Images. In order to use the Yahoo! REST API, you must have a Yahoo! Application ID. To obtain an Application ID, please complete and submit the Application ID Request Form [http://developer.yahoo.com/wsregapp/].
1133
Zend_Service
1134
Zend_Service
Zend_Service_Yahoo Classes
The following classes are all returned by the various Yahoo! searches. Each search type returns a type-specific result set which can be easily iterated, with each result being contained in a type result object. All result set classes implement the SeekableIterator interface, allowing for easy iteration and seeking to a specific result. Zend_Service_Yahoo_ResultSet Zend_Service_Yahoo_WebResultSet Zend_Service_Yahoo_ImageResultSet Zend_Service_Yahoo_VideoResultSet Zend_Service_Yahoo_LocalResultSet Zend_Service_Yahoo_NewsResultSet Zend_Service_Yahoo_InlinkDataResultSet Zend_Service_Yahoo_PageDataResultSet Zend_Service_Yahoo_Result Zend_Service_Yahoo_WebResult Zend_Service_Yahoo_ImageResult Zend_Service_Yahoo_VideoResult Zend_Service_Yahoo_LocalResult Zend_Service_Yahoo_NewsResult Zend_Service_Yahoo_InlinkDataResult Zend_Service_Yahoo_PageDataResult
1135
Zend_Service
Zend_Service_Yahoo_Image
Zend_Service_Yahoo_ResultSet
Each of the search specific result sets is extended from this base class. Each of the specific result sets returns a search specific Zend_Service_Yahoo_Result objects.
Zend_Service_Yahoo_ResultSet::totalResults()
int totalResults(); Returns the number of results returned for the search.
Zend_Service_Yahoo_WebResultSet
Zend_Service_Yahoo_WebResultSet represents a Yahoo! Web Search result set.
Nota
Zend_Service_Yahoo_WebResultSet extends Zend_Service_Yahoo_ResultSet Back to Class List
Zend_Service_Yahoo_ImageResultSet
Zend_Service_Yahoo_ImageResultSet represents a Yahoo! Image Search result set.
Nota
Zend_Service_Yahoo_ImageResultSet extends Zend_Service_Yahoo_ResultSet Back to Class List
Zend_Service_Yahoo_VideoResultSet
Zend_Service_Yahoo_VideoResultSet represents a Yahoo! Video Search result set.
Nota
Zend_Service_Yahoo_VideoResultSet extends Zend_Service_Yahoo_ResultSet
1136
Zend_Service
Zend_Service_Yahoo_LocalResultSet
Zend_Service_Yahoo_LocalResultSet represents a Yahoo! Local Search result set.
Nota
Zend_Service_Yahoo_LocalResultSet extends Zend_Service_Yahoo_ResultSet Back to Class List
Zend_Service_Yahoo_NewsResultSet
Zend_Service_Yahoo_NewsResultSet represents a Yahoo! News Search result set.
Nota
Zend_Service_Yahoo_NewsResultSet extends Zend_Service_Yahoo_ResultSet Back to Class List
Zend_Service_Yahoo_InlinkDataResultSet
Zend_Service_Yahoo_InlinkDataResultSet represents a Yahoo! Inbound Link Search result set.
Nota
Zend_Service_Yahoo_InlinkDataResultSet extends Zend_Service_Yahoo_ResultSet Back to Class List
Zend_Service_Yahoo_PageDataResultSet
Zend_Service_Yahoo_PageDataResultSet represents a Yahoo! PageData Search result set.
Nota
Zend_Service_Yahoo_PageDataResultSet extends Zend_Service_Yahoo_ResultSet Back to Class List
Zend_Service_Yahoo_Result
Each of the search specific results is extended from this base class.
1137
Zend_Service
Zend_Service_Yahoo_WebResult
Each Web Search result is returned as a Zend_Service_Yahoo_WebResult object.
Zend_Service_Yahoo_ImageResult
Each Image Search result is returned as a Zend_Service_Yahoo_ImageResult object.
1138
Zend_Service
Type Zend_Service_Yahoo_Image
Zend_Service_Yahoo_VideoResult
Each Video Search result is returned as a Zend_Service_Yahoo_VideoResult object.
Zend_Service_Yahoo_LocalResult
Each Local Search result is returned as a Zend_Service_Yahoo_LocalResult object.
1139
Zend_Service
Description A URL of a map for the result The URL for the business website, if known The URL for linking to the business website, if known
Zend_Service_Yahoo_NewsResult
Each News Search result is returned as a Zend_Service_Yahoo_NewsResult object.
Zend_Service_Yahoo_InlinkDataResult
Each Inbound Link Search result is returned as a Zend_Service_Yahoo_InlinkDatabResult object. Back to Class List
Zend_Service_Yahoo_PageDataResult
Each Page Data Search result is returned as a Zend_Service_Yahoo_PageDatabResult object. Back to Class List
Zend_Service_Yahoo_Image
All images returned either by the Yahoo! Image Search or the Yahoo! News Search are represented by Zend_Service_Yahoo_Image objects
1140
Zend_Service
1141
1142
Basic Usage
Zend_Session_Namespace instances provide the primary API for manipulating session data in the Zend Framework. Namespaces are used to segregate all session data, although a default namespace exists for those who only want one namespace for all their session data. Zend_Session utilizes ext/session and its special $_SESSION superglobal as the storage mechanism for session state data. While $_SESSION is still available in PHP's global namespace, developers should refrain from directly accessing it, so that Zend_Session and Zend_Session_Namespace can most effectively and securely provide its suite of session related functionality. Each instance of Zend_Session_Namespace corresponds to an entry of the $_SESSION superglobal array, where the namespace is used as the key. $myNamespace = new Zend_Session_Namespace('myNamespace');
1143
Zend_Session
// $myNamespace corresponds to $_SESSION['myNamespace'] It is possible to use Zend_Session in conjunction with other code that uses $_SESSION directly. To avoid problems, however, it is highly recommended that such code only uses parts of $_SESSION that do not correspond to instances of Zend_Session_Namespace.
Tutorial Ejemplos
If no namespace is specified when instantiating Zend_Session_Namespace, all data will be transparently stored in a namespace called "Default". Zend_Session is not intended to work directly on the contents of session namespace containers. Instead, we use Zend_Session_Namespace. The example below demonstrates use of this default namespace, showing how to count the number of client requests during a session:
1144
Zend_Session
Advanced Usage
While the basic usage examples are a perfectly acceptable way to utilize Zend Framework sessions, there are some best practices to consider. This section discusses the finer details of session handling and illustrates more advanced usage of the Zend_Session component.
Starting a Session
If you want all requests to have a session facilitated by Zend_Session, then start the session in the bootstrap file:
1145
Zend_Session
By starting the session in the bootstrap file, you avoid the possibility that your session might be started after headers have been sent to the browser, which results in an exception, and possibly a broken page for website viewers. Various advanced features require Zend_Session::start() first. (More on advanced features later.) There are four ways to start a session, when using Zend_Session. Two are wrong. 1. Wrong: Do not enable PHP's session.auto_start setting [http://www.php.net/manual/en/ ref.session.php#ini.session.auto-start]. If you do not have the ability to disable this setting in php.ini, you are using mod_php (or equivalent), and the setting is already enabled in php.ini, then add the following to your .htaccess file (usually in your HTML document root directory):
php_value session.auto_start 0 2. Wrong: Do not use PHP's session_start() [http://www.php.net/session_start] function directly. If you use session_start() directly, and then start using Zend_Session_Namespace, an exception will be thrown by Zend_Session::start() ("session has already been started"). If you call session_start() after using Zend_Session_Namespace or calling Zend_Session::start(), an error of level E_NOTICE will be generated, and the call will be ignored. 3. Correct: Use Zend_Session::start(). If you want all requests to have and use sessions, then place this function call early and unconditionally in your bootstrap code. Sessions have some overhead. If some requests need sessions, but other requests will not need to use sessions, then: Unconditionally set the strict option to TRUE using Zend_Session::setOptions() in your bootstrap. Call Zend_Session::start() only for requests that need to use sessions and before any Zend_Session_Namespace objects are instantiated. Use "new Zend_Session_Namespace()" normally, Zend_Session::start() has been called previously. where needed, but make sure
The strict option prevents new Zend_Session_Namespace() from automatically starting the session using Zend_Session::start(). Thus, this option helps application developers enforce a design decision to avoid using sessions for certain requests, since it causes an exception to be thrown when Zend_Session_Namespace is instantiated before Zend_Session::start() is called. Developers should carefully consider the impact of using Zend_Session::setOptions(), since these options have global effect, owing to their correspondence to the underlying options for ext/session. 4. Correct: Just instantiate Zend_Session_Namespace whenever needed, and the underlying PHP session will be automatically started. This offers extremely simple usage that works well in most situations. However, you then become responsible for ensuring that the first new Zend_Session_Namespace() happens before any output (e.g., HTTP headers [http://www.php.net/headers_sent]) has been sent by PHP to the client, if you are using the default, cookie-based sessions (strongly recommended). See the section called Error: Headers Already Sent for more information.
1146
Zend_Session
Namespace Expiration
Limits can be placed on the longevity of both namespaces and individual keys in namespaces. Common use cases include passing temporary information between requests, and reducing exposure to certain security risks by removing access to potentially sensitive information some time after authentication occurred. Expiration can be based on either elapsed seconds or the number of "hops", where a hop occurs for each successive request.
1147
Zend_Session
// ... // in the question view controller $testSpace = new Zend_Session_Namespace('testSpace'); // expire only this variable $testSpace->setExpirationSeconds(300, 'accept_answer'); $testSpace->accept_answer = true; //... Below, the controller that processes the answers to test questions determines whether or not to accept an answer based on whether the user submitted the answer within the allotted time:
// ... // in the answer processing controller $testSpace = new Zend_Session_Namespace('testSpace'); if ($testSpace->accept_answer === true) { // within time } else { // not within time } // ...
1148
Zend_Session
echo 'Cannot instantiate this namespace since ' . '$authSpaceAccessor2 was created\n'; } The second parameter in the constructor above tells Zend_Session_Namespace that any future instances with the "Zend_Auth" namespace are not allowed. Attempting to create such an instance causes an exception to be thrown by the constructor. The developer therefore becomes responsible for storing a reference to an instance object ($authSpaceAccessor1, $authSpaceAccessor2, or $authSpaceAccessor3 in the example above) somewhere, if access to the session namespace is needed at a later time during the same request. For example, a developer may store the reference in a static variable, add the reference to a registry [http://www.martinfowler.com/ eaaCatalog/registry.html] (see Captulo 44, Zend_Registry), or otherwise make it available to other methods that may need access to the session namespace.
1149
Zend_Session
// modfiy the array copy $tmp['fruit'] = 'peach'; // assign a copy of the array back to the session namespace $sessionNamespace->array = $tmp; echo $sessionNamespace->array['fruit']; // prints "peach"
1150
Zend_Session
$s->setExpirationSeconds(5); Zend_Session::regenerateId(); $id = Zend_Session::getId(); session_write_close(); // release session so process below can use it sleep(4); // not long enough for things to expire exec($script . "expireAll $id expireAll", $result); $result = $this->sortResult($result); $expect = ';a === apple;o === orange;p === pear'; $this->assertTrue($result === $expect, "iteration over default Zend_Session namespace failed; " . "expecting result === '$expect', but got '$result'"); sleep(2); // long enough for things to expire (total of 6 seconds // waiting, but expires in 5) exec($script . "expireAll $id expireAll", $result); $result = array_pop($result); $this->assertTrue($result === '', "iteration over default Zend_Session namespace failed; " . "expecting result === '', but got '$result')"); session_start(); // resume artificially suspended session // We could split this into a separate test, but actually, if anything // leftover from above contaminates the tests below, that is also a // bug that we want to know about. $s = new Zend_Session_Namespace('expireGuava'); $s->setExpirationSeconds(5, 'g'); // now try to expire only 1 of the // keys in the namespace $s->g = 'guava'; $s->p = 'peach'; $s->p = 'plum'; session_write_close(); // release session so process below can use it sleep(6); // not long enough for things to expire exec($script . "expireAll $id expireGuava", $result); $result = $this->sortResult($result); session_start(); // resume artificially suspended session $this->assertTrue($result === ';p === plum', "iteration over named Zend_Session namespace failed (result=$result)");
Configuration Options
When the first session namespace is requested, Zend_Session will automatically start the PHP session, unless already started with Zend_Session::start(). The underlying PHP session will use defaults from Zend_Session, unless modified first by Zend_Session::setOptions().
1151
Zend_Session
To set a session configuration option, include the basename (the part of the name after "session.") as a key of an array passed to Zend_Session::setOptions(). The corresponding value in the array is used to set the session option value. If no options are set by the developer, Zend_Session will utilize recommended default options first, then the default php.ini settings. Community feedback about best practices for these options should be sent to fwauth@lists.zend.com [mailto:fw-auth@lists.zend.com].
1152
Zend_Session
$config = new Zend_Config_Ini('myapp.ini', 'development'); Zend_Session::setOptions($config->toArray()); Most options shown above need no explanation beyond that found in the standard PHP documentation, but those of particular interest are noted below. boolean strict - disables Zend_Session_Namespace(). automatic starting of Zend_Session when using new
integer remember_me_seconds - how long should session id cookie persist, after user agent has ended (e.g., browser application terminated). string save_path - The correct value is system dependent, and should be provided by the developer using an absolute path to a directory readable and writable by the PHP process. If a writable path is not supplied, then Zend_Session will throw an exception when started (i.e., when start() is called).
Security Risk
If the path is readable by other applications, then session hijacking might be possible. If the path is writable by other applications, then session poisoning [http://en.wikipedia.org/wiki/Session_poisoning] might be possible. If this path is shared with other users or other PHP applications, various security issues might occur, including theft of session content, hijacking of sessions, and collision of garbage collection (e.g., another user's application might cause PHP to delete your application's session files). For example, an attacker can visit the victim's website to obtain a session cookie. Then, he edits the cookie path to his own domain on the same server, before visiting his own website to execute var_dump($_SESSION). Armed with detailed knowledge of the victim's use of data in their sessions, the attacker can then modify the session state (poisoning the session), alter the cookie path back to the victim's website, and then make requests from the victim's website using the poisoned session. Even if two applications on the same server do not have read/write access to the other application's save_path, if the save_path is guessable, and the attacker has control over one of these two websites, the attacker could alter their website's save_path to use the other's save_path, and thus accomplish session poisoning, under some common configurations of PHP. Thus, the value for save_path should not be made public knowledge and should be altered to a secure location unique to each application. string name - The correct value is system dependent and should be provided by the developer using a value unique to the application.
Security Risk
If the php.ini setting for session.name is the same (e.g., the default "PHPSESSID"), and there are two or more PHP applications accessible through the same domain name then they will share the same session data for visitors to both websites. Additionally, possible corruption of session data may result. boolean use_only_cookies - In order to avoid introducing additional security risks, do not alter the default value of this option.
Security Risk
If this setting is not enabled, an attacker can easily fix victim's session ids, using links on the attacker's website, such as http://www.example.com/index.php?PHPSESSID=fixed_session_id. The fixation works, if the victim does not already have a session id cookie for example.com. Once a victim is using a known session id, the attacker can then attempt to hijack the session by pretending to be the victim, and emulating the victim's user agent.
1153
Zend_Session
Session Identifiers
Introduction: Best practice in relation to using sessions with Zend Framework calls for using a browser cookie (i.e. a normal cookie stored in your web browser), instead of embedding a unique session identifier in URLs as a means to track individual users. By default this component uses only cookies to maintain session identifiers. The cookie's value is the unique identifier of your browser's session. PHP's ext/session uses this identifier to maintain a unique one-to-one relationship between website visitors, and persistent session data storage unique to each visitor. Zend_Session* wraps this storage mechanism ($_SESSION) with an object-oriented interface. Unfortunately, if an attacker gains access to the value of the cookie (the session id), an attacker might be able to hijack a visitor's session. This problem is not unique to PHP, or Zend Framework. The regenerateId() method allows an application to change the session id (stored in the visitor's cookie) to a new, random, unpredictable value. Note: Although not the same, to make this section easier to read, we use the terms "user agent" and "web browser" interchangeably. Why?: If an attacker obtains a valid session identifier, an attacker might be able to impersonate a valid user (the victim), and then obtain access to confidential information or otherwise manipulate the victim's data managed by your application. Changing session ids helps protect against session hijacking. If the session id is changed, and an attacker does not know the new value, the attacker can not use the new session id in their attempts to hijack the visitor's session. Even if an attacker gains access to an old session id, regenerateId() also moves the session data from the old session id "handle" to the new one, so no data remains accessible via the old session id. When to use regenerateId(): Adding Zend_Session::regenerateId() to your Zend Framework bootstrap yields one of the safest and most secure ways to regenerate session id's in user agent cookies. If there is no conditional logic to determine when to regenerate the session id, then there are no flaws in that logic. Although regenerating on every request prevents several possible avenues of attack, not everyone wants the associated small performance and bandwidth cost. Thus, applications commonly try to dynamically determine situations of greater risk, and only regenerate the session ids in those situations. Whenever a website visitor's session's privileges are "escalated" (e.g.
1154
Zend_Session
a visitor re-authenticates their identity before editing their personal "profile"), or whenever a security "sensitive" session parameter change occurs, consider using regenerateId() to create a new session id. If you call the rememberMe() function, then don't use regenerateId(), since the former calls the latter. If a user has successfully logged into your website, use rememberMe() instead of regenerateId().
1155
Zend_Session
rememberMe(integer $seconds)
Ordinarily, sessions end when the user agent terminates, such as when an end user exits a web browser program. However, your application may provide the ability to extend user sessions beyond the lifetime of the client program through the use of persistent cookies. Use Zend_Session::rememberMe() before a session is started to control the length of time before a persisted session cookie expires. If you do not specify a number of seconds, then the session cookie lifetime defaults to remember_me_seconds, which may be set using Zend_Session::setOptions(). To help thwart session fixation/hijacking, use this function when a user successfully authenticates with your application (e.g., from a "login" form).
forgetMe()
This function complements rememberMe() by writing a session cookie that has a lifetime ending when the user agent terminates.
sessionExists()
Use this method to determine if a session already exists for the current user agent/request. It may be used before starting a session, and independently of all other Zend_Session and Zend_Session_Namespace methods.
Throws
By default, $readonly is enabled and further actions involving writing to the session data store will throw an exception.
stop()
This method does absolutely nothing more than toggle a flag in Zend_Session to prevent further writing to the session data store. We are specifically requesting feedback on this feature. Potential uses/abuses might include temporarily disabling the use of Zend_Session_Namespace instances or Zend_Session methods to write to the session data store, while execution is transferred to view- related code. Attempts to perform actions involving writes via these instances or methods will throw an exception.
writeClose($readonly = true)
Shutdown the session, close writing and detach $_SESSION from the back-end storage mechanism. This will complete the internal data transformation on this request. The optional $readonly boolean parameter can
1156
Zend_Session
remove write access by throwing an exception upon any attempt to write to the session via Zend_Session or Zend_Session_Namespace.
Throws
By default, $readonly is enabled and further actions involving writing to the session data store will throw an exception. However, some legacy application might expect $_SESSION to remain writable after ending the session via session_write_close(). Although not considered "best practice", the $readonly option is available for those who need it.
expireSessionCookie()
This method sends an expired session id cookie, causing the client to delete the session cookie. Sometimes this technique is used to perform a client-side logout.
setSaveHandler(Zend_Session_SaveHandler_Interface $interface)
Most developers will find the default save handler sufficient. This method provides an object-oriented wrapper for session_set_save_handler() [http://php.net/session_set_save_handler].
namespaceIsset($namespace)
Use this method to determine if a session namespace exists, or if a particular index exists in a particular namespace.
Throws
An exception will be thrown if Zend_Session is not marked as readable (e.g., before Zend_Session has been started).
namespaceUnset($namespace)
Use Zend_Session::namespaceUnset($namespace) to efficiently remove an entire namespace and its contents. As with all arrays in PHP, if a variable containing an array is unset, and the array contains other objects, those objects will remain available, if they were also stored by reference in other array/objects that remain accessible via other variables. So namespaceUnset() does not perform a "deep" unsetting/deleting of the contents of the entries in the namespace. For a more detailed explanation, please see References Explained [http://php.net/references] in the PHP manual.
Throws
An exception will be thrown if the namespace is not writable (e.g., after destroy()).
namespaceGet($namespace)
DEPRECATED: Use getIterator() in Zend_Session_Namespace. This method returns an array of the contents of $namespace. If you have logical reasons to keep this method publicly accessible, please provide feedback to the fw-auth@lists.zend.com [mailto:fw-auth@lists.zend.com] mail list. Actually, all participation on any relevant topic is welcome :)
1157
Zend_Session
Throws
An exception will be thrown if Zend_Session is not marked as readable (e.g., before Zend_Session has been started).
getIterator()
Use getIterator() to obtain an array containing the names of all namespaces.
Throws
An exception will be thrown if Zend_Session is not marked as readable (e.g., before Zend_Session has been started).
Zend_Session_SaveHandler_DbTable
The basic setup for Zend_Session_SaveHandler_DbTable must at least have four columns, denoted in the config array or Zend_Config object: primary, which is the primary key and defaults to just the session id which by default is a string of length 32; modified, which is the unix timestamp of the last modified date; lifetime, which is the lifetime of the session (modified + lifetime > time();); and data, which is the serialized data stored in the session
//get your database connection ready $db = Zend_Db::factory('Pdo_Mysql', array( 'host' =>'example.com', 'username' => 'dbuser', 'password' => '******', 'dbname' => 'dbname' )); //you can either set the Zend_Db_Table default adapter //or you can pass the db connection straight to the save handler $config Zend_Db_Table_Abstract::setDefaultAdapter($db); $config = array( 'name' => 'session', 'primary' => 'id', 'modifiedColumn' => 'modified', 'dataColumn' => 'data', 'lifetimeColumn' => 'lifetime' ); //create your Zend_Session_SaveHandler_DbTable and
1158
Zend_Session
//set the save handler for Zend_Session Zend_Session::setSaveHandler(new Zend_Session_SaveHandler_DbTable($config)); //start your session! Zend_Session::start(); //now you can use Zend_Session like any other time You can also use Multiple Columns in your primary key for Zend_Session_SaveHandler_DbTable.
//setup your DB connection like before //NOTE: this config is also passed to Zend_Db_Table so anything specific //to the table can be put in the config as well $config = array( 'name' => 'session', //table name as per Zend_Db_Table 'primary' => array( 'session_id', //the sessionID given by PHP 'save_path', //session.save_path 'name', //session name ), 'primaryAssignment' => array( //you must tell the save handler which columns you //are using as the primary key. ORDER IS IMPORTANT 'sessionId', //first column of the primary key is of the sessionID 'sessionSavePath', //second column of the primary key is the save path 'sessionName', //third column of the primary key is the session name ), 'modifiedColumn' => 'modified', //time the session should expire 'dataColumn' => 'session_data', //serialized data 'lifetimeColumn' => 'lifetime', //end of life for a specific record ); //Tell Zend_Session to use your Save Handler Zend_Session::setSaveHandler(new Zend_Session_SaveHandler_DbTable($config)); //start your session Zend_Session::start(); //use Zend_Session as normal
1159
1160
Zend_Soap_Server constructor
Zend_Soap_Server constructor should be used a bit differently for WSDL and non-WSDL modes.
1161
Zend_Soap
The following options are recognized in the non-WSDL mode: 'soap_version' ('soapVersion') - soap version to use (SOAP_1_1 or SOAP_1_2). 'actor' - the actor URI for the server. 'classmap' ('classMap') which can be used to map some WSDL types to PHP classes. The option must be an array with WSDL types as keys and names of PHP classes as values. 'encoding' - internal character encoding (UTF-8 is always used as an external encoding). 'uri' (required) - URI namespace for SOAP server.
... class MyClass { /** * This method takes ... * * @param integer $inputParam * @return string */ public function method1($inputParam) { ... } /** * This method takes ... * * @param integer $inputParam1 * @param string $inputParam2 * @return float */ public function method2($inputParam1, $inputParam2) { ... } ... } ... $server = new Zend_Soap_Server(null, $options); // Bind Class to Soap Server $server->setClass('MyClass'); // Bind already initialized object to Soap Server $server->setObject(new MyClass()); ... $server->handle();
1162
Zend_Soap
Important!
You should completely describe each method using method docblock if you plan to use autodiscover functionality to prepare corresponding Web Service WSDL. The second method of defining Web Service API is using set of functions and addFunction() or loadFunctions() methods:
... /** * This function ... * * @param integer $inputParam * @return string */ function function1($inputParam) { ... } /** * This function ... * * @param integer $inputParam1 * @param string $inputParam2 * @return float */ function function2($inputParam1, $inputParam2) { ... } ... $server = new Zend_Soap_Server(null, $options); $server->addFunction('function1'); $server->addFunction('function2'); ... $server->handle();
Request processing
Zend_Soap_Server::handle() method takes request from the standard input stream ('php://input'). It may be overridden either by supplying optional parameter to the handle() method or by setting request using setRequest() method:
...
1163
Zend_Soap
$server = new Zend_Soap_Server(...); ... // Set request using optional $request parameter $server->handle($request); ... // Set request using setRequest() method $server->setRequest(); $server->handle(); Request object may be represented using any of the following: DOMDocument (casted to XML) DOMNode (owner document is grabbed and casted to XML) SimpleXMLElement (casted to XML) stdClass (__toString() is called and verified to be valid XML) string (verified to be valid XML) Last processed request may be retrieved using getLastRequest() method as an XML string:
Response pre-processing
Zend_Soap_Server::handle() method automatically emits generated response to the output stream. It may be blocked using setReturnResponse() with TRUE or FALSE as a parameter4. Generated response is returned by handle() method in this case.
... $server = new Zend_Soap_Server(...); ... // Get a response as a return value of handle() method // instead of emitting it to the standard output $server->setReturnResponse(true); ... $response = $server->handle(); ... Last response may be also retrieved by getLastResponse() method for some post-processing:
Current state of the Return Response flag may be requested with setReturnResponse() method.
1164
Zend_Soap
Zend_Soap_Client
The Zend_Soap_Client class simplifies SOAP client development for PHP programmers. It may be used in WSDL or non-WSDL mode. Under the WSDL mode, the Zend_Soap_Client component uses a WSDL document to define transport layer options. The WSDL description is usually provided by the web service the client will access. If the WSDL description is not made available, you may want to use Zend_Soap_Client in non-WSDL mode. Under this mode, all SOAP protocol options have to be set explicitly on the Zend_Soap_Client class.
Zend_Soap_Client Constructor
The Zend_Soap_Client constructor takes two parameters: $wsdl - the URI of a WSDL file. $options - options to create SOAP client object. Both of these parameters may be set later using setWsdl($wsdl) and setOptions($options) methods respectively.
Important!
If you use Zend_Soap_Client component in non-WSDL mode, you must set the 'location' and 'uri' options. The following options are recognized: 'soap_version' ('soapVersion') - soap version to use (SOAP_1_1 or SOAP_1_2). 'classmap' ('classMap') - can be used to map some WSDL types to PHP classes. The option must be an array with WSDL types as keys and names of PHP classes as values. 'encoding' - internal character encoding (UTF-8 is always used as an external encoding). 'wsdl' which is equivalent to setWsdl($wsdlValue) call. Changing this option may switch Zend_Soap_Client object to or from WSDL mode. 'uri' - target namespace for the SOAP service (required for non-WSDL-mode, doesn't work for WSDL mode). 'location' - the URL to request (required for non-WSDL-mode, doesn't work for WSDL mode). 'style' - request style (doesn't work for WSDL mode): SOAP_RPC or SOAP_DOCUMENT. 'use' - method to encode messages (doesn't work for WSDL mode): SOAP_ENCODED or SOAP_LITERAL. 'login' and 'password' - login and password for an HTTP authentication.
1165
Zend_Soap
'proxy_host', 'proxy_port', 'proxy_login', and 'proxy_password' - an HTTP connection through a proxy server. 'local_cert' and 'passphrase' - HTTPS client certificate authentication options. 'compression' - compression options; it's a combination of SOAP_COMPRESSION_ACCEPT, SOAP_COMPRESSION_GZIP and SOAP_COMPRESSION_DEFLATE options which may be used like this: // Accept response compression $client = new Zend_Soap_Client("some.wsdl", array('compression' => SOAP_COMPRESSION_ACCEPT)); ... // Compress requests using gzip with compression level 5 $client = new Zend_Soap_Client("some.wsdl", array('compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | 5)); ... // Compress requests using deflate compression $client = new Zend_Soap_Client("some.wsdl", array('compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_DEFLATE));
1166
Zend_Soap
// } // // ... // } // ... // $server = new Zend_Soap_Server(null, $options); // $server->setClass('MyClass'); // ... // $server->handle(); // //**************************************************************** // End of server code //**************************************************************** $client = new Zend_Soap_Client("MyService.wsdl"); ... // $result1 is a string $result1 = $client->method1(10); ... // $result2 is a float $result2 = $client->method2(22, 'some string');
WSDL Accessor
Nota
Zend_Soap_Wsdl class is used by Zend_Soap_Server component internally to operate with WSDL documents. Nevertheless, you could also use functionality provided by this class for your own needs. The Zend_Soap_Wsdl package contains both a parser and a builder of WSDL documents. If you don't plan to do this, you can skip this documentation section.
Zend_Soap_Wsdl constructor
Zend_Soap_Wsdl constructor takes three parameters: 1. $name - name of the Web Service being described. 2. $uri - URI where the WSDL will be available (could also be a reference to the file in the filesystem.) 3. $strategy - optional flag used to identify the strategy for complex types (objects) detection. This was a boolean $extractComplexTypes before version 1.7 and can still be set as a boolean for backwards compatibility. By default the 1.6 detection behaviour is set. To read more on complex type detection strategies go to the section: the section called Adding complex type information.
addMessage() method
addMessage($name, $parts) method adds new message description to the WSDL document (/definitions/ message element). Each message correspond to methods in terms of Zend_Soap_Server and Zend_Soap_Client functionality.
1167
Zend_Soap
$name parameter represents message name. $parts parameter is an array of message parts which describe SOAP call parameters. It's an associative array: 'part name' (SOAP call parameter name) => 'part type'. Type mapping management is performed using addTypes(), addTypes() and addComplexType() methods (see below).
Nota
Messages parts can use either 'element' or 'type' attribute for typing (see http://www.w3.org/TR/ wsdl#_messages). 'element' attribute must refer to a corresponding element of data type definition. 'type' attribute refers to a corresponding complexType entry. All standard XSD types have both 'element' and 'complexType' definitions (see http://schemas.xmlsoap.org/ soap/encoding/). All non-standard types, which may be added using Zend_Soap_Wsdl::addComplexType() method, are described using 'complexType' node of '/definitions/types/schema/' section of WSDL document. So addMessage() method always uses 'type' attribute to describe types.
addPortType() method
addPortType($name) method adds new port type to the WSDL document (/definitions/portType) with the specified port type name. It joins a set of Web Service methods defined in terms of Zend_Soap_Server implementation. See http://www.w3.org/TR/wsdl#_porttypes for the details.
addPortOperation() method
addPortOperation($portType, $name, $input = false, $output = false, $fault = false) method adds new port operation to the specified port type of the WSDL document (/definitions/portType/ operation). Each port operation corresponds to a class method (if Web Service is based on a class) or function (if Web Service is based on a set of methods) in terms of Zend_Soap_Server implementation. It also adds corresponding port operation messages depending on specified $input, $output and $fault parameters.
Nota
Zend_Soap_Server component generates two messages for each port operation while describing service based on Zend_Soap_Server class: input message with name $methodName . 'Request'. output message with name $methodName . 'Response'. See http://www.w3.org/TR/wsdl#_request-response for the details.
1168
Zend_Soap
addBinding() method
addBinding($name, $portType) method adds new binding to the WSDL document (/definitions/binding). 'binding' WSDL document node defines message format and protocol details for operations and messages defined by a particular portType (see http://www.w3.org/TR/wsdl#_bindings). The method creates binding node and returns it. Then it may be used to fill with actual data. Zend_Soap_Server implementation uses $serviceName . 'Binding' name for 'binding' element of WSDL document.
addBindingOperation() method
addBindingOperation($binding, $name, $input = false, $output = false, $fault = false) method adds an operation to a binding element (/definitions/binding/operation) with the specified name. It takes XML_Tree_Node object returned by addBinding() as an input ($binding parameter) to add 'operation' element with input/output/false entries depending on specified parameters Zend_Soap_Server implementation adds corresponding binding entry for each Web Service method with input and output entries defining 'soap:body' element as '<soap:body use="encoded" encodingStyle="http:// schemas.xmlsoap.org/soap/encoding/"/> See http://www.w3.org/TR/wsdl#_bindings for the details.
addSoapBinding() method
addSoapBinding($binding, $style = 'document', $transport = 'http:// schemas.xmlsoap.org/soap/http') method adds SOAP binding ('soap:binding') entry to the binding element (which is already linked to some port type) with the specified style and transport (Zend_Soap_Server implementation uses RPC style over HTTP). '/definitions/binding/soap:binding' element is used to signify that the binding is bound to the SOAP protocol format. See http://www.w3.org/TR/wsdl#_bindings for the details.
addSoapOperation() method
addSoapOperation($binding, $soap_action) method adds SOAP operation ('soap:operation') entry to the binding element with the specified action. 'style' attribute of the 'soap:operation' element is not used since programming model (RPC-oriented or document-oriented) may be using addSoapBinding() method 'soapAction' attribute of '/definitions/binding/soap:operation' element specifies the value of the SOAPAction header for this operation. This attribute is required for SOAP over HTTP and must not be specified for other transports. Zend_Soap_Server implementation uses $serviceUri . '#' . $methodName for SOAP operation action name. See http://www.w3.org/TR/wsdl#_soap:operation for the details.
addService() method
addService($name, $port_name, $binding, $location) method adds '/definitions/service' element to the WSDL document with the specified Wed Service name, port name, binding, and location.
1169
Zend_Soap
WSDL 1.1 allows to have several port types (sets of operations) per service. This ability is not used by Zend_Soap_Server implementation and not supported by Zend_Soap_Wsdl class. Zend_Soap_Server implementation uses: $name . 'Service' as a Web Service name, $name . 'Port' as a port type name, 'tns:' . $name . 'Binding' 5 as binding name, script URI6 as a service URI for Web Service definition using classes. where $name is a class name for the Web Service definition mode using class and script name for the Web Service definition mode using set of functions. See http://www.w3.org/TR/wsdl#_services for the details.
Type mapping
Zend_Soap WSDL accessor implementation uses the following type mapping between PHP and SOAP types: PHP strings <-> xsd:string. PHP integers <-> xsd:int. PHP floats and doubles <-> xsd:float. PHP booleans <-> xsd:boolean. PHP arrays <-> soap-enc:Array. PHP object <-> xsd:struct. PHP class <-> based on complex type strategy (See: the section called Adding complex type information) 7. PHP void <-> empty type. If type is not matched to any of these types by some reason, then xsd:anyType is used. Where xsd: is "http://www.w3.org/2001/XMLSchema" namespace, soap-enc: is a "http://schemas.xmlsoap.org/ soap/encoding/" namespace, tns: is a "target namespace" for a service.
... $wsdl = new Zend_Soap_Wsdl('My_Web_Service', $myWebServiceUri); ... $soapIntType = $wsdl->getType('int'); ... class MyClass { ...
1170
Zend_Soap
addDocumentation() method
addDocumentation($input_node, using optional 'wsdl:document' element. $documentation) method adds human readable documentation
1171
Zend_Soap
'/definitions/binding/soap:binding' element is used to signify that the binding is bound to the SOAP protocol format. See http://www.w3.org/TR/wsdl#_documentation for the details.
AutoDiscovery
AutoDiscovery Introduction
SOAP functionality implemented within Zend Framework is intended to make all steps required for SOAP communications more simple. SOAP is language independent protocol. So it may be used not only for PHP-to-PHP communications. There are three configurations for SOAP applications where Zend Framework may be utilized: 1. SOAP server PHP application <---> SOAP client PHP application 2. SOAP server non-PHP application <---> SOAP client PHP application 3. SOAP server PHP application <---> SOAP client non-PHP application We always have to know, which functionality is provided by SOAP server to operate with it. WSDL [http:// www.w3.org/TR/wsdl] is used to describe network service API in details. WSDL language is complex enough (see http://www.w3.org/TR/wsdl for the details). So it's difficult to prepare correct WSDL description. Another problem is synchronizing changes in network service API with already existing WSDL. Both these problem may be solved by WSDL autogeneration. A prerequisite for this is a SOAP server autodiscovery. It constructs object similar to object used in SOAP server application, extracts necessary information and generates correct WSDL using this information. There are two ways for using Zend Framework for SOAP server application: Use separated class. Use set of functions Both methods are supported by Zend Framework Autodiscovery functionality. TheZend_Soap_AutoDiscover class also supports datatypes mapping from PHP to XSD types [http:// www.w3.org/TR/xmlschema-2/]. Here is an example of common usage of the autodiscovery functionality. The handle() function generates the WSDL file and posts it to the browser.
1172
Zend_Soap
$autodiscover = new Zend_Soap_AutoDiscover(); $autodiscover->setClass('My_SoapServer_Class'); $autodiscover->handle(); If you need access to the generated WSDL file either to save it to a file or as an XML string you can use the dump($filename) or toXml() functions the AutoDiscover class provides.
if(isset($_GET['wsdl'])) { $autodiscover = new Zend_Soap_AutoDiscover(); $autodiscover->setClass('HelloWorldService'); $autodiscover->handle(); } else { // pointing to the current file here $soap = new Zend_Soap_Server("http://example.com/soap.php?wsdl"); $soap->setClass('HelloWorldService'); $soap->handle(); }
Class autodiscovering
If class is used to provide SOAP server functionality, then the same class should be provided to Zend_Soap_AutoDiscover for WSDL generation:
$autodiscover = new Zend_Soap_AutoDiscover(); $autodiscover->setClass('My_SoapServer_Class'); $autodiscover->handle(); The following rules are used while WSDL generation: Generated WSDL describes an RPC style Web Service. Class name is used as a name of the Web Service being described. 'http://' .$_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] is used as an URI where the WSDL is available by default but can be overwritten via setUri() method. It's also used as a target namespace for all service related names (including described complex types). Class methods are joined into one Port Type [http://www.w3.org/TR/wsdl#_porttypes]. $className . 'Port' is used as Port Type name. Each class method is registered as a corresponding port operation.
1173
Zend_Soap
Each method prototype generates corresponding Request/Response messages. Method may have several prototypes if some method parameters are optional.
Important!
WSDL autodiscovery utilizes the PHP docblocks provided by the developer to determine the parameter and return types. In fact, for scalar types, this is the only way to determine the parameter types, and for return types, this is the only way to determine them. That means, providing correct and fully detailed docblocks is not only best practice, but is required for discovered class.
Functions autodiscovering
If set of functions are used to provide SOAP server functionality, then the same set should be provided to Zend_Soap_AutoDiscovery for WSDL generation:
$autodiscover = new Zend_Soap_AutoDiscover(); $autodiscover->addFunction('function1'); $autodiscover->addFunction('function2'); $autodiscover->addFunction('function3'); ... $autodiscover->handle(); The following rules are used while WSDL generation: Generated WSDL describes an RPC style Web Service. Current script name is used as a name of the Web Service being described. 'http://' .$_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] is used as an URI where the WSDL is available. It's also used as a target namespace for all service related names (including described complex types). Functions are joined into one Port Type [http://www.w3.org/TR/wsdl#_porttypes]. $functionName . 'Port' is used as Port Type name. Each function is registered as a corresponding port operation. Each function prototype generates corresponding Request/Response messages. Function may have several prototypes if some method parameters are optional.
Important!
WSDL autodiscovery utilizes the PHP docblocks provided by the developer to determine the parameter and return types. In fact, for scalar types, this is the only way to determine the parameter types, and for return types, this is the only way to determine them. That means, providing correct and fully detailed docblocks is not only best practice, but is required for discovered class.
1174
Zend_Soap
Autodiscovering Datatypes
Input/output datatypes are converted into network service types using the following mapping: PHP strings <-> xsd:string. PHP integers <-> xsd:int. PHP floats and doubles <-> xsd:float. PHP booleans <-> xsd:boolean. PHP arrays <-> soap-enc:Array. PHP object <-> xsd:struct. PHP class <-> based on complex type strategy (See: the section called Adding complex type information) 8. type[] or object[] (ie. int[]) <-> based on complex type strategy PHP void <-> empty type. If type is not matched to any of these types by some reason, then xsd:anyType is used. Where xsd: is "http://www.w3.org/2001/XMLSchema" namespace, soap-enc: is a "http://schemas.xmlsoap.org/ soap/encoding/" namespace, tns: is a "target namespace" for a service.
$autodiscover = new Zend_Soap_AutoDiscover(); // Default is 'use' => 'encoded' and // 'encodingStyle' => 'http://schemas.xmlsoap.org/soap/encoding/' $autodiscover->setOperationBodyStyle( array('use' => 'literal', 'namespace' => 'http://framework.zend.com') ); // Default is 'style' => 'rpc' and // 'transport' => 'http://schemas.xmlsoap.org/soap/http' $autodiscover->setBindingStyle( array('style' => 'document', 'transport' => 'http://framework.zend.com') ); ... $autodiscover->addFunction('myfunc1'); $autodiscover->handle();
1175
1176
// Create the item list $list = new Zend_Tag_ItemList(); // Assign $list[] = $list[] = $list[] = tags to it new Zend_Tag_Item(array('title' => 'Code', 'weight' => 50)); new Zend_Tag_Item(array('title' => 'Zend Framework', 'weight' => 1)); new Zend_Tag_Item(array('title' => 'PHP', 'weight' => 5));
// Spread absolute values on the items $list->spreadWeightValues(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); // Output the items with their absolute values foreach ($list as $item) { printf("%s: %d\n", $item->getTitle(), $item->getParam('weightValue')); } This will output the three items Code, Zend Framework and PHP with the absolute values 10, 1 and 2.
Zend_Tag_Cloud
Zend_Tag_Cloud is the rendering part of Zend_Tag. By default it comes with a set of HTML decorators, which allow you to create tag clouds for a website, but also supplies you with two abstract classes to create your own decorators, to create tag clouds in PDF documents for example. You can instantiate and configure Zend_Tag_Cloud either programatically or completely via an array or an instance of Zend_Config. The available options are: cloudDecorator: defines the decorator for the cloud. Can either be the name of the class which should be loaded by the pluginloader, an instance of Zend_Tag_Cloud_Decorator_Cloud or an array containing the string decorator and optionally an array options, which will be passed to the decorators constructor.
1177
Zend_Tag
tagDecorator: defines the decorator for individual tags. This can either be the name of the class which should be loaded by the pluginloader, an instance of Zend_Tag_Cloud_Decorator_Tag or an array containing the string decorator and optionally an array options, which will be passed to the decorators constructor. pluginLoader: a different plugin loader Zend_Loader_PluginLoader_Interface. to use. Must be an instance of
prefixPath: prefix paths to add to the plugin loader. Must be an array containing the keys prefix and path or multiple arrays containing the keys prefix and path. Invalid elements will be skipped. itemList: a different item list to use. Must be an instance of Zend_Tag_ItemList. tags: a list of tags to assign to the cloud. Each tag must either implement Zend_Tag_Taggable or be an array which can be used to instantiate Zend_Tag_Item.
// Create the cloud and assign static tags to it $cloud = new Zend_Tag_Cloud(array( 'tags' => array( array('title' => 'Code', 'weight' => 50, 'params' => array('url' => '/tag/code')), array('title' => 'Zend Framework', 'weight' => 1, 'params' => array('url' => '/tag/zend-framework')), array('title' => 'PHP', 'weight' => 5, 'params' => array('url' => '/tag/php')), ) )); // Render the cloud echo $cloud; This will output the tag cloud with the three tags, spread with the default font-sizes.
Decorators
Zend_Tag_Cloud requires two types of decorators to be able to render a tag cloud. This includes a decorator which renders the single tags as well as a decorator which renders the surounding cloud. Zend_Tag_Cloud ships a default decorator set for formatting a tag cloud in HTML. This set will by default create a tag cloud as ul/li-list, spread with different font-sizes according to the weight values of the tags assigned to them.
URL parameter
As the HTML tag decorator always surounds the tag title with an anchor, you should define an URL parameter for every tag used in it.
1178
Zend_Tag
The tag decorator can either spread different font-sizes over the anchors or a defined list of classnames. When setting options for one of those possibilities, the corespondening one will automatically be enabled. The following configuration options are available: fontSizeUnit: defines the font-size unit used for all font-sizes. The possible values are: em, ex, px, in, cm, mm, pt, pc and %. minFontSize: the minimum font-size distributed through the tags (must be an integer). maxFontSize: the maximum font-size distributed through the tags (must be an integer). classList: an arry of classes distributed through the tags. htmlTags: an array of HTML tags surounding the anchor. Each element can either be a string, which is used as element type then, or an array containing an attribute list for the element, defined as key/value pair. In this case, the array key is used as element type.
1179
1180
Zend_Test_PHPUnit
Zend_Test_PHPUnit provides a TestCase for MVC applications that contains assertions for testing against a variety of responsibilities. Probably the easiest way to understand what it can do is to see an example.
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { public function setUp() { $this->bootstrap = array($this, 'appBootstrap'); parent::setUp(); } public function appBootstrap() { $this->frontController ->registerPlugin(new Bugapp_Plugin_Initialize('development')); } public function testCallWithoutActionShouldPullFromIndexAction() { $this->dispatch('/user'); $this->assertController('user'); $this->assertAction('index'); } public function testIndexActionShouldContainLoginForm() { $this->dispatch('/user'); $this->assertAction('index');
1181
Zend_Test
$this->assertQueryCount('form#loginForm', 1); } public function testValidLoginShouldGoToProfilePage() { $this->request->setMethod('POST') ->setPost(array( 'username' => 'foobar', 'password' => 'foobar' )); $this->dispatch('/user/login'); $this->assertRedirectTo('/user/view'); $this->resetRequest() ->resetResponse(); $this->request->setMethod('GET') ->setPost(array()); $this->dispatch('/user/view'); $this->assertRoute('default'); $this->assertModule('default'); $this->assertController('user'); $this->assertAction('view'); $this->assertNotRedirect(); $this->assertQuery('dl'); $this->assertQueryContentContains('h2', 'User: foobar'); } } This example could be written somewhat simpler -- not all the assertions shown are necessary, and are provided for illustration purposes only. Hopefully, it shows how simple it can be to test your applications.
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { public function setUp() { // Assign and instantiate in one step: $this->bootstrap = new Zend_Application( 'testing',
1182
Zend_Test
APPLICATION_PATH . '/configs/application.ini' ); parent::setUp(); } } Second, you can set this property to point to a file. If you do this, the file should not dispatch the front controller, but merely setup the front controller and any application specific needs.
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { public $bootstrap = '/path/to/bootstrap/file.php' // ... } Third, you can provide a PHP callback to execute in order to bootstrap your application. This method is seen in the Login example. If the callback is a function or static method, this could be set at the class level:
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { public $bootstrap = array('App', 'bootstrap'); // ... } In cases where an object instance is necessary, we recommend performing this in your setUp() method:
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { public function setUp() { // Use the 'start' method of a Bootstrap object instance: $bootstrap = new Bootstrap('test'); $this->bootstrap = array($bootstrap, 'start'); parent::setUp(); } } Note the call to parent::setUp(); this is necessary, as the setUp() method of Zend_Test_PHPUnit_ControllerTestCase will perform the remainder of the bootstrapping process (which includes calling the callback). During normal operation, the setUp() method will bootstrap the application. This process first will include cleaning up the environment to a clean request state, resetting any plugins and helpers, resetting the front controller instance, and creating new request and response objects. Once this is done, it will then either include the file specified in $bootstrap, or call the callback specified. Bootstrapping should be as close as possible to how the application will be bootstrapped. However, there are several caveats: Do not provide objects; they will alternate not be implementations of the Request and Response used. Zend_Test_PHPUnit_ControllerTestCase uses
1183
Zend_Test
custom request and response objects, Zend_Controller_Request_HttpTestCase and Zend_Controller_Response_HttpTestCase, respectively. These objects provide methods for setting up the request environment in targeted ways, and pulling response artifacts in specific ways. Do not expect to test server specifics. In other words, the tests are not a guarantee that the code will run on a specific server configuration, but merely that the application should run as expected should the router be able to route the given request. To this end, do not set server-specific headers in the request object. Once the application is bootstrapped, you can then start creating your tests.
1184
Zend_Test
'timestamp' => time(), 'host' => 'foobar', )); // Set headers, even: $this->request->setHeader('X-Requested-With', 'XmlHttpRequest'); // Set the request method: $this->request->setMethod('POST'); // Dispatch: $this->dispatch('/foo/bar'); // ... } } Now that the request is made, it's time to start making assertions against it.
class MyController extends Zend_Controller_Action { public function indexAction() { if($someCondition == true) { return $this->_redirect(...); } else if($anotherCondition == true) { $this->_redirector->gotoSimple("foo"); return; } // do some stuff here } }
Important
Depending on your application this is not enough as additional action, preDispatch() or postDispatch() logic might be executed. This cannot be handled in a good way with Zend Test currently.
1185
Zend_Test
Assertions
Assertions are at the heart of Unit Testing; you use them to verify that the results are what you expect. To this end, Zend_Test_PHPUnit_ControllerTestCase provides a number of assertions to make testing your MVC apps and controllers simpler.
XPath Assertions
Some developers are more familiar with XPath than with CSS selectors, and thus XPath variants of all the Query assertions are also provided. These are: assertXpath($path, $message = '') assertNotXpath($path, $message = '')
1186
Zend_Test
assertXpathContentContains($path, $match, $message = '') assertNotXpathContentContains($path, $match, $message = '') assertXpathContentRegex($path, $pattern, $message = '') assertNotXpathContentRegex($path, $pattern, $message = '') assertXpathCount($path, $count, $message = '') assertNotXpathCount($path, $count, $message = '') assertXpathCountMin($path, $count, $message = '') assertNotXpathCountMax($path, $count, $message = '')
Redirect Assertions
Often an action will redirect. Instead of following the redirect, Zend_Test_PHPUnit_ControllerTestCase allows you to test for redirects with a handful of assertions. assertRedirect($message = ''): assert simply that a redirect has occurred. assertNotRedirect($message = ''): assert that no redirect has occurred. assertRedirectTo($url, $message = ''): assert that a redirect has occurred, and that the value of the Location header is the $url provided. assertNotRedirectTo($url, $message = ''): assert that a redirect has either NOT occurred, or that the value of the Location header is NOT the $url provided. assertRedirectRegex($pattern, $message = ''): assert that a redirect has occurred, and that the value of the Location header matches the regular expression provided by $pattern. assertNotRedirectRegex($pattern, $message = ''): assert that a redirect has either NOT occurred, or that the value of the Location header does NOT match the regular expression provided by $pattern.
1187
Zend_Test
Request Assertions
It's often useful to assert against the last run action, controller, and module; additionally, you may want to assert against the route that was matched. The following assertions can help you in this regard: assertModule($module, $message = ''): Assert that the given module was used in the last dispatched action. assertController($controller, $message = ''): Assert that the given controller was selected in the last dispatched action. assertAction($action, $message = ''): Assert that the given action was last dispatched. assertRoute($route, $message = ''): Assert that the given named route was matched by the router. Each also has a 'Not' variant for negative assertions.
Ejemplos
Knowing how to setup your testing infrastructure and how to make assertions is only half the battle; now it's time to start looking at some actual testing scenarios to see how you can leverage them.
1188
Zend_Test
/** * @var string Current environment */ protected $_env; /** * @var Zend_Controller_Front */ protected $_front; /** * @var string Path to application root */ protected $_root; /** * Constructor * * Initialize environment, root path, and configuration. * * @param string $env * @param string|null $root * @return void */ public function __construct($env, $root = null) { $this->_setEnv($env); if (null === $root) { $root = realpath(dirname(__FILE__) . '/../../../'); } $this->_root = $root; $this->initPhpConfig(); $this->_front = Zend_Controller_Front::getInstance(); } /** * Route startup * * @return void */ public function routeStartup(Zend_Controller_Request_Abstract $request) { $this->initDb(); $this->initHelpers(); $this->initView(); $this->initPlugins(); $this->initRoutes(); $this->initControllers(); } // definition of methods would follow... }
1189
Zend_Test
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { public function appBootstrap() { $controller = $this->getFrontController(); $controller->registerPlugin( new Bugapp_Plugin_Initialize('development') ); } public function setUp() { $this->bootstrap = array($this, 'appBootstrap'); parent::setUp(); } // ... } Once we have that in place, we can write our tests. However, what about those tests that require a user is logged in? The easy solution is to use our application logic to do so... and fudge a little by using the resetRequest() and resetResponse() methods, which will allow us to dispatch another request.
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { // ... public function loginUser($user, $password) { $this->request->setMethod('POST') ->setPost(array( 'username' => $user, 'password' => $password, )); $this->dispatch('/user/login'); $this->assertRedirectTo('/user/view'); $this->resetRequest() ->resetResponse(); $this->request->setPost(array()); // ... } // ... } Now let's write tests:
1190
Zend_Test
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { // ... public function testCallWithoutActionShouldPullFromIndexAction() { $this->dispatch('/user'); $this->assertController('user'); $this->assertAction('index'); } public function testLoginFormShouldContainLoginAndRegistrationForms() { $this->dispatch('/user'); $this->assertQueryCount('form', 2); } public function testInvalidCredentialsShouldResultInRedisplayOfLoginForm() { $request = $this->getRequest(); $request->setMethod('POST') ->setPost(array( 'username' => 'bogus', 'password' => 'reallyReallyBogus', )); $this->dispatch('/user/login'); $this->assertNotRedirect(); $this->assertQuery('form'); } public function testValidLoginShouldRedirectToProfilePage() { $this->loginUser('foobar', 'foobar'); } public function testAuthenticatedUserShouldHaveCustomizedProfilePage() { $this->loginUser('foobar', 'foobar'); $this->request->setMethod('GET'); $this->dispatch('/user/view'); $this->assertNotRedirect(); $this->assertQueryContentContains('h2', 'foobar'); } public function testAuthenticatedUsersShouldBeRedirectedToProfileWhenVisitingLogin() { $this->loginUser('foobar', 'foobar'); $this->request->setMethod('GET'); $this->dispatch('/user'); $this->assertRedirectTo('/user/view'); } public function testUserShouldRedirectToLoginPageOnLogout()
1191
Zend_Test
{ $this->loginUser('foobar', 'foobar'); $this->request->setMethod('GET'); $this->dispatch('/user/logout'); $this->assertRedirectTo('/user'); } public function testRegistrationShouldFailWithInvalidData() { $data = array( 'username' => 'This will not work', 'email' => 'this is an invalid email', 'password' => 'Th1s!s!nv@l1d', 'passwordVerification' => 'wrong!', ); $request = $this->getRequest(); $request->setMethod('POST') ->setPost($data); $this->dispatch('/user/register'); $this->assertNotRedirect(); $this->assertQuery('form .errors'); } } Notice that these are terse, and, for the most part, don't look for actual content. Instead, they look for artifacts within the response -- response codes and headers, and DOM nodes. This allows you to verify that the structure is as expected -- preventing your tests from choking every time new content is added to the site. Also notice that we use the structure of the document in our tests. For instance, in the final test, we look for a form that has a node with the class of "errors"; this allows us to test merely for the presence of form validation errors, and not worry about what specific errors might have been thrown. This application may utilize a database. If so, you will probably need some scaffolding to ensure that the database is in a pristine, testable configuration at the beginning of each test. PHPUnit already provides functionality for doing so; read about it in the PHPUnit documentation [http://www.phpunit.de/pocket_guide/3.3/en/database.html]. We recommend using a separate database for testing versus production, and in particular recommend using either a SQLite file or inmemory database, as both options perform very well, do not require a separate server, and can utilize most SQL syntax.
Zend_Test_PHPUnit_Db
Coupling of data-access and the domain model often requires the use of a database for testing purposes. But the database is persistent across different tests which leads to test results that can affect each other. Furthermore setting up the database to be able to run a test is quite some work. PHPUnit's Database extension simplifies testing with a database by offering a very simple mechanism to set up and teardown the database between different tests. This component extends the PHPUnit Database extension with Zend Framework specific code, such that writing database tests against a Zend Framework application is simplified. Database Testing can be explained with two conceptual entities, DataSets and DataTables. Internally the PHPUnit Database extension can build up an object structure of a database, its tables and containing rows from configuration files or the real database content. This abstract object graph can then be compared using assertions. A common use-case in database testing is setting up some tables with seed data, then performing some operations, and finally asserting that the operated on database-state is equal to some predefined expected state. Zend_Test_PHPUnit_Db simplifies this task by allowing to generate DataSets and DataTables from existing Zend_Db_Table_Abstract or Zend_Db_Table_Rowset_Abstract instances.
1192
Zend_Test
Furthermore this component allows to integrate any Zend_Db_Adapter_Abstract for testing whereas the original extension only works with PDO. A Test Adapter implementation for Zend_Db_Adapter_Abstract is also included in this component. It allows to instantiate a Db Adapter that requires no database at all and acts as an SQL and result stack which is used by the API methods.
Quickstart
Setup a Database TestCase
We are now writting some database tests for the Bug Database example in the Zend_Db_Table documentation. First we begin to test that inserting a new bug is actually saved in the database correctly. First we have to setup a test-class that extends Zend_Test_PHPUnit_DatabaseTestCase. This class extends the PHPUnit Database Extension, which in turn extends the basic PHPUnit_Framework_TestCase. A database testcase contains two abstract methods that have to be implemented, one for the database connection and one for the initial dataset that should be used as seed or fixture.
Nota
You should be familiar with the PHPUnit Database extension to follow this quickstart easily. Although all the concepts are explained in this documentation it may be helpful to read the PHPUnit documentation first.
class BugsTest extends Zend_Test_PHPUnit_DatabaseTestCase { private $_connectionMock; /** * Returns the test database connection. * * @return PHPUnit_Extensions_Database_DB_IDatabaseConnection */ protected function getConnection() { if($this->_connectionMock == null) { $connection = Zend_Db::factory(...); $this->_connectionMock = $this->createZendDbConnection( $connection, 'zfunittests' ); Zend_Db_Table_Abstract::setDefaultAdapter($connection); } return $this->_connectionMock; } /** * @return PHPUnit_Extensions_Database_DataSet_IDataSet */ protected function getDataSet() { return $this->createFlatXmlDataSet( dirname(__FILE__) . '/_files/bugsSeed.xml' ); } }
1193
Zend_Test
Here we create the database connection and seed some data into the database. Some important details should be noted on this code: You cannot directly return a Zend_Db_Adapter_Abstract from the getConnection() method, but a PHPUnit specific wrapper which is generated with the createZendDbConnection() method. The database schema (tables and database) is not re-created on every testrun. The database and tables have to be created manually before running the tests. Database tests by default truncate the data during setUp() and then insert the seed data which is returned from the getDataSet() method. DataSets have to implement the interface PHPUnit_Extensions_Database_DataSet_IDataSet. There is a wide range of XML and YAML configuration file types included in PHPUnit which allows to specifiy how the tables and datasets should look like and you should look into the PHPUnit documentation to get the latest information on these dataset specifications.
1194
Zend_Test
class BugsTest extends Zend_Test_PHPUnit_DatabaseTestCase { public function testBugInsertedIntoDatabase() { $bugsTable = new Bugs(); $data = array( 'created_on' 'updated_on' 'bug_description' 'bug_status' 'reported_by' 'verified_by' 'assigned_to' );
'2007-03-22 00:00:00', '2007-03-22 00:00:00', 'Something wrong', 'NEW', 'garfield', 'garfield', 'mmouse',
$bugsTable->insert($data); $ds = new Zend_Test_PHPUnit_Db_DataSet_QueryDataSet( $this->getConnection() ); $ds->addTable('zfbugs', 'SELECT * FROM zfbugs'); $this->assertDataSetsEqual( $this->createFlatXmlDataSet(dirname(__FILE__) . "/_files/bugsInsertIntoAssertion.xml"), $ds ); } } Now up to the $bugsTable->insert($data); everything looks familiar. The lines after that contain the assertion methodname. We want to verify that after inserting the new bug the database has been updated correctly with the given data. For this we create a Zend_Test_PHPUnit_Db_DataSet_QueryDataSet instance and give it a database connection. We will then tell this dataset that it contains a table "zfbugs" which is given by an SQL statement. This current/actual state of the database is compared to the expected database state which is contained in another XML file "bugsInsertIntoAssertions.xml". This XML file is a slight deviation from the one given above and contains another row with the expected data:
<?xml version="1.0" encoding="UTF-8" ?> <dataset> <!-- previous 4 rows --> <zfbugs bug_id="5" bug_description="Something wrong" bug_status="NEW" created_on="2007-03-22 00:00:00" updated_on="2007-03-22 00:00:00" reported_by="garfield" assigned_to="mmouse" verified_by="garfield" /> </dataset>
1195
Zend_Test
There are other ways to assert that the current database state equals an expected state. The "Bugs" table in the example already nows a lot about its inner state, so why not use this to our advantage? The next example will assert that deleting from the database is possible:
class BugsTest extends Zend_Test_PHPUnit_DatabaseTestCase { public function testBugDelete() { $bugsTable = new Bugs(); $bugsTable->delete( $bugsTable->getAdapter()->quoteInto("bug_id = ?", 4) ); $ds = new Zend_Test_PHPUnit_Db_DataSet_DbTableDataSet(); $ds->addTable($bugsTable); $this->assertDataSetsEqual( $this->createFlatXmlDataSet(dirname(__FILE__) . "/_files/bugsDeleteAssertion.xml"), $ds ); } } We have created a Zend_Test_PHPUnit_Db_DataSet_DbTableDataSet dataset here, which takes any Zend_Db_Table_Abstract instance and adds it to the dataset with its table name, in this example "zfbugs". You could add several tables more if you wanted using the method addTable() if you want to check for expected database state in more than one table. Here we only have one table and check against an expected database state in "bugsDeleteAssertion.xml" which is the original seed dataset without the row with id 4. Since we have only checked that two specific tables (not datasets) are equal in the previous examples we should also look at how to assert that two tables are equal. Therefore we will add another test to our TestCase which verifies updating behaviour of a dataset.
class BugsTest extends Zend_Test_PHPUnit_DatabaseTestCase { public function testBugUpdate() { $bugsTable = new Bugs(); $data = array( 'updated_on' 'bug_status' );
1196
Zend_Test
$ds = new Zend_Test_PHPUnit_Db_DataSet_DbRowset($rowset); $assertion = $this->createFlatXmlDataSet( dirname(__FILE__) . '/_files/bugsUpdateAssertion.xml' ); $expectedRowsets = $assertion->getTable('zfbugs'); $this->assertTablesEqual( $expectedRowsets, $ds ); } } Here we create the current database state from a Zend_Db_Table_Rowset_Abstract instance in conjunction with the Zend_Test_PHPUnit_Db_DataSet_DbRowset($rowset) instance which creates an internal data-representation of the rowset. This can again be compared against another data-table by using the $this>assertTablesEqual() assertion.
1197
Zend_Test
5. When the database tester has finished setting up the database, PHPUnit runs the test. 6. After running the test, tearDown() is called. Because the database is wiped in setUp() before inserting the required initial fixture, no actions are executed by the database tester at this stage.
Nota
The Database TestCase expects the database schema and tables to be setup correctly to run the tests. There is no mechanism to create and tear down database tables. The Zend_Test_PHPUnit_DatabaseTestCase class has some convenience functions that can help writing tests that interact with the database and the database testing extension. The next table lists only the new methods compared to the PHPUnit_Extensions_Database_TestCase, whose API is documented in the PHPUnit Documentation [http://www.phpunit.de/manual/current/en/database.html].
createDbRowset(Zend_Db_Table_Rowset_Abstract Create a DataTable Object that is filled with the data $rowset, $tableName = null) from a given Zend_Db_Table_Rowset_Abstract instance. The table the rowset is connected to is chosen when $tableName is null. createDbTable(Zend_Db_Table_Abstract Create a DataTable object that represents the data $table, $where = null, $order = null, contained in a Zend_Db_Table_Abstract instance. $count = null, $offset = null) For retrieving the data fetchAll() is used, where the optional parameters can be used to restrict the data table to a certain subset. createDbTableDataSet(array $tables=array()) Create a DataSet containing the given $tables, an array of Zend_Db_Table_Abstract instances.
1198
Zend_Test
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { public function setUp() { $this->setupDatabase(); $this->bootstrap = array($this, 'appBootstrap'); parent::setUp(); } public function setupDatabase() { $db = Zend_Db::factory(...); $connection = new Zend_Test_PHPUnit_Db_Connection($db, 'database_schema_name'); $databaseTester = new Zend_Test_PHPUnit_Db_SimpleTester($connection); $databaseFixture = new PHPUnit_Extensions_Database_DataSet_FlatXmlDataSet( dirname(__FILE__) . '/_files/initialUserFixture.xml' ); $databaseTester->setupDatabase($databaseFixture); } } Now the Flat XML dataset "initialUserFixture.xml" is used to set the database into an initial state before each test, exactly as the DatabaseTestCase works internally.
$adapter = new Zend_Test_DbAdapter(); $stmt1Rows = array(array('foo' => 'bar'), array('foo' => 'baz')); $stmt1 = Zend_Test_DbStatement::createSelectStatement($stmt1Rows); $adapter->appendStatementToStack($stmt1); $stmt2Rows = array(array('foo' => 'bar'), array('foo' => 'baz')); $stmt2 = Zend_Test_DbStatement::createSelectStatement($stmt2Rows); $adapter->appendStatementToStack($stmt2); $rs = $adapter->query('SELECT ...'); // Returns Statement 2 while ($row = $rs->fetch()) { echo $rs['foo']; // Prints "Bar", "Baz"
1199
Zend_Test
} $rs = $adapter->query('SELECT ...'); // Returns Statement 1 Behaviour of any real database adapter is simulated as much as possible such that methods like fetchAll(), fetchObject(), fetchColumn and more are working for the test adapter. You can also put INSERT, UPDATE and DELETE statement onto the result stack, these however only return a statement which allows to specifiy the result of $stmt->rowCount().
$adapter = new Zend_Test_DbAdapter(); $adapter->appendStatementToStack( Zend_Test_DbStatement::createInsertStatement(1) ); $adapter->appendStatementToStack( Zend_Test_DbStatement::createUpdateStatement(2) ); $adapter->appendStatementToStack( Zend_Test_DbStatement::createDeleteStatement(10 )); By default the query profiler is enabled, so that you can retrieve the executed SQL statements and their bound parameters to check for the correctness of the execution.
$adapter = new Zend_Test_DbAdapter(); $stmt = $adapter->query("SELECT * FROM bugs"); $qp = $adapter->getProfiler()->getLastQueryProfile(); echo $qp->getQuerY(); // SELECT * FROM bugs
The test adapter never checks if the query specified is really of the type SELECT, DELETE, INSERT or UPDATE which is returned next from the stack. The correct order of returning the data has to be implemented by the user of the test adapter. The Test adapter also specifies methods to simulate the use of the methods listTables(), describeTables() and lastInsertId().
1200
Compressed fonts
Zend_Text_Figlet supports gzipped fonts. This means that you can take an .flf file and gzip it. To allow Zend_Text_Figlet to recognize this, the gzipped font must have the extension .gz. Further, to be able to use gzipped fonts, you have to have enabled the GZIP extension of PHP.
Encoding
Zend_Text_Figlet expects your strings to be UTF-8 encoded by default. If this is not the case, you can supply the character encoding as second parameter to the render() method. You can define multiple options for a FIGlet. When instantiating Zend_Text_Figlet, you can supply an array or an instance of Zend_Config. font - Defines the font which should be used for rendering. If not defines, the built-in font will be used. outputWidth - Defines the maximum width of the output string. This is used for word-wrap as well as justification. Beware of too small values, they may result in an undefined behaviour. The default value is 80. handleParagraphs - A boolean which indicates, how new lines are handled. When set to true, single new lines are ignored and instead treated as single spaces. Only multiple new lines will be handled as such. The default value is FALSE. justification - May be one of the values of Zend_Text_Figlet::JUSTIFICATION_*. There is JUSTIFICATION_LEFT, JUSTIFICATION_CENTER and JUSTIFICATION_RIGHT The default justification is defined by the rightToLeft value. rightToLeft - Defines in which direction the text is written. May be either Zend_Text_Figlet::DIRECTION_LEFT_TO_RIGHT or Zend_Text_Figlet::DIRECTION_RIGHT_TO_LEFT. By default the setting of the font file is used. When justification is not defined, a text written from right-to-left is automatically right-aligned. smushMode - An integer bitfield which defines, how the single characters are smushed together. Can be the sum of multiple values from Zend_Text_Figlet::SM_*. There are the following smush modes: SM_EQUAL, SM_LOWLINE, SM_HIERARCHY, SM_PAIR, SM_BIGX, SM_HARDBLANK, SM_KERN and SM_SMUSH. A value of 0 doesn't disable the entire smushing, but forces SM_KERN to be applied, while a value of -1 disables it. An explanation of the different smush modes can be found here [http://www.jave.de/figlet/figfont.txt]. By default the setting of the font file is used. The smush mode option is normally used only by font designers testing the various layoutmodes with a new font.
1201
Zend_Text
$figlet = new Zend_Text_Figlet(); echo $figlet->render('Zend'); Assuming you are using a monospace font, this would look as follows:
Zend_Text_Table
Zend_Text_Table is a component to create text based tables on the fly with different decorators. This can be helpful, if you either want to send structured data in text emails, which are used to have mono-spaced fonts, or to display table information in a CLI application. Zend_Text_Table supports multi-line columns, colspan and align as well.
Encoding
Zend_Text_Table expects your strings to be UTF-8 encoded by default. If this is not the case, you can either supply the character encoding as a parameter to the constructor or the setContent method of Zend_Text_Table_Column. Alternatively if you have a different encoding in the entire process, you can define the standard input charset with Zend_Text_Table::setInputCharset($charset). In case you need another output charset for the table, you can set this with Zend_Text_Table::setOutputCharset($charset). A Zend_Text_Table object consists of rows, which contain columns, represented by Zend_Text_Table_Row and Zend_Text_Table_Column. When creating a table, you can supply an array with options for the table. Those are: columnWidths (required): An array defining all columns width their widths in characters. decorator: The decorator to use for the table borders. The default is unicode, but you may also specify ascii or give an instance of a custom decorator object. padding: The left and right padding withing the columns in characters. The default padding is zero. AutoSeparate: The way how the rows are separated with horizontal lines. The default is a separation between all rows. This is defined as a bitmask containing one ore more of the following constants of Zend_Text_Table: Zend_Text_Table::AUTO_SEPARATE_NONE Zend_Text_Table::AUTO_SEPARATE_HEADER Zend_Text_Table::AUTO_SEPARATE_FOOTER Zend_Text_Table::AUTO_SEPARATE_ALL Where header is always the first row, and the footer is always the last row. Rows are simply added to the table by creating a new instance of Zend_Text_Table_Row, and appending it to the table via the appendRow method. Rows themselves have no options. You can also give an array to directly to the appendRow method, which then will automatically converted to a row object, containing multiple column objects.
1202
Zend_Text
The same way you can add columns to the rows. Create a new instance of Zend_Text_Table_Column and then either set the column options in the constructor or later with the set* methods. The first parameter is the content of the column which may have multiple lines, which in the best case are separated by just the \n character. The second parameter defines the align, which is left by default and can be one of the class constants of Zend_Text_Table_Column: ALIGN_LEFT ALIGN_CENTER ALIGN_RIGHT The third parameter is the colspan of the column. For example, when you choose "2" as colspan, the column will span over two columns of the table. The last parameter defines the encoding of the content, which should be supplied, if the content is neither ASCII nor UTF-8. To append the column to the row, you simply call appendColumn in your row object with the column object as parameter. Alternatively you can directly give a string to the appendColumn method. To finally render the table, you can either use the render method of the table, or use the magic method __toString by doing echo $table; or $tableString = (string) $table.
$table = new Zend_Text_Table(array('columnWidths' => array(10, 20))); // Either simple $table->appendRow(array('Zend', 'Framework')); // Or verbose $row = new Zend_Text_Table_Row(); $row->appendColumn(new Zend_Text_Table_Column('Zend')); $row->appendColumn(new Zend_Text_Table_Column('Framework')); $table->appendRow($row); echo $table; This will result in the following output:
1203
1204
Background
Zend_TimeSync is not able to change the server's time, but it will return a Zend_Date instance from which the difference from the server's time can be worked with.
Why Zend_TimeSync ?
So why would someone use Zend_TimeSync ? Normally every server within a multi-server farm will have a service running which synchronizes its own time with a time server. So within a standard environment it should not be necessary to use Zend_TimeSync. But it can become handy if there is no service available and if you don't have the right to install such a service. Here are some example use cases, for which Zend_TimeSync is perfect suited: Server without time service If your application is running on a server and this server does not have any time service running, it may make sense to use Zend_TimeSync in your application. Separate database server If your database is running on a different server and this server is not connected with NTP or SNTP to the application server, you might have problems using storing and using time stamp data. Multiple servers If your application is running on more than one server and these servers' time bases are not syncronized, you can expect problems within your application when part of the application is coming from one server and another part from another server. Batch processing If you want to work with a time service within a batch file or within a command line application, Zend_TimeSync may be of use. Zend_TimeSync may provide a good solution in all of these cases and can be used if you are unable to run any services on your server.
What is NTP ?
The Network Time Protocol (NTP) is a protocol for synchronizing multiple systems' clocks over packetswitched, variable-latency data networks. NTP uses UDP port 123 as its transport layer. See the wikipedia article [http://en.wikipedia.org/wiki/Network_Time_Protocol] for details about this protocol.
1205
Zend_TimeSync
What is SNTP?
The Simple Network Time Protocol (SNTP) is a protocol synchronizing multiple systems' clocks over packet-switched, variable-latency data networks. SNTP uses UDP port 37 as its transport layer. It is closely related to the Network Time Protocol, but simpler.
Problematic usage
Be warned that when you are using Zend_TimeSync you will have to think about some details related to the structure of time sync and the internet itself. Correct usage and best practices will be described here. Read carefully before you begin using Zend_TimeSync.
Nota
All examples in this chapter use a public, generic time server: 0.europe.pool.ntp.org. You should use a public, generic time server which is close to your application server. See http://www.pool.ntp.org for information.
1206
Zend_TimeSync
$server = new Zend_TimeSync('0.pool.ntp.org'); print $server->getDate()->getIso(); So what is happening in the background of Zend_TimeSync? First the syntax of the time server is checked. In our example, '0.pool.ntp.org' is checked and recognised as a possible address for a time server. Then when calling getDate() the actual set time server is requested and it will return its own time. Zend_TimeSync then calculates the difference to the actual time of the server running the script and returns a Zend_Date object with the correct time. For details about Zend_Date and its methods see the Zend_Date documentation.
$server = new Zend_TimeSync(array('0.pool.ntp.org', '1.pool.ntp.org', '2.pool.ntp.org')); $server->addServer('3.pool.ntp.org'); print $server->getDate()->getIso(); There is no limit to the number of time servers you can add. When a time server can not be reached, Zend_TimeSync will fallback and try to connect to the next time server. When you supply more than one time server- which is considered a best practice for Zend_TimeSync- you should name each server. You can name your servers with array keys, with the second parameter at instantiation, or with the second parameter when adding another time server.
$server = new Zend_TimeSync(array('generic' => '0.pool.ntp.org', 'fallback' => '1.pool.ntp.org', 'reserve' => '2.pool.ntp.org')); $server->addServer('3.pool.ntp.org', 'additional'); print $server->getDate()->getIso(); Naming the time servers allows you to request a specific time server as we will see later in this chapter.
1207
Zend_TimeSync
$server = new Zend_TimeSync(array('generic' => 'ntp:\\0.pool.ntp.org', 'fallback' => 'ntp:\\1.pool.ntp.org', 'reserve' => 'ntp:\\2.pool.ntp.org')); $server->addServer('sntp:\\internal.myserver.com', 'additional'); print $server->getDate()->getIso(); Zend_TimeSync can handle mixed time servers. So you are not restricted to only one protocol; you can add any server independently from its protocol.
$server = new Zend_TimeSync(array('generic' => 'ntp:\\0.pool.ntp.org:200', 'fallback' => 'ntp:\\1.pool.ntp.org')); $server->addServer('sntp:\\internal.myserver.com:399', 'additional'); print $server->getDate()->getIso();
Zend_TimeSync::setOptions(array('timeout' => 3, 'myoption' => 'timesync')); $server = new Zend_TimeSync(array('generic' => 'ntp:\\0.pool.ntp.org', 'fallback' => 'ntp:\\1.pool.ntp.org')); $server->addServer('sntp:\\internal.myserver.com', 'additional'); print $server->getDate()->getIso(); print_r(Zend_TimeSync::getOptions(); print "Timeout = " . Zend_TimeSync::getOptions('timeout'); As you can see, the options for Zend_TimeSync are static. Each instance of Zend_TimeSync will use the same options.
1208
Zend_TimeSync
$server = new Zend_TimeSync(array('generic' => 'ntp:\\0.pool.ntp.org', 'fallback' => 'ntp:\\1.pool.ntp.org')); $server->addServer('sntp:\\internal.myserver.com', 'additional'); $actual = $server->getServer(); $server = $server->setServer('additional');
$server = new Zend_TimeSync(array('generic' => 'ntp:\\0.pool.ntp.org', 'fallback' => 'ntp:\\1.pool.ntp.org')); print_r ($server->getInfo()); The returned information differs with the protocol used and can also differ with the server used.
Handling Exceptions
Exceptions are collected for all time servers and returned as an array. So you can iterate through all thrown exceptions as shown in the following example:
$serverlist = array( // invalid servers 'invalid_a' => 'ntp://a.foo.bar.org', 'invalid_b' => 'sntp://b.foo.bar.org', ); $server = new Zend_TimeSync($serverlist); try { $result = $server->getDate(); echo $result->getIso(); } catch (Zend_TimeSync_Exception $e) { $exceptions = $e->get(); foreach ($exceptions as $key => $myException) { echo $myException->getMessage(); echo '<br />';
1209
Zend_TimeSync
} }
1210
1211
Zend_Tool_Framework
Architecture
Registry
Because providers and manifests may come from anywhere in the include_path, a registry is provided to simplify access to the various pieces of the toolchain. This registry is injected into registry-aware components, which may then pull dependencies from them as necessary. Most dependencies registered with the registry will be sub-componentspecific repositories. The interface for the registry consists of the following definition: interface Zend_Tool_Framework_Registry_Interface { public function setClient(Zend_Tool_Framework_Client_Abstract $client); public function getClient(); public function setLoader(Zend_Tool_Framework_Loader_Abstract $loader); public function getLoader(); public function setActionRepository( Zend_Tool_Framework_Action_Repository $actionRepository ); public function getActionRepository(); public function setProviderRepository( Zend_Tool_Framework_Provider_Repository $providerRepository ); public function getProviderRepository(); public function setManifestRepository( Zend_Tool_Framework_Manifest_Repository $manifestRepository ); public function getManifestRepository(); public function setRequest(Zend_Tool_Framework_Client_Request $request); public function getRequest(); public function setResponse(Zend_Tool_Framework_Client_Response $response); public function getResponse(); } The various objects the registry manages will be discussed in their appropriate sections. Classes that should be registry-aware should implement Zend_Tool_Framework_Registry_EnabledInterface. This interface merely allows initialization of the registry in the target class. interface Zend_Tool_Framework_Registry_EnabledInterface { public function setRegistry( Zend_Tool_Framework_Registry_Interface $registry ); }
Providers
Zend_Tool_Framework_Provider represents the functional or "capability" aspect of the framework. Fundamentally, Zend_Tool_Framework_Provider will provide the interfaces necessary to produce
1212
Zend_Tool_Framework
"providers", or bits of tooling functionality that can be called and used inside the Zend_Tool_Framework toolchain. The simplistic nature of implementing this provider interface allows the developer a "one-stop-shop" of adding functionality or capabilities to Zend_Tool_Framework. The provider interface is an empty interface and enforces no methods (this is the Marker Interface pattern):
interface Zend_Tool_Framework_Provider_Interface {} Or, if you wish, you can implement the base (or abstract) Provider which will give you access to the Zend_Tool_Framework_Registry:
abstract class Zend_Tool_Framework_Provider_Abstract implements Zend_Tool_Framework_Provider_Interface, Zend_Tool_Registry_EnabledInterface { protected $_registry; public function setRegistry( Zend_Tool_Framework_Registry_Interface $registry ); }
Loaders
The purpose of a Loader is to find Providers and Manifest files that contain classes which implement either Zend_Tool_Framework_Provider_Interface or Zend_Tool_Framework_Manifest_Interface. Once these files are found by a loader, providers are loaded into the Provider Repository and manifest metadata is loaded into the Manifest Repository. To implement a loader, one must extend the following abstract class:
abstract class Zend_Tool_Framework_Loader_Abstract { abstract protected function _getFiles(); public function load() { /** ... */ } } The _getFiles() method should return an array of files (absolute paths). The built-in loader supplied with Zend Framework is called the IncludePath loader. By default, the Tooling framework will use an include_path based loader to find files that might include Providers or Manifest Metadata objects. Zend_Tool_Framework_Loader_IncludePathLoader, without any other options, will search for files inside the include path that end in Mainfest.php, Tool.php or Provider.php. Once found, they will be tested (by the load() method of the Zend_Tool_Framework_Loader_Abstract) to determine if they implement any of the supported interfaces. If they do, an instance of the found class is instantiated, and it is appended to the proper repository.
1213
Zend_Tool_Framework
class Zend_Tool_Framework_Loader_IncludePathLoader extends Zend_Tool_Framework_Loader_Abstract { protected $_filterDenyDirectoryPattern = '.*(/|\\\\).svn'; protected $_filterAcceptFilePattern = '.*(?:Manifest|Provider)\.php$'; protected function _getFiles() { /** ... */ } } As you can see, the IncludePath loader will search all include_paths for the files that match the $_filterAcceptFilePattern and not match the $_filterDenyDirectoryPattern.
Manifests
In short, the Manifest shall contain specific or arbitrary metadata that is useful to any provider or client, as well as be responsible for loading any additional providers into the provider repository. To introduce metadata into the manifest repository, all one must do is implement the empty Zend_Tool_Framework_Manifest_Interface, and provide a getMetadata() method which shall return an array of objects that implement Zend_Tool_Framework_Manifest_Metadata. interface Zend_Tool_Framework_Manifest_Interface { public function getMetadata(); } Metadata objects are loaded (by a loader defined below) into the Manifest Repository (Zend_Tool_Framework_Manifest_Repository). Manifests will be processed after all Providers have been found to be loaded into the provider repository. This shall allow Manifests to create Metadata objects based on what is currently inside the provider repository. There are a few different metadata classes that can be used to describe metadata. The Zend_Tool_Framework_Manifest_Metadata is the base metadata object. As you can see by the following code snippet, the base metadata class is fairly lightweight and abstract in nature: class Zend_Tool_Framework_Metadata_Basic { protected protected protected protected $_type $_name $_value $_reference = = = = 'Global'; null; null; null;
public function public function public function public function /** ... */ }
1214
Zend_Tool_Framework
There are other built in metadata classes as well for describing more specialized metadata: ActionMetadata and ProviderMetadata. These classes will help you describe in more detail metadata that is specific to either actions or providers, and the reference is expected to be a reference to an action or a provider respectively. These classes are described in the following code snippet.
class Zend_Tool_Framework_Manifest_ActionMetadata extends Zend_Tool_Framework_Manifest_Metadata { protected $_type = 'Action'; protected $_actionName = null; public function getActionName(); /** ... */ } class Zend_Tool_Framework_Manifest_ProviderMetadata extends Zend_Tool_Framework_Manifest_Metadata { protected protected protected protected $_type = 'Provider'; $_providerName = null; $_actionName = null; $_specialtyName = null;
public function getProviderName(); public function getActionName(); public function getSpecialtyName(); /** ... */ } 'Type' in these classes is used to describe the type of metadata the object is responsible for. In the cases of the ActionMetadata, the type would be 'Action', and conversely in the case of the ProviderMetadata the type is 'Provider'. These metadata types will also include additional structured information about both the "thing" they are describing as well as the object (the getReference()) they are referencing with this new metadata. In order to create your own metadata type, all one must do is extend the base Zend_Tool_Framework_Manifest_Metadata class and return these new metadata objects via a local Manifest class or object. These user based classes will live in the Manifest Repository Once these metadata objects are in the repository, there are then two different methods that can be used in order to search for them in the repository.
class Zend_Tool_Framework_Manifest_Repository { /** * To use this method to search, $searchProperties should contain the names * and values of the key/value pairs you would like to match within the * manifest. * * For Ejemplo: * $manifestRepository->findMetadatas(array( * 'action' => 'Foo',
1215
Zend_Tool_Framework
* 'name' => 'cliActionName' * )); * * Will find any metadata objects that have a key with name 'action' value * of 'Foo', AND a key named 'name' value of 'cliActionName' * * Note: to either exclude or include name/value pairs that exist in the * search criteria but do not appear in the object, pass a bool value to * $includeNonExistentProperties */ public function findMetadatas(Array $searchProperties = array(), $includeNonExistentProperties = true); /** * The following will return exactly one of the matching search criteria, * regardless of how many have been returned. First one in the manifest is * what will be returned. */ public function findMetadata(Array $searchProperties = array(), $includeNonExistentProperties = true) { $metadatas = $this->getMetadatas($searchProperties, $includeNonExistentProperties); return array_shift($metadatas); } } Looking at the search methods above, the signatures allow for extremely flexible searching. In order to find a metadata object, simply pass in an array of matching constraints via an array. If the data is accessible through the Property accessor (the getSomething() methods implemented on the metadata object), then it will be passed back to the user as a "found" metadata object.
Clients
Clients are the interface which bridges a user or external tool into the Zend_Tool_Framework system. Clients can come in all shapes and sizes: RPC endpoints, Command Line Interface, or even a web interface. Zend_Tool has implemented the command line interface as the default interface for interacting with the Zend_Tool_Framework system. To implement a client, one would need to extend the following abstract class:
abstract class Zend_Tool_Framework_Client_Abstract { /** * This method should be implemented by the client implementation to * construct and set custom loaders, request and response objects. * * (not required, but suggested) */ protected function _preInit(); /** * This method should be implemented by the client implementation to parse
1216
Zend_Tool_Framework
* out and set up the request objects action, provider and parameter * information. */ abstract protected function _preDispatch(); /** * This method should be implemented by the client implementation to take * the output of the response object and return it (in an client specific * way) back to the Tooling Client. * * (not required, but suggested) */ abstract protected function _postDispatch(); } As you can see, there 1 method is required to fulfill the needs of a client (two others suggested), the initialization, prehandling and post handling. For a more in depth study of how the command line client works, please see the source code [http://framework.zend.com/svn/framework/standard/branches/release-1.8/library/Zend/ Tool/Framework/Client/Console.php].
1217
Zend_Tool_Framework
Local Storage
Once a home directory can be located, Zend_Tool_Framework's Console Client can either autodiscover the local storage directory, or it can be told where to expect the local storage directory. Assuming the home directory has been found (here noted as $HOME), the Console Client will then look for the local storage directory in $HOME/.zf/. If found, it will set the local storage directory to this location. If the directory cannot be found, or the developer wishes to override this location, that can be done by setting an environment variable. Regardless if $HOME has been previously set or not, the developer may supply the environment variable ZF_STORAGE_DIR. Once the path to a local storage directory is found, the directory must exist for it to be passed into the Zend_Tool_Framework runtime, as it will not be created for you.
User Configuration
Like local storage, once a home directory can be located, Zend_Tool_Framework's Console Client can then either attempt to autodiscover the path to a configuration file, or it can be told specifically where to find the configuration file.
1218
Zend_Tool_Framework
Assuming the home directory has been found (here noted as $HOME), the Console Client will then attempt to look for the existence of a configuration file located at $HOME/.zf.ini. This file, if found, will be used as the configuration file for Zend_Tool_Framework. If that location does not exist, but a local storage directory does, then the Console Client will then attempt to locate the configuration file within the local storage directory. Assuming the local storage directory exists in $LOCAL_STORAGE, then if a file exists as $LOCAL_STORAGE/zf.ini, it will be found by the Console Client and utilized as the Zend_Tool_Framework configuration file. If the file cannot be autodiscovered or the developer wishes to specify the location of location of the configuration file, the developer can do so by setting an environment variable. If the environment variable ZF_CONFIG_FILE is set, then its value will be used as the location of the configuration file to use with the Console Client. The ZF_CONFIG_FILE can point to any Zend_Config readable INI, XML or PHP File. If the file does not exist in either the autodiscovered or the provided location, it will not be used as Zend_Tool_Framework does not attempt to create the file automatically.
project.profile = some/path/to/some-directory The only reserved ini prefix is the value "php". The "php" prefix to values will be reserved to store names and values of runtime settable php values, such as include_path or error_reporting. To override the include_path and error_reporting with an ini value, a developer would set:
Important
The reserved prefix "php" only works with INI files. You can't set PHP INI values with PHP or XML config.
1219
1220
Create A Project
Nota
The following examples will assume you have the command line interface of Zend_Tool_Framework available to you.
Nota
To issue any of the commands for Zend_Tool_Project with CLI, you must be in the directory where the project was initially created. To get started with Zend_Tool_Project, you simply need to create a project. Creating a project is simple: go to a place on your filesystem, create a directory, change to that directory, then issue the following command: /tmp/project$ zf create project Optionally, you can create a directory anywhere by the following: $ zf create project /path/to/non-existent-dir The following table will describe the capabilities of providers that are available to you. As you can see in this table, there is a "Project" provider. The Project provider has a couple of actions associated to it, and with those actions a number of options that can be used to modify the behavior of the action and provider.
1221
Zend_Tool_Project
1222
Starting multi-lingual
So let's get started with multi-lingual business. What we want to do is translate our string output so the view produces the translated output. Otherwise we would have to write one view for each language, and no one would like to do this. Generally, multi-lingual sites are very simple in their design. There are only four steps you would have to do: 1. Decide which adapter you want to use; 2. Create your view and integrate Zend_Translate in your code; 3. Create the source file from your code; 4. Translate your source file to the desired language.
1223
Zend_Translate
The following sections guide you through all four steps. Read through the next few pages to create your own multilingual web application.
Use comma separated (*.csv/*.txt) Simple text file format; fast; possible files problems with unicode characters Use binary gettext (*.mo) files Use simple ini (*.ini) files GNU standard for linux; thread-safe; needs tools for translation Simple text file format; fast; possible problems with unicode characters
Use termbase exchange (*.tbx/*.xml) Industry standard for inter application files terminology strings; XML format Use tmx (*.tmx/*.xml) files Industry standard for inter application translation; XML format; human readable Cross platform application framework; XML format; human readable A simpler format as TMX but related to it; XML format; human readable Industry standard for XML document translation memory; XML format; human readable Different other adapters may be implemented in the future
Qt
Xliff XmlTm
Others
*.sql
Nota
When deciding your adapter you should also be aware of the used encoding. Even if Zend Framework declares UTF-8 as default encoding you will sometimes be in the need of other encoding. Zend_Translate will not change any encoding which is defined within the source file which means that if your Gettext source is build upon ISO-8859-1 it will also return strings in this encoding without converting them. There is only one restriction:
1224
Zend_Translate
When you use a xml based source format like TMX or XLIFF you must define the encoding within the xml files header because xml files without defined encoding will be treated as UTF-8 by any xml parser by default. You should also be aware that actually the encoding of xml files is limited to the encodings supported by PHP which are UTF-8, ISO-8859-1 and US-ASCII.
Zend_Translate_Adapter_Array
The Array Adapter is the Adapter which is simplest to use for programmers. But when you have numerous translation strings or many languages you should think about another Adapter. For example, if you have 5000 translation strings, the Array Adapter is possibly not the best choice for you. You should only use this Adapter for small sites with a handful of languages, and if you or your programmer team creates the translations yourselves.
Zend_Translate_Adapter_Csv
The Csv Adapter is the Adapter which is simplest to use for customers. CSV files are readable by standard text editors, but text editors often do not support utf8 character sets. You should only use this Adapter if your customer wants to do translations himself.
Nota
Beware that the Csv Adapter has problems when your Csv files are encoded differently than the locale setting of your environment. This is due to a Bug of PHP itself which will not be fixed before PHP 6.0 (http:// bugs.php.net/bug.php?id=38471). So you should be aware that the Csv Adapter due to PHP restrictions is not locale aware.
Zend_Translate_Adapter_Gettext
The Gettext Adapter is the Adapter which is used most frequently. Gettext is a translation source format which was introduced by GNU, and is now used worldwide. It is not human readable, but there are several freeware tools (for instance, POEdit [http://sourceforge.net/projects/poedit/]), which are very helpful. The Zend_Translate Gettext Adapter is not implemented using PHP's gettext extension. You can use the Gettext Adapter even if you do not have the PHP gettext extension installed. Also the Adapter is thread-safe and the PHP gettext extension is currently not thread-safe. Most people will use this adapter. With the available tools, professional translation is very simple. But gettext data are is stored in a machine-readable format, which is not readable without tools.
Zend_Translate_Adapter_Ini
The Ini Adapter is a very simple Adapter which can even be used directly by customers. INI files are readable by standard text editors, but text editors often do not support utf8 character sets. You should only use this Adapter when your customer wants to do translations himself. Do not use this adapter as generic translation source.
1225
Zend_Translate
characters, you may find your translations no longer work when using the INI adapter. If this is the case, we recommend utilizing a different adapter.
Zend_Translate_Adapter_Tbx
The Tbx Adapter is an Adapter which will be used by customers which already use the TBX format for their internal translation system. Tbx is no standard translation format but more a collection of already translated and pre translated source strings. When you use this adapter you have to be sure that all your needed source string are translated. TBX is a XML file based format and a completely new format. XML files are human-readable, but the parsing is not as fast as with gettext files. This adapter is perfect for companies when pre translated source files already exist. The files are human readable and system-independent.
Zend_Translate_Adapter_Tmx
The Tmx Adapter is the Adapter which will be used by most customers which have multiple systems which use the same translation source, or when the translation source must be system-independent. TMX is a XML file based format, which is announced to be the next industry standard. XML files are human-readable, but the parsing is not as fast as with gettext files. Most medium to large companies use this adapter. The files are human readable and system-independent.
Zend_Translate_Adapter_Qt
The Qt Adapter is for all customers which have TS files as their translation source which are made by QtLinguist. QT is a XML file based format. XML files are human-readable, but the parsing is not as fast as with gettext files. Several big players have build software upon the QT framework. The files are human readable and system-independent.
Zend_Translate_Adapter_Xliff
The Xliff Adapter is the Adapter which will be used by most customers which want to have XML files but do not have tools for TMX. XLIFF is a XML file based format, which is related to TMX but simpler as it does not support all possibilities of it. XML files are human-readable, but the parsing is not as fast as with gettext files. Most medium companies use this adapter. The files are human readable and system-independent.
Zend_Translate_Adapter_XmlTm
The XmlTm Adapter is the Adapter which will be used by customers which do their layout themself. XmlTm is a format which allows the complete html source to be included in the translation source, so the translation is coupled with the layout. XLIFF is a XML file based format, which is related to XLIFF but its not as simple to read. This adapter should only be used when source files already exist. The files are human readable and system-independent.
1226
Zend_Translate
The usage of the prefix "Zend" should be limited to Zend Framework. If you extend Zend_Translate with your own adapter, you should name it like "Company_Translate_Adapter_MyFormat". The following code shows an example of how a self written adapter class could be implemented: try { $translate = new Zend_Translate('Company_Translate_Adapter_MyFormat', '/path/to/translate.xx', 'en', array('myoption' => 'myvalue')); } catch (Exception $e) { // File not found, no adapter class... // General failure }
Nota
You must set the cache before you use or initiate any adapter or instance of Zend_Translate. Otherwise your translation source will not be cached until you add a new source with the addTranslation() method.
1227
Zend_Translate
The example above shows some output with no support for translation. You probably write your code in your native language. Generally you need to translate not only the output, but also error and log messages. The next step is to integrate Zend Translate into your existing code. Of course it is much easier if you had already written your code with translation in mind, than changing your code afterwards.
$translate = new Zend_Translate 'gettext', '/path/to/translation/source-de.mo', 'de' ); In this example we chose the Gettext Adapter. We place our file source-de.mo into the directory /path/to/translation. The gettext file will have German translation included, and we also added another language source for French. The next step is to wrap all strings which are to be translated. The simplest approach is to have only simple strings or sentences like this:
print $translate->_("Ejemplo") . "\n"; print "=======\n"; print $translate->_("Here is line one") . "\n"; Some strings do not needed to be translated. The separating line is always a separating line, even in other languages. Having data values integrated into a translation string is also supported through the use of embedded parameters.
printf($translate->_("Today is the %1\$s") . "\n", date("d.m.Y")); Instead of print(), use the printf() function and replace all parameters with %1\$s parts. The first is %1\$s, the second is %2\$s, and so on. This way a translation can be done without knowing the exact value. In our example, the date is always the actual day, but the string can be translated without the knowledge of the actual day. Each string is identified in the translation storage by a message ID. You can use message IDs instead of strings in your code, like this:
1228
Zend_Translate
print $translate->_(1) . "\n"; print "=======\n"; print $translate->_(2) . "\n"; But doing this has several disadvantages: You can not see what your code should output just by viewing your code. Also you will have problems if some strings are not translated. You must always keep in mind how translation works. First Zend_Translate checks whether the specified language has a translation for the given message ID or string. If no translation string has been found it refers to the next lower level language as defined within Zend_Locale. So "de_AT" becomes "de" only. If there is no translation found for "de" either, then the original message is returned. This way you always have an output, even in case the message translation does not exist in your message storage. Zend_Translate never throws an error or exception when translating strings.
/application/ /languages/ /languages/lang.en /languages/lang.de /library/ Positive: all source files for every languages are stored in one directory. No splitting of related files. Language structured source
/application/ /languages/ /languages/en/ /languages/en/first.en /languages/en/second.en /languages/de/ /languages/de/first.de /languages/de/second.de /library Positive: Every language is stored in their own directories. Easy translation, as every language team has to translate only one directory. Also the usage of multiple files is transparent. Application structured source
/application/ /application/languages/
1229
Zend_Translate
/application/languages/first.en /application/languages/first.de /application/languages/second.en /application/languages/second.de /library/ Positive: all source files for every language are stored in one directory. No splitting of related files. Negative: having multiple files for the same language can be problematic. Gettext structured source
/application/ /languages/ /languages/de/ /languages/de/LC_MESSAGES/ /languages/de/LC_MESSAGES/first.mo /languages/de/LC_MESSAGES/second.mo /languages/en/ /languages/en/LC_MESSAGES/ /languages/en/LC_MESSAGES/first.mo /languages/en/LC_MESSAGES/second.mo /library/ Positive: existing gettext sources can be used without changing structure. Negative: having sub-sub directories may be confusing for people who have not used gettext before. File structured source
/application/ /application/models/ /application/models/MyModel.php /application/models/MyModel.de /application/models/MyModel.en /application/controllers/ /application/controllers/MyController.php /application/controllers/MyController.de /application/controllers/MyController.en /library/ Positive: translation files are localted near their source. Negative: too many and also small translation files result in being tendious to translate. Also every file has to be added as translation source. Single structured and language structured source files are most usable for Zend_Translate. So now, that we know which structure we want to have, we should create our translation source files.
1230
Zend_Translate
Nota
Note that most of the described formats should be created by using a tool or a generation process. These Tools and processes are not part of Zend Framework and for most of the described formats free tools are available.
Nota
Files which do not return an array will fail to be included. Also any output within this file will be ignored and suppressed.
1231
Zend_Translate
As you can see the adapters are used exactly the same way, with one small difference: change array to gettext. All other usages are exactly the same as with all other adapters. With the gettext adapter you no longer have to be aware of gettext's standard directory structure, bindtextdomain and textdomain. Just give the path and filename to the adapter.
Nota
You should always use UTF-8 as source encoding. Otherwise you will have problems when using two different source encodings. E.g. one of your source files is encoded with ISO-8815-11 and another one with CP815. You can set only one encoding for your source file, so one of your languages probably will not display correctly. UTF-8 is a portable format which supports all languages. When using UTF-8 for all languages, you will eliminate the problem of incompatible encodings. Many gettext editors add adapter informations as empty translation string. This is the reason why empty strings are not translated when using the gettext adapter. Instead they are erased from the translation table and provided by the getAdapterInfo() method. It will return the adapter informations for all added gettext files as array using the filename as key. // Getting the adapter informations $translate = new Zend_Translate('gettext', '/path/to/english.mo', 'en'); print_r($translate->getAdapterInfo());
$translate = new Zend_Translate('tmx', 'path/to/mytranslation.tmx', 'en'); TMX files can have several languages within the same file. All other included languages are added automatically, so you do not have to call addLanguage().
1232
Zend_Translate
If you want to have only specified languages from the source translated you can set the option 'defined_language' to TRUE. With this option you can add the wished languages explicitly with addLanguage(). The default value for this option is to add all languages.
$translate = new Zend_Translate('csv', '/path/to/mytranslation.csv', 'de'); $translate->addTranslation('path/to/other.csv', 'fr'); There are three different options for the CSV adapter. You can set 'delimiter', 'limit' and 'enclosure'. The default delimiter for CSV string is ';', but with the option 'delimiter' you can decide to use another one. The default limit for a line within a CSV file is '0'. This means that the end of a CSV line is searched automatically. If you set 'limit' to any value, then the CSV file will be read faster, but any line exceeding this limit will be truncated. The default enclosure to use for CSV files is '"'. You can set a different one using the option 'enclosure'.
$translate = new Zend_Translate( 'csv', '/path/to/mytranslation.csv', 'de', array('delimiter' => ',')); $translate->addTranslation('/path/to/other.csv', 'fr');
Nota
When you are using non-ASCII characters within your CSV file, like umlauts or UTF-8 chars, then you should always use enclosure. Omitting the enclosure can lead to missing characters in your translation.
1233
Zend_Translate
$translate = new Zend_Translate('ini', '/path/to/mytranslation.ini', 'de'); $translate->addTranslation('/path/to/other.ini', 'it'); INI files have several restrictions. If a value in the ini file contains any non-alphanumeric characters it needs to be enclosed in double-quotes ("). There are also reserved words which must not be used as keys for ini files. These include: NULL, yes, no, TRUE, and FALSE. Values NULL, no and FALSE results in "", yes and TRUE results in 1. Characters {}|&~![()" must not be used anywhere in the key and have a special meaning in the value. Do not use them as it will produce unexpected behaviour.
1234
Zend_Translate
disableNotices
all
ignore
all
log
all
logMessage
all
logUntranslated
all
reload
all
scan
all
1235
Zend_Translate
Option
Adapter
Description Default value Zend_Translate::LOCALE_DIRECTORY the locale will be detected within the directory. If set to Zend_Translate::LOCALE_FILENAME the locale will be detected within the filename. See the section called Automatic source detection for details Defines which sign is used ; as delimiter for separating source and translation Defines the enclosure " character to be used. Defaults to a doublequote Defines the maximum 0 length of a csv line. When set to 0 it will be detected automatically
delimiter
Csv
enclosure
Csv
length
Csv
When you want to have self defined options, you are also able to use them within all adapters. The setOptions() method can be used to define your option. setOptions() needs an array with the options you want to set. If an given option exists it will be signed over. You can define as much options as needed as they will not be checked by the adapter. Just make sure not to overwrite any existing option which is used by an adapter. To return the option you can use the getOptions() method. When getOptions() is called without a parameter it will return all options set. When the optional parameter is given you will only get the specified option.
Handling languages
When working with different languages there are a few methods which will be useful. The getLocale() method can be used to get the currently set language. It can either hold an instance of Zend_Locale or the identifier of a locale. The setLocale() method sets a new standard language for translation. This prevents the need of setting the optional language parameter more than once to the translate() method. If the given language does not exist, or no translation data is available for the language, setLocale() tries to downgrade to the language without the region if any was given. A language of en_US would be downgraded to en. When even the downgraded language can not be found an exception will be thrown. The isAvailable() method checks if a given language is already available. It returns TRUE if data for the given language exist. And finally the getList() method can be used to get all currently set languages for an adapter returned as array.
1236
Zend_Translate
echo $translate->_("my_text", "fr"); // or set a new language $translate->setLocale("fr"); echo $translate->_("my_text"); // refer to the base language // fr_CH will be downgraded to fr $translate->setLocale("fr_CH"); echo $translate->_("my_text"); // check if this language exist if ($translate->isAvailable("fr")) { // language exists }
1237
Zend_Translate
// Ejemplo 4: // Returns 'it' as translation source and overrides the automatic settings $translate = new Zend_Translate( 'gettext', 'my_it.mo', 'auto', array('scan' => Zend_Translate::LOCALE_FILENAME)); $translate->addTranslation('my_ru.mo', 'ru'); $translate->setLocale('it_IT'); After setting a language manually with the setLocale() method the automatic detection will be switched off and overridden. If you want to use it again, you can set the language auto with setLocale() which will reactivate the automatic detection for Zend_Translate. Since Zend Framework 1.7.0 Zend_Translate also recognises an application wide locale. You can simply set a Zend_Locale instance to the registry like shown below. With this notation you can forget about setting the locale manually with each instance when you want to use the same locale multiple times. // in your bootstrap file $locale = new Zend_Locale(); Zend_Registry::set('Zend_Locale', $locale); // default language when requested language is not available $defaultlanguage = 'en'; // somewhere in your application $translate = new Zend_Translate('gettext', 'my_de.mo'); if (!$translate->isAvailable($locale->getLanguage())) { // not available languages are rerouted to another language $translate->setLocale($defaultlanguage); } $translate->getLocale();
Nota
Automatic source detection is available since Zend Framework version 1.5 . The usage is quite the same as initiating a single translation source with one difference. You must give a directory which has to be scanned instead a file.
1238
Zend_Translate
// // // // //
$translate = new Zend_Translate('tmx', '/language'); So Zend_Translate does not only search the given directory, but also all subdirectories for translation source files. This makes the usage quite simple. But Zend_Translate will ignore all files which are not sources or which produce failures while reading the translation data. So you have to make sure that all of your translation sources are correct and readable because you will not get any failure if a file is bogus or can not be read.
Nota
Depending on how deep your directory structure is and how much files are within this structure it can take a long time for Zend_Translate to complete. In our example we have used the TMX format which includes the language to be used within the source. But many of the other source formats are not able to include the language within the file. Even this sources can be used with automatic scanning if you do some pre-requisits as described below:
Nota
This works only for adapters which do not include the language within the source file. Using this option for example with TMX will be ignored. Also language definitions within the filename will be ignored when using this option.
Nota
You should be aware if you have several subdirectories under the same structure. Assuming we have a structure like /language/module/de/en/file.mo. In this case the path contains multiple strings
1239
Zend_Translate
which would be detected as locale. It could be either de or en. In such a case the behaviour is undefined and it is recommended to use file detection in such situations.
Complete filename
Having the whole file named after the language is the simplest way but only viable if you have only one file per language.
Filename tokens
Zend_Translate is also capable of detecting the language if it is included within the filename. But if you go this way you will have to separate the language with a token. There are three supported tokens which can be used: a dot '.', an underscore '_', or a hyphen '-'.
1240
Zend_Translate
/languages/ /languages/view_en.mo -> detects english /languages/view_de.mo -> detects german /languages/view_it.mo -> detects italian The first found string delimited by a token which can be interpreted as a locale will be used. See the following example for details.
/languages/ /languages/view_en_de.mo -> detects english /languages/view_en_es.mo -> detects english and overwrites the first file /languages/view_it_it.mo -> detects italian All three tokens are used to detect the locale. When the filename contains multiple tokens, the first found token depends on the order of the tokens which are used. See the following example for details.
/languages/ /languages/view_en-it.mo -> detects english because '_' will be used before '-' /languages/view-en_it.mo -> detects italian because '_' will be used before '-' /languages/view_en.it.mo -> detects italian because '.' will be used before '_'
1241
Zend_Translate
Nota
You should note that any translation which can not be found will be logged. This means all translations when a user requests a language which is not supported. Also every request for a message which can not be translated will be logged. Be aware, that 100 people requesting the same translation, will result 100 logged notices. This feature can not only be used to log messages but also to attach this untranslated messages into an empty translation file. To do so you will have to write your own log writer which writes the format you want to have and strips the prepending "Untranslated message". You can also set the 'logMessage' option when you want to have your own log message. Use the '%message%' token for placing the messageId within your log message, and the '%locale%' token for the requested locale. See the following example for a self defined log message:
1242
Zend_Translate
$translate->setOptions(array( 'log' => $log, 'logMessage' => "Missing '%message%' within locale '%locale%'", 'logUntranslated' => true)); $translate->translate('unknown string');
Nota
Attention: the returned array can be very big, depending on the number of added locales and the amount of translation data.
1243
Zend_Translate
When you want to use plurals with Zend_Translate you must not need to know how the plurals are defined, only the translator must know as he does the translation. The only information you need to have is the language. There are two way for using plurals... the traditional one, which means that you use a own method, and a modern one, which allows you to do plural translations with the same method as normal translations.
$translate = new Zend_Translate('gettext', '/path/to/german.mo', 'de'); $translate->translate(array('Car', 'Cars', $number)); Using modern plural translations it is also possible to use any language as source for messageId's.
Ejemplo 57.19. Ejemplo of modern plural translations using a different source language
Let's expect we want to use russian and let's also expect that the given messageId's are russian and not english.
$translate = new Zend_Translate('gettext', '/path/to/german.mo', 'de'); $translate->translate(array('Car', 'Cars first plural', 'Cars second plural', $number, 'ru'));
1244
Zend_Translate
As you can see you can give more than just the one english plural. But you must give the source language in this case so Zend_Translate knows which plural rules it has to apply. When you omit the plural language then english will be used per default and any additional plural definition will be ignored.
In the above example plural_0 and plural_1 are the plural definitions from the source code. And the array at plural_0 has all translated plural forms available. Take a look at the following example with real content and translation from english source to german.
1245
Zend_Translate
); When your translated language supports more plural forms then simply add them to the array below the first plural form. When your source language suppors more plural forms, than simply add a new empty translation.
"plural_0";"plural_0 (ru)";"plural_1 (ru)";"plural_2 (ru)";"plural_3 (ru)" "plural_1"; All translated plural forms have to be added after the first plural of the source language. And all further plural forms of the source language have to be added below but without translation. Note that you must add a delimiter to empty source plurals.
Nota
Note that gettext does not support the usage of source languages which are not using english plural forms. When you plan to use a source language which supports other plural forms like russian for example, then you can not use gettext sources.
1246
At the time of writing, Zend_Uri only supports the HTTP and HTTPS schemes.
1247
Zend_Uri
URI Validation
The Zend_Uri::check() method can only be used if validation of an existing URI is needed.
Nota
Zend_Uri::setConfig() sets configuration options globally. It is recommended to reset the 'allow_unwise' option to 'false', like in the example above, unless you are certain you want to always allow unwise characters globally.
1248
Zend_Uri
The getScheme() instance method returns only the scheme part of the URI object.
The getUri() method returns the string representation of the entire URI.
The valid() instance method provides a means to check that the URI object is still valid.
1249
1250
Qu es un validador?
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 tambin podr proporcionar informacin adicional sobre que requisito(s) no son satisfechos. Por ejemplo, una aplicacin web podra requerir que un usuario ingrese su nombre, de entre seis y doce caracteres de longitud y que slo puede contener caracteres alfanumricos. 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, sera til saber cul de estos requisitos no se cumple.
Nota
El mtodo getMessages() devuelve informacin del fracaso de la validacin slo para la llamada ms reciente a isValid(). Cada llamada a isValid() borra los mensajes y errores causados por una llamada anterior isValid(), porque es probable que cada llamada a isValid() se refiera al valor de una entrada diferente. El siguiente ejemplo ilustra la validacin de una direccin de e-mail:
$validator = new Zend_Validate_EmailAddress(); if ($validator->isValid($email)) { // email parece ser vlido } else { // email es invlido; muestre la razones foreach ($validator->getMessages() as $messageId => $message) { echo "Falla de validacin '$messageId': $message\n"; }
1251
Zend_Validate
$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" } Puede establecer varios mensajes usando el mtodo setMessages(). Su argumento es un array que contiene pares de clave/mensaje.
$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' )); Incluso, si su aplicacin requiere una mayor flexibilidad para informar los fallos de validacin, puede acceder a las propiedades por el mismo nombre, tal como los tokens de mensajes apoyados por una determinada clase de validacin. La propiedad value siempre est disponible en un validador; es el valor que especific en el argumento de isValid(). En cada clase de validacin se puede dar apoyo a otras propiedades basndose en el esquema de caso por caso.
1252
Zend_Validate
if (!validator->isValid('word')) { echo 'Palabra fallada: ' . $validator->value . '; su longitud no est entre ' . $validator->min . ' y ' . $validator->max . "\n"; }
if (Zend_Validate::is($email, 'EmailAddress')) { // Si, el email parece ser vlido } Si el validador lo necesita, tambin puede pasar un array de constructores de argumentos.
if (Zend_Validate::is($value, 'Between', array(1, 12))) { // Si, $value est entre 1 y 12 } El mtodo is() devuelve un valor booleano, lo mismo que el mtodo isValid(). Cuando se utiliza el mtodo esttico is(), no estn disponibles los mensajes de fracaso de validacin. El uso esttico puede ser conveniente para invocar un validador ad-hoc (hecho especialmente), pero si tiene la necesidad de ejecutar el validador para mltiples entradas, es ms eficiente usar mtodos no estticos, creando una instancia del objeto validador y llamando a su mtodo isValid(). Tambin la clase Zend_Filter_Input le permite crear ejemplos y ejecutar mltiples filtros y clases de validadores por demanda, para procesar juegos de datos de entrada. Ver the section called Zend_Filter_Input.
Translating messages
Validate classes provide a setTranslator() method with which you can specify a instance of Zend_Translate which will translate the messages in case of a validation failure. The getTranslator() method returns the set translator instance.
$validator = new Zend_Validate_StringLength(8, 12); $translate = new Zend_Translate( 'array', array(Zend_Validate_StringLength::TOO_SHORT => 'Translated \'%value%\''), 'en' );
1253
Zend_Validate
$validator->setTranslator($translate); With the static setDefaultTranslator() method you can set a instance of Zend_Translate which will be used for all validation classes, and can be retrieved with getDefaultTranslator(). This prevents you from setting a translator manually for all validator classes, and simplifies your code.
$translate = new Zend_Translate( 'array', array(Zend_Validate_StringLength::TOO_SHORT => 'Translated \'%value%\''), 'en' ); Zend_Validate::setDefaultTranslator($translate);
Nota
When you have set an application wide locale within your registry, then this locale will be used as default translator. Sometimes it is necessary to disable the translator within a validator. To archive this you can use the setDisableTranslator() method, which accepts a boolean parameter, and translatorIsDisabled() to get the set value.
$validator = new Zend_Validate_StringLength(8, 12); if (!$validator->isTranslatorDisabled()) { $validator->setDisableTranslator(); } It is also possible to use a translator instead of setting own messages with setMessage(). But doing so, you should keep in mind, that the translator works also on messages you set your own.
Alnum
Devuelve true si y slo si $valor contiene caracteres alfanumricos nicamente. Este validador incluye una opcin para considerar tambin al espacio en blanco como caracter vlido.
Nota
Los caracteres alfabticos significan caracteres que componen palabras en cada idioma. Sin embargo, el alfabeto ingls es tratado como caracteres alfabticos en los siguientes idiomas: chino, japons, coreano. El lenguaje es especificado por Zend_Locale.
Alpha
Devuelve true si y slo si $valor slo contiene caracteres alfabticos. Este validador incluye una opcin para considerar tambin al espacio en blanco como caracter vlido.
1254
Zend_Validate
Barcode
Este validador es instanciado con un tipo de cdigo de barras contra el valor del cdigo de barras que quiere validar. En la actualidad acepta los tipos de cdigo de barras "UPC-A" (Universal Product Code) y "EAN-13" (European Article Number), adems el mtodo isValid() devuelve verdadero si y slo si la entrada valida satisfactoriamente contra el algoritmo de validacin del cdigo de barras. Antes de enviar los datos de entrada al validador, debe asegurarse de eliminar todos los caracteres distintos a los dgitos cero a nueve (0-9).
Between
Devuelve true si y slo si $valor est entre los valores lmites mnimo y mximo. La comparacin es inclusiva por defecto ($valor puede ser igual a una valor lmite), aunque esto puede ser anulado a fin de hacer una comparacin estricta, donde $valor debe ser estrictamente mayor al mnimo y estrictamente menor al mximo.
Ccnum
Devuelve true si y slo si $valor sigue el algoritmo Luhn (mod-10 checksum) para tarjetas de crdito.
Date
Devuelve true si y slo si $valor es una fecha vlida en el formato YYYY-MM-DD (AAAA-MM-DD). Si se usa la opcin locale entonces la fecha ser validada de acuerdo a lo establecido para ese locale. Adems, si se establece la opcin format ese formato se utiliza para la validacin. Para ms detalles acerca de los parmetros opcionales ver en: Zend_Date::isDate().
Basic usage
An example of basic usage of the validators:
//Check that the email address exists in the database $validator = new Zend_Validate_Db_RecordExists( array( 'table' => 'users', 'field' => 'emailaddress' ) ); if ($validator->isValid($emailaddress)) { // email address appears to be valid } else { // email address is invalid; print the reasons foreach ($validator->getMessages() as $message) { echo "$message\n"; } }
1255
Zend_Validate
The above will test that a given email address is in the database table. If no record is found containing the value of $emailaddress in the specified column, then an error message is displayed. //Check that the username is not present in the database $validator = new Zend_Validate_Db_NoRecordExists( array( 'table' => 'users', 'field' => 'username' ) ); if ($validator->isValid($username)) { // username appears to be valid } else { // username is invalid; print the reason $messages = $validator->getMessages(); foreach ($messages as $message) { echo "$message\n"; } } The above will test that a given username is not in the database table. If a record is found containing the value of $username in the specified column, then an error message is displayed.
Excluding records
Zend_Validate_Db_RecordExists and Zend_Validate_Db_NoRecordExists also provide a means to test the database, excluding a part of the table, either by providing a where clause as a string, or an array with the keys "field" and "value". When providing an array for the exclude clause, the != operator is used, so you can check the rest of a table for a value before altering a record (for example on a user profile form) //Check no other users have the username $user_id = $user->getId(); $validator = new Zend_Validate_Db_NoRecordExists( array( 'table' => 'users', 'field' => 'username', 'exclude' => array( 'field' => 'id', 'value' => $user_id ) ) ); if ($validator->isValid($username)) { // username appears to be valid } else { // username is invalid; print the reason $messages = $validator->getMessages(); foreach ($messages as $message) { echo "$message\n"; }
1256
Zend_Validate
} The above example will check the table to ensure no records other than the one where id = $user_id contains the value $username. You can also provide a string to the exclude clause so you can use an operator other than !=. This can be useful for testing against composite keys.
$post_id = $post->getId(); $clause = $db->quoteInto('post_id = ?', $category_id); $validator = new Zend_Validate_Db_RecordExists( array( 'table' => 'posts_categories', 'field' => 'post_id', 'exclude' => $clause ) ); if ($validator->isValid($username)) { // username appears to be valid } else { // username is invalid; print the reason $messages = $validator->getMessages(); foreach ($messages as $message) { echo "$message\n"; } } The above example will check the posts_categories table to ensure that a record with the post_id has a value matching $category_id
Database Adapters
You can also specify an adapter. This will allow you to work with applications using multiple database adapters, or where you have not set a default adapter. As in the example below:
$validator = new Zend_Validate_Db_RecordExists( array( 'table' => 'users', 'field' => 'id', 'adapter' => $dbAdapter ) );
Database Schemas
You can specify a schema within your database for adapters such as PostgreSQL and DB/2 by simply supplying an array with table and schema keys. As in the example below:
1257
Zend_Validate
Digits
Devuelve true si y slo si $valor contiene solamente dgitos.
Direccin de Email
Zend_Validate_EmailAddress Le permite validar una direccin de email. El validador primero divide la direccin de email en la parte local @ nombre de host e intenta igualar a estos contra especificaciones conocidas para direcciones y nombres de host para el correo electrnico. Utilizacin bsica Un ejemplo bsico de uso se ve a continuacin:
$validator = new Zend_Validate_EmailAddress(); if ($validator->isValid($email)) { // El email parece ser vlido } else { // El email es invlido; muestre las razones foreach ($validator->getMessages() as $message) { echo "$message\n"; } } Esto coincide con el correo electrnico $email y si fracasa, alimenta $validator->getMessages() con mensajes de error tiles. Partes locales complejas Zend_Validate_EmailAddress se comparar con cualquier direccin de correo vlida de acuardo a RFC2822. Por ejemplo, correos electrnicos vlidos incluyen bob@domain.com , bob+jones@domain.us , "bob@jones"@domain.com y "bob jones"@domain.com Algunos formatos obsoletos de email actualmente no validan (por ejemplo los retornos de carro o "\" un caracter en una direccin de correo electrnico). Validar diferentes tipos de nombres de host La parte nombre de host de una direccin de correo es validado contra Zend_Validate_Hostname. Por defecto slo son aceptados nombres de host DNS de la forma domain.com, aunque si lo desea tambin puede aceptar direcciones IP y nombres de host locales. Para ello necesita instanciar a Zend_Validate_EmailAddress pasando un parmetro para indicar el tipo de nombres de host que quiere aceptar. Ms detalles estn incluidos en Zend_Validate_EmailAddress, aunque abajo hay un ejemplo de cmo aceptar tanto nombres de host DNS y locales:
1258
Zend_Validate
Zend_Validate_Hostname::ALLOW_LOCAL); if ($validator->isValid($email)) { // email parece ser vlido } else { // email es invlido; muestre las razones foreach ($validator->getMessages() as $message) { echo "$message\n"; } } Verificar si el nombre de host realmente acepta email Slo porque una direccin de correo electrnico est en el formato correcto, no necesariamente significa que esa direccin de correo electrnico existe realmente. Para ayudar a resolver este problema, puede usar la validacin MX para comprobar si existe una entrada MX (email) en el registro DNS para correo electrnico en ese nombre de host. Esto le dice que el nombre de host acepta email, pero no le dice si la direccin de correo electrnico exacta es vlida en si misma. La comprobacin MX no est activada por defecto y en este momento es soportada slo por plataformas UNIX. Para habilitar el control MX puede pasar un segundo parmetro al constructor Zend_Validate_EmailAddress.
$validator = new Zend_Validate_EmailAddress(Zend_Validate_Hostname::ALLOW_DNS, true); Alternativamente, para activar o desactivar la validacin MX puede pasar true o false a $validator>setValidateMx(). Al habilitarlo, se usarn las funciones de red para comprobar la presencia de un registro MX en el nombre de host de la direccin de correo electrnico que desea validar. Tenga en cuenta esto probablemente har ms lento su script. Validating International Domains Names Zend_Validate_EmailAddress tambin comparar caracteres internationales que existen en algunos dominios. Esto se conoce como soporte de International Domain Name (IDN). Est activado por defecto, aunque puede deshabilitarlo internamente cambiando el ajuste a travs del objeto Zend_Validate_Hostname que existe en Zend_Validate_EmailAddress.
Tenga en cuenta que los IDNs se validarn solo si usted permite que nombres de host DNS sean validados. Validar Dominios de Nivel Superior (TLD) Por defecto, un nombre de host se cotejar con una lista conocida de TLDs. Est activado por defecto, aunque puede deshabilitarlo cambiando el ajuste a travs del objeto interno Zend_Validate_Hostname que existe en Zend_Validate_EmailAddress.
1259
Zend_Validate
Tenga en cuenta que los TLDs se validarn solo si usted permite que nombres de host DNS sean validados.
Float
Devuelve true si y slo si $value es un valor de punto flotante. Desde Zend Framework 1.8 toma en cuenta la localizacion actual del navegador, las variables o el uso. Puede usar get/setLocale para cambiar la configuracion regional o crear una instancia para este validador
GreaterThan
Devuelve true si y slo si $valor es mayor al lmite mnimo.
Hex
Devuelve true si y slo si $valor contiene caracteres hexadecimales (0-9 y A-F).
$validator = new Zend_Validate_Hostname(); if ($validator->isValid($hostname)) { // hostname parece ser vlido } else { // hostname es invlido; muestre las razones foreach ($validator->getMessages() as $message) { echo "$message\n"; } } Comprobar el nombre de host $hostname y si fracasa alimentar a $validator->getMessages() con mensajes de error. Validar diferentes tipos de nombres de host Tambin se puede encontrar coincidencias de direcciones IP, nombres de host locales, o una combinacin de todos los tipos permitidos. Esto puede hacerse pasando un parmetro a Zend_Validate_Hostname cuando lo instancia. El parmetro debe ser un entero que determina qu tipos de nombres de host estn permitidos. Se recomienda el uso de las constantes de Zend_Validate_Hostname para hacerlo. Las constantes de Zend_Validate_Hostname son: ALLOW_DNS para permitir slo nombres de host DNS, ALLOW_IP para permitir direcciones IP, ALLOW_LOCAL para permitir nombres de host de la red local, y ALLOW_ALL para permitir todos estos tres tipos. Para comprobar que direcciones IP puede utilizar, vea el siguiente ejemplo:
1260
Zend_Validate
if ($validator->isValid($hostname)) { // hostname parece ser vlido } else { // hostname es invlido; muestre las razones foreach ($validator->getMessages() as $message) { echo "$message\n"; } } Usando ALLOW_ALL para aceptar todos los tipos de nombres de host, tambin puede combinar estos tipos para realizar combinaciones. Por ejemplo, para aceptar nombres de host DNS y locales, instancie el objeto Zend_Validate_Hostname como:
$validator = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_DNS | Zend_Validate_Hostname::ALLOW_IP); Validacin de Nombres de Dominio Internacionales Algunos (ccTLD), es decir pases "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 ingls). Se puede buscar una coincidencia de estos dominios con Zend_Validate_Hostname, a travs de caracteres extendidos que se utilizan en el proceso de validacin. En la actualidad la lista de las ccTLDs incluyen a: at (Austria) ch (Suiza) li (Liechtenstein) de (Alemania) fi (Finlandia) hu (Hungra) no (Noruega) se (Suecia) Cotejar dominios IDN es tan simple como usar el validador estndar Hostname, ya que este viene habilitado por defecto. Si desea desactivar la validacin IDN, se puede hacer ya sea pasando un parmetro al constructor Zend_Validate_Hostname o a travs del mtodo $validator->setValidateIdn(). Puede deshabilitar la validacin IDN, pasando un segundo parmetro al constructor Zend_Validate_Hostname de la siguiente manera.
$validator = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_DNS, false); Alternativamente puede pasar TRUE o FALSE a $validator->setValidateIdn() para activar o desactivar la validacin IDN. Si est tratando de cotejar un nombre de host IDN que actualmente no est soportado, es probable que falle la validacin 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 validacin normal.
1261
Zend_Validate
Tenga en cuenta que una validacin IDN solo se realizar si tiene habilidada la validacin para nombres de host DNS. Validar dominios de nivel superior 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 validacin TLD pasando un tercer parmetro al constructor Zend_Validate_Hostname. En el siguiente ejemplo estamos dando respaldo a la validacin IDN a travs del segundo parmetro.
$validator = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_DNS, true, false); Alternativamente puede pasar TRUE o FALSE a $validator->setValidateTld() para activar o desactivar la validacin TLD. Tenga en cuenta que una validacin de TLDs solo se realizar si tiene habilidada la validacin para nombres de host DNS.
Iban
Returns true if and only if $value contains a valid IBAN (International Bank Account Number). IBAN numbers are validated against the country where they are used and by a checksum. There are two ways to validate IBAN numbers. As first way you can give a locale which represents a country. Any given IBAN number will then be validated against this country.
$validator = new Zend_Validate_Iban('de_AT'); $iban = 'AT611904300234573201'; if ($validator->isValid($iban)) { // IBAN appears to be valid } else { // IBAN is invalid foreach ($validator->getMessages() as $message) { echo "$message\n"; } } This should be done when you want to validate IBAN numbers for a single countries. The simpler way of validation is not to give a locale like shown in the next example.
$validator = new Zend_Validate_Iban(); $iban = 'AT611904300234573201'; if ($validator->isValid($iban)) { // IBAN appears to be valid } else { // IBAN is invalid } But this shows one big problem: When you have to accept only IBAN numbers from one single country, for example france, then IBAN numbers from other countries would also be valid. Therefor just remember: When you have to
1262
Zend_Validate
validate a IBAN number against a defined country you should give the locale. And when you accept all IBAN numbers regardless of any country omit the locale for simplicity.
InArray
Devuelve true si y slo si $valor se encuentra en un array, y si la opcin es estricta entonces tambin verificar el tipo de dato de $valor.
Int
Returns true if and only if $value is a valid integer. Since Zend Framework 1.8 this validator takes into account the actual locale from browser, environment or application wide set locale. You can of course use the get/setLocale accessors to change the used locale or give it while creating a instance of this validator.
Ip
Devuelve true si y slo si $valor es una direccin IP vlida.
LessThan
Devuelve true si y slo si $valor es menor al lmite mximo.
NotEmpty
Devuelve true si y slo si $valor no es vaco.
Regex
Devuelve true si y slo si $valor coincide con el patrn de una expresin regular.
Sitemap Validators
The following validators conform to the Sitemap XML protocol [http://www.sitemaps.org/protocol.php].
Sitemap_Changefreq
Validates whether a string is valid for using as a 'changefreq' element in a Sitemap XML document. Valid values are: 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', or 'never'. Returns TRUE if and only if the value is a string and is equal to one of the frequencies specified above.
Sitemap_Lastmod
Validates whether a string is valid for using as a 'lastmod' element in a Sitemap XML document. The lastmod element should contain a W3C date string, optionally discarding information about time. Returns TRUE if and only if the given value is a string and is valid according to the protocol.
1263
Zend_Validate
$validator = new Zend_Validate_Sitemap_Lastmod(); $validator->isValid('1999-11-11T22:23:52-02:00'); // true $validator->isValid('2008-05-12T00:42:52+02:00'); // true $validator->isValid('1999-11-11'); // true $validator->isValid('2008-05-12'); // true $validator->isValid('1999-11-11t22:23:52-02:00'); // false $validator->isValid('2008-05-12T00:42:60+02:00'); // false $validator->isValid('1999-13-11'); // false $validator->isValid('2008-05-32'); // false $validator->isValid('yesterday'); // false
Sitemap_Loc
Validates whether a string is valid for using as a 'loc' element in a Sitemap XML document. This uses Zend_Form::check() internally. Read more at URI Validation.
Sitemap_Priority
Validates whether a value is valid for using as a 'priority' element in a Sitemap XML document. The value should be a decimal between 0.0 and 1.0. This validator accepts both numeric values and string values.
StringLength
Devuelve true si y slo si la longitud del string $valor es por lo menos un mnimo y no mayor a un mximo (cuando la opcin max no es NULL). Desde la versin 1.5.0, el mtodo setMin() lanza una excepcin si la longitud mnima tiene un valor mayor que la longitud mxima establecida, y el mtodo setMax() lanza una excepcin si la longitud mxima se fija a un valor inferior que la longitud mnima establecida. Desde la versin 1.0.2, esta clase soporta UTF-8 y a otras codificaciones, basado en el valor actual de: iconv.internal_encoding [http://www.php.net/manual/ en/ref.iconv.php#iconv.configuration].
Cadenas de Validadores
Frecuentemente deben aplicarse mltiples validaciones a algn valor en un orden particular. El siguiente cdigo demuestra una forma de resolver el ejemplo de la introduccin, donde el nombre de usuario debe tener entre 6 y 12 caracteres alfanumricos.
1264
Zend_Validate
// 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 validacin } else { // username fall en la validacin; muestre las razones foreach ($validatorChain->getMessages() as $message) { echo "$message\n"; } } Los validadores se ejecutan en el orden en que se agregaron a Zend_Validate. 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 slo contiene caracteres alfanumricos. La segunda validacin; de caracteres alfanumricos; se realiza independientemente de que la primera validacin; de longitud entre 6 y 12 caracteres; tenga xito. Esto significa que si ambas validaciones fallan, getMessages() devolver mensajes de fracaso desde ambos validadores. En algunos casos tiene sentido detener la cadena de validacin si falla alguno de los procesos de validacin. Zend_Validate acepta tales casos pasando como segundo parmetro el mtodo addValidator(). Poniendo $breakChainOnFailure a true, el validador agregado quebrar la cadena de ejecucin por el fracaso, que evita correr cualquier otra validacin que se decida que es innecesaria o inapropiada para la situacin. Si el ejemplo anterior fue escrito como sigue, entonces el sistema de validacin alfanumrica no se ejecutar si falla la longitud del string de validacin:
$validatorChain->addValidator(new Zend_Validate_StringLength(6, 12), true) ->addValidator(new Zend_Validate_Alnum()); Cualquier objeto que implemente Zend_Validate_Interface puede ser utilizado en una cadena de validacin.
Escribiendo Validadores
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 seccin. Zend_Validate_Interface define tres mtodos, isValid(), getMessages(), y getErrors(), que pueden ser implementadas por clases de usuario a fin de crear objetos de validacin personalizados. Un objeto que implementa una interfaz Zend_Validate_Interface puede aadirse a una cadena de validacin con Zend_Validate::addValidator(). Tales objetos tambin pueden ser usados con Zend_Filter_Input. De la descripcin anterior de Zend_Validate_Interface, podr inferir que las clases de validacin que proporciona Zend Framework devuelven un valor booleano para cuando un valor se valida satisfactoriamente o no. Tambin proporcionan informacin sobre por qu un valor fall en la validacin. La disponibilidad de las razones para los fracasos de validacin puede ser valiosa para una aplicacin por diversos motivos, tales como proporcionar estadsticas para anlisis de usabilidad. La funcionalidad de los mensajes de validacin bsica de fallos estn implementados en Zend_Validate_Abstract. A fin de incluir esta funcionalidad al crear una clase de validacin, simplemente
1265
Zend_Validate
extienda Zend_Validate_Abstract. En la extensin de la clase deber aplicar la lgica del mtodo isValid() y definir las variables y plantillas de mensajes que correspondan a los tipos de fallos de validacin que puedan suceder. Si falla un valor en su test de validacin, entonces isValid() deber devolver false. Si el valor pasa su test de validacin, entonces isValid() deber devolver true. En general, el mtodo isValid() no debera arrojar excepciones, salvo que sea imposible determinar si el valor de entrada es vlido o no. Algunos ejemplos de casos razonables para lanzar una excepcin podra ser si un archivo no puede abrirse, que un servidor LDAP no pudiera ser contactado, o una conexin a una base de datos no estuviera disponible. Estos son casos en los que puede ser necesario determinar el xito o fracaso de la validacin.
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; } } La clase define una plantilla para su nico mensaje de fallo de validacin, que incluye el mgico parmetro %value%. La llamada a _setValue() prepara al objeto para insertar automticamente en el mensaje de fallo al valor probado, si ste falla en la validacin. La llamada a _error() sigue las pistas para establecer una razn por el fracaso de la validacin. Dado que esta clase slo define un mensaje de fallo, no es necesario darle a _error() el nombre de la plantilla del mensaje de fallo.
1266
Zend_Validate
Estas razones en el fallo de validacin, son traducidas a las definiciones en la clase: 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 numrico", 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; } } Las propiedades pblicas $minimum y $maximum se han establecido para proporcionar los lmites mnimo y mximo, respectivamente, de un valor a validar. La clase tambin define dos variables de mensajes que corresponden a las propiedades pblicas y permiten usar min y max en plantillas de mensajes como parmetros mgicos, al igual que con value. Tenga en cuenta que si cualquiera de las comprobaciones de validacin falla en isValid(), ya est preparado un mensaje apropiado, y el mtodo inmediatamente devuelve false. Estas reglas de validacin 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 validacin. Sin embargo, esta necesidad no ser el caso. El siguiente ejemplo ilustra cmo escribir una clase
1267
Zend_Validate
con reglas de validacin independientes, donde el objeto validacin puede devolver mltiples razones por las cuales fracas un intento de validacin en particular.
Ejemplo 59.5. Validacin con Condiciones Independientes, Mltiples Razones del Fracaso
Considere escribir una clase de validacin y control de contraseas - cuando es necesario que un usuario elija una contrasea que cumple determinados criterios para ayudar a tener cuentas de usuario seguras. Supongamos que la seguridad de la contrasea aplica criterios que fuerzan a lo siguiente: debe tener al menos una longitud de 8 caracteres, contener al menos una letra en mayscula, contener al menos una letra en minscula, contener al menos un dgito. La siguiente clase implementa estos criterios de validacin:
class MyValid_PasswordStrength extends Zend_Validate_Abstract { const LENGTH = 'length'; const UPPER = 'upper'; const LOWER = 'lower'; const DIGIT = 'digit'; protected $_messageTemplates = self::LENGTH => "'%value%' self::UPPER => "'%value%' self::LOWER => "'%value%' self::DIGIT => "'%value%' ); 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; } array( debe tener al debe contener debe contener debe contener
menos una longitud de 8 caracteres", al menos una letra en mayscula", al menos una letra en minscula", al menos un dgito"
1268
Zend_Validate
if (!preg_match('/\d/', $value)) { $this->_error(self::DIGIT); $isValid = false; } return $isValid; } } Las cuatro pruebas de criterio en isValid() no devuelven inmediatamente false. Esto permite a la clase de validacin a proporcionar todas las razones por las que la contrasea de entrada no cumpli los requisitos de validacin. Si, por ejemplo, un usuario ingresara el string "#$%" como contrasea, isValid() causara que los cuatro mensajes de fracaso de validacin sean devueltos por un llamado posterior a getMessages().
Validation Messages
Each validator which is based on Zend_Validate provides one or multiple messages in the case of a failed validation. You can use this information for setting own messages or when you have to translate the messages a validator can return. The following table lists all available messages which are returned by each validator.
'%value%' is an invalid UPC-A barcode '%value%' should be 12 characters '%value%' is not between '%min%' and '%max%', inclusively '%value%' is not strictly between '%min%' and '%max%' '%value%' must contain between 13 and 19 digits Luhn algorithm (mod-10 checksum) failed on '%value%' '%value%' does not fit given date format
Date
1269
Zend_Validate
Validator
Message '%value%' does not appear to be a valid date No record matching %value% was found A record matching %value% was found '%value%' contains not only digit characters '%value%' is an empty string '%value%' is not a valid email address in the basic format localpart@hostname '%value%' is not a valid email address in the basic format localpart@hostname '%hostname%' is not a valid hostname for email address '%value%' '%hostname%' does not appear to have a valid MX record for the email address '%value%' '%localPart%' not matched against dot-atom format '%localPart%' not matched against quoted-string format '%localPart%' is not a valid local part for email address '%value%' '%value%' exceeds the allowed length Too much files, maximum '%max%' are allowed but '%count%' are given Too less files, minimum '%min%' are expected but '%count%' are given The file '%value%' does not match the given crc32 hashes There was no crc32 hash detected for the given file The file '%value%' could not be found The file '%value%' has a false extension The file '%value%' was not found The file '%value%' has a false mimetype of '%type%' The mimetype of file '%value%' could not been detected The file '%value%' can not be read
Db_Abstract
ERROR_RECORD_FOUND NOT_DIGITS
INVALID_FORMAT
INVALID_HOSTNAME INVALID_MX_RECORD
EmailAddress
DOT_ATOM QUOTED_STRING INVALID_LOCAL_PART LENGTH_EXCEEDED TOO_MUCH File_Count TOO_LESS DOES_NOT_MATCH File_Crc32 NOT_DETECTED NOT_FOUND FALSE_EXTENSION File_ExcludeExtension NOT_FOUND FALSE_TYPE File_ExcludeMimeType NOT_DETECTED NOT_READABLE
1270
Zend_Validate
Message The file '%value%' does not exist The file '%value%' has a false extension The file '%value%' was not found All files in sum should have a maximum size of '%max%' but '%size %' were detected All files in sum should have a minimum size of '%min%' but '%size %' were detected One or more files can not be read The file '%value%' does not match the given hashes There was no hash detected for the given file The file '%value%' could not be found Maximum allowed width for image '%value%' should be '%maxwidth%' but '%width%' detected Minimum expected width for image '%value%' should be '%minwidth%' but '%width%' detected Maximum allowed height for image '%value%' should be '%maxheight%' but '%height%' detected Minimum expected height for image '%value%' should be '%minheight%' but '%height%' detected The size of image '%value%' could not be detected The image '%value%' can not be read The file '%value%' is not compressed, '%type%' detected The mimetype of file '%value%' could not been detected The file '%value%' can not be read The file '%value%' is no image, '%type%' detected The mimetype of file '%value%' could not been detected The file '%value%' can not be read The file '%value%' does not match the given md5 hashes
File_FilesSize
TOO_SMALL
WIDTH_TOO_SMALL
NOT_DETECTED NOT_READABLE FALSE_TYPE File_IsCompressed NOT_DETECTED NOT_READABLE FALSE_TYPE File_IsImage NOT_DETECTED NOT_READABLE File_Md5 DOES_NOT_MATCH
1271
Zend_Validate
Validator
Message There was no md5 hash detected for the given file The file '%value%' could not be found The file '%value%' has a false mimetype of '%type%' The mimetype of file '%value%' could not been detected The file '%value%' can not be read The file '%value%' does exist The file '%value%' does not match the given sha1 hashes There was no sha1 hash detected for the given file The file '%value%' could not be found Maximum allowed size for file '%value%' is '%max%' but '%size%' detected Minimum expected size for file '%value%' is '%min%' but '%size%' detected The file '%value%' could not be found The file '%value%' exceeds the defined ini size The file '%value%' exceeds the defined form size The file '%value%' was only partially uploaded The file '%value%' was not uploaded No temporary directory was found for the file '%value%' The file '%value%' can't be written The extension returned an error while uploading the file '%value%' The file '%value%' was uploaded, possible attack illegal
File_MimeType
NOT_DETECTED NOT_READABLE
File_NotExists
DOES_EXIST DOES_NOT_MATCH
File_Sha1
File_Size
TOO_SMALL
NOT_FOUND INI_SIZE FORM_SIZE PARTIAL NO_FILE NO_TMP_DIR File_Upload CANT_WRITE EXTENSION ATTACK FILE_NOT_FOUND UNKNOWN TOO_MUCH File_WordCount
The file '%value%' was not found Unknown error while uploading the file '%value%' Too much words, maximum '%max %' are allowed but '%count%' were counted
1272
Zend_Validate
Validator
Constant TOO_LESS
Message Too less words, minimum '%min %' are expected but '%count%' were counted The file '%value%' could not be found '%value%' does not appear to be a float '%value%' is not greater than '%min%' '%value%' has not only hexadecimal digit characters '%value%' appears to be an IP address, but IP addresses are not allowed '%value%' appears to be a DNS hostname but cannot match TLD against known list '%value%' appears to be a DNS hostname but contains a dash (-) in an invalid position '%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%' '%value%' appears to be a DNS hostname but cannot extract TLD part '%value%' does not match the expected structure for a DNS hostname '%value%' does not appear to be a valid local network name '%value%' appears to be a local network name but local network names are not allowed '%value%' does not have IBAN '%value%' has a false format '%value%' has failed the IBAN check The token '%token%' does not match the given token '%value%' No token was provided to match against '%value%' was not found in the haystack '%value%' does not appear to be an integer '%value%' does not appear to be a valid IP address '%value%' is not less than '%max%' Value is required and can't be empty
INVALID_DASH
INVALID_LOCAL_NAME LOCAL_NAME_NOT_ALLOWED
NOTSUPPORTED Iban FALSEFORMAT CHECKFAILED NOT_SAME Identical MISSING_TOKEN NOT_IN_ARRAY NOT_INT NOT_IP_ADDRESS NOT_LESS IS_EMPTY
1273
Zend_Validate
Validator Regex
Message '%value%' does not match against pattern '%pattern%' '%value%' is less than %min% characters long '%value%' is greater than %max% characters long
StringLength
TOO_LONG
Additionally you can retrieve all message templates of a validator with the method getMessageTemplates(). It returns you an array with the messages a validator could return in the case of a failed validation.
Zend_Validate::setMessageLength(100);
Nota
Note that the set message length is used for all validators, even for self defined ones as long as they extend Zend_Validate_Abstract.
1274
1275
1276
Controller Script
As a simple example, let us say your controller has a list of book data that it wants to have rendered by a view. The controller script might look something like this:
// use a model to get the data for book authors and titles. $data = array( array( 'author' => 'Hernando de Soto', 'title' => 'The Mystery of Capitalism' ), array( 'author' => 'Henry Hazlitt', 'title' => 'Economics in One Lesson' ), array( 'author' => 'Milton Friedman', 'title' => 'Free to Choose' ) ); // now assign the book data to a Zend_View instance Zend_Loader::loadClass('Zend_View'); $view = new Zend_View(); $view->books = $data; // and render a view script called "booklist.php" echo $view->render('booklist.php');
View Script
Now we need the associated view script, "booklist.php". This is a PHP script like any other, with one exception: it executes inside the scope of the Zend_View instance, which means that references to $this point to the Zend_View instance properties and methods. (Variables assigned to the instance by the controller are public properties of the Zend_View instance). Thus, a very basic view script could look like this:
1277
Zend_View
if ($this->books): ?> <!-- A table of some books. --> <table> <tr> <th>Author</th> <th>Title</th> </tr> <?php foreach ($this->books as $key => $val): ?> <tr> <td><?php echo $this->escape($val['author']) ?></td> <td><?php echo $this->escape($val['title']) ?></td> </tr> <?php endforeach; ?> </table> <?php else: ?> <p>There are no books to display.</p> <?php endif;?> Note how we use the "escape()" method to apply output escaping to variables.
Options
Zend_View has several options that may be set to configure the behaviour of your view scripts. basePath: indicate a base path from which to set the script, helper, and filter path. It assumes a directory structure of:
base/path/ helpers/ filters/ scripts/ This may be set via setBasePath(), addBasePath(), or the basePath option to the constructor. encoding: indicate the character encoding to use with htmlentities(), htmlspecialchars(), and other operations. Defaults to ISO-8859-1 (latin1). May be set via setEncoding() or the encoding option to the constructor. escape: indicate a callback to be used by escape(). May be set via setEscape() or the escape option to the constructor. filter: indicate a filter to use after rendering a view script. May be set via setFilter(), addFilter(), or the filter option to the constructor. strictVars: force Zend_View to emit notices and warnings when uninitialized view variables are accessed. This may be set by calling strictVars(true) or passing the strictVars option to the constructor.
1278
Zend_View
php_value "short_open_tag" "on" This will only be possible if you are allowed to create and utilize .htaccess files. This directive can also be added to your httpd.conf file. Enable an optional stream wrapper to convert short tags to long tags on the fly:
$view->setUseStreamWrapper(true); This registers Zend_View_Stream as a stream wrapper for view scripts, and will ensure that your code continues to work as if short tags were enabled.
Utility Accessors
Typically, you'll only ever need to call on assign(), render(), or one of the methods for setting/adding filter, helper, and script paths. However, if you wish to extend Zend_View yourself, or need access to some of its internals, a number of accessors exist: getVars() will return all assigned variables. clearVars() will clear all assigned variables; useful when you wish to re-use a view object, but want to control what variables are available. getScriptPath($script) will retrieve the resolved path to a given view script. getScriptPaths() will retrieve all registered script paths. getHelperPath($helper) will retrieve the resolved path to the named helper class. getHelperPaths() will retrieve all registered helper paths.
1279
Zend_View
getFilterPath($filter) will retrieve the resolved path to the named filter class. getFilterPaths() will retrieve all registered filter paths.
Controller Scripts
The controller is where you instantiate and configure Zend_View. You then assign variables to the view, and tell the view to render output using a particular script.
Assigning Variables
Your controller script should assign necessary variables to the view before it hands over control to the view script. Normally, you can do assignments one at a time by assigning to property names of the view instance:
$view = new Zend_View(); $view->a = "Hay"; $view->b = "Bee"; $view->c = "Sea"; However, this can be tedious when you have already collected the values to be assigned into an array or object. The assign() method lets you assign from an array or object "in bulk". The following examples have the same effect as the above one-by-one property assignments.
$view = new Zend_View(); // assign an array of key-value pairs, where the // key is the variable name, and the value is // the assigned value. $array = array( 'a' => "Hay", 'b' => "Bee", 'c' => "Sea", ); $view->assign($array); // do the same with an object's public properties; // note how we cast it to an array when assigning. $obj = new StdClass; $obj->a = "Hay"; $obj->b = "Bee"; $obj->c = "Sea"; $view->assign((array) $obj); Alternatively, you can use the assign method to assign one-by-one by passing a string variable name, and then the variable value.
1280
Zend_View
$view->assign('c', "Sea");
$view = new Zend_View(); $view->a = "Hay"; $view->b = "Bee"; $view->c = "Sea"; echo $view->render('someView.php');
$view = new Zend_View(); $view->setScriptPath('/path/to/app/views'); Now when you call $view->render('someView.php'), it will look for "/path/to/app/views/someView.php". In fact, you can "stack" paths using the addScriptPath() method. As you add paths to the stack, Zend_View will look at the most-recently-added path for the requested view script. This allows you override default views with custom views so that you may create custom "themes" or "skins" for some views, while leaving others alone.
$view = new Zend_View(); $view->addScriptPath('/path/to/app/views'); $view->addScriptPath('/path/to/custom/'); // // // // now when you call $view->render('booklist.php'), Zend_View will look first for "/path/to/custom/booklist.php", then for "/path/to/app/views/booklist.php", and finally in the current directory for "booklist.php".
// $_GET['foo'] == '../../../etc'
1281
Zend_View
$view->addScriptPath($_GET['foo']); $view->render('passwd'); While this example is contrived, it does clearly show the potential issue. If you must rely on user input to set your script path, properly filter the input and check to ensure it exists under paths controlled by your application.
View Scripts
Once your controller has assigned variables and called render(), Zend_View then includes the requested view script and executes it "inside" the scope of the Zend_View instance. Therefore, in your view scripts, references to $this actually point to the Zend_View instance itself. Variables assigned to the view from the controller are referred to as instance properties. For example, if the controller were to assign a variable 'something', you would refer to it as $this->something in the view script. (This allows you to keep track of which values were assigned to the script, and which are internal to the script itself.) By way of reminder, here is the example view script from the Zend_View introduction.
<?php if ($this->books): ?> <!-- A table of some books. --> <table> <tr> <th>Author</th> <th>Title</th> </tr> <?php foreach ($this->books as $key => $val): ?> <tr> <td><?php echo $this->escape($val['author']) ?></td> <td><?php echo $this->escape($val['title']) ?></td> </tr> <?php endforeach; ?> </table> <?php else: ?> <p>There are no books to display.</p> <?php endif;?>
Escaping Output
One of the most important tasks to perform in a view script is to make sure that output is escaped properly; among other things, this helps to avoid cross-site scripting attacks. Unless you are using a function, method, or helper that does escaping on its own, you should always escape variables when you output them. Zend_View comes with a method called escape() that does such escaping for you.
1282
Zend_View
// bad view-script practice: echo $this->variable; // good view-script practice: echo $this->escape($this->variable); By default, the escape() method uses the PHP htmlspecialchars() function for escaping. However, depending on your environment, you may wish for escaping to occur in a different way. Use the setEscape() method at the controller level to tell Zend_View what escaping callback to use.
// create a Zend_View instance $view = new Zend_View(); // tell it to use htmlentities as the escaping callback $view->setEscape('htmlentities'); // or tell it to use a static class method as the callback $view->setEscape(array('SomeClass', 'methodName')); // or even an instance method $obj = new SomeClass(); $view->setEscape(array($obj, 'methodName')); // and then render your view echo $view->render(...); The callback function or method should take the value to be escaped as its first parameter, and all other parameters should be optional.
include_once 'template.inc'; $tpl = new Template(); if ($this->books) { $tpl->setFile(array( "booklist" => "booklist.tpl", "eachbook" => "eachbook.tpl", )); foreach ($this->books as $key => $val) { $tpl->set_var('author', $this->escape($val['author']);
1283
Zend_View
$tpl->set_var('title', $this->escape($val['title']); $tpl->parse("books", "eachbook", true); } $tpl->pparse("output", "booklist"); } else { $tpl->setFile("nobooks", "nobooks.tpl") $tpl->pparse("output", "nobooks"); } These would be the related template files:
<!-- booklist.tpl --> <table> <tr> <th>Author</th> <th>Title</th> </tr> {books} </table> <!-- eachbook.tpl --> <tr> <td>{author}</td> <td>{title}</td> </tr> <!-- nobooks.tpl --> <p>There are no books to display.</p>
/** * Return the actual template engine object */ public function getEngine(); /** * Set the path to view scripts/templates */ public function setScriptPath($path); /** * Set a base path to all view resources */ public function setBasePath($path, $prefix = 'Zend_View'); /** * Add an additional base path to view resources
1284
Zend_View
*/ public function addBasePath($path, $prefix = 'Zend_View'); /** * Retrieve the current script paths */ public function getScriptPaths(); /** * Overloading methods for assigning template variables as object * properties */ public function __set($key, $value); public function __isset($key); public function __unset($key); /** * Manual assignment of template variables, or ability to assign * multiple variables en masse. */ public function assign($spec, $value = null); /** * Unset all assigned template variables */ public function clearVars(); /** * Render the template named $name */ public function render($name); Using this interface, it becomes relatively easy to wrap a third-party template engine as a Zend_View-compatible class. As an example, the following is one potential wrapper for Smarty:
class Zend_View_Smarty implements Zend_View_Interface { /** * Smarty object * @var Smarty */ protected $_smarty; /** * Constructor * * @param string $tmplPath * @param array $extraParams * @return void */ public function __construct($tmplPath = null, $extraParams = array()) { $this->_smarty = new Smarty;
1285
Zend_View
if (null !== $tmplPath) { $this->setScriptPath($tmplPath); } foreach ($extraParams as $key => $value) { $this->_smarty->$key = $value; } } /** * Return the template engine object * * @return Smarty */ public function getEngine() { return $this->_smarty; } /** * Set the path to the templates * * @param string $path The directory to set as the path. * @return void */ public function setScriptPath($path) { if (is_readable($path)) { $this->_smarty->template_dir = $path; return; } throw new Exception('Invalid path provided'); } /** * Retrieve the current template directory * * @return string */ public function getScriptPaths() { return array($this->_smarty->template_dir); } /** * Alias for setScriptPath * * @param string $path * @param string $prefix Unused * @return void */ public function setBasePath($path, $prefix = 'Zend_View')
1286
Zend_View
{ return $this->setScriptPath($path); } /** * Alias for setScriptPath * * @param string $path * @param string $prefix Unused * @return void */ public function addBasePath($path, $prefix = 'Zend_View') { return $this->setScriptPath($path); } /** * Assign a variable to the template * * @param string $key The variable name. * @param mixed $val The variable value. * @return void */ public function __set($key, $val) { $this->_smarty->assign($key, $val); } /** * Allows testing with empty() and isset() to work * * @param string $key * @return boolean */ public function __isset($key) { return (null !== $this->_smarty->get_template_vars($key)); } /** * Allows unset() on object properties to work * * @param string $key * @return void */ public function __unset($key) { $this->_smarty->clear_assign($key); } /** * Assign variables to the template * * Allows setting a specific key to the specified value, OR passing
1287
Zend_View
* an array of key => value pairs to set en masse. * * @see __set() * @param string|array $spec The assignment strategy to use (key or * array of key => value pairs) * @param mixed $value (Optional) If assigning a named variable, * use this as the value. * @return void */ public function assign($spec, $value = null) { if (is_array($spec)) { $this->_smarty->assign($spec); return; } $this->_smarty->assign($spec, $value); } /** * Clear all assigned variables * * Clears all variables assigned to Zend_View either via * {@link assign()} or property overloading * ({@link __get()}/{@link __set()}). * * @return void */ public function clearVars() { $this->_smarty->clear_all_assign(); } /** * Processes a template and returns the output. * * @param string $name The template to process. * @return string The output. */ public function render($name) { return $this->_smarty->fetch($name); } } In this example, you would instantiate the Zend_View_Smarty class instead of Zend_View, and then use it in roughly the same fashion as Zend_View:
1288
Zend_View
->setViewBasePathSpec($view->_smarty->template_dir) ->setViewScriptPathSpec(':controller/:action.:suffix') ->setViewScriptPathNoControllerSpec(':action.:suffix') ->setViewSuffix('tpl'); //Ejemplo 2. Usage in action controller remains the same... class FooController extends Zend_Controller_Action { public function barAction() { $this->view->book = 'Zend PHP 5 Certification Study Guide'; $this->view->author = 'Davey Shafik and Ben Ramsey' } } //Ejemplo 3. Initializing view in action controller class FooController extends Zend_Controller_Action { public function init() { $this->view = new Zend_View_Smarty('/path/to/templates'); $viewRenderer = $this->_helper->getHelper('viewRenderer'); $viewRenderer->setView($this->view) ->setViewBasePathSpec($view->_smarty->template_dir) ->setViewScriptPathSpec(':controller/:action.:suffix') ->setViewScriptPathNoControllerSpec(':action.:suffix') ->setViewSuffix('tpl'); }
View Helpers
In your view scripts, often it is necessary to perform certain complex functions over and over: e.g., formatting a date, generating form elements, or displaying action links. You can use helper classes to perform these behaviors for you. A helper is simply a class. Let's say we want a helper named 'fooBar'. By default, the class is prefixed with 'Zend_View_Helper_' (you can specify a custom prefix when setting a helper path), and the last segment of the class name is the helper name; this segment should be TitleCapped; the full class name is then: Zend_View_Helper_FooBar. This class should contain at the minimum a single method, named after the helper, and camelCased: fooBar().
1289
Zend_View
method. The object instance is persistent within the Zend_View instance, and is reused for all future calls to $this>helperName().
Initial Helpers
Zend_View comes with an initial set of helper classes, most of which relate to form element generation and perform the appropriate output escaping automatically. In addition, there are helpers for creating route-based URLs and HTML lists, as well as declaring variables. The currently shipped helpers include: declareVars(): Primarily for use when using strictVars(), this helper can be used to declare template variables that may or may not already be set in the view object, as well as to set default values. Arrays passed as arguments to the method will be used to set default values; otherwise, if the variable does not exist, it is set to an empty string. fieldset($name, $content, $attribs): Creates an XHTML fieldset. If $attribs contains a 'legend' key, that value will be used for the fieldset legend. The fieldset will surround the $content as provided to the helper. form($name, $attribs, $content): Generates an XHTML form. All $attribs are escaped and rendered as XHTML attributes of the form tag. If $content is present and not a boolean false, then that content is rendered within the start and close form tags; if $content is a boolean false (the default), only the opening form tag is generated. formButton($name, $value, $attribs): Creates an <button /> element. formCheckbox($name, $value, $attribs, $options): Creates an <input type="checkbox" /> element. By default, when no $value is provided and no $options are present, '0' is assumed to be the unchecked value, and '1' the checked value. If a $value is passed, but no $options are present, the checked value is assumed to be the value passed. $options should be an array. If the array is indexed, the first value is the checked value, and the second the unchecked value; all other values are ignored. You may also pass an associative array with the keys 'checked' and 'unChecked'. If $options has been passed, if $value matches the checked value, then the element will be marked as checked. You may also mark the element as checked or unchecked by passing a boolean value for the attribute 'checked'. The above is probably best summed up with some examples: // '1' and '0' as checked/unchecked options; not checked echo $this->formCheckbox('foo'); // '1' and '0' as checked/unchecked options; checked echo $this->formCheckbox('foo', null, array('checked' => true)); // 'bar' and '0' as checked/unchecked options; not checked echo $this->formCheckbox('foo', 'bar'); // 'bar' and '0' as checked/unchecked options; checked echo $this->formCheckbox('foo', 'bar', array('checked' => true)); // 'bar' and 'baz' as checked/unchecked options; unchecked echo $this->formCheckbox('foo', null, null, array('bar', 'baz');
1290
Zend_View
// 'bar' and 'baz' as checked/unchecked options; unchecked echo $this->formCheckbox('foo', null, null, array( 'checked' => 'bar', 'unChecked' => 'baz' )); // 'bar' and 'baz' as checked/unchecked options; checked echo $this->formCheckbox('foo', 'bar', null, array('bar', 'baz'); echo $this->formCheckbox('foo', null, array('checked' => true), array('bar', 'baz'); // 'bar' and 'baz' as checked/unchecked options; unchecked echo $this->formCheckbox('foo', 'baz', null, array('bar', 'baz'); echo $this->formCheckbox('foo', null, array('checked' => false), array('bar', 'baz'); In all cases, the markup prepends a hidden element with the unchecked value; this way, if the value is unchecked, you will still get a valid value returned to your form. formErrors($errors, $options): Generates an XHTML unordered list to show errors. $errors should be a string or an array of strings; $options should be any attributes you want placed in the opening list tag. You can specify alternate opening, closing, and separator content when rendering the errors by calling several methods on the helper: setElementStart($string); default is '<ul class="errors"%s"><li>', where %s is replaced with the attributes as specified in $options. setElementSeparator($string); default is '</li><li>'. setElementEnd($string); default is '</li></ul>'. formFile($name, $attribs): Creates an <input type="file" /> element. formHidden($name, $value, $attribs): Creates an <input type="hidden" /> element. formLabel($name, $value, $attribs): Creates a <label> element, setting the for attribute to $name, and the actual label text to $value. If disable is passed in attribs, nothing will be returned. formMultiCheckbox($name, $value, $attribs, $options, $listsep): Creates a list of checkboxes. $options should be an associative array, and may be arbitrarily deep. $value may be a single value or an array of selected values that match the keys in the $options array. $listsep is an HTML break ("<br />") by default. By default, this element is treated as an array; all checkboxes share the same name, and are submitted as an array. formPassword($name, $value, $attribs): Creates an <input type="password" /> element. formRadio($name, $value, $attribs, $options): Creates a series of <input type="radio" /> elements, one for each of the $options elements. In the $options array, the element key is the radio value, and the element value is the radio label. The $value radio will be preselected for you. formReset($name, $value, $attribs): Creates an <input type="reset" /> element.
1291
Zend_View
formSelect($name, $value, $attribs, $options): Creates a <select>...</select> block, with one <option>one for each of the $options elements. In the $options array, the element key is the option value, and the element value is the option label. The $value option(s) will be preselected for you. formSubmit($name, $value, $attribs): Creates an <input type="submit" /> element. formText($name, $value, $attribs): Creates an <input type="text" /> element. formTextarea($name, $value, $attribs): Creates a <textarea>...</textarea> block. url($urlOptions, $name, $reset): Creates a URL string based on a named route. $urlOptions should be an associative array of key/value pairs used by the particular route. htmlList($items, $ordered, $attribs, $escape): generates unordered and ordered lists based on the $items passed to it. If $items is a multidimensional array, a nested list will be built. If the $escape flag is true (default), individual items will be escaped using the view objects registered escaping mechanisms; pass a false value if you want to allow markup in your lists. Using these in your view scripts is very easy, here is an example. Note that you all you need to do is call them; they will load and instantiate themselves as they are needed.
// inside your view script, $this refers to the Zend_View instance. // // say that you have already assigned a series of select options under // the name $countries as array('us' => 'United States', 'il' => // 'Israel', 'de' => 'Germany'). ?> <form action="action.php" method="post"> <p><label>Your Email: <?php echo $this->formText('email', 'you@example.com', array('size' => 32)) ?> </label></p> <p><label>Your Country: <?php echo $this->formSelect('country', 'us', null, $this->countries) ?> </label></p> <p><label>Would you like to opt in? <?php echo $this->formCheckbox('opt_in', 'yes', null, array('yes', 'no')) ?> </label></p> </form> The resulting output from the view script will look something like this:
<form action="action.php" method="post"> <p><label>Your Email: <input type="text" name="email" value="you@example.com" size="32" /> </label></p> <p><label>Your Country: <select name="country"> <option value="us" selected="selected">United States</option> <option value="il">Israel</option> <option value="de">Germany</option> </select> </label></p> <p><label>Would you like to opt in?
1292
Zend_View
<input type="hidden" name="opt_in" value="no" /> <input type="checkbox" name="opt_in" value="yes" checked="checked" /> </label></p> </form>
<div id="sidebar right"> <div class="item"> <?php echo $this->action('list', 'comment', null, array('count' => 10)); ?> </div> </div>
BaseUrl Helper
While most URLs generated by the framework have the base URL prepended automatically, developers will need to prepend the base URL to their own URLs in order for paths to resources to be correct. Usage of the BaseUrl helper is very straightforward:
/* * The following assume that the base URL of the page/application is "/mypage". */ /* * Prints: * <base href="/mypage/" /> */ <base href="<?php echo $this->baseUrl(); ?>" /> /* * Prints: * <link rel="stylesheet" type="text/css" href="/mypage/css/base.css" /> */
1293
Zend_View
Nota
For simplicity's sake, we strip out the entry PHP file (e.g., "index.php") from the base URL that was contained in Zend_Controller. However, in some situations this may cause a problem. If one occurs, use $this->getHelper('BaseUrl')->setBaseUrl() to set your own BaseUrl.
Cycle Helper
The Cycle helper is used to alternate a set of values.
<?php foreach ($this->books as $book):?> <tr style="background-color:<?php echo $this->cycle(array("#F0F0F0", "#FFFFFF")) ->next()?>"> <td><?php echo $this->escape($book['author']) ?></td> </tr> <?php endforeach;?> // Moving in backwards order and assign function $this->cycle()->assign(array("#F0F0F0","#FFFFFF")); $this->cycle()->prev(); ?> The output
<?php foreach ($this->books as $book):?> <tr style="background-color:<?php echo $this->cycle(array("#F0F0F0", "#FFFFFF")) ->next()?>"> <td><?php echo $this->cycle(array(1,2,3),'number')->next()?></td> <td><?php echo $this->escape($book['author'])?></td> </tr>
1294
Zend_View
<?php endforeach;?>
Partial Helper
The Partial view helper is used to render a specified template within its own variable scope. The primary use is for reusable template fragments with which you do not need to worry about variable name clashes. Additionally, they allow you to specify partial view scripts from specific modules. A sibling to the Partial, the PartialLoop view helper allows you to pass iterable data, and render a partial for each item.
PartialLoop Counter
The PartialLoop view helper assigns a variable to the view named partialCounter which passes the current position of the array to the view script. This provides an easy way to have alternating colors on table rows for example.
<?php // partial.phtml ?> <ul> <li>From: <?php echo $this->escape($this->from) ?></li> <li>Subject: <?php echo $this->escape($this->subject) ?></li> </ul> You would then call it from your view script using the following:
<?php echo $this->partial('partial.phtml', array( 'from' => 'Team Framework', 'subject' => 'view partials')); ?> Which would then render:
What is a model?
A model used with the Partial view helper can be one of the following: Array. If an array is passed, it should be associative, as its key/value pairs are assigned to the view with keys as view variables. Object implementing toArray() method. If an object is passed an has a toArray() method, the results of toArray() will be assigned to the view object as view variables. Standard object. Any other object will assign the results of object_get_vars() (essentially all public properties of the object) to the view object.
1295
Zend_View
If your model is an object, you may want to have it passed as an object to the partial script, instead of serializing it to an array of variables. You can do this by setting the 'objectKey' property of the appropriate helper:
// Tell partial to pass objects as 'model' variable $view->partial()->setObjectKey('model'); // Tell partial to pass objects from partialLoop as 'model' variable // in final partial view script: $view->partialLoop()->setObjectKey('model'); This technique is particularly useful when passing Zend_Db_Table_Rowsets to partialLoop(), as you then have full access to your row objects within the view scripts, allowing you to call methods on them (such as retrieving values from parent or dependent rows).
<?php // partialLoop.phtml ?> <dt><?php echo $this->key ?></dt> <dd><?php echo $this->value ?></dd> And the following "model":
'Mammal', 'value' => 'Camel'), 'Bird', 'value' => 'Penguin'), 'Reptile', 'value' => 'Asp'), 'Fish', 'value' => 'Flounder'),
In your view script, you could then invoke the PartialLoop helper:
1296
Zend_View
<?php echo $this->partial('pager.phtml', 'list', $pagerData) ?> In this way, you can re-use partials created specifically for other modules. That said, it's likely a better practice to put re-usable partials in shared view script paths.
Placeholder Helper
The Placeholder view helper is used to persist content between view scripts and view instances. It also offers some useful features such as aggregating content, capturing view script content for later use, and adding pre- and posttext to content (and custom separators for aggregated content).
<?php $this->placeholder('foo')->set("Some text for later") ?> <?php echo $this->placeholder('foo'); // outputs "Some text for later" ?>
1297
Zend_View
setSeparator($prefix) sets text with which to separate aggregated content. Use getSeparator() at any time to determine what the current setting is. setIndent($prefix) can be used to set an indentation value for content. If an integer is passed, that number of spaces will be used; if a string is passed, the string will be used. Use getIndent() at any time to determine what the current setting is.
<!-- later view script --> <?php $this->placeholder('foo')->setPrefix("<ul>\n <li>") ->setSeparator("</li><li>\n") ->setIndent(4) ->setPostfix("</li></ul>\n"); ?> <?php echo $this->placeholder('foo'); // outputs as unordered list with pretty indentation ?> Because the Placeholder container objects extend ArrayObject, you can also assign content to a specific key in the container easily, instead of simply pushing it into the container. Keys may be accessed either as object properties or as array keys.
<?php $this->placeholder('foo')->bar = $this->data ?> <?php echo $this->placeholder('foo')->bar ?> <?php $foo = $this->placeholder('foo'); echo $foo['bar']; ?>
1298
Zend_View
<!-- Default capture: append --> <?php $this->placeholder('foo')->captureStart(); foreach ($this->data as $datum): ?> <div class="foo"> <h2><?php echo $datum->title ?></h2> <p><?php echo $datum->content ?></p> </div> <?php endforeach; ?> <?php $this->placeholder('foo')->captureEnd() ?> <?php echo $this->placeholder('foo') ?>
<!-- Capture to key --> <?php $this->placeholder('foo')->captureStart('SET', 'data'); foreach ($this->data as $datum): ?> <div class="foo"> <h2><?php echo $datum->title ?></h2> <p><?php echo $datum->content ?></p> </div> <?php endforeach; ?> <?php $this->placeholder('foo')->captureEnd() ?> <?php echo $this->placeholder('foo')->data ?>
Doctype Helper
Valid HTML and XHTML documents should include a DOCTYPE declaration. Besides being difficult to remember, these can also affect how certain elements in your document should be rendered (for instance, CDATA escaping in <script> and <style> elements. The Doctype helper allows you to specify one of the following types: XHTML11
1299
Zend_View
XHTML1_STRICT XHTML1_TRANSITIONAL XHTML1_FRAMESET XHTML_BASIC1 HTML4_STRICT HTML4_LOOSE HTML4_FRAMESET HTML5 You can also specify a custom doctype as long as it is well-formed. The Doctype helper is a concrete implementation of the Placeholder helper.
HeadLink Helper
The HTML <link> element is increasingly used for linking a variety of resources for your site: stylesheets, feeds, favicons, trackbacks, and more. The HeadLink helper provides a simple interface for creating and aggregating these elements for later retrieval and output in your layout script. The HeadLink helper has special methods for adding stylesheet links to its stack: appendStylesheet($href, $media, $conditionalStylesheet, $extras)
1300
Zend_View
offsetSetStylesheet($index, $href, $media, $conditionalStylesheet, $extras) prependStylesheet($href, $media, $conditionalStylesheet, $extras) setStylesheet($href, $media, $conditionalStylesheet, $extras) The $media value defaults to 'screen', but may be any valid media value. $conditionalStylesheet is a string or boolean false, and will be used at rendering time to determine if special comments should be included to prevent loading of the stylesheet on certain platforms. $extras is an array of any extra values that you want to be added to the tag. Additionally, the HeadLink helper has special methods for adding 'alternate' links to its stack: appendAlternate($href, $type, $title, $extras) offsetSetAlternate($index, $href, $type, $title, $extras) prependAlternate($href, $type, $title, $extras) setAlternate($href, $type, $title, $extras) The headLink() helper method allows specifying all attributes necessary for a <link> element, and allows you to also specify placement -- whether the new element replaces all others, prepends (top of stack), or appends (end of stack). The HeadLink helper is a concrete implementation of the Placeholder helper.
<?php // setting links in a view script: $this->headLink()->appendStylesheet('/styles/basic.css') ->headLink(array('rel' => 'favicon', 'href' => '/img/favicon.ico'), 'PREPEND') ->prependStylesheet('/styles/moz.css', 'screen', true, array('id' => 'my_stylesheet')); ?> <?php // rendering the links: ?> <?php echo $this->headLink() ?>
HeadMeta Helper
The HTML <meta> element is used to provide meta information about your HTML document -- typically keywords, document character set, caching pragmas, etc. Meta tags may be either of the 'http-equiv' or 'name' types, must contain a 'content' attribute, and can also have either of the 'lang' or 'scheme' modifier attributes. The HeadMeta helper supports the following methods for setting and adding meta tags: appendName($keyValue, $content, $conditionalName)
1301
Zend_View
offsetSetName($index, $keyValue, $content, $conditionalName) prependName($keyValue, $content, $conditionalName) setName($keyValue, $content, $modifiers) appendHttpEquiv($keyValue, $content, $conditionalHttpEquiv) offsetSetHttpEquiv($index, $keyValue, $content, $conditionalHttpEquiv) prependHttpEquiv($keyValue, $content, $conditionalHttpEquiv) setHttpEquiv($keyValue, $content, $modifiers) The $keyValue item is used to define a value for the 'name' or 'http-equiv' key; $content is the value for the 'content' key, and $modifiers is an optional associative array that can contain keys for 'lang' and/or 'scheme'. You may also set meta tags using the headMeta() helper method, which has the following signature: headMeta($content, $keyValue, $keyType = 'name', $modifiers = array(), $placement = 'APPEND'). $keyValue is the content for the key specified in $keyType, which should be either 'name' or 'http-equiv'. $placement can be either 'SET' (overwrites all previously stored values), 'APPEND' (added to end of stack), or 'PREPEND' (added to top of stack). HeadMeta overrides each of append(), offsetSet(), prepend(), and set() to enforce usage of the special methods as listed above. Internally, it stores each item as a stdClass token, which it later serializes using the itemToString() method. This allows you to perform checks on the items in the stack, and optionally modify these items by simply modifying the object returned. The HeadMeta helper is a concrete implementation of the Placeholder helper.
// setting meta keywords $this->headMeta()->appendName('keywords', 'framework, PHP, productivity'); If you wished to set some client-side caching rules, you'd set http-equiv tags with the rules you wish to enforce:
// disabling client-side cache $this->headMeta()->appendHttpEquiv('expires', 'Wed, 26 Feb 1997 08:21:57 GMT') ->appendHttpEquiv('pragma', 'no-cache') ->appendHttpEquiv('Cache-Control', 'no-cache'); Another popular use for meta tags is setting the content type, character set, and language:
// setting content type and character set $this->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=UTF-8') ->appendHttpEquiv('Content-Language', 'en-US');
1302
Zend_View
As a final example, an easy way to display a transitional message before a redirect is using a "meta refresh":
// setting a meta refresh for 3 seconds to a new url: $this->headMeta()->appendHttpEquiv('Refresh', '3;URL=http://www.some.org/some.html'); When you're ready to place your meta tags in the layout, simply echo the helper:
HeadScript Helper
The HTML <script> element is used to either provide inline client-side scripting elements or link to a remote resource containing client-side scripting code. The HeadScript helper allows you to manage both. The HeadScript helper supports the following methods for setting and adding scripts: appendFile($src, $type = 'text/javascript', $attrs = array()) offsetSetFile($index, $src, $type = 'text/javascript', $attrs = array()) prependFile($src, $type = 'text/javascript', $attrs = array()) setFile($src, $type = 'text/javascript', $attrs = array()) appendScript($script, $type = 'text/javascript', $attrs = array()) offsetSetScript($index, $script, $type = 'text/javascript', $attrs = array()) prependScript($script, $type = 'text/javascript', $attrs = array()) setScript($script, $type = 'text/javascript', $attrs = array()) In the case of the *File() methods, $src is the remote location of the script to load; this is usually in the form of a URL or a path. For the *Script() methods, $script is the client-side scripting directives you wish to use in the element.
1303
Zend_View
Finally, you can also use the headScript() method to quickly add script elements; the signature for this is headScript($mode = 'FILE', $spec, $placement = 'APPEND'). The $mode is either 'FILE' or 'SCRIPT', depending on if you're linking a script or defining one. $spec is either the script file to link or the script source itself. $placement should be either 'APPEND', 'PREPEND', or 'SET'. HeadScript overrides each of append(), offsetSet(), prepend(), and set() to enforce usage of the special methods as listed above. Internally, it stores each item as a stdClass token, which it later serializes using the itemToString() method. This allows you to perform checks on the items in the stack, and optionally modify these items by simply modifying the object returned. The HeadScript helper is a concrete implementation of the Placeholder helper.
1304
Zend_View
HeadStyle Helper
The HTML <style> element is used to include CSS stylesheets inline in the HTML <head> element.
1305
Zend_View
$this->headStyle()->appendStyle($styles, array('conditional' => 'lt IE 7'); HeadStyle also allows capturing style declarations; this can be useful if you want to create the declarations programmatically, and then place them elsewhere. The usage for this will be showed in an example below. Finally, you can also use the headStyle() method to quickly add declarations elements; the signature for this is headStyle($content$placement = 'APPEND', $attributes = array()). $placement should be either 'APPEND', 'PREPEND', or 'SET'. HeadStyle overrides each of append(), offsetSet(), prepend(), and set() to enforce usage of the special methods as listed above. Internally, it stores each item as a stdClass token, which it later serializes using the itemToString() method. This allows you to perform checks on the items in the stack, and optionally modify these items by simply modifying the object returned. The HeadStyle helper is a concrete implementation of the Placeholder helper.
// adding styles $this->headStyle()->appendStyle($styles); Order is very important with CSS; you may need to ensure that declarations are loaded in a specific order due to the order of the cascade; use the various append, prepend, and offsetSet directives to aid in this task:
// Putting styles in order // place at a particular offset: $this->headStyle()->offsetSetStyle(100, $customStyles); // place at end: $this->headStyle()->appendStyle($finalStyles); // place at beginning $this->headStyle()->prependStyle($firstStyles); When you're finally ready to output all style declarations in your layout script, simply echo the helper:
<?php $this->headStyle()->captureStart() ?> body { background-color: <?php echo $this->bgColor ?>; } <?php $this->headStyle()->captureEnd() ?>
1306
Zend_View
The following assumptions are made: The style declarations will be appended to the stack. If you wish for them to replace the stack or be added to the top, you will need to pass 'SET' or 'PREPEND', respectively, as the first argument to captureStart(). If you wish to specify any additional attributes for the <style> tag, pass them in an array as the second argument to captureStart().
HeadTitle Helper
The HTML <title> element is used to provide a title for an HTML document. The HeadTitle helper allows you to programmatically create and store the title for later retrieval and output. The HeadTitle helper is a concrete implementation of the Placeholder helper. It overrides the toString() method to enforce generating a <title> element, and adds a headTitle() method for quick and easy setting and aggregation of title elements. The signature for that method is headTitle($title, $setType = 'APPEND'); by default, the value is appended to the stack (aggregating title segments), but you may also specify either 'PREPEND' (place at top of stack) or 'SET' (overwrite stack).
// setting the controller and action name as title segments: $request = Zend_Controller_Front::getInstance()->getRequest(); $this->headTitle($request->getActionName()) ->headTitle($request->getControllerName()); // setting the site in the title; possibly in the layout script: $this->headTitle('Zend Framework'); // setting a separator string for segments: $this->headTitle()->setSeparator(' / '); When you're finally ready to render the title in your layout script, simply echo the helper:
<!-- renders <action> / <controller> / Zend Framework --> <?php echo $this->headTitle() ?>
1307
Zend_View
All of these helpers share a similar interface. For this reason, this documentation will only contain examples of two of these helpers.
<object data="/path/to/flash.swf" type="application/x-shockwave-flash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"> </object> Additionally you can specify attributes, parameters and content that can be rendered along with the <object>. This will be demonstrated using the htmlObject helper.
echo $this->htmlObject( '/path/to/file.ext', 'mime/type', array( 'attr1' => 'aval1', 'attr2' => 'aval2' ), array( 'param1' => 'pval1', 'param2' => 'pval2' ), 'some content' ); /* This would output: <object data="/path/to/file.ext" type="mime/type" attr1="aval1" attr2="aval2"> <param name="param1" value="pval1" /> <param name="param2" value="pval2" /> some content
1308
Zend_View
</object> */
InlineScript Helper
The HTML <script> element is used to either provide inline client-side scripting elements or link to a remote resource containing client-side scripting code. The InlineScript helper allows you to manage both. It is derived from HeadScript, and any method of that helper is available; however, use the inlineScript() method in place of headScript().
JSON Helper
When creating views that return JSON, it's important to also set the appropriate response header. The JSON view helper does exactly that. In addition, by default, it disables layouts (if currently enabled), as layouts generally aren't used with JSON responses. The JSON helper sets the following header: Content-Type: application/json Most AJAX libraries look for this header when parsing responses to determine how to handle the content. Usage of the JSON helper is very straightforward: <?php echo $this->json($this->data) ?>
1309
Zend_View
<?php echo $this->json($this->data, array( 'enableJsonExprFinder' => true, 'keepLayouts' => true, )) ?>
Navigation Helpers
The navigation helpers are used for rendering navigational elements from Zend_Navigation_Container instances. There are 5 built-in helpers: Breadcrumbs, used for rendering the path to the currently active page. Links, used for rendering navigational head links (e.g. <link rel="next" href="..." />) Menu, used for rendering menus. Sitemap, used for rendering sitemaps conforming to the Sitemaps XML format [http://www.sitemaps.org/ protocol.php]. Navigation, used for proxying calls to other navigational helpers. All built-in helpers extend Zend_View_Helper_Navigation_HelperAbstract, which adds integration with ACL and translation. The abstract class implements the interface Zend_View_Helper_Navigation_Helper, which defines the following methods: {get|set}Container() gets/sets the navigation container the helper should operate on by default, and hasContainer() checks if the helper has container registered. {get|set}Translator() gets/sets the translator used for translating labels and titles, and {get| set}UseTranslator() controls whether the translator should be enabled. The method hasTranslator() checks if the helper has a translator registered. {get|set}Acl(), {get|set}Role(), gets/sets ACL (Zend_Acl) instance and role (String or Zend_Acl_Role_Interface) used for filtering out pages when rendering, and {get|set}UseAcl() controls whether ACL should be enabled. The methods hasAcl() and hasRole() checks if the helper has an ACL instance or a role registered. __toString(), magic method to ensure that helpers can be rendered by echoing the helper instance directly. render(), must be implemented by concrete helpers to do the actual rendering. In addition to the method stubs from the interface, the abstract class also implements the following methods: {get|set}Indent() gets/set indentation. The setter accepts a String or an int. In the case of an int, the helper will use the given number of spaces for indentation. I.e., setIndent(4) means 4 initial spaces of indentation. Indentation can be specified for all helpers except the Sitemap helper. {get|set}MinDepth() gets/set the minimum depth a page must have to be included by the helper. Setting NULL means no minimum depth. {get|set}MaxDepth() gets/set the maximum depth a page can have to be included by the helper. Setting NULL means no maximum depth. {get|set}RenderInvisible() gets/set whether to render items that have been marked as invisible or not. __call() is used for proxying calls to the container registered in the helper, which means you can call methods on a helper as if it was a container. See example below.
1310
Zend_View
findActive($container, $minDepth, $maxDepth) is used for finding the deepest active page in the given container. If depths are not given, the method will use the values retrieved from getMinDepth() and getMaxDepth(). The deepest active page must be between $minDepth and $maxDepth inclusively. Returns an array containing a reference to the found page instance and the depth at which the page was found. htmlify() renders an a HTML element from a Zend_Navigation_Page instance. accept() is used for determining if a page should be accepted when iterating containers. This method checks for page visibility and verifies that the helper's role is allowed access to the page's resource/privilege. static setDefaultAcl() is used for setting a defualt ACL object that will be used by helpers. static setDefaultRole() is used for setting a default ACL that will be used by helpers If a navigation container is not explicitly set in a helper using $helper->setContainer($nav), the helper will look for a container instance with the key Zend_Navigation in the registry. If a container is not explicitly set or found in the registry, the helper will create an empty Zend_Navigation container when calling $helper>getContainer().
$this->navigation()->addPage(array( 'type' => 'uri', 'label' => 'New page')); The call above will add a page to the container in the Navigation helper.
Nota
There is no translation in the sitemap helper, since there are no page labels or titles involved in an XML sitemap.
1311
Zend_View
If a page is not accepted by ACL, any descendant page will also be excluded from rendering. The proxy helper will inject its own ACL and role to the helper it proxies to if the proxied helper doesn't already have any. The examples below all show how ACL affects rendering.
1312
Zend_View
'action' => 'index', 'pages' => array( array( 'label' => 'FAQ', 'module' => 'products', 'controller' => 'server', 'action' => 'faq', 'rel' => array( 'canonical' => 'http://www.example.com/?page=faq', 'alternate' => array( 'module' => 'products', 'controller' => 'server', 'action' => 'faq', 'params' => array('format' => 'xml') ) ) ), array( 'label' => 'Editions', 'module' => 'products', 'controller' => 'server', 'action' => 'editions' ), array( 'label' => 'System Requirements', 'module' => 'products', 'controller' => 'server', 'action' => 'requirements' ) ) ), array( 'label' => 'Foo Studio', 'module' => 'products', 'controller' => 'studio', 'action' => 'index', 'pages' => array( array( 'label' => 'Customer Stories', 'module' => 'products', 'controller' => 'studio', 'action' => 'customers' ), array( 'label' => 'Support', 'module' => 'prodcts', 'controller' => 'studio', 'action' => 'support' ) ) ) ) ), array(
1313
Zend_View
'label' => 'Company', 'title' => 'About us', 'module' => 'company', 'controller' => 'about', 'action' => 'index', 'pages' => array( array( 'label' => 'Investor Relations', 'module' => 'company', 'controller' => 'about', 'action' => 'investors' ), array( 'label' => 'News', 'class' => 'rss', // class 'module' => 'company', 'controller' => 'news', 'action' => 'index', 'pages' => array( array( 'label' => 'Press Releases', 'module' => 'company', 'controller' => 'news', 'action' => 'press' ), array( 'label' => 'Archive', 'route' => 'archive', // route 'module' => 'company', 'controller' => 'news', 'action' => 'archive' ) ) ) ) ), array( 'label' => 'Community', 'module' => 'community', 'controller' => 'index', 'action' => 'index', 'pages' => array( array( 'label' => 'My Account', 'module' => 'community', 'controller' => 'account', 'action' => 'index', 'resource' => 'mvc:community.account' // resource ), array( 'label' => 'Forums', 'uri' => 'http://forums.example.com/', 'class' => 'external' // class )
1314
Zend_View
) ), array( 'label' => 'Administration', 'module' => 'admin', 'controller' => 'index', 'action' => 'index', 'resource' => 'mvc:admin', // resource 'pages' => array( array( 'label' => 'Write new article', 'module' => 'admin', 'controller' => 'post', 'aciton' => 'write' ) ) ) ); // Create container from array $container = new Zend_Navigation($pages); // Store the container in the proxy helper: $view->getHelper('navigation')->setContainer($container); // ...or simply: $view->navigation($container); // ...or store it in the reigstry: Zend_Registry::set('Zend_Navigation', $container); In addition to the container above, the following setup is assumed:
// Setup router (default routes and 'archive' route): $front = Zend_Controller_Front::getInstance(); $router = $front->getRouter(); $router->addDefaultRoutes(); $router->addRoute( 'archive', new Zend_Controller_Router_Route( '/archive/:year', array( 'module' => 'company', 'controller' => 'news', 'action' => 'archive', 'year' => (int) date('Y') - 1 ), array('year' => '\d+') ) ); // Setup ACL: $acl = new Zend_Acl();
1315
Zend_View
$acl->addRole(new Zend_Acl_Role('member')); $acl->addRole(new Zend_Acl_Role('admin')); $acl->add(new Zend_Acl_Resource('mvc:admin')); $acl->add(new Zend_Acl_Resource('mvc:community.account')); $acl->allow('member', 'mvc:community.account'); $acl->allow('admin', null); // Store ACL and role in the proxy helper: $view->navigation()->setAcl($acl)->setRole('member'); // ...or set default ACL and role statically: Zend_View_Helper_Navigation_HelperAbstract::setDefaultAcl($acl); Zend_View_Helper_Navigation_HelperAbstract::setDefaultRole('member');
Breadcrumbs Helper
Breadcrumbs are used for indicating where in a sitemap a user is currently browsing, and are typically rendered like this: "You are here: Home > Products > FantasticProduct 1.0". The breadcrumbs helper follows the guidelines from Breadcrumbs Pattern - Yahoo! Design Pattern Library [http://developer.yahoo.com/ypatterns/pattern.php? pattern=breadcrumbs], and allows simple customization (minimum/maximum depth, indentation, separator, and whether the last element should be linked), or rendering using a partial view script. The Breadcrumbs helper works like this; it finds the deepest active page in a navigation container, and renders an upwards path to the root. For MVC pages, the "activeness" of a page is determined by inspecting the request object, as stated in the section on Zend_Navigation_Page_Mvc. The helper sets the minDepth property to 1 by default, meaning breadcrumbs will not be rendered if the deepest active page is a root page. If maxDepth is specified, the helper will stop rendering when at the specified depth (e.g. stop at level 2 even if the deepest active page is on level 3). Methods in the breadcrumbs helper: {get|set}Separator() gets/sets separator string that is used between breadcrumbs. Defualt is ' > '. {get|set}LinkLast() gets/sets whether the last breadcrumb should be rendered as an anchor or not. Default is FALSE. {get|set}Partial() gets/sets a partial view script that should be used for rendering breadcrumbs. If a partial view script is set, the helper's render() method will use the renderPartial() method. If no partial is set, the renderStraight() method is used. The helper expects the partial to be a String or an Array with two elements. If the partial is a String, it denotes the name of the partial script to use. If it is an Array, the first element will be used as the name of the partial view script, and the second element is the module where the script is found. renderStraight() is the default render method. renderPartial() is used for rendering using a partial view script.
1316
Zend_View
<?php echo $this->navigation()->breadcrumbs()->render(); ?> Output: <a href="/products">Products</a> > <a href="/products/server">Foo Server</a> > FAQ
1317
Zend_View
$partial = ; echo $this->navigation()->breadcrumbs() ->setPartial(array('breadcrumbs.phtml', 'default')); Contents of application/modules/default/views/breadcrumbs.phtml: echo implode(', ', array_map( create_function('$a', 'return $a->getLabel();'), $this->pages)); Output: Products, Foo Server, FAQ
Links Helper
The links helper is used for rendering HTML LINK elements. Links are used for describing document relationships of the currently active page. Read more about links and link types at Document relationships: the LINK element (HTML4 W3C Rec.) [http://www.w3.org/TR/html4/struct/links.html#h-12.3] and Link types (HTML4 W3C Rec.) [http://www.w3.org/TR/html4/types.html#h-6.12] in the HTML4 W3C Recommendation. There are two types of relations; forward and reverse, indicated by the keyords 'rel' and 'rev'. Most methods in the helper will take a $rel param, which must be either 'rel' or 'rev'. Most methods also take a $type param, which is used for specifying the link type (e.g. alternate, start, next, prev, chapter, etc). Relationships can be added to page objects manually, or found by traversing the container registered in the helper. The method findRelation($page, $rel, $type) will first try to find the given $rel of $type from the $page by calling $page->findRel($type) or $page->findRel($type). If the $page has a relation that can be converted to a page instance, that relation will be used. If the $page instance doesn't have the specified $type, the helper will look for a method in the helper named search$rel$type (e.g. searchRelNext() or searchRevAlternate()). If such a method exists, it will be used for determining the $page's relation by traversing the container. Not all relations can be determined by traversing the container. These are the relations that will be found by searching: searchRelStart(), forward 'start' relation: the first page in the container. searchRelNext(), forward 'next' relation; finds the next page in the container, i.e. the page after the active page. searchRelPrev(), forward 'prev' relation; finds the previous page, i.e. the page before the active page. searchRelCaptulo(), forward 'chapter' relations; finds all pages on level 0 except the 'start' relation or the active page if it's on level 0. searchRelSection(), forward 'section' relations; finds all child pages of the active page if the active page is on level 0 (a 'chapter'). searchRelSubsection(), forward 'subsection' relations; finds all child pages of the active page if the active pages is on level 1 (a 'section'). searchRevSection(), reverse 'section' relation; finds the parent of the active page if the active page is on level 1 (a 'section'). searchRevSubsection(), reverse 'subsection' relation; finds the parent of the active page if the active page is on level 2 (a 'subsection').
1318
Zend_View
Nota
When looking for relations in the page instance ($page->getRel($type) or $page>getRev($type)), the helper accepts the values of type String, Array, Zend_Config, or Zend_Navigation_Page. If a string is found, it will be converted to a Zend_Navigation_Page_Uri. If an array or a config is found, it will be converted to one or several page instances. If the first key of the array/config is numeric, it will be considered to contain several pages, and each element will be passed to the page factory. If the first key is not numeric, the array/config will be passed to the page factory directly, and a single page will be returned. The helper also supports magic methods for finding relations. E.g. to find forward alternate relations, call $helper->findRelAlternate($page), and to find reverse section relations, call $helper>findRevSection($page). Those calls correspond to $helper->findRelation($page, 'rel', 'alternate'); and $helper->findRelation($page, 'rev', 'section'); respectively. To customize which relations should be rendered, the helper uses a render flag. The render flag is an integer value, and will be used in a bitwse and (&) operation [http://php.net/manual/en/language.operators.bitwise.php] against the helper's render constants to determine if the relation that belongs to the render constant should be rendered. See the example below for more information. Zend_View_Helper_Navigation_Link::RENDER_ALTERNATE Zend_View_Helper_Navigation_Link::RENDER_STYLESHEET Zend_View_Helper_Navigation_Link::RENDER_START Zend_View_Helper_Navigation_Link::RENDER_NEXT Zend_View_Helper_Navigation_Link::RENDER_PREV Zend_View_Helper_Navigation_Link::RENDER_CONTENTS Zend_View_Helper_Navigation_Link::RENDER_INDEX Zend_View_Helper_Navigation_Link::RENDER_GLOSSARY Zend_View_Helper_Navigation_Link::RENDER_COPYRIGHT Zend_View_Helper_Navigation_Link::RENDER_CHAPTER Zend_View_Helper_Navigation_Link::RENDER_SECTION Zend_View_Helper_Navigation_Link::RENDER_SUBSECTION Zend_View_Helper_Navigation_Link::RENDER_APPENDIX Zend_View_Helper_Navigation_Link::RENDER_HELP Zend_View_Helper_Navigation_Link::RENDER_BOOKMARK Zend_View_Helper_Navigation_Link::RENDER_CUSTOM Zend_View_Helper_Navigation_Link::RENDER_ALL The constants from RENDER_ALTERNATE to RENDER_BOOKMARK denote standard HTML link types. RENDER_CUSTOM denotes non-standard relations that specified in pages. RENDER_ALL denotes standard and nonstandard relations. Methods in the links helper:
1319
Zend_View
{get|set}RenderFlag() gets/sets the render flag. Default is RENDER_ALL. See examples below on how to set the render flag. findAllRelations() finds all relations of all types for a given page. findRelation() finds all relations of a given type from a given page. searchRel{Start|Next|Prev|Captulo|Section|Subsection}() traverses a container to find forward relations to the start page, the next page, the previous page, chapters, sections, and subsections. searchRev{Section|Subsection}() traverses a container to find reverse relations to sections or subsections. renderLink() renders a single link element.
$container = new Zend_Navigation(array( array( 'label' => 'Relations using strings', 'rel' => array( 'alternate' => 'http://www.example.org/' ), 'rev' => array( 'alternate' => 'http://www.example.net/' ) ), array( 'label' => 'Relations using arrays', 'rel' => array( 'alternate' => array( 'label' => 'Ejemplo.org', 'uri' => 'http://www.example.org/' ) ) ), array( 'label' => 'Relations using configs', 'rel' => array( 'alternate' => new Zend_Config(array( 'label' => 'Ejemplo.org', 'uri' => 'http://www.example.org/' )) ) ), array( 'label' => 'Relations using pages instance', 'rel' => array( 'alternate' => Zend_Navigation_Page::factory(array( 'label' => 'Ejemplo.org', 'uri' => 'http://www.example.org/' ))
1320
Zend_View
) ) ));
Render only native link types: $helper->setRenderFlag(Zend_View_Helper_Navigation_Links::RENDER_ALL ^ Zend_View_Helper_Navigation_Links::RENDER_CUSTOM); Output: <link rel="alternate" href="/products/server/faq/format/xml"> <link rel="start" href="/" title="Home"> <link rel="next" href="/products/server/editions" title="Editions"> <link rel="prev" href="/products/server" title="Foo Server"> <link rel="chapter" href="/products" title="Products"> <link rel="chapter" href="/company/about" title="Company"> <link rel="chapter" href="/community" title="Community"> <link rev="subsection" href="/products/server" title="Foo Server">
1321
Zend_View
$helper->setRenderFlag(Zend_View_Helper_Navigation_Links::RENDER_ALL ^ Zend_View_Helper_Navigation_Links::RENDER_CHAPTER); Output: <link rel="alternate" href="/products/server/faq/format/xml"> <link rel="start" href="/" title="Home"> <link rel="next" href="/products/server/editions" title="Editions"> <link rel="prev" href="/products/server" title="Foo Server"> <link rel="canonical" href="http://www.example.com/?page=server-faq"> <link rev="subsection" href="/products/server" title="Foo Server">
Menu Helper
The Menu helper is used for rendering menus from navigation containers. By default, the menu will be rendered using HTML UL and LI tags, but the helper also allows using a partial view script. Methods in the Menu helper: {get|set}UlClass() gets/sets the CSS class used in renderMenu(). {get|set}OnlyActiveBranch() gets/sets a flag specifying whether only the active branch of a container should be rendered. {get|set}RenderParents() gets/sets a flag specifying whether parents should be rendered when only rendering active branch of a container. If set to FALSE, only the deepest active menu will be rendered. {get|set}Partial() gets/sets a partial view script that should be used for rendering menu. If a partial view script is set, the helper's render() method will use the renderPartial() method. If no partial is set, the renderMenu() method is used. The helper expects the partial to be a String or an Array with two elements. If the partial is a String, it denotes the name of the partial script to use. If it is an Array, the first element will be used as the name of the partial view script, and the second element is the module where the script is found. htmlify() overrides the method from the abstract class to return span elements if the page has no href. renderMenu($container = null, $options = array()) is the default render method, and will render a container as a HTML UL list. If $container is not given, the container registered in the helper will be rendered. $options is used for overriding options specified temporarily without rsetting the values in the helper instance. It is an associative array where each key corresponds to an option in the helper. Recognized options: indent; indentation. Expects a String or an int value. minDepth; minimum depth. Expcects an int or NULL (no minimum depth). maxDepth; maximum depth. Expcects an int or NULL (no maximum depth). ulClass; CSS class for ul element. Expects a String. onlyActiveBranch; whether only active branch should be rendered. Expects a Boolean value. renderParents; whether parents should be rendered if only rendering active branch. Expects a Boolean value. If an option is not given, the value set in the helper will be used.
1322
Zend_View
renderPartial() is used for rendering the menu using a partial view script. renderSubMenu() renders the deepest menu level of a container's active branch.
In a view script or layout: <?php echo $this->navigation()->menu()->render() ?> Or simply: <?php echo $this->navigation()->menu() ?> Output: <ul class="navigation"> <li> <a title="Go Home" href="/">Home</a> </li> <li class="active"> <a href="/products">Products</a> <ul> <li class="active"> <a href="/products/server">Foo Server</a> <ul> <li class="active"> <a href="/products/server/faq">FAQ</a> </li> <li> <a href="/products/server/editions">Editions</a> </li> <li> <a href="/products/server/requirements">System Requirements</a> </li> </ul> </li> <li> <a href="/products/studio">Foo Studio</a> <ul> <li> <a href="/products/studio/customers">Customer Stories</a> </li> <li> <a href="/prodcts/studio/support">Support</a> </li> </ul> </li> </ul> </li> <li> <a title="About us" href="/company/about">Company</a> <ul>
1323
Zend_View
<li> <a href="/company/about/investors">Investor Relations</a> </li> <li> <a class="rss" href="/company/news">News</a> <ul> <li> <a href="/company/news/press">Press Releases</a> </li> <li> <a href="/archive">Archive</a> </li> </ul> </li> </ul> </li> <li> <a href="/community">Community</a> <ul> <li> <a href="/community/account">My Account</a> </li> <li> <a class="external" href="http://forums.example.com/">Forums</a> </li> </ul> </li> </ul>
<?php // render only the 'Community' menu $community = $this->navigation()->findOneByLabel('Community'); $options = array( 'indent' => 16, 'ulClass' => 'community' ); echo $this->navigation() ->menu() ->renderMenu($community, $options); ?> Output: <ul class="community"> <li> <a href="/community/account">My Account</a> </li> <li> <a class="external" href="http://forums.example.com/">Forums</a> </li>
1324
Zend_View
</ul>
<?php echo $this->navigation() ->menu() ->renderSubMenu(null, 'sidebar', 4); ?> The output will be the same if 'FAQ' or 'Foo Server' is active: <ul class="sidebar"> <li class="active"> <a href="/products/server/faq">FAQ</a> </li> <li> <a href="/products/server/editions">Editions</a> </li> <li> <a href="/products/server/requirements">System Requirements</a> </li> </ul>
1325
Zend_View
<ul> <li class="active"> <a href="/products/server">Foo Server</a> </li> <li> <a href="/products/studio">Foo Studio</a> </li> </ul> </li> <li> <a title="About us" href="/company/about">Company</a> <ul> <li> <a href="/company/about/investors">Investor Relations</a> </li> <li> <a class="rss" href="/company/news">News</a> </li> </ul> </li> <li> <a href="/community">Community</a> <ul> <li> <a href="/community/account">My Account</a> </li> <li> <a class="external" href="http://forums.example.com/">Forums</a> </li> </ul> </li> </ul>
1326
Zend_View
<a href="/products/server/requirements">System Requirements</a> </li> </ul> </li> <li> <a href="/products/studio">Foo Studio</a> <ul> <li> <a href="/products/studio/customers">Customer Stories</a> </li> <li> <a href="/prodcts/studio/support">Support</a> </li> </ul> </li> <li> <a href="/company/about/investors">Investor Relations</a> </li> <li> <a class="rss" href="/company/news">News</a> <ul> <li> <a href="/company/news/press">Press Releases</a> </li> <li> <a href="/archive">Archive</a> </li> </ul> </li> <li> <a href="/community/account">My Account</a> </li> <li> <a class="external" href="http://forums.example.com/">Forums</a> </li> </ul>
1327
Zend_View
<li class="active"> <a href="/products/server/faq">FAQ</a> </li> <li> <a href="/products/server/editions">Editions</a> </li> <li> <a href="/products/server/requirements">System Requirements</a> </li> </ul> </li> </ul> </li> </ul>
Ejemplo 61.37. Rendering only the active branch of a menu with minimum depth
<?php echo $this->navigation() ->menu() ->setOnlyActiveBranch(true) ->setMinDepth(1); ?> Output: <ul class="navigation"> <li class="active"> <a href="/products/server">Foo Server</a> <ul> <li class="active"> <a href="/products/server/faq">FAQ</a> </li> <li> <a href="/products/server/editions">Editions</a> </li> <li> <a href="/products/server/requirements">System Requirements</a> </li> </ul> </li> </ul>
Ejemplo 61.38. Rendering only the active branch of a menu with maximum depth
<?php echo $this->navigation() ->menu() ->setOnlyActiveBranch(true) ->setMaxDepth(1); ?> Output:
1328
Zend_View
<ul class="navigation"> <li class="active"> <a href="/products">Products</a> <ul> <li class="active"> <a href="/products/server">Foo Server</a> </li> <li> <a href="/products/studio">Foo Studio</a> </li> </ul> </li> </ul>
Ejemplo 61.39. Rendering only the active branch of a menu with maximum depth and no parents
<?php echo $this->navigation() ->menu() ->setOnlyActiveBranch(true) ->setRenderParents(false) ->setMaxDepth(1); ?> Output: <ul class="navigation"> <li class="active"> <a href="/products/server">Foo Server</a> </li> <li> <a href="/products/studio">Foo Studio</a> </li> </ul>
1329
Zend_View
echo $this->navigation()->menu()->htmlify($page), PHP_EOL; } Output: <a <a <a <a title="Go Home" href="/">Home</a> href="/products">Products</a> title="About us" href="/company/about">Company</a> href="/community">Community</a>
Sitemap Helper
The Sitemap helper is used for generating XML sitemaps, as defined by the Sitemaps XML format [http:// www.sitemaps.org/protocol.php]. Read more about Sitemaps on Wikpedia [http://en.wikipedia.org/wiki/Sitemaps]. By default, the sitemap helper uses sitemap validators to validate each element that is rendered. This can be disabled by calling $helper->setUseSitemapValidators(false).
Nota
If you disable sitemap validators, the custom properties (see table) are not validated at all. The sitemap helper also supports Sitemap XSD Schema [http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd] validation of the generated sitemap. This is disabled by default, since it will require a request to the Schema file. It can be enabled with $helper->setUseSchemaValidation(true).
1330
Zend_View
Element
Description never The helper will try to retrieve the changefreq value from the page's custom property changefreq if it is set in the page. If the value is not valid, it is ignored.
priority
The priority of this URL relative to other URLs on your site. Valid values range from 0.0 to 1.0. The helper will try to retrieve the priority value from the page's custom property priority if it is set in the page. If the value is not valid, it is ignored.
Methods in the sitemap helper: {get|set}FormatOutput() gets/sets a flag indicating whether XML output should be formatted. This corresponds to the formatOutput property of the native DOMDocument class. Read more at PHP: DOMDocument - Manual [http://php.net/domdocument]. Default is FALSE. {get|set}UseXmlDeclaration() gets/sets a flag indicating whether the XML declaration should be included when rendering. Default is TRUE. {get|set}UseSitemapValidators() gets/sets a flag indicating whether sitemap validators should be used when generating the DOM sitemap. Default is TRUE. {get|set}UseSchemaValidation() gets/sets a flag indicating whether the helper should use XML Schema validation when generating the DOM sitemap. Default is FALSE. If TRUE. {get|set}ServerUrl() gets/sets server URL that will be prepended to non-absolute URLs in the url() method. If no server URL is specified, it will be determined by the helper. url() is used to generate absolute URLs to pages. getDomSitemap() generates a DOMDocument from a given container.
// print sitemap echo $this->navigation()->sitemap(); Notice how pages that are invisible or pages with ACL roles incompatible with the view helper are filtered out:
1331
Zend_View
<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>http://www.example.com/</loc> </url> <url> <loc>http://www.example.com/products</loc> </url> <url> <loc>http://www.example.com/products/server</loc> </url> <url> <loc>http://www.example.com/products/server/faq</loc> </url> <url> <loc>http://www.example.com/products/server/editions</loc> </url> <url> <loc>http://www.example.com/products/server/requirements</loc> </url> <url> <loc>http://www.example.com/products/studio</loc> </url> <url> <loc>http://www.example.com/products/studio/customers</loc> </url> <url> <loc>http://www.example.com/prodcts/studio/support</loc> </url> <url> <loc>http://www.example.com/company/about</loc> </url> <url> <loc>http://www.example.com/company/about/investors</loc> </url> <url> <loc>http://www.example.com/company/news</loc> </url> <url> <loc>http://www.example.com/company/news/press</loc> </url> <url> <loc>http://www.example.com/archive</loc> </url> <url> <loc>http://www.example.com/community</loc> </url> <url> <loc>http://www.example.com/community/account</loc> </url> <url> <loc>http://forums.example.com/</loc> </url>
1332
Zend_View
</urlset> Render the sitemap using no ACL role (should filter out /community/account): echo $this->navigation() ->sitemap() ->setFormatOutput(true) ->setRole(); <?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>http://www.example.com/</loc> </url> <url> <loc>http://www.example.com/products</loc> </url> <url> <loc>http://www.example.com/products/server</loc> </url> <url> <loc>http://www.example.com/products/server/faq</loc> </url> <url> <loc>http://www.example.com/products/server/editions</loc> </url> <url> <loc>http://www.example.com/products/server/requirements</loc> </url> <url> <loc>http://www.example.com/products/studio</loc> </url> <url> <loc>http://www.example.com/products/studio/customers</loc> </url> <url> <loc>http://www.example.com/prodcts/studio/support</loc> </url> <url> <loc>http://www.example.com/company/about</loc> </url> <url> <loc>http://www.example.com/company/about/investors</loc> </url> <url> <loc>http://www.example.com/company/news</loc> </url> <url> <loc>http://www.example.com/company/news/press</loc> </url> <url> <loc>http://www.example.com/archive</loc> </url>
1333
Zend_View
<url> <loc>http://www.example.com/community</loc> </url> <url> <loc>http://forums.example.com/</loc> </url> </urlset> Render the sitemap using a maximum depth of 1. echo $this->navigation() ->sitemap() ->setFormatOutput(true) ->setMaxDepth(1);
<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>http://www.example.com/</loc> </url> <url> <loc>http://www.example.com/products</loc> </url> <url> <loc>http://www.example.com/products/server</loc> </url> <url> <loc>http://www.example.com/products/studio</loc> </url> <url> <loc>http://www.example.com/company/about</loc> </url> <url> <loc>http://www.example.com/company/about/investors</loc> </url> <url> <loc>http://www.example.com/company/news</loc> </url> <url> <loc>http://www.example.com/community</loc> </url> <url> <loc>http://www.example.com/community/account</loc> </url> <url> <loc>http://forums.example.com/</loc> </url> </urlset>
Navigation Helper
The Navigation helper is a proxy helper that relays calls to other navigational helpers. It can be considered an entry point to all navigation-related view tasks. The aforementioned navigational helpers are in the namespace
1334
Zend_View
Zend_View_Helper_Navigation, and would thus require the path Zend/View/Helper/Navigation to be added as a helper path to the view. With the proxy helper residing in the Zend_View_Helper namespace, it will always be available, without the need to add any helper paths to the view. The Navigation helper finds other helpers that implement the Zend_View_Helper_Navigation_Helper interface, which means custom view helpers can also be proxied. This would, however, require that the custom helper path is added to the view. When proxying to other helpers, the Navigation helper can inject its container, ACL/role, and translator. This means that you won't have to explicitly set all three in all navigational helpers, nor resort to injecting by means of Zend_Registry or static methods. findHelper() finds the given helper, verifies that it is a navigational helper, and injects container, ACL/role and translator. {get|set}InjectContainer() gets/sets a flag indicating whether the container should be injected to proxied helpers. Default is TRUE. {get|set}InjectAcl() gets/sets a flag indicating whether the ACL/role should be injected to proxied helpers. Default is TRUE. {get|set}InjectTranslator() gets/sets a flag indicating whether the translator should be injected to proxied helpers. Default is TRUE. {get|set}DefaultProxy() gets/sets the default proxy. Default is 'menu'. render() proxies to the render method of the default proxy.
Translate Helper
Often web sites are available in several languages. To translate the content of a site you should simply use Zend Translate and to integrate Zend Translate within your view you should use the Translate View Helper. In all following examples we are using the simple Array Translation Adapter. Of course you can also use any instance of Zend_Translate and also any subclasses of Zend_Translate_Adapter. There are several ways to initiate the Translate View Helper: Registered, through a previously registered instance in Zend_Registry Afterwards, through the fluent interface Directly, through initiating the class A registered instance of Zend_Translate is the preferred usage for this helper. You can also select the locale to be used simply before you add the adapter to the registry.
Nota
We are speaking of locales instead of languages because a language also may contain a region. For example English is spoken in different dialects. There may be a translation for British and one for American English. Therefore, we say "locale" instead of "language."
1335
Zend_View
// our example adapter $adapter = new Zend_Translate('array', array('simple' => 'einfach'), 'de'); Zend_Registry::set('Zend_Translate', $adapter); // within your view echo $this->translate('simple'); // this returns 'einfach' If you are more familiar with the fluent interface, then you can also create an instance within your view and initiate the helper afterwards.
// within your view $adapter = new Zend_Translate('array', array('simple' => 'einfach'), 'de'); $this->translate()->setTranslator($adapter)->translate('simple'); // this returns 'einfach' If you are using the helper without Zend_View then you can also use it directly.
// within your view $date = "Monday"; $this->translate("Today is %1\$s", $date); // could return 'Heute ist Monday'
Nota
Keep in mind that if you are using parameters which are also text, you may also need to translate these parameters.
1336
Zend_View
1337
Zend_View
$date = array("Monday", "April", "11:20:55"); // returns 'de' as set default locale from our above examples $this->translate()->getLocale(); $this->translate()->setLocale('it'); $this->translate("Today is %1\$s in %2\$s. Actual time: %3\$s", $date); // returns 'it' as new set default locale $this->translate()->getLocale();
Helper Paths
As with view scripts, your controller can specify a stack of paths for Zend_View to search for helper classes. By default, Zend_View looks in "Zend/View/Helper/*" for helper classes. You can tell Zend_View to look in other locations using the setHelperPath() and addHelperPath() methods. Additionally, you can indicate a class prefix to use for helpers in the path provided, to allow namespacing your helper classes. By default, if no class prefix is provided, 'Zend_View_Helper_' is assumed. $view = new Zend_View(); // Set path to /path/to/more/helpers, with prefix 'My_View_Helper' $view->setHelperPath('/path/to/more/helpers', 'My_View_Helper'); In fact, you can "stack" paths using the addHelperPath() method. As you add paths to the stack, Zend_View will look at the most-recently-added path for the requested helper class. This allows you to add to (or even override) the initial distribution of helpers with your own custom helpers. $view = new Zend_View(); // Add /path/to/some/helpers with class prefix 'My_View_Helper' $view->addHelperPath('/path/to/some/helpers', 'My_View_Helper'); // Add /other/path/to/helpers with class prefix 'Your_View_Helper' $view->addHelperPath('/other/path/to/helpers', 'Your_View_Helper'); // // // // // // // now when you call $this->helperName(), Zend_View will look first for "/path/to/some/helpers/HelperName" using class name "Your_View_Helper_HelperName", then for "/other/path/to/helpers/HelperName.php" using class name "My_View_Helper_HelperName", and finally for "Zend/View/Helper/HelperName.php" using class name "Zend_View_Helper_HelperName".
1338
Zend_View
and should, give the class name a prefix, and it is recommended that you use 'View_Helper' as part of that prefix: "My_View_Helper_SpecialPurpose". (You will need to pass in the prefix, with or without the trailing underscore, to addHelperPath() or setHelperPath()). The class must have a public method that matches the helper name; this is the method that will be called when your template calls "$this->specialPurpose()". In our "specialPurpose" helper example, the required method declaration would be "public function specialPurpose()". In general, the class should not echo or print or otherwise generate output. Instead, it should return values to be printed or echoed. The returned values should be escaped appropriately. The class must be in a file named after the helper class. Again using our "specialPurpose" helper example, the file has to be named "SpecialPurpose.php". Place the helper class file somewhere in your helper path stack, and Zend_View will automatically load, instantiate, persist, and execute it for you. Here is an example of our SpecialPurpose helper code:
class My_View_Helper_SpecialPurpose extends Zend_View_Helper_Abstract { protected $_count = 0; public function specialPurpose() { $this->_count++; $output = "I have seen 'The Jerk' {$this->_count} time(s)."; return htmlspecialchars($output); } } Then in a view script, you can call the SpecialPurpose helper as many times as you like; it will be instantiated once, and then it persists for the life of that Zend_View instance.
// remember, in a view script, $this refers to the Zend_View instance. echo $this->specialPurpose(); echo $this->specialPurpose(); echo $this->specialPurpose(); The output would look something like this:
I have seen 'The Jerk' 1 time(s). I have seen 'The Jerk' 2 time(s). I have seen 'The Jerk' 3 time(s). Sometimes you will need access to the calling Zend_View object -- for instance, if you need to use the registered encoding, or want to render another view script as part of your helper. To get access to the view object, your helper class should have a setView($view) method, like the following:
1339
Zend_View
public function setView(Zend_View_Interface $view) { $this->view = $view; } public function scriptPath($script) { return $this->view->getScriptPath($script); } } If your helper class has a setView() method, it will be called when the helper class is first instantiated, and passed the current view object. It is up to you to persist the object in your class, as well as determine how it should be accessed. If you are extending Zend_View_Helper_Abstract, you do not need to define this method, as it is defined for you.
Zend_View_Abstract
Zend_View_Abstract is the base class on which Zend_View is built; Zend_View itself simply extends it and declares a concrete implementation of the _run() method (which is invoked by render()). Many developers find that they want to extend Zend_View_Abstract to add custom functionality, and inevitably run into issues with its design, which includes a number of private members. This document aims to explain the decision behind the design. Zend_View is something of an anti-templating engine in that it uses PHP natively for its templating. As a result, all of PHP is available, and view scripts inherit the scope of their calling object. It is this latter point that is salient to the design decisions. Internally, Zend_View::_run() does the following:
protected function _run() { include func_get_arg(0); } As such, the view scripts have access to the current object ($this), and any methods or members of that object. Since many operations depend on members with limited visibility, this poses a problem: the view scripts could potentially make calls to such methods or modify critical properties directly. Imagine a script overwriting $_path or $_file inadvertently -- any further calls to render() or view helpers would break! Fortunately, PHP 5 has an answer to this with its visibility declarations: private members are not accessible by objects extending a given class. This led to the current design: since Zend_View extends Zend_View_Abstract, view scripts are thus limited to only protected or public methods and members of Zend_View_Abstract -- effectively limiting the actions it can perform, and allowing us to secure critical areas from abuse by view scripts.
1340
1341
1342
Zend_XmlRpc_Client
Introducin
Zend Framework provee soporte para consumo remoto para servicios XML-RPC como un cliente en el paquete Zend_XmlRpc_Client . Su mejor caracterstica es la conversin automtica de tipos entre PHP y XML-RPC, un servidor de objeto proxy, y acceso a capacidades de instrospeccin del servidor.
Method Calls
El constructor de Zend_XmlRpc_Client recibe la URL del servidor XML-RPC como su primer parmetro. La nueva instacia devuelta puede ser usada para llamar cualquier nmero de mtodos remotos en el punto final. Para llamar un mtodo remoto con el cliente XML-RPC, instncealo y usa el mtodo de instancia call() . El cdigo de ejemplo a continuacin utiliza una demostracin en el servidor XML-RPC en el sitio web de Zend Framework . Puede utilizarlo para probar o explorar los componentes Zend_XmlRpc.
1343
Zend_XmlRpc
$result = $client->call('test.sayHello', array($arg1, $arg2)); // $result es un tipo nativo PHP si el mtodo remoto no requiere parmetros, este parmetro opcional podr ser excluido o se puede pasar un array() vaco. El array de parmeters para el mtodo repoto puede contener tipos nativos PHPs, objetos Zend_XmlRpc_Value , o una combinacin de estos. El mtodo call() convertir automticamente la respuesta XML-RPC y devolver su tipo nativo PHP equivalente. Un objeto Zend_XmlRpc_Response para el valor devuelto tambin estar disponible para llamar el mtodo getLastResponse() despus de la llamada.
Tipos y Conversiones
Algunas llamadas a mtodos remoto requieren parmetros. stos son dados al mtodo call() de Zend_XmlRpc_Client como un array en el segundo parmetro. Cada parmetro puede ser dado como un tipo nativo PHP, que ser convertido automticamente, o como un objeto que representa un tipo especfico de XML-RPC (uno de los objetos Zend_XmlRpc_Value).
$client->setSkipSystemLookup(true);
1344
Zend_XmlRpc
Automatic Conversion
When building a new Zend_XmlRpc_Value 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 Zend_XmlRpc_Value_Integer object, it will be converted using (int)$value.
1345
Zend_XmlRpc
The getProxy() 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 test namespace will be proxied:
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 test.foo.bar(), it could be called as $test->foo>bar().
Error Handling
Two kinds of errors can occur during an XML-RPC method call: HTTP errors and XML-RPC faults. The Zend_XmlRpc_Client recognizes each and provides the ability to detect and trap them independently.
HTTP Errors
If any HTTP error occurs, such as the remote HTTP server returns a 404 Zend_XmlRpc_Client_HttpException will be thrown. Not Found, a
XML-RPC Faults
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 Zend_XmlRpc_Client is used.
1346
Zend_XmlRpc
When the call() method or the server proxy object is used, an XML-RPC fault will result in a Zend_XmlRpc_Client_FaultException being thrown. The code and message of the exception will map directly to their respective values in the original XML-RPC fault response.
Server Introspection
Some XML-RPC servers support the de facto introspection methods under the XML-RPC system. namespace. Zend_XmlRpc_Client provides special support for servers with these capabilities. A Zend_XmlRpc_Client_ServerIntrospection instance may be retrieved by calling the getIntrospector() method of Zend_XmlRpcClient. It can then be used to perform introspection operations on the server.
1347
Zend_XmlRpc
$client->doRequest($request); // $server->getLastRequest() returns instanceof Zend_XmlRpc_Request // $server->getLastResponse() returns instanceof Zend_XmlRpc_Response Whenever an XML-RPC method call is made by the client through any means, either the call() method, doRequest() method, or server proxy, the last request object and its resultant response object will always be available through the methods getLastRequest() and getLastResponse() respectively.
Zend_XmlRpc_Server
Introduction
Zend_XmlRpc_Server is intended as a fully-featured XML-RPC server, following the specifications outlined at www.xmlrpc.com [http://www.xmlrpc.com/spec]. Additionally, it implements the system.multicall() method, allowing boxcarring of requests.
Basic Usage
An example of the most basic use case:
Server Structure
Zend_XmlRpc_Server is composed of a variety of components, ranging from the server itself to request, response, and fault objects. To bootstrap Zend_XmlRpc_Server, the developer must attach one or more classes or functions to the server, via the setClass() and addFunction() methods. Once done, you may either pass a Zend_XmlRpc_Request object to Zend_XmlRpc_Server::handle(), or it will instantiate a Zend_XmlRpc_Request_Http object if none is provided -- thus grabbing the request from php://input. Zend_XmlRpc_Server::handle() then attempts to dispatch to the appropriate handler based on the method requested. It then returns either a Zend_XmlRpc_Response-based object or a
1348
Zend_XmlRpc
Zend_XmlRpc_Server_Faultobject. These objects both have __toString() methods that create valid XMLRPC XML responses, allowing them to be directly echoed.
Conventions
Zend_XmlRpc_Server allows the developer to attach functions and class method calls as dispatchable XML-RPC methods. Via Zend_Server_Reflection, it does introspection on all attached methods, using the function and method docblocks to determine the method help text and method signatures. XML-RPC types do not necessarily map one-to-one to PHP types. However, the code will do its best to guess the appropriate type based on the values listed in @param and @return lines. Some XML-RPC types have no immediate PHP equivalent, however, and should be hinted using the XML-RPC type in the PHPDoc. These include: dateTime.iso8601, a string formatted as 'YYYYMMDDTHH:mm:ss' base64, base64 encoded data struct, any associative array An example of how to hint follows:
/** * This is a sample function * * @param base64 $val1 Base64-encoded data * @param dateTime.iso8601 $val2 An ISO date * @param struct $val3 An associative array * @return struct */ function myFunc($val1, $val2, $val3) { } PhpDocumentor does no validation of the types specified for params or return values, so this will have no impact on your API documentation. Providing the hinting is necessary, however, when the server is validating the parameters provided to the method call. It is perfectly valid to specify multiple types for both params and return values; the XML-RPC specification even suggests that system.methodSignature should return an array of all possible method signatures (i.e., all possible combinations of param and return values). You may do so just as you normally would with PhpDocumentor, using the '|' operator:
/** * This is a sample function * * @param string|base64 $val1 String or base64-encoded data * @param string|dateTime.iso8601 $val2 String or an ISO date * @param array|struct $val3 Normal indexed array or an associative array * @return boolean|struct */ function myFunc($val1, $val2, $val3) { }
1349
Zend_XmlRpc
One note, however: allowing multiple signatures can lead to confusion for developers using the services; generally speaking, an XML-RPC method should only have a single signature.
Utilizing Namespaces
XML-RPC has a concept of namespacing; basically, it allows grouping XML-RPC methods by dot-delimited namespaces. This helps prevent naming collisions between methods served by different classes. As an example, the XML-RPC server is expected to server several methods in the 'system' namespace: system.listMethods system.methodHelp system.methodSignature Internally, these map to the methods of the same name in Zend_XmlRpc_Server. If you want to add namespaces to the methods you serve, simply provide a namespace to the appropriate method when attaching a function or class:
// All public methods in My_Service_Class will be accessible as // myservice.METHODNAME $server->setClass('My_Service_Class', 'myservice'); // Function 'somefunc' will be accessible as funcs.somefunc $server->addFunction('somefunc', 'funcs');
Custom Responses
Similar to request objects, Zend_XmlRpc_Server can return custom response objects; by default, a Zend_XmlRpc_Response_Http object is returned, which sends an appropriate Content-Type HTTP header for use with XML-RPC. Possible uses of a custom object would be to log responses, or to send responses back to STDOUT. To use a custom response class, use Zend_XmlRpc_Server::setResponseClass() prior to calling handle().
1350
Zend_XmlRpc
Exception classes can be whitelisted to be used as fault responses, however. To do so, simply utilize Zend_XmlRpc_Server_Fault::attachFaultException() to pass an exception class to whitelist: Zend_XmlRpc_Server_Fault::attachFaultException('My_Project_Exception'); If you utilize an exception class that your other project exceptions inherit, you can then whitelist a whole family of exceptions at a time. Zend_XmlRpc_Server_Exceptions are always whitelisted, to allow reporting specific internal errors (undefined methods, etc.). Any exception not specifically whitelisted will generate a fault response with a code of '404' and a message of 'Unknown error'.
Usage Ejemplos
Below are several usage examples, showing the full spectrum of options available to developers. Usage examples will each build on the previous example provided.
1351
Zend_XmlRpc
Basic Usage
The example below attaches a function as a dispatchable XML-RPC method and handles incoming calls.
/** * Return the MD5 sum of a value * * @param string $value Value to md5sum * @return string MD5 sum of value */ function md5Value($value) { return md5($value); } $server = new Zend_XmlRpc_Server(); $server->addFunction('md5Value'); echo $server->handle();
Attaching a class
The example below illustrates attaching a class' public methods as dispatchable XML-RPC methods.
require_once 'Services/Comb.php'; require_once 'Services/Brush.php'; require_once 'Services/Pick.php'; $server = new Zend_XmlRpc_Server(); $server->setClass('Services_Comb', 'comb'); // methods called as comb.* $server->setClass('Services_Brush', 'brush'); // methods called as brush.* $server->setClass('Services_Pick', 'pick'); // methods called as pick.* echo $server->handle();
1352
Zend_XmlRpc
require_once 'Services/Brush.php'; require_once 'Services/Pick.php'; // Allow Services_Exceptions to report as fault responses Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception'); $server = new Zend_XmlRpc_Server(); $server->setClass('Services_Comb', 'comb'); // methods called as comb.* $server->setClass('Services_Brush', 'brush'); // methods called as brush.* $server->setClass('Services_Pick', 'pick'); // methods called as pick.* echo $server->handle();
// Allow Services_Exceptions to report as fault responses Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception'); $server = new Zend_XmlRpc_Server(); $server->setClass('Services_Comb', 'comb'); // methods called as comb.* $server->setClass('Services_Brush', 'brush'); // methods called as brush.* $server->setClass('Services_Pick', 'pick'); // methods called as pick.* // Create a request object $request = new Services_Request(); echo $server->handle($request);
// Allow Services_Exceptions to report as fault responses Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception'); $server = new Zend_XmlRpc_Server(); $server->setClass('Services_Comb', 'comb'); // methods called as comb.* $server->setClass('Services_Brush', 'brush'); // methods called as brush.*
1353
Zend_XmlRpc
// Specify a cache file $cacheFile = dirname(__FILE__) . '/xmlrpc.cache'; // Allow Services_Exceptions to report as fault responses Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception'); $server = new Zend_XmlRpc_Server(); // Attempt to retrieve server definition from cache if (!Zend_XmlRpc_Server_Cache::get($cacheFile, $server)) { $server->setClass('Services_Comb', 'comb'); // methods called as comb.* $server->setClass('Services_Brush', 'brush'); // methods called as brush.* $server->setClass('Services_Pick', 'pick'); // methods called as pick.* // Save cache Zend_XmlRpc_Server_Cache::save($cacheFile, $server); } // Create a request object $request = new Services_Request(); // Utilize a custom response $server->setResponseClass('Services_Response'); echo $server->handle($request);
1354
Versin de PHP
Zend recomienda PHP 5.2.3 o superior por mejoras en la seguridad crticas y en el rendimiento, aunque Zend Framework requiere slo PHP 5.1.4 o posterior. Zend Framework tiene una extensa coleccin de unidades de prueba, que puede ejecutar utilizando PHPUnit 3.0 o posterior.
Extensiones de PHP
Usted encontrar un cuadro con todas las extensiones que suelen encontrarse en PHP y debajo cmo se usan en Zend Framework. Usted debe verificar que las extensiones de componentes ZF que estar usando en su aplicacin estn disponibles en sus entornos PHP. Muchas aplicaciones no exigirn de cada extensin que figuran a continuacin. Una dependencia de tipo "hard" indica que los componentes o clases no pueden funcionar correctamente si las respectivas extensiones no estn disponibles, mientras que una dependencia de tipo "soft" indica que el componente puede usar la extensin si est disponible pero funcionar correctamente si no lo est. Muchos de los componentes utilizarn automticamente determinadas extensiones si estn disponibles para optimizar el rendimiento pero ejecutarn el cdigo con una funcionalidad similar en el propio componente si las extensiones no estn disponibles.
apc [http://www.php.net/manual/ Hard en/ref.apc.php] bcmath [http://www.php.net/ Soft manual/en/ref.bc.php] bitset [http://pecl.php.net/ Soft package/Bitset] bz2 [http://www.php.net/manual/ --en/ref.bzip2.php] calendar [http://www.php.net/ --manual/en/ref.calendar.php]
1355
Extensin
Tipo de Dependencia
Useda por Componentes de Zend Framework --Zend_Auth_Adapter_Http [http://framework.zend.com/manual/ en/zend.auth.adapter.http.html] Zend_Gdata [http:// framework.zend.com/manual/en/ zend.gdata.html] Zend_Http_Client [http:// framework.zend.com/manual/en/ zend.http.html] Zend_Pdf [http:// framework.zend.com/manual/en/ zend.pdf.html]
Zend_Rest_Client [http:// framework.zend.com/manual/en/ zend.rest.client.html] Zend_Rest_Server [http:// framework.zend.com/manual/en/ zend.rest.server.html] Zend_Search_Lucene [http:// framework.zend.com/manual/en/ zend.search.lucene.html] Zend_Uri [http:// framework.zend.com/manual/en/ zend.uri.html] Zend_Validate [http:// framework.zend.com/manual/en/ zend.validate.html]
curl [http://www.php.net/manual/ Hard en/ref.curl.php] date [http://www.php.net/manual/ --en/ref.datetime.php] dba [http://www.php.net/manual/ --en/ref.dba.php] dbase [http://www.php.net/ --manual/en/ref.dbase.php]
Zend_Http_Client_Adapter_Curl [http://framework.zend.com/manual/ en/zend.http.client.adapters.html] ------Zend_Feed [http:// framework.zend.com/manual/en/ zend.feed.html] Zend_Gdata [http:// framework.zend.com/manual/en/ zend.gdata.html]
1356
Extensin
Tipo de Dependencia
Useda por Componentes de Zend Framework Zend_Log_Formatter_Xml [http://framework.zend.com/manual/ en/zend.log.formatters.html] Zend_Rest_Server [http:// framework.zend.com/manual/en/ zend.rest.server.html] Zend_Search_Lucene [http:// framework.zend.com/manual/en/ zend.search.lucene.html] Zend_Service_Amazon [http:// framework.zend.com/manual/en/ zend.service.amazon.html] Zend_Service_Delicious [http://framework.zend.com/manual/ en/zend.service.delicious.html] Zend_Service_Flickr [http:// framework.zend.com/manual/en/ zend.service.flickr.html] Zend_Service_Simpy [http:// framework.zend.com/manual/en/ zend.service.simpy.html] Zend_Service_Yahoo [http:// framework.zend.com/manual/en/ zend.service.yahoo.html] Zend_XmlRpc [http:// framework.zend.com/manual/en/ zend.xmlrpc.html]
exif [http://www.php.net/manual/ --en/ref.exif.php] fbsql [http://www.php.net/ --manual/en/ref.fbsql.php] fdf [http://www.php.net/manual/ --en/ref.fdf.php] filter [http://www.php.net/ --manual/en/ref.filter.php] ftp [http://www.php.net/manual/ --en/ref.ftp.php] gd [http://www.php.net/manual/en/ Hard ref.image.php] gettext [http://www.php.net/ --manual/en/ref.gettext.php] gmp [http://www.php.net/manual/ --en/ref.gmp.php]
1357
Extensin
Tipo de Dependencia
Useda por Componentes de Zend Framework Zend_Auth_Adapter_Http [http://framework.zend.com/manual/ en/zend.auth.adapter.http.html] Zend_Db_Adapter_Db2 [http:// framework.zend.com/manual/en/ zend.db.html] Zend_Currency [http:// framework.zend.com/manual/en/ zend.currency.html] Zend_Locale_Format [http:// framework.zend.com/manual/en/ zend.locale.parsing.html] Zend_Mime [http:// framework.zend.com/manual/en/ zend.mime.html] Zend_Pdf [http:// framework.zend.com/manual/en/ zend.pdf.html] Zend_Search_Lucene [http:// framework.zend.com/manual/en/ zend.search.lucene.html] Zend_Service_Audioscrobbler [http://framework.zend.com/manual/ en/zend.service.audioscrobbler.html] Zend_Service_Flickr [http:// framework.zend.com/manual/en/ zend.service.flickr.html] Zend_XmlRpc_Client [http:// framework.zend.com/manual/en/ zend.xmlrpc.client.html]
imap [http://www.php.net/manual/ --en/ref.imap.php] informix [http://www.php.net/ --manual/en/ref.ifx.php] interbase [http://www.php.net/ Hard manual/en/ref.ibase.php] json [http://www.php.net/manual/ Soft en/ref.json.php] ldap [http://www.php.net/manual/ --en/ref.ldap.php] libxml [http://www.php.net/ Hard manual/en/ref.libxml.php]
----Zend_Db_Adapter_Firebird Zend_Json [http:// framework.zend.com/manual/en/ zend.json.html] --DOM [http://www.php.net/manual/en/ ref.dom.php] SimpleXML [http://www.php.net/ manual/en/ref.simplexml.php]
1358
Extensin
Tipo de Dependencia
mbstring [http://www.php.net/ Hard manual/en/ref.mbstring.php] mcrypt [http://www.php.net/ --manual/en/ref.mcrypt.php] memcache [http://www.php.net/ Hard manual/en/ref.memcache.php] mhash [http://www.php.net/ --manual/en/ref.mhash.php] mime_magic [http://www.php.net/ Hard manual/en/ref.mime-magic.php] ming [http://www.php.net/manual/ --en/ref.ming.php] msql [http://www.php.net/manual/ --en/ref.msql.php] mssql [http://www.php.net/ --manual/en/ref.mssql.php] mysql [http://www.php.net/ --manual/en/ref.mysql.php] mysqli [http://www.php.net/ Hard manual/en/ref.mysqli.php] ncurses [http://www.php.net/ --manual/en/ref.ncurses.php] oci8 [http://www.php.net/manual/ Hard en/ref.oci8.php] odbc [http://www.php.net/manual/ --en/ref.uodbc.php] openssl [http://www.php.net/ --manual/en/ref.openssl.php] pcntl [http://www.php.net/ --manual/en/ref.pcntl.php] pcre [http://www.php.net/manual/ Hard en/ref.pcre.php] pdo [http://www.php.net/manual/ Hard en/ref.pdo.php] pdo_dblib [http://www.php.net/ --manual/en/ref.pdo-dblib.php]
Zend_Feed [http:// framework.zend.com/manual/en/ zend.feed.html] --Zend_Cache_Backend_Memcached [http://framework.zend.com/manual/ en/zend.cache.backends.html] --Zend_Http_Client [http:// framework.zend.com/manual/en/ zend.http.html] --------Zend_Db_Adapter_Mysqli [http://framework.zend.com/manual/ en/zend.db.html] --Zend_Db_Adapter_Oracle [http://framework.zend.com/manual/ en/zend.db.html] ------Virtually all components All PDO database adapters ---
1359
Extensin
Tipo de Dependencia
Zend_Db_Adapter_Pdo_Mssql [http://framework.zend.com/manual/ en/zend.db.html] Zend_Db_Adapter_Pdo_Mysql [http://framework.zend.com/manual/ en/zend.db.html] Zend_Db_Adapter_Pdo_Oci [http://framework.zend.com/manual/ en/zend.db.html] Zend_Db_Adapter_Pdo_Pgsql [http://framework.zend.com/manual/ en/zend.db.html] Zend_Db_Adapter_Pdo_Sqlite [http://framework.zend.com/manual/ en/zend.db.html] --Zend_Mail [http:// framework.zend.com/manual/en/ zend.mail.html] ------Zend_Controller [http:// framework.zend.com/manual/en/ zend.controller.html] Zend_Filter [http:// framework.zend.com/manual/en/ zend.filter.html]
pdo_mysql [http://www.php.net/ Hard manual/en/ref.pdo-mysql.php] pdo_oci [http://www.php.net/ Hard manual/en/ref.pdo-oci.php] pdo_pgsql [http://www.php.net/ Hard manual/en/ref.pdo-pgsql.php] pdo_sqlite [http://www.php.net/ Hard manual/en/ref.pdo-sqlite.php] pgsql [http://www.php.net/ --manual/en/ref.pgsql.php] posix [http://www.php.net/ Soft manual/en/ref.posix.php] pspell [http://www.php.net/ --manual/en/ref.pspell.php] readline [http://www.php.net/ --manual/en/ref.readline.php] recode [http://www.php.net/ --manual/en/ref.recode.php]
Zend_Filter_Input [http:// framework.zend.com/manual/en/ zend.filter.input.html] Zend_Json [http:// framework.zend.com/manual/en/ zend.json.html] Zend_Log [http:// framework.zend.com/manual/en/ zend.log.html]
1360
Extensin
Tipo de Dependencia
Useda por Componentes de Zend Framework Zend_Rest_Server [http:// framework.zend.com/manual/en/ zend.rest.server.html] Zend_Server_Reflection [http://framework.zend.com/manual/ en/zend.server.reflection.html] Zend_Validate [http:// framework.zend.com/manual/en/ zend.validate.html] Zend_View [http:// framework.zend.com/manual/en/ zend.view.html] Zend_XmlRpc_Server [http:// framework.zend.com/manual/en/ zend.xmlrpc.server.html]
shmop [http://www.php.net/ --manual/en/ref.shmop.php] Zend_Config_Xml [http:// framework.zend.com/manual/en/ zend.config.adapters.xml.html] Zend_Feed [http:// framework.zend.com/manual/en/ zend.feed.html] SimpleXML [http://www.php.net/ Hard manual/en/ref.simplexml.php] Zend_Rest_Client [http:// framework.zend.com/manual/en/ zend.rest.client.html] Zend_Service_Audioscrobbler [http://framework.zend.com/manual/ en/zend.service.audioscrobbler.html] Zend_XmlRpc [http:// framework.zend.com/manual/en/ zend.xmlrpc.html] soap [http://www.php.net/manual/ Hard en/ref.soap.php] sockets [http://www.php.net/ --manual/en/ref.sockets.php] Zend_Service_StrikeIron [http://framework.zend.com/manual/ en/zend.service.strikeiron.html] ---
1361
Extensin
Tipo de Dependencia
Useda por Componentes de Zend Framework Virtually all components Zend_Cache_Backend_Sqlite [http:// framework.zend.com/manual/en/ zend.cache.backends.html] Virtually all components -------------Zend_Translate_Adapter_Qt [http://framework.zend.com/manual/ en/zend.translate.adapter.html]
SPL [http://www.php.net/manual/ Hard en/ref.spl.php] SQLite [http://www.php.net/ Hard manual/en/ref.sqlite.php] standard Hard
XMLReader [http://www.php.net/ --manual/en/ref.xmlreader.php] xmlrpc [http://www.php.net/ --manual/en/ref.xmlrpc.php] XMLWriter [http://www.php.net/ --manual/en/ref.xmlwriter.php] xsl [http://www.php.net/manual/ --en/ref.xsl.php] zip [http://www.php.net/manual/ --en/ref.zip.php]
1362
Tabla A.2. Componentes de Zend Framework y las extensiones que usan de PHP
Componentes Framework de Zend Tipo de Dependencia Subclase Extensin PHP pcre [http://www.php.net/ manual/en/ref.pcre.php] All Components Hard --SPL [http://www.php.net/ manual/en/ref.spl.php] standard Zend_Acl [http:// --framework.zend.com/ manual/en/zend.acl.html] Zend_Auth [http:// framework.zend.com/ Hard manual/en/ zend.auth.html] -----
ctype [http:// Zend_Auth_Adapter_Http www.php.net/manual/en/ [http:// ref.ctype.php] framework.zend.com/ manual/en/ hash [http://www.php.net/ zend.auth.adapter.http.html] manual/en/ref.hash.php] Zend_Cache_Backend_Apc apc [http://www.php.net/ [http:// manual/en/ref.apc.php] framework.zend.com/ manual/en/ zend.cache.backends.html] Zend_Cache_Backend_Memcached memcache [http:// [http:// www.php.net/manual/en/ framework.zend.com/ ref.memcache.php] manual/en/ zend.cache.backends.html] Zend_Cache_Backend_Sqlite sqlite [http:// [http:// www.php.net/manual/en/ framework.zend.com/ ref.sqlite.php] manual/en/ zend.cache.backends.html] Zend_Cache_Backend_Zlib zlib [http://www.php.net/ [http:// manual/en/ref.zlib.php] framework.zend.com/ manual/en/ zend.cache.backends.html]
1363
Componentes Framework
de
Subclase
Extensin PHP
Zend_Config [http:// framework.zend.com/ Hard manual/en/ zend.config.html] Zend_Console_Getopt --[http:// framework.zend.com/ manual/en/ zend.console.getopt.html]
libxml [http:// Zend_Config_Xml www.php.net/manual/en/ [http:// ref.libxml.php] framework.zend.com/ SimpleXML [http:// manual/en/ www.php.net/manual/en/ zend.config.adapters.xml.html] ref.simplexml.php] -----
Hard
Zend_Controller_Action_Helper_Redirector session [http:// [http:// www.php.net/manual/en/ framework.zend.com/ ref.session.php] manual/en/ zend.controller.actionhelpers.html] --iconv [http:// www.php.net/manual/en/ ref.iconv.php] ---
Zend_Currency [http:// Hard framework.zend.com/ manual/en/ zend.currency.html] Zend_Date [http:// --framework.zend.com/ manual/en/ zend.date.html]
---
Zend_Db_Adapter_Db2 ibm_db2 [http:// [http:// www.php.net/manual/en/ framework.zend.com/ ref.ibm-db2.php] manual/en/zend.db.html] Zend_Db_Adapter_Mysqli mysqli [http:// [http:// www.php.net/manual/en/ framework.zend.com/ ref.mysqli.php] manual/en/zend.db.html] Zend_Db_Adapter_Oracle oci8 [http://www.php.net/ [http:// manual/en/ref.oci8.php] framework.zend.com/ manual/en/zend.db.html] Zend_Db_Adapter_Pdo_Mssql pdo_mssql [http:// framework.zend.com/ manual/en/zend.db.html]
1364
Componentes Framework
de
Subclase
Extensin PHP
Zend_Db_Adapter_Pdo_Mysql pdo_mysql [http:// [http:// www.php.net/manual/en/ framework.zend.com/ ref.pdo-mysql.php] manual/en/zend.db.html] Zend_Db_Adapter_Pdo_Oci pdo_oci [http:// [http:// www.php.net/manual/en/ framework.zend.com/ ref.pdo-oci.php] manual/en/zend.db.html] Zend_Db_Adapter_Pdo_Pgsql pdo_pgsql [http:// [http:// www.php.net/manual/en/ framework.zend.com/ ref.pdo-pgsql.php] manual/en/zend.db.html] Zend_Db_Adapter_Pdo_Sqlite pdo_sqlite [http:// [http:// www.php.net/manual/en/ framework.zend.com/ ref.pdo-sqlite.php] manual/en/zend.db.html] Zend_Debug [http:// --framework.zend.com/ manual/en/ zend.debug.html] Zend_Exception [http:// framework.zend.com/ manual/en/ zend.exception.html] -------
---
---
dom [http://www.php.net/ manual/en/ref.dom.php] libxml [http:// www.php.net/manual/en/ ref.libxml.php] --mbstring [http:// www.php.net/manual/en/ ref.mbstring.php] SimpleXML [http:// www.php.net/manual/en/ ref.simplexml.php] Zend_Filter [http:// Hard framework.zend.com/ manual/en/ zend.filter.html] Zend_Form [http:// --framework.zend.com/ manual/en/ zend.form.html] --Reflection [http:// www.php.net/manual/en/ language.oop5.reflection.php] ---
---
1365
Componentes Framework
de
Subclase
Extensin PHP
Zend_Gdata_App ctype [http:// [http:// www.php.net/manual/en/ framework.zend.com/ ref.ctype.php] manual/en/zend.gdata.html] dom [http://www.php.net/ manual/en/ref.dom.php] --libxml [http:// www.php.net/manual/en/ ref.libxml.php]
Zend_Http_Client_Adapter_Curl curl [http://www.php.net/ [http:// manual/en/ref.curl.php] framework.zend.com/ manual/en/ zend.http.client.adapters.html] Zend_Http_Client [http:// framework.zend.com/ manual/en/zend.http.html] --ctype [http:// www.php.net/manual/en/ ref.ctype.php] mime_magic [http:// www.php.net/manual/en/ ref.mime-magic.php] ---
Zend_InfoCard [http:// --framework.zend.com/ manual/en/ zend.infocard.html] Soft Zend_Json [http:// framework.zend.com/ Hard manual/en/ zend.json.html] Zend_Layout [http:// --framework.zend.com/ manual/en/ zend.layout.html] Zend_Ldap [http:// --framework.zend.com/ manual/en/ zend.ldap.html] Zend_Loader [http:// --framework.zend.com/ manual/en/ zend.loader.html] Zend_Locale [http:// framework.zend.com/ manual/en/ zend.locale.html] Soft
-----
---
---
---
---
---
1366
Componentes Framework
de
Subclase
Extensin PHP
Zend_Locale_Format iconv [http:// [http:// www.php.net/manual/en/ framework.zend.com/ ref.iconv.php] manual/en/ zend.locale.parsing.html] dom [http://www.php.net/ Zend_Log_Formatter_Xml manual/en/ref.dom.php] [http:// framework.zend.com/ libxml [http:// manual/en/ www.php.net/manual/en/ zend.log.formatters.html] ref.libxml.php] --Reflection [http:// www.php.net/manual/en/ language.oop5.reflection.php] posix [http:// www.php.net/manual/en/ ref.posix.php] ---
Zend_Mail [http:// Soft framework.zend.com/ manual/en/ zend.mail.html] Zend_Measure [http:// --framework.zend.com/ manual/en/ zend.measure.html] Zend_Memory [http:// --framework.zend.com/ manual/en/ zend.memory.html] Zend_Mime [http:// Hard framework.zend.com/ manual/en/ zend.mime.html] Zend_OpenId [http:// --framework.zend.com/ manual/en/ zend.openid.html]
---
---
---
---
---
ctype [http:// www.php.net/manual/en/ ref.ctype.php] Zend_Pdf [http:// framework.zend.com/ Hard manual/en/zend.pdf.html] gd [http://www.php.net/ manual/en/ref.image.php] iconv [http:// www.php.net/manual/en/ ref.iconv.php] zlib [http://www.php.net/ manual/en/ref.zlib.php] Zend_Registry [http:// --framework.zend.com/ -----
---
1367
Componentes de Zend Tipo de Dependencia Framework manual/en/ zend.registry.html] Zend_Request [http:// --framework.zend.com/ manual/en/ zend.request.html]
Subclase
Extensin PHP
---
---
ctype [http:// www.php.net/manual/en/ ref.ctype.php] libxml [http:// www.php.net/manual/en/ ref.libxml.php] SimpleXML [http:// www.php.net/manual/en/ ref.simplexml.php] ctype [http:// www.php.net/manual/en/ ref.ctype.php]
Zend_Rest [http:// framework.zend.com/ Hard manual/en/zend.rest.html] Zend_Rest_Server [http:// framework.zend.com/ manual/en/ zend.rest.server.html]
dom [http://www.php.net/ manual/en/ref.dom.php] libxml [http:// www.php.net/manual/en/ ref.libxml.php] Reflection [http:// www.php.net/manual/en/ language.oop5.reflection.php]
Soft
bitset [http:// pecl.php.net/package/ Bitset] ctype [http:// www.php.net/manual/en/ ref.ctype.php] --dom [http://www.php.net/ manual/en/ref.dom.php] iconv [http:// www.php.net/manual/en/ ref.iconv.php] libxml [http:// www.php.net/manual/en/ ref.libxml.php]
---
1368
Componentes Framework
de
Subclase ---
Zend_Service_Akismet --[http:// framework.zend.com/ manual/en/ zend.service.akismet.html] Zend_Service_Amazon [http:// framework.zend.com/ Hard manual/en/ zend.service.amazon.html]
dom [http://www.php.net/ manual/en/ref.dom.php] --libxml [http:// www.php.net/manual/en/ ref.libxml.php] iconv [http:// www.php.net/manual/en/ ref.iconv.php] --libxml [http:// www.php.net/manual/en/ ref.libxml.php] SimpleXML [http:// www.php.net/manual/en/ ref.simplexml.php] dom [http://www.php.net/ manual/en/ref.dom.php] --libxml [http:// www.php.net/manual/en/ ref.libxml.php] dom [http://www.php.net/ manual/en/ref.dom.php]
---
Zend_Service_Nirvanix --[http:// framework.zend.com/ manual/en/ zend.service.nirvanix.html] Zend_Service_Simpy [http:// framework.zend.com/ Hard manual/en/ zend.service.simpy.html] Zend_Service_SlideShare --[http:// framework.zend.com/
---
---
---
1369
Componentes de Zend Tipo de Dependencia Framework manual/en/ zend.service.slideshare.html] Zend_Service_StrikeIron Hard [http:// framework.zend.com/ manual/en/ zend.service.strikeiron.html] Zend_Service_Technorati --[http:// framework.zend.com/ manual/en/ zend.service.technorati.html] Zend_Service_Yahoo [http:// framework.zend.com/ Hard manual/en/ zend.service.yahoo.html] Zend_Session [http:// Hard framework.zend.com/ manual/en/ zend.session.html] Zend_TimeSync [http:// --framework.zend.com/ manual/en/ zend.timesync.html]
Subclase
Extensin PHP
---
---
---
dom [http://www.php.net/ manual/en/ref.dom.php] --libxml [http:// www.php.net/manual/en/ ref.libxml.php] session [http:// www.php.net/manual/en/ ref.session.php] ---
---
---
Zend_Translate_Adapter_Qt xml [http://www.php.net/ [http:// manual/en/ref.xml.php] framework.zend.com/ manual/en/ zend.translate.adapter.html] Zend_Translate [http:// framework.zend.com/ manual/en/ zend.translate.html] Zend_Translate_Adapter_Tmx xml [http://www.php.net/ [http:// manual/en/ref.xml.php] framework.zend.com/ manual/en/ zend.translate.adapter.html] Zend_Translate_Adapter_Xliff xml [http://www.php.net/ [http:// manual/en/ref.xml.php] framework.zend.com/ manual/en/ zend.translate.adapter.html] Zend_Uri [http:// Hard framework.zend.com/ manual/en/zend.uri.html] Zend_Validate [http:// framework.zend.com/ Hard manual/en/ zend.validate.html] --ctype [http:// www.php.net/manual/en/ ref.ctype.php] ctype [http:// www.php.net/manual/en/ ref.ctype.php]
Hard
---
1370
Componentes Framework
de
Subclase
Zend_Version [http:// --framework.zend.com/ manual/en/ zend.version.html] Zend_Validate [http:// Hard framework.zend.com/ manual/en/ zend.validate.html]
---
---
---
Reflection [http:// www.php.net/manual/en/ language.oop5.reflection.php] dom [http://www.php.net/ manual/en/ref.dom.php] libxml [http:// www.php.net/manual/en/ ref.libxml.php] SimpleXML [http:// www.php.net/manual/en/ ref.simplexml.php]
---
Zend_XmlRpc_Client iconv [http:// [http:// www.php.net/manual/en/ framework.zend.com/ ref.iconv.php] manual/en/ zend.xmlrpc.client.html] Zend_XmlRpc_Server Reflection [http:// [http:// www.php.net/manual/en/ framework.zend.com/ language.oop5.reflection.php] manual/en/ zend.xmlrpc.server.html]
Nota
Incluso si es posible separar componentes indiduales para usarlo desde Zend Framework completo, usted debe tener en cuenta que esto puede conducir a problemas cuando se perdieron los ficheros o los componentes se utilizan dinmicamente.
1371
Tabla A.3. Componenetes de Zend Framework y sus dependencias a otros Componenetes de Zend Framework
Componente Framework de Zend Tipo de Componente Dependiente de Zend Framework Dependencia Zend_Exception zend.exception.html] Zend_Exception zend.exception.html] Zend_InfoCard zend.infocard.html] Zend_OpenId zend.openid.html] Zend_Session zend.session.html] Zend_Cache [http:// framework.zend.com/manual/ Hard en/zend.cache.html] Zend_Config [http:// Hard framework.zend.com/manual/ en/zend.config.html] Zend_Console_Getopt [http://framework.zend.com/ manual/en/ zend.console.getopt.html] Zend_Exception zend.exception.html] Zend_Loader zend.loader.html] Zend_Exception zend.exception.html] Zend_Exception zend.exception.html] [http://framework.zend.com/manual/en/
[http://framework.zend.com/manual/en/
[http://framework.zend.com/manual/en/
Hard
Zend_Json [http://framework.zend.com/manual/en/zend.json.html] Zend_Config zend.config.html] Zend_Exception zend.exception.html] Zend_Filter zend.filter.html] [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
Zend_Json [http://framework.zend.com/manual/en/zend.json.html] Zend_Controller [http:// framework.zend.com/manual/ Hard en/zend.controller.html] Zend_Layout zend.layout.html] Zend_Loader zend.loader.html] Zend_Registry zend.registry.html] Zend_Session zend.session.html] [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
Zend_Uri [http://framework.zend.com/manual/en/zend.uri.html]
1372
Componente Framework
de
Zend Tipo de Componente Dependiente de Zend Framework Dependencia Zend_View [http://framework.zend.com/manual/en/zend.view.html] Zend_Exception zend.exception.html] Zend_Locale zend.locale.html] Zend_Exception zend.exception.html] Zend_Locale zend.locale.html] Zend_Config zend.config.html] [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
Zend_Currency [http:// framework.zend.com/manual/ Hard en/zend.currency.html] Zend_Date [http:// framework.zend.com/manual/ Hard en/zend.date.html]
---
---
Zend_Exception zend.exception.html] Zend_Feed [http:// framework.zend.com/manual/ Hard en/zend.feed.html] Zend_Loader zend.loader.html] Zend_Exception zend.exception.html] Zend_Filter [http:// framework.zend.com/manual/ Hard en/zend.filter.html] Zend_Loader zend.loader.html] Zend_Locale zend.locale.html] Zend_Validate zend.validate.html] Zend_Controller zend.controller.html] Zend_Form [http:// framework.zend.com/manual/ Hard en/zend.form.html] Zend_Exception zend.exception.html] Zend_Filter zend.filter.html]
[http://framework.zend.com/manual/en/
1373
Componente Framework
de
Zend Tipo de Componente Dependiente de Zend Framework Dependencia Zend_Json [http://framework.zend.com/manual/en/zend.json.html] Zend_Loader zend.loader.html] Zend_Registry zend.registry.html] Zend_Session zend.session.html] Zend_Validate zend.validate.html] Zend_Exception zend.exception.html] [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
Zend_Http [http://framework.zend.com/manual/en/zend.http.html] Zend_Gdata [http:// framework.zend.com/manual/ Hard en/zend.gdata.html] Zend_Loader zend.loader.html] Zend_Version zend.version.html] Zend_Http [http:// framework.zend.com/manual/ Hard en/zend.http.html] Zend_InfoCard [http:// Hard framework.zend.com/manual/ en/zend.infocard.html] Zend_Json [http:// Hard framework.zend.com/manual/ en/zend.json.html] Zend_Exception zend.exception.html] Zend_Loader zend.loader.html] Zend_Loader zend.loader.html] Zend_Exception zend.exception.html] Zend_Controller zend.controller.html] Zend_Layout [http:// framework.zend.com/manual/ Hard en/zend.layout.html] Zend_Exception zend.exception.html] Zend_Filter zend.filter.html] Zend_Loader zend.loader.html] Zend_Ldap [http:// Hard framework.zend.com/manual/ en/zend.ldap.html] Zend_Loader [http:// Hard framework.zend.com/manual/ en/zend.loader.html] Zend_Exception zend.exception.html] Zend_Exception zend.exception.html] [http://framework.zend.com/manual/en/
[http://framework.zend.com/manual/en/
[http://framework.zend.com/manual/en/
1374
Componente Framework
de
Zend Tipo de Componente Dependiente de Zend Framework Dependencia Zend_Exception zend.exception.html] Zend_Exception zend.exception.html] Zend_Exception zend.exception.html] [http://framework.zend.com/manual/en/
Zend_Locale [http:// Hard framework.zend.com/manual/ en/zend.locale.html] Zend_Log [http:// Hard framework.zend.com/manual/ en/zend.log.html]
[http://framework.zend.com/manual/en/
[http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
Zend_Measure [http:// framework.zend.com/manual/ Hard en/zend.measure.html] Zend_Memory [http:// framework.zend.com/manual/ Hard en/zend.memory.html] Zend_Mime [http:// Hard framework.zend.com/manual/ en/zend.mime.html]
Zend_Exception zend.exception.html] Zend_Locale zend.locale.html] Zend_Cache zend.cache.html] Zend_Exception zend.exception.html] Zend_Exception zend.exception.html] Zend_Controller zend.controller.html]
[http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
1375
Componente Framework
de
Zend Tipo de Componente Dependiente de Zend Framework Dependencia Zend_Exception zend.exception.html] [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
Zend_Uri [http://framework.zend.com/manual/en/zend.uri.html] Zend_Search_Lucene [http://framework.zend.com/ manual/en/ zend.search.lucene.html] Zend_Server_Reflection [http://framework.zend.com/ manual/en/ zend.server.reflection.html] Hard [http://framework.zend.com/manual/en/
Hard
Zend_Exception zend.exception.html]
[http://framework.zend.com/manual/en/
[http://framework.zend.com/manual/en/
Zend_Http [http://framework.zend.com/manual/en/zend.http.html] Zend_Uri [http://framework.zend.com/manual/en/zend.uri.html] Zend_Version zend.version.html] Zend_Exception zend.exception.html] [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
Hard
[http://framework.zend.com/manual/en/
Hard
1376
Componente Framework
de
Zend Tipo de Componente Dependiente de Zend Framework Dependencia Zend_Exception zend.exception.html] Hard Zend_Loader zend.loader.html] Zend_Exception zend.exception.html] Hard [http://framework.zend.com/manual/en/
Zend_Http [http://framework.zend.com/manual/en/zend.http.html] Zend_Rest [http://framework.zend.com/manual/en/zend.rest.html] Zend_Cache zend.cache.html] Zend_Exception zend.exception.html] Zend_Exception zend.exception.html] Zend_Loader zend.loader.html] Zend_Exception zend.exception.html] Zend_Locale zend.locale.html] [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
Zend_Http [http://framework.zend.com/manual/en/zend.http.html] Zend_Rest [http://framework.zend.com/manual/en/zend.rest.html] Zend_Validate zend.validate.html] Zend_Exception zend.exception.html] Zend_Loader zend.loader.html] Zend_Exception zend.exception.html] [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
Zend_Session [http:// framework.zend.com/manual/ Hard en/zend.session.html] Zend_TimeSync [http:// framework.zend.com/manual/ Hard en/zend.timesync.html]
1377
Componente Framework
de
Zend Tipo de Componente Dependiente de Zend Framework Dependencia Zend_Loader zend.loader.html] Zend_Exception zend.exception.html] [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
Hard
Zend_Controller zend.controller.html] Zend_Exception zend.exception.html] Zend_View [http:// framework.zend.com/manual/ Hard en/zend.view.html] Zend_Layout zend.layout.html] Zend_Loader zend.loader.html] Zend_Locale zend.locale.html] Zend_Registry zend.registry.html]
[http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
1378
Componente Framework
de
Zend Tipo de Componente Dependiente de Zend Framework Dependencia Zend_Exception zend.exception.html] [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/ [http://framework.zend.com/manual/en/
1379
Zend_File_Transfer
Count validation
Before release 1.10 the MimeType validator used a wrong naming. For consistency the following constants have been changed:
TOO_LESS
TOO_FEW
When you are translating these messages within your code then use the new constants. As benefit you don't need to translate the original string anymore to get a correct spelling.
Zend_Validate
Self written validators
When setting returning a error from within a self written validator you have to call the _error() method. Before Zend Framework 1.10 you were able to call this method without giving a parameter. It used then the first found message template. This behaviour is problematic when you have validators with more than one different message to be returned. Also when you extend an existing validator you can get unexpected results. This could lead to the problem that your user get not the message you expected. My_Validator extends Zend_Validate_Abstract { public isValid($value) { ... $this->_error(); // unexpected results between different OS ... } }
1380
Notas de Migracin de Zend Framework To prevent this problem the _error() method is no longer allowed to be called without giving a parameter. My_Validator extends Zend_Validate_Abstract { public isValid($value) { ... $this->_error(self::MY_ERROR); // defined error, no unexpected results ... } }
Zend_File_Transfer
MimeType validation
For security reasons we had to turn off the default fallback mechanism of the MimeType, ExcludeMimeType, IsCompressed and IsImage validators. This means, that if the fileInfo or magicMime extensions can not be found, the validation will always fail.
1381
Notas de Migracin de Zend Framework If you are in need of validation by using the HTTP fields which are provided by the user then you can turn on this feature by using the enableHeaderCheck() method.
Security hint
You should note that relying on the HTTP fields, which are provided by your user, is a security risk. They can easily be changed and could allow your user to provide a malcious file.
Zend_Filter
Prior to the 1.9 release, Zend_Filter allowed the usage of the static get() method. As with release 1.9 this method has been renamed to filterStatic() to be more descriptive. The old get() method is marked as deprecated.
Zend_Http_Client
Changes to internal uploaded file information storage
In version 1.9 of Zend Framework, there has been a change in the way Zend_Http_Client internally stores information about files to be uploaded, set using the Zend_Http_Client::setFileUpload() method. This change was introduced in order to allow multiple files to be uploaded with the same form name, as an array of files. More information about this issue can be found in this bug report [http://framework.zend.com/issues/browse/ ZF-5744].
1382
Notas de Migracin de Zend Framework // ); // In Zend Framework 1.9 or newer, the value of $client->files is: // $client->files = array( // array( // 'formname' => 'userfile[]', // 'filename' => 'file1.txt, // 'ctype' => 'text/plain', // 'data' => 'some raw data' // ), // array( // 'formname' => 'userfile[]', // 'filename' => 'file2.txt', // 'formname' => 'application/octet-stream', // 'formname' => 'some other data' // ) // ); As you can see, this change permits the usage of the same form element name with more than one file - however, it introduces a subtle backwards-compatibility change and as such should be noted.
Deprecation of Zend_Http_Client::_getParametersRecursive()
Starting from version 1.9, the protected method _getParametersRecursive() is no longer used by Zend_Http_Client and is deprecated. Using it will cause an E_NOTICE message to be emitted by PHP. If you subclass Zend_Http_Client and call this method, you should Zend_Http_Client::_flattenParametersArray() static method instead. look into using the
Again, since this _getParametersRecursive is a protected method, this change will only affect users who subclass Zend_Http_Client.
Zend_Locale
Depreciated methods
Some specialized translation methods have been depreciated because they duplicate existing behaviour. Note that the old methods will still work, but a user notice is triggered which describes the new call. The methods will be erased with 2.0. See the following list for old and new method call.
1383
Zend_View_Helper_Navigation
Prior to the 1.9 release, the menu helper (Zend_View_Helper_Navigation_Menu) did not render sub menus correctly. When the onlyActiveBranch was TRUE and the option renderParents FALSE, nothing would be rendered if the deepest active page was at a depth lower than the minDepth option. In simpler words; if minDepth was set to 1 and the active page was at one of the first level pages, nothing would be rendered, as the following example shows. Consider the following container setup:
<?php $container = new Zend_Navigation(array( array( 'label' => 'Home', 'uri' => '#' ), array( 'label' => 'Products', 'uri' => '#', 'active' => true, 'pages' => array( array( 'label' => 'Server', 'uri' => '#' ), array( 'label' => 'Studio', 'uri' => '#' ) ) ), array( 'label' => 'Solutions', 'uri' => '#' ) )); The following code is used in a view script:
<?php echo $this->navigation()->menu()->renderMenu($container, array( 'minDepth' => 1, 'onlyActiveBranch' => true, 'renderParents' => false )); ?> Before release 1.9, the code snippet above would output nothing. Since release 1.9, the _renderDeepestMenu() method in Zend_View_Helper_Navigation_Menu will accept active pages at one level below minDepth, as long as the page has children. The same code snippet will now output the following:
1384
<ul class="navigation"> <li> <a href="#">Server</a> </li> <li> <a href="#">Studio</a> </li> </ul>
Zend_Controller
Standard Route Changes
As translated segments were introduced into the new standard route, the '@' character is now a special character in the beginning of a route segment. To be able to use it in a static segment, you must escape it by prefixing it with second '@' character. The same rule now applies for the ':' character.
Zend_Locale
Default caching
As with Zend Framework 1.8 a default caching was added. The reason behind this change was, that most users had performance problems but did not add caching at all. As the I18n core is a bottleneck when no caching is used we decided to add a default caching when no cache has been set to Zend_Locale. Sometimes it is still wanted to prevent caching at all even if this decreases performance. To do so you can simply disable caching by using the disableCache() method.
Zend_Controller
Dispatcher Interface Changes
Users brought to our attention the fact that Zend_Controller_Action_Helper_ViewRenderer were using a method of the dispatcher abstract class that was not in the dispatcher interface. We have now added the following method to ensure that custom dispatchers will continue to work with the shipped implementations:
1385
Notas de Migracin de Zend Framework formatModuleName(): should be used to take a raw controller name, such as one that would be packaged inside a request object, and reformat it to a proper class name that a class extending Zend_Controller_Action would use
Zend_File_Transfer
Changes when using filters and validators
As noted by users, the validators from Zend_File_Transfer do not work in conjunction with Zend_Config due to the fact that they have not used named arrays. Therefor, all filters and validators for Zend_File_Transfer have been reworked. While the old signatures continue to work, they have been marked as deprecated, and will emit a PHP notice asking you to fix them. The following list shows you the changes you will have to do for proper usage of the parameters.
Filter: Rename
Old method API: Zend_Filter_File_Rename($oldfile, $newfile, $overwrite) New method API: Zend_Filter_File_Rename($options) where $options accepts the following array keys: source equals to $oldfile, target equals to $newfile, overwrite equals to $overwrite.
Ejemplo B.4. Changes for the rename filter from 1.6 to 1.7
// Ejemplo for 1.6 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addFilter('Rename', array('/path/to/oldfile', '/path/to/newfile', true)); // Same example for 1.7 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addFilter('Rename', array('source' => '/path/to/oldfile', 'target' => '/path/to/newfile', 'overwrite' => true));
Validator: Count
Old method API: Zend_Validate_File_Count($min, $max) New method API: Zend_Validate_File_Count($options) where $options accepts the following array keys: min equals to $min, max equals to $max.
Ejemplo B.5. Changes for the count validator from 1.6 to 1.7
// Ejemplo for 1.6 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('Count', array(2, 3)); // Same example for 1.7 $upload = new Zend_File_Transfer_Adapter_Http();
1386
Notas de Migracin de Zend Framework $upload->addValidator('Count', false, array('min' => 2, 'max' => 3));
Validator:Extension
Old method API: Zend_Validate_File_Extension($extension, $case) New method API: Zend_Validate_File_Extension($options) where $options accepts the following array keys: * equals to $extension and can have any other key, case equals to $case.
Ejemplo B.6. Changes for the extension validator from 1.6 to 1.7
// Ejemplo for 1.6 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('Extension', array('jpg,gif,bmp', true)); // Same example for 1.7 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('Extension', false, array('extension1' => 'jpg,gif,bmp', 'case' => true));
Validator: FilesSize
Old method API: Zend_Validate_File_FilesSize($min, $max, $bytestring) New method API: Zend_Validate_File_FilesSize($options) where $options accepts the following array keys: min equals to $min, max equals to $max, bytestring equals to $bytestring. Additionally, the useByteString() method signature has changed. It can only be used to test if the validator is expecting to use byte strings in generated messages. To set the value of the flag, use the setUseByteString() method.
Ejemplo B.7. Changes for the filessize validator from 1.6 to 1.7
// Ejemplo for 1.6 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('FilesSize', array(100, 10000, true)); // Same example for 1.7 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('FilesSize', false, array('min' => 100, 'max' => 10000, 'bytestring' => true)); // Ejemplo for 1.6
1387
Notas de Migracin de Zend Framework $upload->useByteString(true); // set flag // Same example for 1.7 $upload->setUseByteSting(true); // set flag
Validator: Hash
Old method API: Zend_Validate_File_Hash($hash, $algorithm) New method API: Zend_Validate_File_Hash($options) where $options accepts the following array keys: * equals to $hash and can have any other key, algorithm equals to $algorithm.
Ejemplo B.8. Changes for the hash validator from 1.6 to 1.7
// Ejemplo for 1.6 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('Hash', array('12345', 'md5')); // Same example for 1.7 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('Hash', false, array('hash1' => '12345', 'algorithm' => 'md5'));
Validator: ImageSize
Old method API: Zend_Validate_File_ImageSize($minwidth, $minheight, $maxwidth, $maxheight) New method API: Zend_Validate_File_FilesSize($options) where $options accepts the following array keys: minwidth equals to $minwidth, maxwidth equals to $maxwidth, minheight equals to $minheight, maxheight equals to $maxheight.
Ejemplo B.9. Changes for the imagesize validator from 1.6 to 1.7
// Ejemplo for 1.6 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('ImageSize', array(10, 10, 100, 100)); // Same example for 1.7 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('ImageSize', false, array('minwidth' => 10, 'minheight' => 10, 'maxwidth' => 100, 'maxheight' => 100));
Validator: Size
Old method API: Zend_Validate_File_Size($min, $max, $bytestring)
1388
Notas de Migracin de Zend Framework New method API: Zend_Validate_File_Size($options) where $options accepts the following array keys: min equals to $min, max equals to $max, bytestring equals to $bytestring.
Ejemplo B.10. Changes for the size validator from 1.6 to 1.7
// Ejemplo for 1.6 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('Size', array(100, 10000, true)); // Same example for 1.7 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('Size', false, array('min' => 100, 'max' => 10000, 'bytestring' => true));
Zend_Locale
Changes when using isLocale()
According to the coding standards isLocale() had to be changed to return a boolean. In previous releases a string was returned on success. For release 1.7 a compatibility mode has been added which allows to use the old behaviour of a returned string, but it triggers a user warning to mention you to change to the new behaviour. The rerouting which the old behaviour of isLocale() could have done is no longer neccessary as all I18N will now process a rerouting themself. To migrate your scripts to the new API, simply use the method as shown below.
1389
Notas de Migracin de Zend Framework } // Same example for 1.7 // You should change the compatiblity mode to prevent user warnings // But you can do this in your bootstrap Zend_Locale::$compatibilityMode = false; if (Zend_Locale::isLocale($locale, false)) { if (Zend_Locale::isLocale($locale, true)) { // no locale at all } // original string is no locale but can be rerouted }
Nota
Per default the old behaviour is still active, but throws a user warning. When you have changed your code to the new behaviour you should also change the compatibility mode to false so that no warning is thrown anymore.
Zend_Translate
Setting languages
When using automatic detection of languages, or setting languages manually to Zend_Translate you may have mentioned that from time to time a notice is thrown about not added or empty translations. In some previous release also an exception was raised in some cases.
1390
Notas de Migracin de Zend Framework The reason is, that when a user requests a non existing language, you have no simple way to detect what's going wrong. So we added those notices which show up in your log and tell you that the user requested a language which you do not support. Note that the code, even when we trigger such an notice, keeps working without problems. But when you use a own error or exception handler, like xdebug, you will get all notices returned, even if this was not your intention. This is due to the fact that these handlers override all settings from within PHP. To get rid of these notices you can simply set the new option 'disableNotices' to true. It defaults to false.
$language = new Zend_Translate('gettext', '/path/to/translations', 'auto'); In this case we will get an notice about a not available language 'fr'. Simply add the option and the notices will be disabled.
Zend_View
Nota
The API changes within Zend_View are only notable for you when you are upgrading to release 1.7.5 or higher. Prior to the 1.7.5 release, the Zend Framework team was notified of a potential Local File Inclusion (LFI) vulnerability in the Zend_View::render() method. Prior to 1.7.5, the method allowed, by default, the ability to specify view scripts that included parent directory notation (e.g., "../" or "..\"). This opens the possibility for an LFI attack if unfiltered user input is passed to the render() method:
// Where $_GET['foobar'] = '../../../../etc/passwd' echo $view->render($_GET['foobar']); // LFI inclusion Zend_View now by default raises an exception when such a view script is requested.
1391
Notas de Migracin de Zend Framework // Disabling via constructor $view = new Zend_View(array('lfiProtectionOn' => false)); // Disabling via exlicit method call: $view = new Zend_View(); $view->setLfiProtection(false);
Zend_Controller
Dispatcher Interface Changes
Users brought to our attention the fact that Zend_Controller_Front and Zend_Controller_Router_Route_Module were each using methods of the dispatcher that were not in the dispatcher interface. We have now added the following three methods to ensure that custom dispatchers will continue to work with the shipped implementations: getDefaultModule(): should return the name of the default module. getDefaultControllerName(): should return the name of the default controller. getDefaultAction(): should return the name of the default action.
Zend_File_Transfer
Changes when using validators
As noted by users, the validators from Zend_File_Transfer do not work the same way like the default ones from Zend_Form. Zend_Form allows the usage of a $breakChainOnFailure parameter which breaks the validation for all further validators when an validation error has occurred. So we added this parameter also to all existing validators from Zend_File_Transfer. Old method API: addValidator($validator, $options, $files). New method API: addValidator($validator, $breakChainOnFailure, $options, $files). To migrate your scripts to the new API, simply add a FALSE after defining the wished validator.
Ejemplo B.14. How to change your file validators from 1.6.1 to 1.6.2
// Ejemplo for 1.6.1 $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('FilesSize', array('1B', '100kB')); // Same example for 1.6.2 and newer // Note the added boolean false
1392
Notas de Migracin de Zend Framework $upload = new Zend_File_Transfer_Adapter_Http(); $upload->addValidator('FilesSize', false, array('1B', '100kB'));
Zend_Controller
Though most basic functionality remains the same, and all documented functionality remains the same, there is one particular undocumented "feature" that has changed. When writing URLs, the documented way to write camelCased action names is to use a word separator; these are '.' or '-' by default, but may be configured in the dispatcher. The dispatcher internally lowercases the action name, and uses these word separators to re-assemble the action method using camelCasing. However, because PHP functions are not case sensitive, you could still write URLs using camelCasing, and the dispatcher would resolve these to the same location. For example, 'camel-cased' would become 'camelCasedAction' by the dispatcher, whereas 'camelCased' would become 'camelcasedAction'; however, due to the case insensitivity of PHP, both will execute the same method. This causes issues with the ViewRenderer when resolving view scripts. The canonical, documented way is that all word separators are converted to dashes, and the words lowercased. This creates a semantic tie between the actions and view scripts, and the normalization ensures that the scripts can be found. However, if the action 'camelCased' is called and actually resolves, the word separator is no longer present, and the ViewRenderer attempts to resolve to a different location -- camelcased.phtml instead of camel-cased.phtml. Some developers relied on this "feature", which was never intended. Several changes in the 1.5.0 tree, however, made it so that the ViewRenderer no longer resolves these paths; the semantic tie is now enforced. First among these, the dispatcher now enforces case sensitivity in action names. What this means is that referring to your actions on the url using camelCasing will no longer resolve to the same method as using word separators (i.e., 'camel-casing'). This leads to the ViewRenderer now only honoring the word-separated actions when resolving view scripts. If you find that you were relying on this "feature", you have several options: Best option: rename your view scripts. Pros: forward compatibility. Cons: if you have many view scripts that relied on the former, unintended behavior, you will have a lot of renaming to do. Second best option: The ViewRenderer now delegates view script resolution to Zend_Filter_Inflector; you can modify the rules of the inflector to no longer separate the words of an action with a dash:
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); $inflector = $viewRenderer->getInflector(); $inflector->setFilterRule(':action', array( new Zend_Filter_PregReplace( '#[^a-z0-9' . preg_quote(DIRECTORY_SEPARATOR, '#') . ']+#i', '' ), 'StringToLower' )); The above code will modify the inflector to no longer separate the words with dash; you may also want to remove the 'StringToLower' filter if you do want the actual view script names camelCased as well.
1393
Notas de Migracin de Zend Framework If renaming your view scripts would be too tedious or time consuming, this is your best option until you can find the time to do so. Least desirable option: You can force the dispatcher to dispatch camelCased action names with a new front controller flag, useCaseSensitiveActions:
$front->setParam('useCaseSensitiveActions', true); This will allow you to use camelCasing on the url and still have it resolve to the same action as when you use word separators. However, this will mean that the original issues will cascade on through; you will likely need to use the second option above in addition to this for things to work at all reliably. Note, also, that usage of this flag will raise a notice that this usage is deprecated.
Zend_Controller
The principal changes introduced in 1.0.0RC1 are the introduction of and default enabling of the ErrorHandler plugin and the ViewRenderer action helper. Please read the documentation to each thoroughly to see how they work and what effect they may have on your applications. The ErrorHandler plugin runs during postDispatch() checking for exceptions, and forwarding to a specified error handler controller. You should include such a controller in your application. You may disable it by setting the front controller parameter noErrorHandler:
$front->setParam('noErrorHandler', true); The ViewRenderer action helper automates view injection into action controllers as well as autorendering of view scripts based on the current action. The primary issue you may encounter is if you have actions that do not render view scripts and neither forward or redirect, as the ViewRenderer will attempt to render a view script based on the action name. There are several strategies you can take to update your code. In the short term, you can globally disable the ViewRenderer in your front controller bootstrap prior to dispatching:
// Assuming $front is an instance of Zend_Controller_Front $front->setParam('noViewRenderer', true); However, this is not a good long term strategy, as it means most likely you'll be writing more code. When you're ready to start using the ViewRenderer functionality, there are several things to look for in your controller code. First, look at your action methods (the methods ending in 'Action'), and determine what each is doing. If none of the following is happening, you'll need to make changes: Calls to $this->render(); Calls to $this->_forward();
1394
Notas de Migracin de Zend Framework Calls to $this->_redirect(); Calls to the Redirector action helper The easiest change is to disable auto-rendering for that method: $this->_helper->viewRenderer->setNoRender(); If you find that none of your action methods are rendering, forwarding, or redirecting, you will likely want to put the above line in your preDispatch() or init() methods: public function preDispatch() { // disable view script autorendering $this->_helper->viewRenderer->setNoRender() // .. do other things... } If you are calling render(), and you're using the Conventional Modular directory structure, you'll want to change your code to make use of autorendering: If you're rendering multiple view scripts in a single action, you don't need to change a thing. If you're simply calling render() with no arguments, you can remove such lines. If you're calling render() with arguments, and not doing any processing afterwards or rendering multiple view scripts, you can change these calls to read $this->_helper->viewRenderer();. If you're not using the conventional modular directory structure, there are a variety of methods for setting the view base path and script path specifications so that you can make use of the ViewRenderer. Please read the ViewRenderer documentation for information on these methods. If you're using a view object from the registry, or customizing your view object, or using a different view implementation, you'll want to inject the ViewRenderer with this object. This can be done easily at any time. Prior to dispatching a front controller instance: // Assuming $view has already been defined $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view); Zend_Controller_Action_HelperBroker::addHelper($viewRenderer); Any time during the bootstrap process: $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); $viewRenderer->setView($view); There are many ways to modify the ViewRenderer, including setting a different view script to render, specifying replacements for all replaceable elements of a view script path (including the suffix), choosing a response named segment to utilize, and more. If you aren't using the conventional modular directory structure, you can even associate different path specifications with the ViewRenderer. We encourage you to adapt your code to use the ErrorHandler and ViewRenderer as they are now core functionality.
1395
Zend_Currency
Creating an object of Zend_Currency has become simpler. You no longer have to give a script or set it to NULL. The optional script parameter is now an option which can be set through the setFormat() method.
$currency = new Zend_Currency($currency, $locale); The setFormat() method takes now an array of options. These options are set permanently and override all previously set values. Also a new option 'precision' has been added. The following options have been refactored: position: Replacement for the old 'rules' parameter. script: Replacement for the old 'script' parameter. format: Replacement for the old 'locale' parameter which does not set new currencies but only the number format. display: Replacement for the old 'rules' parameter. precision: New parameter. name: Replacement for the ole 'rules' parameter. Sets the full currencies name. currency: New parameter. symbol: New parameter.
$currency->setFormat(array $options); The toCurrency() method no longer supports the optional 'script' and 'locale' parameters. Instead it takes an options array which can contain the same keys as for the setFormat() method.
$currency->toCurrency($value, array $options); The methods getSymbol(), getShortName(), getName(), getRegionList() and getCurrencyList() are no longer static and can be called from within the object. They return the set values of the object if no parameter has been set.
Zend_Controller
0.9.3 introduces action helpers. As part of this change, the following methods have been removed as they are now encapsulated in the redirector action helper: setRedirectCode(); use Zend_Controller_Action_Helper_Redirector::setCode(). setRedirectPrependBase(); Zend_Controller_Action_Helper_Redirector::setPrependBase(). use
1396
Notas de Migracin de Zend Framework setRedirectExit(); use Zend_Controller_Action_Helper_Redirector::setExit(). Read the action helpers documentation for more information on how to retrieve and manipulate helper objects, and the redirector helper documentation for more information on setting redirect options (as well as alternate methods for redirecting).
Zend_Controller
Per previous changes, the most basic usage of the MVC components remains the same:
Zend_Controller_Front::run('/path/to/controllers'); However, the directory structure underwent an overhaul, several components were removed, and several others either renamed or added. Changes include: Zend_Controller_Router was removed in favor of the rewrite router. Zend_Controller_RewriteRouter was renamed to Zend_Controller_Router_Rewrite, and promoted to the standard router shipped with the framework; Zend_Controller_Front will use it by default if no other router is supplied. A new route class for use with the rewrite router was introduced, Zend_Controller_Router_Route_Module; it covers the default route used by the MVC, and has support for controller modules. Zend_Controller_Router_StaticRoute Zend_Controller_Router_Route_Static. was renamed to
Zend_Controller_Dispatcher was renamed Zend_Controller_Dispatcher_Standard. Zend_Controller_Action::_forward()'s arguments have changed. The signature is now:
final protected function _forward($action, $controller = null, $module = null, array $params = null); $action is always required; if no controller is specified, an action in the current controller is assumed. $module is always ignored unless $controller is specified. Finally, any $params provided will be appended to the request object. If you do not require the controller or module, but still need to pass parameters, simply specify NULL for those values.
1397
Zend_Controller
The most basic usage of the MVC components has not changed; you can still do each of the following:
Zend_Controller_Front::run('/path/to/controllers');
/* -- create a router -- */ $router = new Zend_Controller_RewriteRouter(); $router->addRoute('user', 'user/:username', array('controller' => 'user', 'action' => 'info') ); /* -- set it in a controller -- */ $ctrl = Zend_Controller_Front::getInstance(); $ctrl->setRouter($router); /* -- set controller directory and dispatch -- */ $ctrl->setControllerDirectory('/path/to/controllers'); $ctrl->dispatch(); We encourage use of the Response object to aggregate content and headers. This will allow for more flexible output format switching (for instance, JSON or XML instead of XHTML) in your applications. By default, dispatch() will render the response, sending both headers and rendering any content. You may also have the front controller return the response using returnResponse(), and then render the response using your own logic. A future version of the front controller may enforce use of the response object via output buffering. There are many additional features that extend the existing API, and these are noted in the documentation. The main changes you will need to be aware of will be found when subclassing the various components. Key amongst these are: Zend_Controller_Front::dispatch() by default traps exceptions in the response object, and does not render them, in order to prevent sensitive system information from being rendered. You can override this in several ways: Set throwExceptions() in the front controller:
$response->renderExceptions(true); $front->setResponse($response); $front->dispatch(); // or: $front->returnResponse(true); $response = $front->dispatch(); $response->renderExceptions(true); echo $response;
1398
Notas de Migracin de Zend Framework Zend_Controller_Dispatcher_Interface::dispatch() now accepts and returns a The Request Object instead of a dispatcher token. Zend_Controller_Router_Interface::route() now accepts and returns a The Request Object instead of a dispatcher token. Zend_Controller_Action changes include: The constructor now accepts exactly three arguments, Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, and Array $params (optional). Zend_Controller_Action::__construct() uses these to set the request, response, and invokeArgs properties of the object, and if overriding the constructor, you should do so as well. Better yet, use the init() method to do any instance configuration, as this method is called as the final action of the constructor. run() is no longer defined as final, but is also no longer used by the front controller; its sole purpose is for using the class as a page controller. It now takes two optional arguments, a Zend_Controller_Request_Abstract $request and a Zend_Controller_Response_Abstract $response. indexAction() no longer needs to be defined, but is encouraged as the default action. This allows using the RewriteRouter and action controllers to specify different default action methods. __call() should be overridden to handle any undefined actions automatically. _redirect() now takes an optional second argument, the HTTP code to return with the redirect, and an optional third argument, $prependBase, that can indicate that the base URL registered with the request object should be prepended to the url specified. The $_action property is no longer set. This property was a Zend_Controller_Dispatcher_Token, which no longer exists in the current incarnation. The sole purpose of the token was to provide information about the requested controller, action, and URL parameters. This information is now available in the request object, and can be accessed as follows: // Retrieve the requested controller name // Access used to be via: $this->_action->getControllerName(). // The example below uses getRequest(), though you may also directly // access the $_request property; using getRequest() is recommended as // a parent class may override access to the request object. $controller = $this->getRequest()->getControllerName(); // Retrieve the requested action name // Access used to be via: $this->_action->getActionName(). $action = $this->getRequest()->getActionName(); // Retrieve the request parameters // This hasn't changed; the _getParams() and _getParam() methods simply // proxy to the request object now. $params = $this->_getParams(); // request 'foo' parameter, using 'default' as default value if not found $foo = $this->_getParam('foo', 'default'); noRouteAction() has been removed. The appropriate way to handle non-existent action methods should you wish to route them to a default action is using __call():
1399
Notas de Migracin de Zend Framework public { // // if } throw new Zend_Controller_Exception('Invalid method called'); } Zend_Controller_RewriteRouter::setRewriteBase() has been Zend_Controller_Front::setBaseUrl() instead Zend_Controller_Request_Http::setBaseUrl(), if using that request class). removed. Use (or function __call($method, $args) If an unmatched 'Action' method was requested, pass on to the default action method: ('Action' == substr($method, -6)) { return $this->defaultAction();
Zend_Controller_Plugin_Interface was replaced by Zend_Controller_Plugin_Abstract. All methods now accept and return a The Request Object instead of a dispatcher token.
1400
Nota
Nota: A veces, los desarrolladores consideran el establecimiento de estndares ms importante que lo que el estndar sugiere realmente al nivel ms detallado de diseo. Estas pautas en los estndares de cdigo de Zend Framework han demostrado funcionar bien en otros projectos ZF. Puede modificar estos estndares o usarlos en conformidad con los trminos de nuestra licencia [http://framework.zend.com/license] Temas includos en los estndares de cdigo ZF: Dar formato a archivos PHP Convenciones de nombrado Estilo de cdigo Documentacin integrada
Objetivos
Los estndares de cdigo resultan importantes en cualquier proyecto de desarrollo, pero son especialmente importantes cuando muchos desarrolladores trabajan en el mismo proyecto. Los estndares de cdigo ayudan a asegurar que el cdigo tenga una alta calidad, menos errores, y pueda ser mantenido fcilmente.
Nota
IMPORTANTE: La inclusin de datos binarios arbitrarios permitidos por __HALT_COMPILER() est prohibida en los archivos PHP de Zend Framework, as como en cualquier fichero derivado. El uso de esta caracterstica slo est permitido en algunos scripts de instalacin.
1401
Identacin
La identacin suele estar compuesta por 4 espacios. Las tabulaciones no estn permitidas.
Final de lnea
El Final de Lnea sigue la convencin de archivos de texto Unix. Las lneas deben acabar con un carcter linefeed (LF). Los caracteres Linefeed estn representados con el nmero 10 ordinal, o el nmero 0x0A hexadecimal. Nota: No use retornos de carro (carriage returns, CR) como en las fuentes de Apple (0x0D) o la combinacin de retorno de carro - linefeed (CRLF) estandar para sistemas operativos Windows (0x0D, 0x0A).
Convenciones de Nombres
Clases
Zend Framework se estandariza una convencion de nombres de clases donde los nombres de las clases apuntan directamente a las carpetas en las que estan contenidas. La carpeta raiz de la biblioteca estandar de ZF es la carpeta "Zend/", mientras que la carpeta raz de las bibliotecas extra de ZF es la carpeta "ZendX/". Todas las clases de Zend Framework estn almacenadas jerrquicamente bajo estas carpetas raz. Los nombres de clases pueden contener slo caracteres alfanumricos. Los nmeros estn permitidos en los nombres de clase, pero desaconsejados en la mayora de casos. Las barras bajas (_) estn permitidas solo como separador de ruta (el archivo "Zend/Db/Table.php" debe apuntar al nombre de clase "Zend_Db_Table"). Si el nombre de una clase esta compuesto por mas de una palabra, la primera letra de cada palabra debe aparecer en maysculas. Poner en maysculas las letras siguientes no est permitido, ej: "Zend_PDF" no est permitido, mientras que "Zend_Pdf" es admisible. 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. Vea los nombres de clase en las bibliotecas estandar y adicionales (extras) como ejemplos de esta convencin de nombres.
Nota
IMPORTANTE: El cdigo que deba distribuirse junto a las bibliotecas ZF, pero no forma parte de las bibliotecas estndar o extras de Zend (e.g.: cdigo o bibliotecas que no estn distribudas por Zend) no puede empezar nunca por "Zend_" o "ZendX_".
Clases Abstractas
En general, las clases abstractas siguen las mismas convenciones que las clases, con una regla adicional: Los nombres de las clases abstractas deben acabar con el trmino, "Abstract", y ese trmino no debe ser precedida
1402
Estndares de codificacin de Zend Framework para PHP por un guin bajo. Ejemplo, Zend_Controller_Plugin_Abstract es considerado un nombre no vlido, pero Zend_Controller_PluginAbstract o Zend_Controller_Plugin_PluginAbstract serian nombres vlidos.
Nota
Esta convencin de nombres es nuevo con la versin 1.9.0 de Zend Framework. Las clases que preceden aquella versin no pueden seguir esta regla, pero sern renombradas en el futuro a fin de cumplir la regla.
Interfaces
En general, las clases abstractas siguen las mismas convenciones que las classes, con una regla adicional: Los nombres de las interfaces opcionalmente pueden acabar con el trmino, "Interface",pero trmino no debe ser precedida por un guin bajo. Ejemplo, Zend_Controller_Plugin_Interface es considerado un nombre no vlido, pero Zend_Controller_PluginInterface o Zend_Controller_Plugin_PluginInterface serian nombres vlidos. Si bien esta regla no es necesaria, se recomienda encarecidamente su uso, ya que proporciona una buena refrencia visual a los desarrolladores, como saber que archivos contienen interfaces en lugar de clases.
Nota
Esta convencin de nombres es nuevo con la versin 1.9.0 de Zend Framework. Las clases que preceden aquella versin no pueden seguir esta regla, pero sern renombradas en el futuro a fin de cumplir la regla.
Nombres de Archivo
Para cualquier otro archivo, slo caracteres alfanumricos, barras bajas (_) y guiones (-) estn permitidos. Los espacios en blanco estn estrictamente prohibidos. Cualquier archivo que contenga cdigo PHP debe terminar con la extensin ".php", con la excepcin de los scripts de la vista. Los siguientes ejemplos muestran nombres de archivo admisibles para clases de Zend Framework..:
Los nombres de archivo deben apuntar a nombres de clases como se describe arriba.
Funciones y Mtodos
Los nombres de funciones pueden contener nicamente caracteres alfanumricos. Las guiones bajos (_) no estan permitidos. Los nmeros estn permitidos en los nombres de funcin pero no se aconseja en la mayora de los casos. Los nombres de funciones deben empezar siempre con una letra minscula. Cuando un nombre de funcin consiste en ms de una palabra, la primera letra de cada nueva palabra debe estar en maysculas. Esto es llamado comnmente como formato "camelCase".
1403
Estndares de codificacin de Zend Framework para PHP Por norma general, se recomienda la elocuencia. Los nombres de funcin deben ser lo suficientemente elocuentes como para describir su propsito y comportamiento. Estos son ejemplos de nombres de funciones admisibles:
Para la programacin orientada a objetos, los mtodos de acceso para las instancias o variables estticas deben ir antepuestos con un "get" o un "set". Al implementar el patron de diseo, tales como el patrn singleton o el patrn factory, el nombre del mtodo debe contener en la prctica el nombre del patrn para describir su comportamiento de forma ms completa. Para el caso en que los mtodos son declarados con el modificador "private" o "protected", el primer carcter del nombre de la variable debe ser una barra baja (_). Este es el nico uso admisible de una barra baja en un nombre de mtodo. Los mtodos declarados como pblicos no deberan contener nunca una barra baja. Las funciones de alcance global (tambin llamadas "funciones flotantes") estn permitidas pero desaconsejadas en la mayora de los casos. Considere envolver esas funciones en una clase esttica.
Variables
Los nombres de variables pueden contener caracteres alfanumricos. Las barras bajas (_) no estn permitidas. Los nmeros estn permitidos en los nombres de variable pero no se aconseja en la mayora de los casos. Para las variables de instancia que son declaradas con el modificador "private" o "protected", el primer carcter de la variable debe ser una nica barra baja (_). Este 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. Al igual que los nombres de funciones (ver seccin 3.3), los nombres de variables deben empezar siempre con una letra en minscula y seguir la convencin "camelCaps". Por norma general, se recomienda la elocuencia. Las variables deberan ser siempre tan elocuentes como prcticas para describir los datos que el desarrollador pretende almacenar en ellas. Variables escuetas como "$i" y "$n" estn desaconsejadas, salvo para el contexto de los bucles ms pequeos. Si un bucle contiene ms de 20 lneas de cdigo, las variables de ndice deberan tener nombres ms descriptivos.
Constantes
Las constantes pueden contener tanto caracteres alfanumricos como barras bajas (_). Los nmeros estn permitidos. Todos las letras pertenecientes al nombre de una constante deben aparecer en maysculas. Las palabras dentro del nombre de una constante deben separarse por barras bajas (_). Por ejemplo, EMBED_SUPPRESS_EMBED_EXCEPTION est permitido, pero EMBED_SUPPRESSEMBEDEXCEPTION no. Las constantes deben ser definidas como miembros de clase con el modificador "const". Definir constantes en el alcance global con la funcin "define" est permitido pero no recomendado.
1404
Estilo de cdigo
Demarcacin de cdigo PHP
El cdigo PHP debe estar delimitado siempre por la forma completa de las etiquetas PHP estndar: <?php ?>
Las etiquetas cortas (short tags) no se permiten nunca. Para archivos que contengan nicamente cdigo PHP, la etiqueta de cierrre debe omitirse siempre (Ver the section called General).
Cadenas de Caracteres
Cadenas Literales de Caracteres
Cuando una cadena es literal (no contiene sustitucin de variables), el apstrofo o "comilla" debera ser usado siempre para delimitar la cadena: $a = 'Ejemplo String';
Sustitucin de Variables
La sustitucin de variables est permitida en cualquiera de estas formas: $greeting = "Hello $name, welcome back!"; $greeting = "Hello {$name}, welcome back!"; Por consistencia, esta forma no est permitida: $greeting = "Hello ${name}, welcome back!";
Concatenacin de cadenas
Las cadenas deben ser concatenadas usando el operador punto ("."). Un espacio debe aadirse siempre antes y despus del operador "." para mejorar la legibilidad:
1405
$company = 'Zend' . ' ' . 'Technologies'; Al concatenar cadenas con el operador ".", se recomienda partir la sentencia en mltiples lneas 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 "=": $sql = "SELECT `id`, `name` FROM `people` " . "WHERE `name` = 'Susan' " . "ORDER BY `name` ASC ";
Arrays
Arrays Indexados Numricamente
No estn permitidos nmeros negativos como ndices. Un array indexado puede empezar por cualquier valor no negativo, sin embargo, no se recomiendan ndices base distintos a 0. Al declarar arrays indexados con la funcin array, un espacio de separacin deben aadirse despus de cada coma, para mejorar la legibilidad: $sampleArray = array(1, 2, 3, 'Zend', 'Studio'); Se permite declarar arrays indexados multilnea usando la construccin "array". En este caso, cada lnea sucesiva debe ser tabulada con cuatro espacios de forma que el principio de cada lnea est alineado: $sampleArray = array(1, 2, 3, 'Zend', 'Studio', $a, $b, $c, 56.44, $d, 500); Alternativamente, el elemento inicial del array puede comenzar en la siguiente lnea. Si es as, debe ser alineado en un nivel de sangra superior a la lnea que contiene la declaracin del array, y todas las sucesivas lneas deben tener la mismo indentacin, el parntesis de cierre debe ser en una nueva lnea al mismo nivel de indentacin que la lnea que contiene la declaracin del array: $sampleArray = array( 1, 2, 3, 'Zend', 'Studio', $a, $b, $c, 56.44, $d, 500, ); Al utilizar esta ltima declaracin, recomendamos la utilizacin de una coma detrs de el ltimo elemento de la matriz, lo que minimizar el impacto de aadir nuevos elementos en las siguientes lneas, y ayuda a garantizar que no se produzcan errores debido a la falta de una coma.
Arrays Asociativos
Al declarar arrays asociativos con la construccin array, se recomienda partir la declaracin en mltiples lneas. En este caso, cada lnea sucesiva debe ser tabuladas con cuatro espacios de forma que tanto las llaves como los valores estn alineados:
1406
$sampleArray = array('firstKey' => 'firstValue', 'secondKey' => 'secondValue'); Alternativamente, el elemento inicial del array puede comenzar en la siguiente lnea. Si es as, debe ser alineado en un nivel de sangra superior a la lnea que contiene la declaracin del array, y todas las sucesivas lneas deben tener la mismo indentacin, el parntesis de cierre debe ser en una nueva lnea al mismo nivel de indentacin que la lnea que contiene la declaracin del array: Para mejor legibilidad, los diversos operadores de asigancin "=>" deben ser rellenados con espacios en blanco hasta que se alinien.
$sampleArray = array( 'firstKey' => 'firstValue', 'secondKey' => 'secondValue', ); Al utilizar esta ltima declaracin, recomendamos la utilizacin de una coma detrs de el ltimo elemento de la matriz, lo que minimizar el impacto de aadir nuevos elementos en las siguientes lneas, y ayuda a garantizar que no se produzcan errores debido a la falta de una coma.
Clases
Declaracin de clases
Las Clases deben ser nombradas de acuerdo a las convencion de nombres de Zend Framework. La llave "{" deber escribirse siempre en la lnea debajo del nombre de la clase ("one true brace"). Cada clase debe contener un bloque de documentacin acorde con el estndar de PHPDocumentor. Todo el cdigo contenido en una clase debe ser separado con cuatro espacios. nicamente una clase est permitida por archivo PHP. Incluir cdigo adicional en archivos de clase est permitido pero esta desaconsejado. En archivos de ese tipo, dos lneas en blanco deben separar la clase de cualquier cdigo PHP adicional en el archivo de clase. A continuacin se muestra un ejemplo de una declaracin de clase que es permitida:
/** * Bloque de Documentacin aqu */ class SampleClass { // el contenido de la clase // debe separarse con cuatro espacios } Las clases que extiendan otras clases o interfaces deberan declarar sus dependencias en la misma lnea siempre que sea posible.
1407
Estndares de codificacin de Zend Framework para PHP { } Si como resultado de esas declaraciones, la longitud de la lnea excede la longitud del Tamao mximo de lnea, se debe romper la lnea antes de la palabra clave "extends" y / o "implements" e indentarlo con un nivel de indentacin (4 espacios).
class SampleClass extends FooAbstract implements BarInterface { } If the class implements multiple interfaces and the declaration exceeds the maximum line length, break after each comma separating the interfaces, and indent the interface names such that they align.
Funciones y Mtodos
Declaracin de Funciones y Mtodos
Las Funciones deben ser nombradas de acuerdo a las convenciones de nombrado de Zend Framework. Los mtodos dentro de clases deben declarar siempre su visibilidad usando un modificador private, protected, o public. Como en las clases, la llave "{" debe ser escrita en la lnea siguiente al nombre de la funcin ("one true brace" form). No est permitido un espacio entre el nombre de la funcin y el parntesis de apertura para los argumentos. Las funciones de alcance global no estn permitidas. Lo siguiente es un ejemplo de una declaracin admisible de una funcin en una clase:
/**
1408
Estndares de codificacin de Zend Framework para PHP * Bloque de Documentacin aqu */ class Foo { /** * Bloque de Documentacin aqu */ public function bar() { // el contenido de la funcin // debe separarse con cuatro espacios } } In cases where the argument list exceeds the maximum line length, you may introduce line breaks. Additional arguments to the function or method must be indented one additional level beyond the function or method declaration. A line break should then occur before the closing argument paren, which should then be placed on the same line as the opening brace of the function or method with one space separating the two, and at the same indentation level as the function or method declaration. The following is an example of one such situation:
/** * Documentation Block Here */ class Foo { /** * Documentation Block Here */ public function bar($arg1, $arg2, $arg3, $arg4, $arg5, $arg6 ) { // all contents of function // must be indented four spaces } }
Nota
NOTA: El paso por referencia es el nico mecanismo de paso de parmetros permitido en una declaracin de mtodo.
/** * Bloque de Documentacin aqu */ class Foo { /** * Bloque de Documentacin aqu */ public function bar(&$baz) {} }
1409
Estndares de codificacin de Zend Framework para PHP La llamada por referencia est estrictamente prohibida. El valor de retorno no debe estar indicado entre parntesis. Esto podra afectar a la legibilidad, adems de romper el cdigo si un mtodo se modifica posteriormente para que devuelva por referencia.
/** * Bloque de Documentacin aqu */ class Foo { /** * INCORRECTO */ public function bar() { return($this->bar); } /** * CORRECTO */ public function bar() { return $this->bar; } }
threeArguments(1, 2, 3); La llamada por referencia est estrictamente prohibida. Vea la seccin de declaraciones de funciones para el mtodo correcto de pasar argumentos por referencia. Al pasar arrays como argumentos a una funcin, la llamada a la funcin puede incluir el indicador "hint" y puede separarse en mltiples lneas para aumentar la legibilidad. En esos casos, se aplican las pautas normales para escribir arrays:
threeArguments(array(1, 2, 3), 2, 3); threeArguments(array(1, 2, 3, 'Zend', 'Studio', $a, $b, $c, 56.44, $d, 500), 2, 3); threeArguments(array( 1, 2, 3, 'Zend', 'Studio', $a, $b, $c, 56.44, $d, 500 ), 2, 3);
1410
Sentencias de Control
If/Else/Elseif
Las sentencias de control basadas en las construcciones if y elseif deben tener un solo espacio en blanco antes del parntesis de apertura del condicional y un solo espacio en blanco despus del parntesis de cierre. Dentro de las sentencias condicionales entre parntesis, los operadores deben separarse con espacios, por legibilidad. Se aconseja el uso de parntesis internos para mejorar la agrupacin lgica en expresiones condicionales ms largas. La llave de apertura "{" se escribe en la misma lnea que la sentencia condicional. La llave de cierre "}" se escribe siempre en su propia lnea. Cualquier contenido dentro de las llaves debe separarse con cuatro espacios en blanco. if ($a != 2) { $a = 2; } If the conditional statement causes the line length to exceed the maximum line length and has several clauses, you may break the conditional into multiple lines. In such a case, break the line prior to a logic operator, and pad the line such that it aligns under the first character of the conditional clause. The closing paren in the conditional will then be placed on a line with the opening brace, with one space separating the two, at an indentation level equivalent to the opening control statement. if (($a == $b) && ($b == $c) || (Foo::CONST == $d) ) { $a = $d; } The intention of this latter declaration format is to prevent issues when adding or removing clauses from the conditional during later revisions. Para las declaraciones "if" que incluyan "elseif" o "else", las convenciones de formato son similares a la construccin "if". Los ejemplos siguientes demuestran el formato correcto para declaraciones "if" con construcciones "else" y/o "elseif": if ($a $a } else $a } != 2) { = 2; { = 7;
1411
Estndares de codificacin de Zend Framework para PHP && ($b == $c) || (Foo::CONST == $d) ) { $a = $d; } elseif (($a != $b) || ($b != $c) ) { $a = $c; } else { $a = $b; } PHP permite escribir sentencias sin llaves -{}- en algunas circunstancias. Este estndar de cdigo no hace ninguna diferenciacin- toda sentencia "if", "elseif" o "else" debe usar llaves. El uso de la construccin "elseif" est permitido pero no se aconseja, en favor de la combinacin "else if".
Switch
Las declaraciones de control escritas con la declaracin "switch" deben tener un nico espacio en blanco antes del parntesis de apertura del condicional y despus del parntesis de cierre. Todo contenido dentro de una declaracin "switch" debe separarse usando cuatro espacios. El contenido dentro de cada declaracin "case" debe separarse usando cuatro espacios adicionales. switch ($numPeople) { case 1: break; case 2: break; default: break; }
Nota
NOTA: En ocasiones, resulta til escribir una declaracin case que salta al siguiente case al no incluir un break o return dentro de ese case. Para distinguir estos casos de posibles errores, cualquier declaracin donde break o return sean omitidos debern contener un comentario indicando que se omitieron intencionadamente.
Documentacin integrada
Formato de documentacin
Todos los bloques de documentacin ("docblocks") deben ser compatibles con el formato de phpDocumentor. Describir el formato de phpDocumentor est fuera del alcance de este documento. Para ms informacin, visite: http:// phpdoc.org/
1412
Estndares de codificacin de Zend Framework para PHP Todos los archivos de clase deben contener un bloque de documentacin "a nivel de archivo" al principio de cada archivo y un bloque de documentacin "a nivel de clase" inmediatamente antes de cada clase. Ejemplo de estos bloques de documentacin pueden encontrarse debajo.
Archivos
Cada archivo que contenga cdigo PHP debe tener un bloque de documentacin al principio del archivo que contenga como mnimo las siguientes etiquetas phpDocumentor:
/** * Descripcin corta del fichero * * Descripcin larga del fichero (si la hubiera)... * * LICENSE: Some license information * * @category Zend * @package Zend_Magic * @subpackage Wand * @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 */ The @category annotation must have a value of "Zend". The @package annotation must be assigned, and should be equivalent to the component name of the class contained in the file; typically, this will only have two segments, the "Zend" prefix, and the component name. The @subpackage annotation is optional. If provided, it should be the subcomponent name, minus the class prefix. In the example above, the assumption is that the class in the file is either "Zend_Magic_Wand", or uses that classname as part of its prefix.
Clases
Cada clase debe contener un bloque de documentacin que contenga como mnimo las siguientes etiquetas phpDocumentor:
/** * Descripcin * * Descripcion * * @category * @package * @subpackage * @copyright * @license * @version * @link * @since
corta de la clase larga de la clase (si la hubiera)... Zend Zend_Magic Wand 2008 Zend Technologies http://framework.zend.com/license BSD License Release: @package_version@ http://framework.zend.com/package/PackageName Class available since Release 1.5.0
1413
Estndares de codificacin de Zend Framework para PHP * @deprecated Class deprecated in Release 2.0.0 */ The @category annotation must have a value of "Zend". The @package annotation must be assigned, and should be equivalent to the component to which the class belongs; typically, this will only have two segments, the "Zend" prefix, and the component name. The @subpackage annotation is optional. If provided, it should be the subcomponent name, minus the class prefix. In the example above, the assumption is that the class described is either "Zend_Magic_Wand", or uses that classname as part of its prefix.
Funciones
Cada funcin, incluyendo mtodos de objeto, debe contener un bloque de documentacin que contenga como mnimo: Una descripcin de la funcin Todos los argumentos Todos los posibles valores de retorno 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 funcin. Si una funcin/mtodo puede lanzar una excepcin, utilice @throws para todos los tipos de excepciones conocidas:
1414
Indentation
Indentation should consist of 4 spaces. Tabs are not allowed. Tags which are at the same level must have the same indentation. <sect1>
1415
Zend Framework Documentation Standard </sect1> <sect1> </sect1> Tags which are one level under the previous tag must be indented with 4 additional spaces.
<sect1> <sect2> </sect2> </sect1> Multiple block tags within the same line are not allowed; multiple inline tags are allowed, however.
<!-- NOT ALLOWED: --> <sect1><sect2> </sect2></sect1> <!-- ALLOWED --> <para> <code>Zend_Magic</code> does not exist. <code>Zend_Acl</code> does. </para>
Line Termination
Line termination follows the Unix text file convention. Lines must end with a single linefeed (LF) character. Linefeed characters are represented as ordinal 10, or hexadecimal 0x0A. Note: Do not use carriage returns (CR) as is the convention in Apple OS's (0x0D) or the carriage return - linefeed combination (CRLF) as is standard for the Windows OS (0x0D, 0x0A).
Empty tags
Empty tags are not allowed; all tags must contain text or child tags.
<!-- NOT ALLOWED --> <para> Some text. <link></link> </para> <para> </para>
1416
Zend Framework Documentation Standard <!-- NOT ALLOWED --> <sect1>WHITESPACE </sect1> Opening inline tags should have no whitespace immediately following them.
<!-- NOT ALLOWED --> This is the class <classname> Zend_Class</classname>. <!-- OK --> This is the class <classname>Zend_Class</classname>. Closing block tags may be preceded by whitespace equivalent to the current indentation level, but no more than that amount.
<!-- NOT ALLOWED --> <sect1> </sect1> <!-- OK --> <sect1> </sect1> Closing inline tags must not be preceded by any whitespace.
<!-- NOT ALLOWED --> This is the class <classname>Zend_Class </classname> <!-- OK --> This is the class <classname>Zend_Class</classname>
<!-- NOT ALLOWED --> <para> Some text... ... and more text </para>
<para> Another paragraph. </para> <!-- OK --> <para> Some text... ... and more text
1417
<!-- NOT ALLOWED --> <para> Some text... </para> <para> More text... </para> <!-- OK --> <para> Some text... </para> <para> More text... </para> The first child tag should open directly below its parent, with no empty line between them; the last child tag should close directly before the closing tag of its parent.
<!-- NOT ALLOWED --> <sect1> <sect2> </sect2> <sect2> </sect2> <sect2> </sect2> </sect1> <!-- OK --> <sect1> <sect2> </sect2> <sect2> </sect2>
1418
Program Listings
The opening <programlisting> tag must indicate the appropriate "language" attribute and be indented at the same level as its sibling blocks.
<para>Sibling paragraph.</para> <programlisting language="php"><![CDATA[ CDATA should be used around all program listings. <programlisting> sections must not add linebreaks or whitespace at the beginning or end of the section, as these are then represented in the final output.
<!-- NOT ALLOWED --> <programlisting language="php"><![CDATA[ $render = "xxx"; ]]></programlisting> <!-- OK --> <programlisting language="php"><![CDATA[ $render = "xxx"; ]]></programlisting> Ending CDATA and <programlisting> tags should be on the same line, without any indentation.
<!-- NOT ALLOWED --> <programlisting language="php"><![CDATA[ $render = "xxx"; ]]> </programlisting> <!-- NOT ALLOWED --> <programlisting language="php"><![CDATA[ $render = "xxx"; ]]></programlisting> <!-- OK --> <programlisting language="php"><![CDATA[ $render = "xxx"; ]]></programlisting> The <programlisting> tag should contain the "language" attribute with a value appropriate to the contents of the program listing. Typical values include "css", "html", "ini", "javascript", "php", "text", and "xml".
1419
Zend Framework Documentation Standard <!-- PHP --> <programlisting language="php"><![CDATA[ <!-- Javascript --> <programlisting language="javascript"><![CDATA[ <!-- XML --> <programlisting language="xml"><![CDATA[ For program listings containing only PHP code, PHP tags (e.g., "<?php", "?>") are not required, and should not be used. They simply clutter the narrative, and are implied by the use of the <programlisting> tag. <!-- NOT ALLOWED --> <programlisting language="php"<![CDATA[<?php // ... ?>]]></programlisting> <programlisting language="php"<![CDATA[ <?php // ... ?> ]]></programlisting> Line lengths within program listings should follow the coding standards recommendations. Refrain from using require_once(), require(), include_once(), and include() calls within PHP listings. They simply clutter the narrative, and are largely obviated when using an autoloader. Use them only when they are essential to the example.
varname
Variables must be wrapped in the <varname> tag. Variables must be written using the "$" sigil. No other content is allowed within this tag, unless a class name is used, which indicates a class variable. <para> The variable <varname>$var</varname> and the class variable <varname>Zend_Class::$var</varname>.
1420
methodname
Methods must be wrapped in the <methodname> tag. Methods must either include the full method signature or at the least a pair of closing parentheses (e.g., "()"). No other content is allowed within this tag, unless a class name is used, which indicates a class method.
<para> The method <methodname>foo()</methodname> and the class method <methodname>Zend_Class::foo()</methodname>. A method with a full signature: <methodname>foo($bar, $baz)</methodname> </para>
constant
Use the <constant> tag when denoting constants. Constants must be written in UPPERCASE. No other content is allowed within this tag, unless a class name is used, which indicates a class constant.
<para> The constant <constant>FOO</constant> and the class constant <constant>Zend_Class::FOO</constant>. </para>
filename
Filenames and paths must be wrapped in the <filename> tag. No other content is allowed in this tag.
command
Commands, shell scripts, and program calls must be wrapped in the <command> tag. If the command includes arguments, these should also be included within the tag.
code
Usage of the <code> tag is discouraged, in favor of the other inline tasks discussed previously.
1421
<!-- NOT ALLOWED --> <title>Using <classname>Zend_Class</classname></title> <!-- OK --> <title>Using Zend_Class</title>
Recommendations
Use editors without autoformatting
For editing the documentation, typically you should not use formal XML editors. Such editors normally autoformat existing documents to fit their own standards and/or do not strictly follow the docbook standard. As examples, we have seen them erase the CDATA tags, change 4 space seperation to tabs or 2 spaces, etc. The style guidelines were written in large part to assist translators in recognizing the lines that have changed using normal diff tools. Autoformatting makes this process more difficult.
Use Images
Good images and diagrams can improve readability and comprehension. Use them whenever they will assist in these goals. Images should be placed in the documentation/manual/en/figures/ directory, and be named after the section identifier in which they occur.
Use Links
Link to other sections of the manual or to external sources instead of recreating documentation. Linking to other sections of the manual may be done using either the <xref> tag (which will substitute the section title for the link text) or the <link> tag (to which you must provide link text).
1422
Zend Framework Documentation Standard "Link" links to a section, using descriptive text: <link linkend="doc-standard.recommendations.links">documentation on links</link>. </para> To link to an external resource, use <ulink>:
1423
1424
Recommended Project Structure for Zend Framework MVC Applications docs/ library/ public/ css/ images/ js/ .htaccess index.php scripts/ jobs/ build/ temp/ tests/ The following describes the use cases for each directory as listed. application/: This directory contains your application. It will house the MVC system, as well as configurations, services used, and your bootstrap file. configs/: The application-wide configuration directory. controllers/, models/, and views/: These directories serve as the default controller, model or view directories. Having these three directories inside the application directory provides the best layout for starting a simple project as well as starting a modular project that has global controllers/models/views. controllers/helpers/: These directories will contain action helpers. Action helpers will be namespaced either as "Controller_Helper_" for the default module or "<Module>_Controller_Helper" in other modules. layouts/: This layout directory is for MCV-based layouts. Since Zend_Layout is capable of MVC- and non-MVC-based layouts, the location of this directory reflects that layouts are not on a 1-to-1 relationship with controllers and are independent of templates within views/. modules/: Modules allow a developer to group a set of related controllers into a logically organized group. The structure under the modules directory would resemble the structure under the application directory. services/: This directory is for your application specific web-service files that are provided by your application, or for implementing a Service Layer [http://www.martinfowler.com/eaaCatalog/serviceLayer.html] for your models. Bootstrap.php: This file is the entry point for your application, and should implement Zend_Application_Bootstrap_Bootstrapper. The purpose for this file is to bootstrap the application and make components available to the application by initializing them. data/: This directory provides a place to store application data that is volatile and possibly temporary. The disturbance of data in this directory might cause the application to fail. Also, the information in this directory may or may not be committed to a subversion repository. Ejemplos of things in this directory are session files, cache files, sqlite databases, logs and indexes. docs/: This directory contains documentation, either generated or directly authored. library/: This directory is for common libraries on which the application depends, and should be on the PHP include_path. Developers should place their application's library code under this directory in a unique namespace, following the guidelines established in the PHP manual's Userland Naming Guide [http://www.php.net/manual/ en/userlandnaming.php], as well as those established by Zend itself. This may directory may also include Zend Framework itself; if so, you would house it in library/Zend/.
1425
Recommended Project Structure for Zend Framework MVC Applications public/: This directory contains all public files for your application. index.php sets up and invokes Zend_Application, which in turn invokes the application/Bootstrap.php file, resulting in dispatching the front controller. The web root of your web server would typically be set to this directory. scripts/: This directory contains maintenance and/or build scripts. Such scripts might include command line, cron, or phing build scripts that are not executed at runtime but are part of the correct functioning of the application. temp/: The temp/ folder is set aside for transient application data. This information would not typically be committed to the applications svn repository. If data under the temp/ directory were deleted, the application should be able to continue running with a possible decrease in performance until data is once again restored or recached. tests/: This directory contains application tests. These could be hand-written, PHPUnit tests, Selenium-RC based tests or based on some other testing framework. By default, library code can be tested by mimicing the directory structure of your library/ directory. Additionally, functional tests for your application could be written mimicing the application/ directory structure (including the application subdirectory).
Module Structure
The directory structure for modules should mimic that of the application/ directory in the recommended project structure:
<modulename>/ configs/ application.ini controllers/ helpers/ layouts/ filters/ helpers/ scripts/ models/ services/ views/ filters/ helpers/ scripts/ Bootstrap.php The purpose of these directories remains exactly the same as for the recommended project directory structure.
1426
<VirtualHost my.domain.com:80> ServerName my.domain.com DocumentRoot /path/to/server/root/my.domain.com/public RewriteEngine off <Location /> RewriteEngine On RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L] RewriteRule ^.*$ /index.php [NC,L] </Location> </VirtualHost> Note the slash ("/") prefixing index.php; the rules for .htaccess differ in this regard.
RewriteEngine On RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L] RewriteRule ^.*$ index.php [NC,L] There are many ways to configure mod_rewrite; if you would like more information, see Jayson Minard's Blueprint for PHP Applications: Bootstrapping [http://devzone.zend.com/a/70].
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <rewrite> <rules> <rule name="Imported Rule 1" stopProcessing="true"> <match url="^.*$" /> <conditions logicalGrouping="MatchAny">
1427
Recommended Project Structure for Zend Framework MVC Applications <add input="{REQUEST_FILENAME}" matchType="IsFile" pattern="" ignoreCase="false" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" pattern="" ignoreCase="false" /> </conditions> <action type="None" /> </rule> <rule name="Imported Rule 2" stopProcessing="true"> <match url="^.*$" /> <action type="Rewrite" url="index.php" /> </rule> </rules> </rewrite> </system.webServer> </configuration>
1428
Class Loading
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 file system, the various calls to include_once() and require_once() can be problematic. This chapter intends to provide some concrete solutions to these issues.
$paths = array( realpath(dirname(__FILE__) . '/../library'), '.', ); set_include_path(implode(PATH_SEPARATOR, $paths); You can use relative paths -- so long as they are relative to an absolute path:
define('APPLICATION_PATH', realpath(dirname(__FILE__))); $paths = array( APPLICATION_PATH . '/../library'), '.', ); set_include_path(implode(PATH_SEPARATOR, $paths); However, even so, it's typically a trivial task to simply pass the path to realpath().
1429
library Archive/ PEAR/ PHPUnit/ Zend/ This allows us to add our own library code if necessary, while keeping shared libraries intact. 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 file system, without needing to edit the include_path every time. We'll borrow ideas from each of the suggestions above: we'll use absolute paths, as determined using realpath(); we'll include Zend Framework's 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.
1430
% cd path/to/ZendFramework/library % find . -name '*.php' -not -wholename '*/Loader/Autoloader.php' -print0 | \ xargs -0 sed --regexp-extended --in-place 's/(require_once)/\/\/ \1/g' 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. 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 must utilize autoloading; you can do that from your "public/index.php" file with the following code:
1431
Gua de Rendimiento de Zend Framework Zend_Dojo: view helpers, form elements and decorators Zend_File_Transfer: adapters Zend_Filter_Inflector: filters (used by the ViewRenderer action helper and Zend_Layout) Zend_Filter_Input: filters and validators Zend_Form: elements, validators, filters, decorators, captcha and file transfer adapters Zend_Paginator: adapters Zend_View: helpers, filters How can you reduce the number of such calls made?
Zend_Db Performance
Zend_Db is a database abstraction layer, and is intended to provide a common API for SQL operations. Zend_Db_Table is a Table Data Gateway, intended to abstract common table-level database operations. Due to their abstract nature and the "magic" they do under the hood to perform their operations, they can sometimes introduce performance overhead.
How can I reduce overhead introduced by Zend_Db_Table for retrieving table metadata?
In order to keep usage as simple as possible, and also to support constantly changing schemas during development, Zend_Db_Table does some magic under the hood: on first use, it fetches the table schema and stores it within object members. This operation is typically expensive, regardless of the database -- which can contribute to bottlenecks in production. Fortunately, there are techniques for improving the situation.
1432
SQL generated with Zend_Db_Select s not hitting my indexes; how can I make it better?
Zend_Db_Select is relatively good at its job. However, if you are performing complex queries requiring joins or sub-selects, it can often be fairly naive.
1433
Gua de Rendimiento de Zend Framework If high performance is one of your concerns, we suggest utilizing one of the above adapters.
View Rendering
When using Zend Framework's MVC layer, chances are you will be using Zend_View. Zend_View is performs well 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 not optimized. However, Zend_View 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.
1434
Gua de Rendimiento de Zend Framework 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"; } } 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.
1435
Gua de Rendimiento de Zend Framework $name: the name of the view script to render $module: 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 $model argument. $model: an array or object to pass to the partial representing the clean data to assign to the view. The power and use of partial() come from the second and third arguments. The $module argument allows partial() to temporarily add a script path for the given module so that the partial view script will resolve to that module; the $model argument allows you to explicitly pass variables for use with the partial view. If you're not passing either argument, use render() instead! 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 partial(); instead, use Zend_View's built-in render() method to render the view script.
1436
Gua de Rendimiento de Zend Framework $stack = new Zend_Controller_Plugin_ActionStack(); $front->registerPlugin($stack); } else { $stack = $front->getPlugin('ActionStack') } $this->_stack = $stack; } return $this->_stack; } } The UserController::indexAction() method might then use the $responseSegment parameter to indicate which response segment to render to. In the layout script, you would then simply render that response segment:
<?php $this->layout()->login ?> While the ActionStack still requires a dispatch cycle, this is still cheaper than the action() view helper as it does not need to clone objects and reset internal state. Additionally, it ensures that all pre and post dispatch plugins are invoked, which may be of particular concern if you are using front controller plugins for handling ACL's to particular actions.
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"; Using action(), you would then invoke it with the following:
<?php $this->action('list', 'bug') ?> This could be refactored to a view helper that looks like the following:
1437
class My_View_Helper_BugList extends Zend_View_Helper_Abstract { public function bugList() { $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; } } You would then invoke the helper as follows:
<?php $this->bugList() ?> This has two benefits: it no longer incurs the overhead of the action() view helper, and also presents a more semantically understandable API.
1438
1439
Index
1440