Issuu on Google+

 

Kumbia Enterprise Framework  Un Framework para el PHP Empresarial  LouderTechnology 

www.loudertechnology.com 

Abril de 2009  Versión del Producto: 1.0.17GA 

                                           

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                2 

Tabla de Contenido  1  Prefacio .................................................................................................................. 15  1.1  Antes de Leer este Documento .................................................................................................................. 15  1.2  Como esta organizado este Documento................................................................................................. 15  1.3  Convenciones Tipográficas.......................................................................................................................... 16  1.4  A Quien está Orientado este Texto........................................................................................................... 17  1.5  Información sobre marcas y productos referenciados ................................................................... 17  1.6  Referencias a sitios web de terceros....................................................................................................... 17  1.7  Sus comentarios están bienvenidos ........................................................................................................ 18  2  Introducción ........................................................................................................... 19  2.1  Diferencias con la versión Comunitaria................................................................................................. 19  2.2  Licencia ................................................................................................................................................................ 20  3  Instalación .............................................................................................................. 21  3.1  Introducción ...................................................................................................................................................... 21  3.2  Configuración con Apache Web Server 2.x........................................................................................... 21  3.3  Configuración con Microsoft IIS e ISAPI Rewrite .............................................................................. 23  3.4  Configuración de PHP .................................................................................................................................... 24  3.5  Configuración con Zend Application Server ........................................................................................ 25  3.6  Crear una Instancia de Kumbia Enterprise .......................................................................................... 25  3.7  Solución a problemas de instalación....................................................................................................... 25  4  ¿Qué es Kumbia Enterprise Framework?................................................................. 28  4.1  Sobre Aplicaciones Web ............................................................................................................................... 28  4.2  Sobre PHP y la Web ........................................................................................................................................ 28  4.3  Introducción ...................................................................................................................................................... 28  4.4  Características del Framework.................................................................................................................. 29  4.5  PHP en entornos críticos .............................................................................................................................. 30  4.6  Preguntas frecuentes sobre Kumbia Enterprise................................................................................ 31  5  Arquitectura ........................................................................................................... 34  5.1  Introducción ...................................................................................................................................................... 34  5.2  Capas en una Aplicación ............................................................................................................................... 34  5.3  Usando Modelo‐Vista‐Controlador .......................................................................................................... 35  5.4  Ventajas de usar MVC .................................................................................................................................... 36  5.5  Arquitectura SOA............................................................................................................................................. 37  5.6  Beneficios de una SOA ................................................................................................................................... 38  5.7  SOA en Kumbia Enterprise .......................................................................................................................... 38  5.8  Loose Coupling/Tight Coupling ................................................................................................................ 40  6  Caso de Uso: Aplicación de Cajero Bancario ............................................................ 41  6.1  Introducción ...................................................................................................................................................... 41  6.2  Análisis de los Requerimientos ................................................................................................................. 41  6.3  Esqueleto de la Aplicación........................................................................................................................... 45  6.4  Configurar la conexión a la base de datos............................................................................................. 45  6.5  Crear los modelos de Base de Datos........................................................................................................ 46  6.6  Crear el Inicio de Sesión ............................................................................................................................... 49  6.7  Autenticando al Cliente................................................................................................................................. 52  6.8  Un Menú para la Aplicación ........................................................................................................................ 54  6.9  Visualización del saldo del cliente............................................................................................................ 55  6.10  Crear el TransactionActivity .................................................................................................................... 58 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                3 

7  Aplicaciones en Kumbia Enterprise ......................................................................... 62  7.1  Introducción ...................................................................................................................................................... 62  7.2  Instancias del framework ............................................................................................................................ 62  7.3  Estructura de directorios de una Instancia.......................................................................................... 62  7.4  Publicar contenido estático......................................................................................................................... 64  7.5  Bootstrap............................................................................................................................................................. 65  7.6  Crear la acción por defecto en una Aplicación.................................................................................... 66  7.7  Crear un procedimiento de inicialización de la aplicación............................................................ 66  7.8  Detectar un cambio en la ejecución de una instancia a otra......................................................... 67  8  Componente Controller .......................................................................................... 68  8.1  Introducción ...................................................................................................................................................... 68  8.2  Como funciona el componente Controller?.......................................................................................... 68  8.3  Crear un Controlador..................................................................................................................................... 70  8.4  Servicios del Componente Router............................................................................................................ 71  8.5  Servicios proporcionados por Dispatcher ............................................................................................ 73  8.6  Excepciones Generadas en el Dispatcher.............................................................................................. 74  8.7  Peticiones HTTP a Controladores............................................................................................................. 76  8.7.1  Administrar archivos adjuntos en una petición .............................................................................. 77  8.7.2  API de ControllerRequest........................................................................................................................... 78  8.8  Respuestas HTTP de Controladores........................................................................................................ 81  8.8.1  Establecer el tipo de salida de la Petición.......................................................................................... 82  8.8.2  API de ControllerResponse........................................................................................................................ 83  8.9  Controlar acciones no encontradas ......................................................................................................... 84  8.10  Filtros en controladores............................................................................................................................. 85  8.11  Enrutamiento en controladores ............................................................................................................. 86  8.11.1  Ciclo de enrutamiento .............................................................................................................................. 86  8.11.2  Enrutar usando Router::routeTo......................................................................................................... 87  8.11.3  Enrutar usando Router::routeToURI() ............................................................................................. 88  8.12  Inicialización de Controladores.............................................................................................................. 88  8.13  Estado de persistencia de Controladores........................................................................................... 89  8.13.1  Ventajas del Estado de Persistencia................................................................................................... 90  8.13.2  Consideraciones del estado de Persistencia.................................................................................... 90  8.13.3  Transacciones y Concurrencia del Estado de Persistencia ...................................................... 91  8.13.4  Eventos del estado de Persistencia ..................................................................................................... 91  8.14  La Clase ControllerBase ............................................................................................................................. 92  8.15  La Clase Controller ....................................................................................................................................... 92  8.15.1  API de Controller ........................................................................................................................................ 92  8.16  Controladores usando ApplicationController .................................................................................. 96  8.16.1  API de ApplicationController ................................................................................................................ 96  8.16.2  Controladores usando MultiThreadController.............................................................................. 97  8.17  Servicios Web usando WebServiceController.................................................................................. 98  8.17.1  Qué es un Web Service?............................................................................................................................ 98  8.17.2  Para que son necesarios los Web Services....................................................................................... 99  8.17.3  Arquitectura Orientada a Servicios (SOA) ...................................................................................... 99  8.17.4  Crear un Web Service .............................................................................................................................100  8.17.5  WebServiceClient......................................................................................................................................102  8.17.6  Obteniendo el WSDL de un Servicio Web.......................................................................................103  8.17.7  Orquestación de servicios .....................................................................................................................104  8.17.8  Características de Servicios Web en Kumbia Enterprise ........................................................106  8.18  Controladores StandardForm ...............................................................................................................106 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                4 

8.18.1  Características de StandardForm.....................................................................................................106  8.18.2  Limitantes de StandardForm..............................................................................................................107  8.19  Plugins de Controladores ........................................................................................................................107  8.19.1  Crear un Plugin de Controlador.........................................................................................................107 

9  Componente UDDI................................................................................................ 109  9.1  Introducción ....................................................................................................................................................109  9.2  Requerimientos..............................................................................................................................................109  10  Componente BusinessProcess ............................................................................. 110  10.1  Introducción..................................................................................................................................................110  10.1.1  ¿Que es un proceso de negocio?..........................................................................................................110  10.1.2  ¿Qué es BPEL? ............................................................................................................................................110  10.2  Job Executor ..................................................................................................................................................110  10.3  Crear un Proceso de Negocio.................................................................................................................110  10.3.1  Tipos de nodos de un meta­proceso PDL........................................................................................112  10.3.2  Crear los handlers del BusinessProcess ..........................................................................................113  11  Componente Filter .............................................................................................. 114  11.1  Introducción..................................................................................................................................................114  11.2  Estructura del Componente ...................................................................................................................114  11.3  Usar filtros en forma directa..................................................................................................................116  11.4  Crear chains de Filtros..............................................................................................................................116  11.5  Usar filtros en Controladores ................................................................................................................117  11.6  Filtrar la entrada de usuario ..................................................................................................................118  11.7  Crear un filtro de usuario ........................................................................................................................119  11.7.1  Requerimientos de un filtro de usuario ..........................................................................................120  12  ActionHelpers ..................................................................................................... 121  12.1  Introducción..................................................................................................................................................121  12.2  Mensajes usando Flash.............................................................................................................................121  12.2.1  Generar mensajes contextuales..........................................................................................................121  12.2.2  Cambiar el estilo por defecto de los mensajes .............................................................................121  12.2.3  Cambiar el estilo en forma dinámica...............................................................................................122  12.2.4  Enviar múltiples mensajes del mismo tipo en forma simúltanea........................................122  12.2.5  Mostrar mensajes por su tipo..............................................................................................................123  12.2.6  Cachear mensajes para mostrarlos en la próxima petición ..................................................123  12.3  Condiciones SQL con FormCriteria .....................................................................................................124  12.3.1  Criterios de Rangos..................................................................................................................................126  12.3.2  Unir varias condiciones .........................................................................................................................127  12.4  Información del Navegador con Browser ........................................................................................128  12.4.1  API de Browser ..........................................................................................................................................128  12.5  Autocompletar con Scriptaculous........................................................................................................130  13  Componente Validator........................................................................................ 132  13.1  Introducción..................................................................................................................................................132  14  Seguridad con Kumbia Enterprise........................................................................ 133  14.1  Introducción..................................................................................................................................................133  14.2  Características de Seguridad..................................................................................................................133  14.3  Mecanismos de Seguridad.......................................................................................................................134  14.4  Seguridad a nivel de Capa de Aplicación ..........................................................................................134  14.5  Seguridad a nivel de Capa de Transporte.........................................................................................135 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                5 

14.6  Implementar Seguridad Declarativa ..................................................................................................136  14.7  Implementar Seguridad Programacional .........................................................................................138  14.8  Definir Realms, Usuarios y Grupos para Autenticación .............................................................138  14.8.1  Realms...........................................................................................................................................................138  14.8.2  Usuarios........................................................................................................................................................139  14.8.3  Grupos ...........................................................................................................................................................139 

15  Componente ACL (Lista de Control de Acceso) .................................................... 140  15.1  Introducción..................................................................................................................................................140  15.2  Estructura del Componente ...................................................................................................................140  15.3  ¿Que es un Recurso? ..................................................................................................................................141  15.4  ¿Que es un Rol? ............................................................................................................................................141  15.5  ¿Que es un Acceso?.....................................................................................................................................141  15.6  Tipos de Reglas ............................................................................................................................................141  15.7  ACL en Acción...............................................................................................................................................141  15.8  Herencia de Roles .......................................................................................................................................143  15.9  Adaptadores de ACL ..................................................................................................................................143  15.9.1  AclModel.......................................................................................................................................................144  15.9.2  AclMemory...................................................................................................................................................144  15.9.3  AclXML ..........................................................................................................................................................144  15.10  API de un Adaptador...............................................................................................................................146  15.11  API de AclResource ..................................................................................................................................147  15.12  API de AclRole ...........................................................................................................................................147  16  Componente Auth............................................................................................... 148  16.1  Introducción..................................................................................................................................................148  16.2  Adaptadores de Auth.................................................................................................................................148  16.3  Administración de Identidad .................................................................................................................149  16.4  Expiración de Sesión .................................................................................................................................149  16.5  Control de Autenticación concurrente ..............................................................................................149  16.6  Autenticación con Modelos.....................................................................................................................150  16.7  Autenticación con KerberosV ................................................................................................................151  16.8  Autenticación con Radius........................................................................................................................152  16.9  Autenticación con Digest .........................................................................................................................153  16.10  Autenticación con LDAP........................................................................................................................154  17  Componente AuditLogger ................................................................................... 157  17.1  Introducción..................................................................................................................................................157  17.2  Crear un componente de control .........................................................................................................157  18  Componente Security.......................................................................................... 158  18.1  Introducción..................................................................................................................................................158  18.2  Subcomponente SecurityFirewall........................................................................................................158  18.2.1  Introducción ...............................................................................................................................................158  18.2.2  Como se evaluan las reglas ..................................................................................................................159  18.2.3  Tipos de Atributos de una Regla........................................................................................................159  19  Persistencia, Transacciones y Concurrencia......................................................... 161  19.1  Introducción..................................................................................................................................................161  20  Componente Db.................................................................................................. 161  20.1  Introducción..................................................................................................................................................161  20.2  Capas de acceso ...........................................................................................................................................161 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                6 

20.3  Adaptadores del componente Db.........................................................................................................162  20.4  Generación de SQL......................................................................................................................................164  20.5  Conexiones a gestores relacionales por defecto............................................................................165  20.5.1  Consideraciones para Oracle...............................................................................................................165  20.5.2  Consideraciones para Microsoft SQL Server.................................................................................168  20.5.3  Consideraciones para MySQL..............................................................................................................175  20.5.4  Consideraciones para IBM Informix.................................................................................................178  20.5.5  Consideraciones con SQLite .................................................................................................................181  20.6  Pool de Conexiones ....................................................................................................................................182  20.6.1  Conexiones de Bajo Nivel ......................................................................................................................182  20.6.2  Trazar Conexiones ...................................................................................................................................183  20.7  Generar Profiles de ejecución de SQL ................................................................................................184  20.8  Manejar Excepciones de Db....................................................................................................................184  20.8.1  Tipos de Excepciones lanzadas por el componente Db............................................................185  20.8.2  Información extendida de excepciones generadas por Db.....................................................185  20.9  Tipos de Resultado al Obtener de Registros ...................................................................................188  20.10  Leer registros.............................................................................................................................................189  20.11  Manipular Registros................................................................................................................................192  20.12  Administrar Transacciones..................................................................................................................194  20.13  Crear, Cerrar y obtener información de conexiones.................................................................196  20.14  Información de Errores .........................................................................................................................197  20.15  Obtener el valor de la columna identidad .....................................................................................197  20.16  Obtener información de Tablas .........................................................................................................198  20.17  Crear y Eliminar Tablas.........................................................................................................................198  20.18  Fecha del gestor relacional ..................................................................................................................201  20.19  Debug, Seguimiento y Traza ................................................................................................................201 

21  Componente Active Record ‐ ORM ...................................................................... 202  21.1  Introducción..................................................................................................................................................202  21.2  Cuando usar ActiveRecord......................................................................................................................203  21.3  Entidades........................................................................................................................................................203  21.3.1  Requerimientos de las Clases de Entidades...................................................................................203  21.3.2  Atributos de las Entidades....................................................................................................................204  21.4  Atributos y Campos persistentes .........................................................................................................204  21.5  Llaves Primarias..........................................................................................................................................205  21.6  Convenciones en llaves primarias .......................................................................................................206  21.7  Fechas Auto‐Asignables ...........................................................................................................................206  21.8  Multiplicidad en Relaciones de Entidades .......................................................................................206  21.8.1  Convenciones en Relaciones.................................................................................................................207  21.8.2  Relaciones Unidireccionales ................................................................................................................207  21.8.3  Relaciones Bidireccionales ...................................................................................................................207  21.8.4  Muchos a uno .............................................................................................................................................207  21.8.5  Uno a Muchos.............................................................................................................................................209  21.8.6  Uno a Uno ....................................................................................................................................................209  21.8.7  Muchos a Muchos .....................................................................................................................................209  21.9  API de ActiveRecord ..................................................................................................................................210  21.9.1  Origen de Datos.........................................................................................................................................210  21.9.2  Volcado de Meta­Datos..........................................................................................................................210  21.9.3  Debug y Seguimiento ..............................................................................................................................210  21.9.4  Transacciones ............................................................................................................................................211  21.9.5  Consultar registros ..................................................................................................................................212 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                7 

21.9.6  Contar registros ........................................................................................................................................214  21.9.7  Promediar registros ................................................................................................................................215  21.9.8  Realizar sumatorias ................................................................................................................................215  21.9.9  Obtener el valor máximo de un atributo........................................................................................215  21.9.10  Obtener el valor mínimo de un atributo......................................................................................216  21.9.11  Asignar valores a instancias .............................................................................................................216  21.9.12  Validación .................................................................................................................................................216  21.9.13  Información de atributos ...................................................................................................................217  21.9.14  Creación y actualización de registros...........................................................................................218  21.9.15  Eliminación de registros.....................................................................................................................219  21.9.16  Operaciones en Batch ..........................................................................................................................219  21.9.17  Lectura/escritura de Atributos .......................................................................................................219  21.9.18  Validación .................................................................................................................................................219  21.9.19  Multiplicidad de relaciones ...............................................................................................................220  21.9.20  Herencia.....................................................................................................................................................221  21.9.21  Excepciones ..............................................................................................................................................221  21.10  Identifiers ....................................................................................................................................................221  21.10.1  Establecer el Generador......................................................................................................................222  21.10.2  Algoritmo Hi/Lo .....................................................................................................................................222  21.10.3  Algoritmo UUID ......................................................................................................................................223  21.10.4  Generador UniqId ..................................................................................................................................224  21.10.5  Generador Native...................................................................................................................................224  21.10.6  Columnas Identidad y Secuencias ..................................................................................................224  21.11  Convenciones en Identificadores ......................................................................................................225  21.12  Los Meta‐datos en ActiveRecordMetadata ...................................................................................226  21.12.1  Tipos de Meta­Datos Almacenados................................................................................................226  21.12.2  Meta­Datos en etapas de Desarrollo .............................................................................................227  21.12.3  API de ActiveRecordMetaData.........................................................................................................227  21.13  Cursores y Resulsets de Consultas ...................................................................................................229  21.13.1  Utilizar el cursor como tipo Forward­Only ................................................................................229  21.13.2  Utilizar el cursor como Scrollable ..................................................................................................229  21.13.3  API de ActiveRecordResulset ............................................................................................................230  21.14  Mensajes de ActiveRecord ...................................................................................................................231  21.14.1  API de ActiveRecordMessage............................................................................................................232  21.15  Transacciones en ActiveRecord.........................................................................................................232  21.15.1  Administracion de Transacciones ..................................................................................................233  21.15.2  Sincronización de Recursos con Transacciones .......................................................................236  21.15.3  Consideraciones de Sincronización................................................................................................236  21.15.4  API de TransactionDefinition...........................................................................................................239  21.15.5  API de ActiveRecordTransaction ....................................................................................................239  21.15.6  Timeouts en Transacciones...............................................................................................................240  21.16  Validadores de Integridad de Datos.................................................................................................241  21.16.1  Validadores para atributos No­Nulos...........................................................................................243  21.16.2  Tratar el resultado de un proceso de Validación.....................................................................243  21.16.3  Validadores de Usuario .......................................................................................................................245  21.16.4  Eventos en la Validación.....................................................................................................................246  21.16.5  Implementar un evento de validación..........................................................................................249  21.16.6  Detener/Cancelar una operación...................................................................................................250  21.16.7  Establecer un evento con un nombre no estándar..................................................................250  21.16.8  Evento cuando el proceso de validación detiene la operación ..........................................251  21.16.9  Deshabilitar eventos de validación................................................................................................252 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                8 

21.17  Llaves Foráneas Virtuales.....................................................................................................................252  21.17.1  Crear una llave foránea virtual.......................................................................................................253  21.17.2  Opciones de las llaves foráneas .......................................................................................................254  21.18  Entidades Temporales ...........................................................................................................................255  21.18.1  Crear un TemporaryActiveRecord .................................................................................................256  21.18.2  Comportamiento de un TemporaryActiveRecord....................................................................256  21.18.3  Transacciones con Entidades Temporales .................................................................................257  21.18.4  Usar un TemporaryActiveRecord ...................................................................................................257  21.19  ActiveRecordJoin......................................................................................................................................259  21.19.1  Agrupamientos con ActiveRecordJoin ..........................................................................................262  21.19.2  Parámetros de ActiveRecordJoin ....................................................................................................262  21.20  ActiveRecordUnion .................................................................................................................................263  21.21  SessionRecord ...........................................................................................................................................263  21.22  PropertyAccessors y Mutators ...........................................................................................................264  21.23  DynamicUpdate y DynamicInsert .....................................................................................................264  21.24  Manejo de Excepciones..........................................................................................................................265  21.24.1  Capturar excepciones dentro de modelos ...................................................................................266  21.24.2  Información de Excepciones .............................................................................................................266  21.25  Plugins de Modelos..................................................................................................................................266  21.25.1  Crear un Plugin de ActiveRecord ....................................................................................................267  21.26  Organización de Modelos......................................................................................................................267  21.27  Auto‐inicialización de Modelos ..........................................................................................................268  21.27.1  Activar inicialización dinámica.......................................................................................................269 

22  Componente EntityManager ............................................................................... 270  22.1  Introducción..................................................................................................................................................270  22.2  Obtener una nueva instancia de un Modelo....................................................................................270  22.3  API del Componente EntityManager ..................................................................................................271  22.3.1  Métodos para inicializar modelos y obtener instancias de ellos .........................................271  22.3.2  Métodos para administrar relaciones de multiplicidad..........................................................272  22.3.3  Métodos adminitrar para Entidades Temporales......................................................................273  22.3.4  Origenes de datos .....................................................................................................................................274  22.3.5  Administrar generadores de entidades ..........................................................................................274  22.3.6  LLaves foráneas virtuales.....................................................................................................................274  23  Componente TransactionManager ...................................................................... 276  23.1  Introducción..................................................................................................................................................276  23.2  Contexto de Scope Persistente..............................................................................................................276  23.3  Event Listeners ............................................................................................................................................276  23.4  Estados de las entidades..........................................................................................................................277  23.5  Asignar el objeto al estado administrado.........................................................................................277  23.6  API de TransactionManager...................................................................................................................278  24  Presentación....................................................................................................... 279  24.1  Introducción..................................................................................................................................................279  25  Componente View .............................................................................................. 280  25.1  Introducción..................................................................................................................................................280  25.2  Jerarquía de vistas en la presentación...............................................................................................280  25.2.1  Vista Principal ...........................................................................................................................................281  25.2.2  Requerimientos de la Vista Principal ..............................................................................................282  25.2.3  Requerimientos Vistas a nivel de Controlador ............................................................................282  25.2.4  Requerimientos de Layouts de Controladores.............................................................................283 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                9 

25.2.5  Requerimientos de Vistas Parciales en Controladores.............................................................283  25.2.6  Requerimientos de Vistas Parciales Generales............................................................................283  25.2.7  Requerimientos de Plantillas ó Templates....................................................................................284  25.3  Inserción automática y manual de vistas .........................................................................................284  25.4  Implementar los tipos de vistas............................................................................................................285  25.5  Transferir valores del controlador a la vista ..................................................................................288  25.5.1  Transferir mediante atributos públicos .........................................................................................288  25.5.2  Transferir mediante setParamToView ...........................................................................................289  25.6  Controlar Niveles de Renderización...................................................................................................290  25.7  Utilizar modelos en la presentación ...................................................................................................291  25.8  Plugins de View............................................................................................................................................291  25.8.1  Crear un Plugin de View ........................................................................................................................291  25.9  API del Componente View.......................................................................................................................292  25.9.1  Jerarquia de renderización ..................................................................................................................292  25.9.2  Administrar presentación.....................................................................................................................292  25.9.3  Visualizar vistas programacionalmente........................................................................................293  25.10  Crear un componente de Presentación personalizado............................................................294  25.11  Crear un componente de presentación de Excepciones no capturadas...........................295  25.12  Integrar otros Engines de presentación.........................................................................................296  25.12.1  Comportamiento de la integración................................................................................................296  25.12.2  Componentes Soportados...................................................................................................................296 

26  Componente Tag................................................................................................. 299  26.1  Introducción..................................................................................................................................................299  26.2  Establecer el valor de helpers creados con Tag.............................................................................299  26.3  Comportamiento de helpers ..................................................................................................................300  26.4  API del Componente Tag .........................................................................................................................300  26.4.1  Crear enlaces..............................................................................................................................................300  26.4.2  Componentes de interfaz de usuario ...............................................................................................303  26.4.3  Componentes de listas/combos..........................................................................................................304  26.4.4  Tratamiento de etiquetas META .......................................................................................................310  26.4.5  Tratamiento e Inclusión de archivos CSS.......................................................................................310  26.4.6  Componentes para fechas.....................................................................................................................311  26.4.7  Incluir recursos Javascript ...................................................................................................................312  26.4.8  Interacción con la presentación ........................................................................................................313  27  Helpers JavaScript............................................................................................... 315  27.1  Introducción..................................................................................................................................................315  27.2  Clase Format .................................................................................................................................................315  27.2.1  Instanciando la clase ..............................................................................................................................315  27.2.2  Funciones de Format ..............................................................................................................................317  27.3  Clase Validator .............................................................................................................................................318  27.3.1  Instanciando la clase ..............................................................................................................................318  28  Componente PDFDocument................................................................................ 320  28.1  Introducción..................................................................................................................................................320  28.2  Crear un documento PDF ........................................................................................................................320  28.3  Agregar una tabla al documento ..........................................................................................................320  28.4  Tipos de Papel Soportados .....................................................................................................................322  28.5  API de PdfDocument..................................................................................................................................322  29  Componente Report ........................................................................................... 329  29.1  Introducción..................................................................................................................................................329 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

29.2  29.3  29.4  29.5  29.6  29.7 

 

                                                                10 

Alcance del componente..........................................................................................................................329  Adaptadores de Report ............................................................................................................................329  Paginación en reportes.............................................................................................................................331  Ejemplo de un listado usando Report................................................................................................331  Modo Vista Previa.......................................................................................................................................332  API de Report................................................................................................................................................333 

30  Componente Feed............................................................................................... 334  30.1  Introducción..................................................................................................................................................334  30.2  Leer/Importar documentos RSS ..........................................................................................................334  30.3  Crear documentos RSS .............................................................................................................................334  30.4  API de Feed....................................................................................................................................................335  30.4.1  API de FeedItem ........................................................................................................................................336  31  Componente Core ............................................................................................... 338  31.1  Introducción..................................................................................................................................................338  31.2  Jerarquía de Clases .....................................................................................................................................338  31.2.1  Clase Object.................................................................................................................................................338  31.2.2  CoreConfig ...................................................................................................................................................338  31.2.3  CoreLocale...................................................................................................................................................338  31.2.4  CoreClassPath ............................................................................................................................................338  31.2.5  CoreRemote.................................................................................................................................................338  31.3  Servicios del Componente Core............................................................................................................338  31.3.1  Obtener el Instance Name ....................................................................................................................338  31.3.2  Zona Horaria de las Aplicaciones......................................................................................................339  31.3.3  Cambiar el Charset de la aplicación.................................................................................................339  31.3.4  Cambiar la localización por defecto ................................................................................................340  31.3.5  Obtener la versión del Framework ...................................................................................................340  31.4  Subcomponente CoreConfig...................................................................................................................341  31.4.1  API del subcomponente CoreConfig .................................................................................................341  31.5  Subcomponente CoreClassPath............................................................................................................342  31.5.1  Reemplazar un componente del Framework...............................................................................342  31.5.2  API de CoreClassPath..............................................................................................................................343  31.6  Subcomponente CoreType......................................................................................................................343  31.6.1  API de CoreType........................................................................................................................................343  31.7  Crear Plugins de Aplicación....................................................................................................................344  31.7.1  Crear un Plugin de Aplicación ............................................................................................................344  32  Componente PluginManager .............................................................................. 346  32.1  Introducción..................................................................................................................................................346  32.2  Arquitectura de Plug‐Ins .........................................................................................................................346  32.3  Autoinicialización de Plug‐Ins...............................................................................................................346  32.4  API de PluginManager ..............................................................................................................................346  33  Internacionalización y Localización...................................................................... 349  33.1  Introducción..................................................................................................................................................349  34  Componente Locale ............................................................................................ 350  34.1  Introducción..................................................................................................................................................350  34.2  Definir la localización en una sesión de Usuario...........................................................................350  34.2.1  Obtener la localización adecuada.....................................................................................................350  34.3  Establecer la localización por defecto................................................................................................351  34.4  Obtener traducciones localizadas........................................................................................................351 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                11 

34.5  API del Componente Locale....................................................................................................................352  34.6  Subcomponente LocaleMath..................................................................................................................356  34.6.1  API de LocaleMath ...................................................................................................................................356 

35  Componente Traslate.......................................................................................... 358  35.1  Introducción..................................................................................................................................................358  35.2  Adaptadores soportados por Traslate...............................................................................................358  35.3  Como funciona la traducción .................................................................................................................358  35.4  Utilizar traducciones .................................................................................................................................359  35.4.1  Consideraciones para el adaptador Array ....................................................................................360  35.4.2  Consideraciones para el adaptador Csv .........................................................................................360  35.4.3  Consideraciones para el adaptador Ini...........................................................................................360  35.4.4  Consideraciones para el adaptador Database ............................................................................360  36  Componente Date............................................................................................... 361  36.1  Introducción..................................................................................................................................................361  36.2  Porque debe usar este componente ...................................................................................................361  36.3  Timestamps ilimitados .............................................................................................................................361  36.4  Establecer el Timezone ............................................................................................................................362  36.5  Obtener partes ó fragmentos de fechas ............................................................................................362  36.6  Posición en el Tiempo ...............................................................................................................................363  36.7  Información de Fechas .............................................................................................................................364  36.8  Cambiar fragmentos de la fecha ...........................................................................................................365  36.9  Operaciones con fechas............................................................................................................................366  36.10  Localización de Fechas...........................................................................................................................367  36.11  Establecer el formato de la fecha ......................................................................................................368  36.12  Obtener la fecha y hora mundial .......................................................................................................370  37  Componente Currency ........................................................................................ 371  37.1  Introducción..................................................................................................................................................371  37.2  Cantidades usando el formato adecuado..........................................................................................371  37.3  Simbolo y nombre de la moneda utilizada.......................................................................................371  37.4  Versiones escritas de cantidades .........................................................................................................372  37.5  API del Componente Currency..............................................................................................................373  38  Componente ApplicationMonitor ....................................................................... 375  38.1  Introducción..................................................................................................................................................375  38.2  Infraestructura de Eventos comunes .................................................................................................375  38.3  Componentes de la Infraestructura de Eventos ............................................................................376  38.3.1  CommonBaseEvent..................................................................................................................................376  38.3.2  Emmiter........................................................................................................................................................376  38.3.3  Event Service ..............................................................................................................................................376  38.4  ¿Porque usar monitorización? ..............................................................................................................376  38.4.1  Determinación de problemas..............................................................................................................376  38.4.2  Sintonización del Rendimiento...........................................................................................................376  38.4.3  Confiabildad de la Operación..............................................................................................................377  38.5  ¿Qué se puede monitorear?....................................................................................................................377  39  Componente CommonEvent ............................................................................... 378  39.1  Introducción..................................................................................................................................................378  40  Componentes de Propósito General.................................................................... 379  40.1  Introducción..................................................................................................................................................379 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                12 

41  Componente Config ............................................................................................ 380  41.1  Introducción..................................................................................................................................................380  41.2  Adaptadores de Config .............................................................................................................................380  41.2.1  Adaptador de configuración Ini.........................................................................................................380  41.2.2  Adaptador de configuración XML .....................................................................................................381  41.2.3  Adaptador de configuración Arrays de PHP ................................................................................381  41.2.4  Adaptador de configuración Yaml....................................................................................................382  41.2.5  Leer archivos de configuración ..........................................................................................................382  41.2.6  Ejemplo: Leer un archivo de configuración ..................................................................................382  42  Componente Extensions ..................................................................................... 383  42.1  Introducción..................................................................................................................................................383  42.2  Cargar una extensión dinámicamente ...............................................................................................383  42.3  Cargar una extensión estáticamente ..................................................................................................383  42.3.1  Cargar componentes de Zend Framework ....................................................................................384  42.4  Cargar archivos individuales al iniciar la petición .......................................................................384  42.5  Obtener información de extensiones cargadas..............................................................................384  42.6  Inyección de componentes .....................................................................................................................385  43  Componente Logger............................................................................................ 386  43.1  Introducción..................................................................................................................................................386  43.2  Adaptadores de Logger ............................................................................................................................386  43.3  Tipos de Eventos en Logs ........................................................................................................................389  43.4  Logger Facilities ..........................................................................................................................................390  43.5  Transacciones con Logs ...........................................................................................................................391  43.6  API de FileLogger........................................................................................................................................392  43.7  Uso de MailLogger ......................................................................................................................................393  43.8  Uso de DatabaseLogger............................................................................................................................394  43.9  Uso de CompressedLogger .....................................................................................................................394  43.10  Uso de SAMLogger ...................................................................................................................................396  43.11  Uso de StreamLogger..............................................................................................................................396  43.12  Uso de SocketLogger...............................................................................................................................398  44  Componente Utils ............................................................................................... 399  44.1  Introducción..................................................................................................................................................399  44.2  API de Utils ....................................................................................................................................................399  45  Rendimiento y Optimización ............................................................................... 401  45.1  Introducción..................................................................................................................................................401  45.2  Consideraciones de Rendimiento ........................................................................................................401  45.2.1  Utilización de parámetros por nombre ..........................................................................................401  45.2.2  Instalar un Cache de OpCode ..............................................................................................................401  45.2.3  Sintonización del Servidor Web .........................................................................................................402  45.2.4  Sintonización de PHP..............................................................................................................................403  46  Componente Cache............................................................................................. 404  46.1  Introducción..................................................................................................................................................404  47  Componente Compiler ........................................................................................ 405  47.1  Introducción..................................................................................................................................................405  47.2  Teoria de optimización avanzada........................................................................................................406  47.2.1  Optimización de ciclos............................................................................................................................406  47.2.2  Optimización por evaluación de terminos estáticos.................................................................406 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                13 

47.3  Comportamiento de Compiler...............................................................................................................406  47.3.1  Optimizaciones básicas de la compilación....................................................................................406  47.3.2  Optimizaciones avanzadas de la compilación.............................................................................407  47.4  Generar una Compilación........................................................................................................................408  47.5  Limitaciones de Compiler........................................................................................................................408 

48  Componente GarbageCollector ........................................................................... 409  48.1  Introducción..................................................................................................................................................409  48.2  ¿Porque usar este componente?...........................................................................................................409  48.3  Como funciona el GarbageCollector....................................................................................................409  48.3.1  Fase de Compresión.................................................................................................................................409  48.3.2  Fase de Eliminación.................................................................................................................................409  48.4  Activar el GarbageCollector....................................................................................................................410  48.4.1  Activación de manera programacional..........................................................................................410  48.4.2  Activación de manera declarativa....................................................................................................410  48.5  Parámetros del Collector.........................................................................................................................410  48.6  API de GarbageCollector ..........................................................................................................................411  49  Componente Session........................................................................................... 412  49.1  Introducción..................................................................................................................................................412  49.2  Adaptadores de Sesión .............................................................................................................................413  49.2.1  Adaptador de Sesión Memcache ........................................................................................................414  49.2.2  Adaptador de Sesión Database...........................................................................................................414  49.2.3  Adaptador de sesión Files .....................................................................................................................414  49.2.4  Adaptador de sesión Louder Cache ..................................................................................................415  49.3  Comportamiento de Sesiones................................................................................................................415  49.4  Consideraciones de Seguridad ..............................................................................................................415  49.5  Variables de sesión.....................................................................................................................................416  49.5.1  API del Componente Session................................................................................................................416  49.6  SessionNamespace .....................................................................................................................................417  49.6.1  API de SessionNameSpace ....................................................................................................................418  50  Herramientas del Desarrollador .......................................................................... 420  50.1  Introducción..................................................................................................................................................420  51  Errores y Excepciones.......................................................................................... 420  51.1  Introducción..................................................................................................................................................420  51.2  Modo SUPER_STRICT ................................................................................................................................421  51.3  Capturar excepciones de gravedad leve ...........................................................................................421  52  Componente Debug ............................................................................................ 423  52.1  Introducción..................................................................................................................................................423  52.2  Seguimiento al estado de variables.....................................................................................................423  52.3  Visualizar la traza del seguimiento de un valor.............................................................................424  52.4  Detener un proceso mediante Aserciones .......................................................................................425  52.5  Establecer una acción a ejecutar al finalizar el proceso de debug ........................................426  53  Test de Unidad.................................................................................................... 427  53.1  Introducción..................................................................................................................................................427  53.2  Tests para Componentes .........................................................................................................................427  54  Componente Script ............................................................................................. 428  54.1  Introducción..................................................................................................................................................428 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                14 

55  Apendices ........................................................................................................... 429  55.1  Estándares de Codificación.....................................................................................................................429  55.1.1  Objetivos.......................................................................................................................................................429  55.1.2  Formato de Archivos PHP.....................................................................................................................429  55.1.3  Clases .............................................................................................................................................................429  55.1.4  Interfaces .....................................................................................................................................................429  55.1.5  Métodos.........................................................................................................................................................429  55.1.6  Variables ......................................................................................................................................................430  55.1.7  Constantes ...................................................................................................................................................430  55.1.8  Boleanos y valores nulos .......................................................................................................................430  55.1.9  Literales de Cadenas de Caracteres..................................................................................................430  55.1.10  Substituciones de variables ...............................................................................................................430  55.2  Licencia de este Documento...................................................................................................................430  55.2.1  Creative Commons Attribution 3.0 ...................................................................................................430                                                 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                15 

1 Prefacio El presente documento es documento todo‐en‐uno de guía de referencia, API y tutorial para el  desarrollo  de  aplicaciones  usando  Kumbia  Enterprise  Framework.  El  prefacio  contiene  información sobre las convenciones utilizadas para desarrollar este texto. 

1.1 Antes de Leer este Documento Antes  de  leer  este  texto  usted  debe  tener  un  buen  conocimiento  de  lenguaje  PHP,  programación  orientada  a  objetos,  tecnologías  para  desarrollo  Web  como  HTML,  CSS,  JavaScript y otras como XML, AJAX, SQL, así como conocimientos en bases de datos y sistemas  operativos. 

1.2 Como esta organizado este Documento Kumbia Enterprise es un framework robusto para el desarrollo de aplicaciones empresariales  usando  tecnologia  abierta  para  ambientes  con  altos  requerimientos  de  estabilidad,  rendimiento  y  escalabilidad.  Toda  su  robustez  esta  plasmada  en  este  extenso  documento  y  espera ofrecer toda la información posible para el entendimiento y aprovechamiento de esta  plataforma.    El documento ofrece una referencia de cada componente, junto con ejemplos y la API de cada  uno. Se busca que relacione la arquitectura de los componentes y como se integran unos con  otros en forma de servicios.     La  primera  parte  explica  para  que  y  donde  puede  utilizar  Kumbia  Enteprise  Framework  características,  su  instalación  y  la  arquitectura  de  las  aplicaciones  como  introducción  al  contexto de desarrollo e implementación.      El capitulo de Tutorial realiza la creación de una aplicación completa paso a paso como caso  de estudio, integrando los diferentes componentes y aplicando la mayor parte del Framework  como base ilustrativa del mismo.    La segunda parte detalla la capa de lógica de dominio explicando todo lo relacionado con la  orquestación de controladores y servicios Web.    La tercera parte explica cada componente y características de seguridad en el framework. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                16 

  La cuarta parte habla de la lógica de datos y detalla términos de persistencia, concurrencia y  transacciones.    La  quinta  parte  explica  las  características  y  componentes  de  internacionalización  y  localización  que  permiten  adaptar  aplicaciones  a  condiciones  especificas  geográficas,  políticas, culturales ó regionales.    La  sexta  parte  presenta  los  componentes  de  la  capa  de  presentación  y  las  herramientas  de  interacción con el usuario final hacia la aplicación.    La séptima parte explica componentes de monitorización y componentes de propósito general  para el desarrollo de aplicaciones Web.    La octava parte explica los componentes que ayudan a mejorar el rendimiento y optimización  de aplicaciones.    La novena parte detalla el componente de administración, contexto y persistencia de sesiones  de usuario.    La  décima  parte  son  las  herramientas  del  desarrollador  como  test  de  unidad,  debug  de  procesos y datos, generación de código etc. 

1.3 Convenciones Tipográficas La siguiente tabla describe las condiciones tipográficas usadas en este texto:    Fuente  AaBbCdDeFf 

Significado 

Ejemplo 

Hace  referencia  a  extranjerismos  del  El  servidor  de  directorios  lenguaje castellano que hacen referencia  LDAP  a  componentes,  productos,  marcas,  nombres de métodos ó módulos. 

AaBbCdDeFf

Hace  referencia  a  código  fuente  ó  <?php sentencias SQL. 

AaBbCdDeFf

$filter = new Filter();

Hace  referencia  a  Pseudocódigo  para  valor := LLamarFuncion();


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                17 

representar  fragmentos  de  código  ó  procedimientos en lenguaje humano.   

1.4 A Quien está Orientado este Texto Este  documento  está  orientado  a  personas  que  deseen  aprender  en  forma  profunda  las  capacidades  de  Kumbia  Enterprise  Framework  para  el  desarrollo  de  aplicaciones,  soporte  a  software existente y/o extender el mismo. 

1.5 Información sobre marcas y productos referenciados Las  siguientes  son  marcas  de  productos  referenciados  que  pertenecen  a  otras  compañias  y  son mencionadas en este documento:    Excel  ,  Windows,  SQL  Server  y  Word  son  marcas  registradas  de  Microsoft  Corporation  en  estados unidos y otros países.  Oracle  es una marca registrada de Oracle Corporation en estados unidos y otros países.  Informix  es una marca registrada de IBM en estados unidos y otros países.  DB2  es una marca registrada de IBM en estados unidos y otros países.  Adobe  Acrobat    es  una  marca  registrada  de  Adobe  Corporation  en  estados  unidos  y  otros  países.  Windows  es  una  marca  registrada  de  Microsoft  Corporation  en  estados  unidos  y  otros  países.  Mac OS X es una marca registrada de Apple en estados unidos y otros países. 

1.6 Referencias a sitios web de terceros Algunas  URLs  son  referenciadas  en  este  documento  y  proporcionan  información  asociada  a  estas.    Nota:  LouderTechnology  no  se  hace  responsable  por  la  disponibilidad  de  sitios  web  de  terceros  mencionados  en  este  documento.  LouderTechnology  no  se  hace  responsable  por  el  contenido,  publicidad,  productos  ó otros materiales que estén disponibles en estos  sitios.  LouderTechnology  no se hace responsable por daños ó perdidas causadas bajo ó sin conexión con el contenido en esos  sitios y recursos.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                18 

1.7 Sus comentarios están bienvenidos En LouderTechnology estamos interesados en el mejoramiento la documentación de nuestros  y  sus  productos  y  proyectos,  por  esto  sus  comentarios  están  siempre  bienvenidos.  La  referencia  de este documento es KEF‐1108. Escriba a support@loudertechnology.com                                                             


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                19 

Capítulo Introducción   

2 Introducción Kumbia Enterprise es un framework PHP cuyo principal objetivo es la practicidad y facilidad  de uso, sin dejar de darle importancia al rendimiento, robustez, profesionalismo y calidad de  una  aplicación  orientada  a  la  Web.  Esta  implementado  usando  la  versión  5.2  de  PHP  y  está  completamente orientado a Objetos. Los componentes están integrados y optimizados lo cual  aumenta el rendimiento interno del framework y de las aplicaciones desarrolladas con él.  El  framework  adicionalmente  permite  usar  componentes  independientes  y  librerías  de  terceros e integrarlas a las aplicaciones desarrolladas.  Kumbia Enterprise Framework es una versión modificada del Kumbia Framework Comunitario  versión  0.5,  el  cuál  ha  sido  estabilizado  y  refactorizado  para  aumentar  su  robustez  y  velocidad.  La  versión  comunitaria  es  punto  fundamental  de  innovación  y  desarrollo  para  la  constante  integración  a  la  versión  creada  por  LouderTechnology.  El  objetivo  de  este  framework  es  fortalecer  el  desarrollo  de  aplicaciones  de  negocios  orientadas  a  una  presentación  Web  que  funcionen  tanto  en  Intranets  como  en  Internet.  La  creación  de  sitios  Web usando Kumbia Enterprise es posible, aunque pueda encontrar otras herramientas  más  indicadas y ligeras para esta tarea.   El presente documento explica en forma detallada cada componente del framework. 

2.1 Diferencias con la versión Comunitaria La  versión  modificada  que  desarrollamos  en  Louder  Technology  ha  pasado  por  un  riguroso  proceso  de  estabilización  y  calidad  que  exigen  entornos  de  producción  para  aplicaciones  de  alta disponibilidad.  Beneficios clave al usar Kumbia Enterprise:  •

Reducción de costos operacionales cuando se implementan grandes sistemas 

Capacidad de escalamiento mejorada (clusterización, cache distribuido) 

La posibilidad de obtener soporte en diferentes niveles que mitigue el riesgo y ayude a  eliminar el lock‐in de proveedores de herramientas de desarrollo de software. 

Integrar  las  aplicaciones  con  código  PHP5  existente  incluyendo  otros  frameworks  como Zend Framework.  


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                20 

Facilidades  en  la  integración  requerida  para  implementar  arquitecturas  orientadas  a  servicios (SOA). 

  Otras mejoras esta versión:   •

Soporte para múltiples aplicaciones certificado  

Estructura de archivos optimizada para múltiples aplicaciones  

Soporte para Transacciones de Alto y Bajo nivel 

Adaptadores de conexión a gestores relacionales certificados 

Requerimientos de hardware reducidos en un 40%  

Adaptadores de Manejadores de Sesión escalables  

Políticas de Seguridad con adaptadores para gestores relacionales, LDAP, Kerberos5 y  otros  

2.2 Licencia Los  modelo  de  negocios  open‐source  está  diseñado  para  permirle  tanto  a  usted  como  a  sus  socios  expandirse  desde  pequeñas  instalaciones  hasta  las  más  grandes  sin  generarle  sobrecostos adicionales.     Kumbia Enterprise Framework es un proyecto de software abierto con una licencia apta para  negocios  aprovada  por  la  OSI  (http:///www.opensource.org)  llamada  New  BSD  y  que  se  entrega con la distribución del framework.    Soporte comercial para desarrollo, producción y entrenamiento están disponibles a través de  LouderTechnology.                 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                21 

3 Instalación 3.1 Introducción Kumbia  Enterprise  Framework  requiere  de  PHP  versión  5.2.0  ó  superior  para  un  funcionamiento optimo. El framework requiere del Apache Web Server preferiblemente en su  versión 2.0 ó 2.2 y del modulo mod_rewrite instalado para su correcto funcionamiento.    Kumbia Enterprise Framework soporta adicionalmente Microsoft Internet Information Services  (IIS) desde la versión 6.0 utilizando el modulo del servidor ISAPI_Rewrite.    Al  descargar  el  paquete  de  Kumbia  Enterprise  Framework  este  debe  ser  descomprimido  y  ubicado en la raíz de documentos del servidor Web  ó en un subdirectorio de este, este puede  variar de acuerdo a la plataforma ó distribución utilizada. 

3.2 Configuración con Apache Web Server 2.x Kumbia  Enterprise  Framework  implementa  soporte  para  Smart  URLs  lo  cual  las  hace  más  familiares  y  humanas  para  los  usuarios  finales.  Para  esto  es  necesario  instalar  el  modulo  de  Apache llamado mod_rewrite que realiza la reescritura de las URLs a una convención interna  en  el  framework,  esto  es  vital  para  la  correcta  implementación  del  patrón  arquitectacional  Model‐View‐Controller.  Apache  proporciona  el  comando  a2enmod  en  la  mayoría  de  distribuciones  Linux,  mediante  este comando se puede habilitar fácilmente el modulo, después solo es necesario reiniciar el  servidor Web.  Con el usuario administrador root utilizamos el comando así:   # a2enmod rewrite # /etc/init.d/apache2 restart

  En algunos sistemas como RedHat/Fedora el comando para reiniciar el servidor es:     # service httpd restart

  Para  Microsoft  Windows  es  necesario  habilitar  el  modulo  directamente  en  el  archivo  de  configuración de Apache. Para esto se quita el comentario dejando que el modulo de Apache  Web Server sea cargado:  


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                22 

LoadModule rewrite_module modules/mod_rewrite.so

  Las  reglas  de  reescritura  del  framework  deben  ser  leídas  por  Apache  y  ejecutadas  en  cada  petición a la aplicación. Para esto es necesario habilitar la lectura de los archivos .htaccess ó  agregar las reglas al archivo de configuración de Apache.    La  ubicación  del  archivo  httpd.conf  ó  default‐server.conf  puede  variar  de  acuerdo  a  la  distribución Linux ó el sistema operativo.    Tabla:  Directorio  de  publicación  web  y  configuración  del  servidor  en  diversas  plataformas  Distribución  

Ubicación  

Directorio Raíz Web  

RedHat Enterprise 4/5   /etc/httpd/conf/httpd.conf   /var/www/html   OpenSuSE 

/etc/apache2/default‐

10.1/10.2/10.3/11  

server.conf  

Ubuntu/Debian   MacOS  X  (Leopard  10.5)  usando  MAMP   Windows XP/2003  usando XAMPP  

/srv/www/htdocs/  

/etc/apache2/sites‐

/var/www  

available/default   /Applications/MAMP/conf/ apache/httpd.conf   c:\Archivos 

de 

Programa\xampp\apache\c onf\httpd.conf  

/Applications/MAMP/htdocs/  

c:\Archivos 

de 

Programa\xampp\apache\htdocs\  

  Las  reglas  de  reescritura  de  mod_rewrite  pueden  ir  en  los  archivos  .htaccess  incluidos  en  el  framework  ó  en  los  archivos  de  configuración  de  Apache  Web  Server.  Las  siguientes  reglas  deben pertenecer al archivo .htaccess ó al directorio raíz donde esta el framework:   <IfModule mod_rewrite.c> RewriteEngine on RewriteRule ^$ public/ [L] RewriteRule (.*) public/$1 [L] </IfModule>

  Las segundas reglas de configuración deben ir en el archivo .htaccess ubicado en el directorio  public/ así:  


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                23 

  <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?url=$1 [QSA,L] </IfModule>

Cuando  utilizamos  archivos  .htaccess  es  necesario  habilitar  las  opciones  AllowOverride  All  y  Options All para el directorio raíz del Web Server en el archivo de configuración de Apache.  Cuando  agregamos  la  configuración  directamente  a  los  archivos  de  Apache  Web  Server  debemos usar la directiva Directory así:     Tabla: Parámetros de configuración de Apache Web Server directamente en httpd.conf  <Directory "/srv/www/htdocs/application"> <IfModule mod_rewrite.c> RewriteEngine on RewriteRule ^$ public/ [L] RewriteRule (.*) public/$1 [L] /IfModule> </Directory> <Directory "/srv/www/htdocs/application/public"> <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?url=$1 [QSA,L] </IfModule> </Directory>

  Si  no  requerimos  de  la  utilización  de  archivos  .htaccess  es  recomendable  desabilitarlos  mediante  AllowOverride  None,  de  esta  forma  evitamos  que  el  servidor  Web  busque  este  archivo  en  cada  directorio  en  cada  petición  Web  aumentando  considerablemente  el  rendimiento de las aplicaciones.  También  es  importante  revisar  que  el  archivo  index.php  sea  el  primero  en  la  directiva  DirectoryIndex, así Apache Web Server le dará más prioridad antes de otras extensiones:   DirectoryIndex index.php index.html

Después de realizar la configuración es necesario reiniciar el servidor Web. 

3.3 Configuración con Microsoft IIS e ISAPI Rewrite Para  esto  debemos  agregar  al  archivo  httpd.ini  del  directorio  raíz  del  paquete  Kumbia  lo  siguiente:     Ejemplo: Parámetros de configuración para Microsoft IIS  [ISAPI_Rewrite] RewriteCond URL (?!/javascript/|/img/|/files/|/css/|/temp/).*


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

RewriteRule RewriteCond RewriteRule RewriteCond RewriteRule

 

                                                                24 

(.*?\.php)(\?[^/]*)?/([^/]*)/(.*) $1(?2$2&:\?url=/$3/$4) URL (?!/javascript/|/img/|/files/|/css/|/temp/).* ^/(.*) /public/index.php?url=/$1 [L] URL (?!/javascript/|/img/|/files/|/css/|/temp/).* /(.*) /public/$1

Enlaces Relacionados   •

Configuración de Apache en RedHat Enterprise

PHP sobre Microsoft IIS  

PHP sobre Apache 2.x sobre Windows  

PHP sobre Apache 2.x sobre Unix/Linux  

Instalando ISAPI Rewrite en Microsoft IIS  

  

3.4 Configuración de PHP La siguiente configuración es opcional para Aplicaciones Web con Kumbia. A continuación se  listan los parámetros de configuración del php.ini:    Tabla: Parámetros de configuración de PHP opcionales  Nombre  

Descripción   Permite usar las etiquetas especiales de php <?= y <. No se recomienda 

short_open_tag  

si va a redistribuir sus aplicaciones en servidores de terceros. No es un  estándar profesional de PHP el uso de estas etiquetas.   Permite  que  al  generarse  un  error  se  muestren  las  rutas  y  archivos 

display_errors  

donde se generan errores PHP, es útil en entornos development pero  no en modo production.  

memory_limit  

En  entornos  de  producción  64M  es  un  número  adecuado  para  este  parámetro por script. Debe ser ajustada de acuerdo a las circustancias.  Kumbia Enterprise Framework esta desarrollado bajo nivel de reporte 

error_reporting  

E_ALL  |  E_NOTICE  |  E_STRICT  lo  que  asegura  la  calidad  del  código  y  cumplimiento de estándares básicos de desarrollo OOP en PHP5   Permite  que  el  contenido  de  las  superglobales  se  convierta  en 

register_globals  

variables locales. En general se debe dejar deshabilitado ya que no es  seguro de muchas formas.  

magic_quotes_gpc  

Al estar en On podría ayudar a evitar ataques de inyección de SQL, al  mismo tiempo hace que el rendimiento del servidor sea algo menor.  

session.use_only_coo Cuando  tiene  valor  1  ayuda  a  evitar  considerablemente  ataques  de 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

kies  

 

                                                                25 

inyección de SQL y XSS.  

 

3.5 Configuración con Zend Application Server Zend  Application  Server  es  un  servidor  para  aplicaciones  PHP  basado  en  Apache  Web  Server  por lo tanto su configuración es similar.     Puede seguir los pasos de configuración de Apache y reproducirlos en Zend Server. El módulo  rewrite ya está activado por defecto lo que los pasos de configuración deben ser minimos. 

3.6 Crear una Instancia de Kumbia Enterprise El  framework  se  distribuye  en  un  archivo  comprimido  multi‐plataforma  que  contiene  la  estructura  de  archivos  del  framework  y  recursos  necesarios  para  el  desarrollo,  prueba  e  implementación de aplicaciones en Kumbia Enterprise.    El nombre del archivo tiene la siguiente estructura kumbia­ef­version­madurez­extension.   

 

3.7 Solución a problemas de instalación Las siguientes situaciones se pueden presentar al realizar la instalación de una instancia del  framework:    Situación: No tiene Mod­ReWrite de Apache instalado  El servidor web no tiene el modulo rewrite instalado, consulte la sección “Configuración con  Apache Web Server 2.x” en el capítulo de instalación. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                26 

  Situación:  En  la  pantalla  se  presenta  el  mensaje  “No  se  pudo  utilizar  reescritura  de  URLs”   Se debe verificar lo siguiente:    

Si  se  usa  Apache  Web  Server  el  archivo  '.htaccess'  debe  estar  presente  en  la  raíz  del 

directorio donde está la instancia del framework ó las reglas en este deben estar activas  en la configuración del servidor web.  

Apache Web Server soporta archivos de sobreescritura de configuración '.htaccess'.  

La  opción  de  configuración  de  Apache  'AllowOverride  All'  no  está  presente  para  las 

opciones de configuración del DocumentRoot del servidor web.    Situación:  Al  ingresar  a  la  aplicación  por  defecto  se  presenta  una  pantalla  blanca  sin  ningún mensaje    La  directiva  del  servidor  Web  de  archivos  por  defecto  le  está  dando  prioridad  al  archivo  index.html y no al index.php. En el caso de Apache Web Server esto se soluciona mediante la   opción de configuración DirectoryIndex.    Situación:  Al  ingresar  a  la  aplicación  se  genera  la  excepción  “CoreException:  El  directorio public/temp no tiene permisos de escritura”  Esta excepción se genera cuando el directorio public/temp es un directorio de solo lectura ó  no  tiene  permisos  de  escritura  para  el  usuario  con  el  que  se  ejecuta  el  proceso  del  servidor  web.    Situación: Al ingresar a la aplicación se genera la excepción “CoreException: Debe tener  instalado PHP version 5.20 ó superior para utilizar este framework”  La versión de PHP que tiene instalada es igual ó superior a la versión 5.0 pero es inferior a la  5.2.0. La versión 5.2.0 en adelante corrige errores importantes de seguridad en en núcleo de  PHP y tiene un mejor rendimiento.    Situación: Al ingresar a la aplicación se genera la excepción “CoreException: Timezone  inválido”  Ha  definido  una  zona  horaria  en  el  archivo  config/config.ini  inválido  por  lo  que  muchas 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                27 

opciones del framework generarán información erronea.    Situación: Al ingresar a la aplicación se genera la excepción “RouterException: No se ha  indicado la aplicación por defecto en config/config.ini (defaultApp)”  La  opción  defaultApp  en  el  archivo  de  configuración  de  la  instancia  no  existe  ó  define  una  aplicación que no existe en la instancia del framework.    Situación:  Al  ingresar  a  la  aplicación  se  genera  la  excepción:  “CoreConfigException:  Debe indicar el nombre de la aplicación dende está el archivo 'config.ini'”  La  opción  defaultApp  en  el  archivo  de  configuración  de  la  instancia  no  existe  ó  define  una  aplicación que no existe en la instancia del framework.                                             


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                28 

4 ¿Qué es Kumbia Enterprise Framework? 4.1 Sobre Aplicaciones Web Cuando  la  web  se  empezó  a  tomar  más  en  serio,  no  solo  para  presentar  sitios  Web  con  contenido  estático  ó  simplemente  informativo  y  se  dio  paso  a  la  prestación  de  servicios  con  contenido  dinámico,  la  estructuración  y  profesionalización  de  las  aplicaciones  Web  se  hace  evidente  como  una  forma  de  ofrecer  calidad  y  confiabilidad  a  clientes,  proveedores,  inversionistas,  empleados  y  todo  el  entorno  de  las  empresas  y  organizaciones  en  forma  novedosa y eficiente.     La aceptación general del lenguaje PHP como herramienta especializada en el entorno Web y  su  amplio  desenvolvimiento  así  como  sencillez  de  uso,  han  aportado  considerablemente  al  crecimiento y capacidad de implementación de alta tecnología en la Web.    Kumbia  Enterprise  es  un  paso  adelante  en  la  evolución  de  los  frameworks  y  de  PHP  como  plataforma de desarrollo de carácter general.  

4.2 Sobre PHP y la Web A  través  de  los  años  PHP  se  ha  convertido  en  un  estándar  de  facto  para  la  construcción  de  software para Internet de alta escalabilidad y velocidad. Muchos de los sitios más populares y  concurridos en la actualidad incluyendo Wikipedia, Yahoo! y Facebook.   

4.3 Introducción Kumbia Enterprise Framework es un conjunto de tecnologías para la producción de software  que  integra  una  novedosa  plataforma  de  middleware  proporcionando  servicios  de  persistencia,  transacciones,  mensajes  y  clustering  a  aplicaciones  basadas  en  PHP  que  esten  orientadas a la Web.     Por años la madurez del desarrollo empresarial en PHP ha evolucionado incrementalmente y  hoy  en  día  se  cuenta  con  productos  maduros  que  pueden  proporcionar  alternativas  que  reduzcan  los  costos  de  tecnologías  de  información  y  puedan  ser  aplicados  a  entornos  empresariales desde la mediana y pequeña empresa hasta grandes aplicaciones orientadas al  cliente final.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                29 

Nuestra  plataforma  pretende  unificar  la  plataforma  tecnológica  de  backend  y  frontend  acelerando  los  procesos  de  desarrollo  e  implementación  de  software  usando  middleware  multiplataforma escalable con tecnologia open‐source. Para lograr esto una de nuestras fichas  claves es Kumbia Enterprise Framework.    Kumbia  Enterprise  es  un  framework  especialmente  orientado  al  entorno  empresarial,  que  implementa las mejoras prácticas de desarrollo de software y prácticas orientadas a las Web  de  la  actualidad  e  intenta  fomentar  principalmente  la  generación  de  aplicaciones  profesionales,  potentes,  seguras  y  mantenibles  en  el  tiempo  para  empresas  que  deseen  adoptar software abierto y tecnología PHP.     Gracias  al  apoyo  de  diferentes  empresas  patrocinadoras  y  de  LouderTechnology  ahora  es  posible implementar aplicaciones con una base de código más sólida, estable y funcional junto  con un servicio de soporte que asegure que su desarrollo y mejoramiento será continuo en el  tiempo. 

4.4 Características del Framework Sumadas a las de su hermano comunitario, Kumbia Enterprise Framework posee las siguientes  características:  •

Arquitectura Modelo‐Vista‐Controlador (Múltiples Aplicaciones extendible con Plugins  y Eventos) 

Contenedor para aplicaciones y servicios web 

Componente de Cacheo Flexible  

Object‐Relational‐Mapping  (ORM)  potente  y  robusto  (Transacciones,  Validadores,  Joins, Unions, Generadores, Multiplicidad de Relaciones, Herencia) 

Business Process Management (BPEL) 

Servicios Web (Integración y Orquestamiento) (Soap, SCA) 

Componente  de  Administrador  de  Sesión  (Session  Handling)  Flexible  (Memcached,  Database, LouderCache, Files) 

Componente  de  Autenticación  (LDAP,  Model,  KerberosV,  Radius)  con  soporte  para  Sesión Activa y Expiración de Sesión 

Componente de Access List Control (ACL) Flexible (Model, Memory, Xml) 

Componente de Auditoria de Sistemas  


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                30 

Sistema de Logging Flexible (File, Compressed, Mail, Database,Stream,SCA) 

Localización (Traducción, Fechas, Monedas) independiente de la plataforma  

Monitoreo de Aplicaciones (CommonEventInfrastructure) 

Componente para generación de reportes empresariales en múltiples formatos  (Pdf,  Excel, Html) 

Componente para implementación de servicios WebDAV  

Componentes de conexión a motores de base de datos certificados (Oracle y MySQL)  

Semi‐Compilador para el Framework y las aplicaciones 

GarbageCollector de Sesión 

Plantillas rápidas y flexibles  

Filtros y Validación Integrada  

Tests de Unidad 

Debug, Traza y Profiling avanzado 

Componente de Configuración Flexible (Ini, Xml, PHP) 

Documentos PDF con PdfDocument 

Integración con Louder Clustering Technology  

Integración con Louder Cache  

Integración con IBM WebSphere sMash 

4.5 PHP en entornos críticos El lenguaje PHP no ha tenido una gran participación en entornos de aplicaciones críticas y en  un  muchos  casos  ha  sido  relegado  a  la  creación  de  sitios  Web  y  portales.    Algunas  características del lenguaje PHP como la tipificación débil y su carácter interpretado pueden y  han hecho desconfiar a organizaciones en su implementación en software grande y complejo.    Kumbia  Enterprise  Framework  ha  sido  diseñado  para  mantener  estrictos  controles  de  validación  de  tipos  e  integridad  de  datos,  garantizando  en  gran  medida  que  los  procesos,  entrada y salida de datos, cumplan a satisfacción con los requerimientos de negocio sin perder  la potencia y capacidades para el desarrollo rápido que ofrece la tecnología PHP.    Proyectos y productos como APC (Alternative PHP Cache), Zend Optimizer, eAccelator, Zend  Guard  y  otros  más,  permiten  llevar  aplicaciones  en  PHP  a  un  carácter  semi‐interpretado  y  hasta proteger la propiedad intelectual del código fuente del software.    En  resumen  se  puede  decir  que  existe  actualmente  entornos  y  tecnología  que  permiten  el 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                31 

desarrollo e implementación satisfactoria de aplicaciones para entornos críticos basados en el  lenguaje PHP. 

4.6 Preguntas frecuentes sobre Kumbia Enterprise ¿Para qué otro framework PHP?  Como  se  ha  mencionado  anteriormente  PHP  ha  sido  un  lenguaje  usado  para  la  creación  de  software y sitios web. Los frameworks actuales han avanzado mucho en este sentido y ofrecen  todas  las  herramientas  necesarias  para  llevar  a  cabo  estos  proyectos.  La  inmediatez  en  el   desarrollo es algo que todos los desarrolladores PHP hoy en día normalmente buscan.     Por otro lado cuando el objetivo es desarrollar aplicaciones de misión critica, con procesos de  negocio  complejos,  cientos  ó  miles  de  usuarios,  concurrencia  muy  alta,  necesidad  de  integrarse a otros sistemas en otras plataformas de desarrollo y además se requiere que sean  monitorizadas y que se adapten rápidamente a la evolución de los requerimientos del negocio,  el panorama cambia.     Para asegurar el éxito de proyectos complejos de software, aparte de la inversión de recursos  de gerencia y administración, se requiere asegurar que esta inversión no se vaya a perder por  seleccionar las herramientas equivocadas para llevar a cabo el proyecto.     Es  difícil  determinar  cuando  un  proyecto  va  a  crecer  más  de  lo  que  se  espera  y  como  esto  puede  a  obligar  a  cambiar  sobre  el  camino  un  diseño  erroneo  ó  en  el  peor  de  los  casos  reescribir parte de los componentes de las aplicaciones para adaptarse a los cambios.    Kumbia Enterprise nació precisamente cuando un software en PHP tuvo que prepararse para  soportar  250.000  peticiones  diarias  (más  de  7  millones  al  mes),  15000  transacciones  y  además ofrecer funcionalidad reusable a otras aplicaciones haciendo más mantenible toda la  infraestructura de sistemas de una empresa.  La enseñanza: Es mejor pensar en grande ahora,  tardar un poco más en desarrollar y no preocuparse en el futuro por el crecimiento, ni en las  posibles  oportunidades  comerciales  ó  de  requerimientos  y  adaptabilidad  del  negocio  que  se  puedan presentar en el ciclo de vida de un conjunto de sistemas.    ¿Por qué un framework para SOA?  SOA es un concepto, no una tecnología. Un desarrollador puede implementar una arquitectura 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                32 

orientada  a  servicios  usando  otro  lenguaje  u  otro  framework,  no  necesariamente  debe  ser  Kumbia Enterprise.  SOA tampoco es apto para cualquier proyecto, esto debe ser una decisión  planeada y estrategica que beneficie y propenda por los objetivos de negocio de una empresa  u organización.     SOA  se  ha  convertido  en  un  estándar  de  la  industria  para  la  implementación  de  infraestructuras  de  sistemas  que  requieran  una  alta  reusabilidad  y  flexibilidad  de  los  componentes de las aplicaciones tanto internamente como externamente. Grandes compañias  de  software  como  IBM,  JBoss  y  Oracle  invierten  grandes  cantidades  de  recursos  en  el  desarrollo y mejoramiento de soluciones para empresas que busquen implementar este tipo  de arquitecturas.    Puede que tarde más tiempo en implementar una arquitectura eficiente y estable a partir de  componentes poco acoplados de otros frameworks generandole contratiempos y en el peor de  los casos perdidas en su inversión en IT. Kumbia Enterprise ha sido diseñado para facilitar la  definición  y  construcción  de  SOA  utilizando  el  lenguaje  PHP  mediante  un  contenedor  de  aplicaciones  y  servicios  web  diseñado  específicamente  para  este  tipo  de  arquitecturas  y  también para aplicaciones orientadas a la web comunes.    ¿Kumbia  Enterprise  ofrece  más  o  menos  funcionalidad  que  el  Kumbia  PHP  Comunitario?  Kumbia  Enterprise  es  un  proyecto  con  objetivos  claros  diferentes  por  los  que  trabaja  el  Kumbia  Comunitario  ó  otros  frameworks  como  Symfony  ó  CakePHP.  Este  framework  ha  implementado muchos de los componentes que se requieren para construir aplicaciones Web  pero además ofrece características empresariales únicas que facilitan el desarrollo de grandes  y  medianas  aplicaciones  con  procesos  de  negocio  complejos  y  que  debido  a  su  naturaleza  requieran de alguna funcionalidad especifica del framework.    ¿Por  qué  Kumbia  Enterprise  no  parece  ser  completamente  libre  y  manejado  por  la  comunidad como lo es el Kumbia PHP Comunitario?  Kumbia Enterprise tiene una licencia abierta llamada New BSD que ofrece libertades similares  a  la  LGPL.    El  desarrollador  no  tiene  problema  en  crear,  distribuir  y  comercializar  software  basado en el framework gracias a esta licencia.   LouderTechnology busca liderar y asegurar el desarrollo activo y mejoramiento continuo del 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                33 

framework permitiendo que empresas y desarrolladores adopten el software tranquilamente  y  se  puedan  enfocar  en  sus  propias  aplicaciones  ofreciendo  el  espacio  para  que  puedan  retroalimentar aportar y colaborar  al proyecto retroactivamente.    ¿Trabajo  ó  he  trabajado  en  Zend  Framework,  como  puedo  integrarlo  con  Kumbia  Enterprise?  Los  componentes  del  Zend  Framework  pueden  ser  integrados  a  Kumbia  Enterprise  cargandolos  como  extensiones  ya  sea  estáticamente  ó  dinámicamente.    Componentes  de  usuario pueden registrar componentes de auto‐carga de zend ó hacer uso de los mismos.    ¿Conozco  ó  he  trabajado  desarrollando  en  Java,  que  puedo  esperar  de  Kumbia  Enterprise?  Este framework ha sido diseñado para ser familiar en muchos aspectos a los desarrolladores  Java  y  también  a  los  desarrolladores  PHP.  Kumbia  Enterprise  tiene  estrictos  controles  de  validación  en  busca  de  encontrar  más  problemas  y  de  tratar  de  identificar  potenciales  posibles problemas que puedan tener los componentes desarrollados.     Kumbia  Enterprise  además  permite  ejecutar  aplicaciones  bajo  IBM  WebSphere  sMash  permitiendo integrar código nativo Java en aplicaciones PHP y viceversa aprovechando código  y experiencia existente del desarrollador.                              


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                34 

5 Arquitectura 5.1 Introducción Kumbia Enterprise permite el desarrollo de aplicaciones en varias capas esto permite romper  un  sistema  en  subsistemas  más  pequeños  reduciendo  la  complejidad  del  mismo  y  proporcionando importantes beneficios.     Cuando  se  trabaja  con  un  sistema  multi‐capa  se  entiende  que  existen  capas  de  alto  nivel  y  otras  de  menor  nivel,  las  de  mayor  nivel  aprovechan  la  funcionalidad  implementada  en  las  capas inferiores ocultando detalles que no requieren de un entendimiento inmediato aunque  reduciendo la flexibilidad en una u otra medida.    Los principales beneficios de implementar sistemas multi‐capa son:    •

Es posible trabajar sobre una capa superior sin necesidad de conocer como funcionan  las capas inferiores. Cuando desarrolla con Kumbia Enterprise utiliza una capa de alto  nivel que aumenta la productividad sin requerir el entendimiento en profundidad de   comportamientos ó funcionalidad de bajo nivel.  

Una capa puede ser sustituida por otra manteniendo una interface consistente que se  adapte a necesidades especificas sin modificar la aplicación por completo. 

5.2 Capas en una Aplicación Una aplicación Web desarrollada en Kumbia se separa en 3 capas principales llamadas: Lógica  de Dominio, Persistencia y Presentación.     La  lógica  de  dominio  ó  de  negocio  es  quien  dicta  las  reglas  sobre  como  debe  trabajar  la  aplicación  en  si.  Constituye  todo  lo  que  tiene  que  ver  con  cálculos  de  entrada  de  datos,  validaciones, procesos y como se presentaran los datos en la capa de presentación.    La persistencia y/ó lógica del modelo de datos trata sobre como la lógica de dominio requiere  de  los  datos  que  le  proporcionan  servicios  de  bases  de  datos,  sistemas  de  transacciones,  mensajes, sistemas de archivos, etc.    La  presentación  trata  de  todos  aquellos  elementos  que  permiten  la  interacción  entre  el 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                35 

usuario final y la aplicación. En una aplicación Web se refiere además a las tecnologías de lado  del  cliente  como  CSS  ó  JavaScript,  los  navegadores,  los  lenguajes  de  marcas  y  de  transformación.    Cada capa mencionada anteriormente ofrece servicios y tiene responsabilidades diferentes en  una  aplicación  empresarial,  la  clara  separación  de  estas  capas  es  fundamental  para  un  desarrollo  satisfactorio.  Los  componentes  para  la  administración  y  uso  de  cada  capa  son  proporcionados por el framework así como servicios de integración entre ellos también.   

5.3 Usando Modelo-Vista-Controlador Las  aplicaciones  en  Kumbia  utilizan  el  patrón  arquitectacional  llamado  MVC.  Con  él  las  aplicaciones Web se pueden separar en 3 capas bien definidas ayudando a la mantenibilidad  de  la  misma  y  exigiendo  un  orden  y  claridad  que  con  el  tiempo  alarga  la  vida  útil  de  las  mismas.  •

Modelos: Representan la información sobre la cual la aplicación opera, las entidades y  su lógica de negocio. Contienen todas las validaciones, constraints y reglas que hacen  que  la  lógica  del  negocio  se  cumpla  y  haya  integridad  en  los  datos.  Corresponde  a  la  capa de persistencia. 

Vistas: Visualizan el modelo usando interfaces Web e interactuando con los usuarios  de éstas. Corresponde a la capa de Presentación. 

Controladores: Atienden, responden y enrutan las acciones solicitadas por el usuario  final  e  invocan  cambios  en  las  vistas  ó  en  los  modelos  según  sea  necesario.  Corresponde a la capa de lógica de dominio. 

Los  controladores  están  separados  en  partes,  llamadas  front  controller  y  en  un  conjunto  de  acciones. Cada acción puede interactuar de forma diferente de acuerdo al tipo de petición. Las  vistas están separadas en layouts, templates, vistas de acción y partials. El modelo ofrece una  capa de abstracción de la base de datos llamada ORM que además dan funcionalidad agregada  a datos de sesión y validación de integridad relacional. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                36 

  Este modelo ayuda a separar el trabajo de la lógica de negocios (modelos) y la presentación  (Vistas)    El controlador ayuda a ocultar los detalles de protocolo utilizados en la petición (HTTP, modo  consola, etc.) para el modelo y la vista. Finalmente, el modelo abstrae la lógica de datos, que  hace a los modelos independientes de las vistas.    Kumbia  Enterprise  Framework  agrega  componentes  y  plugins  que  interactúan  con  la  arquitectura de la aplicación.    Enlaces Relacionados   •

Modelo Vista Controlador  

5.4 Ventajas de usar MVC Al implementar el patrón arquitectacional MVC es posible separar claramente la forma en la  que  se  presenta  la  información,  de  la  forma  en  la  que  se  almacena,  de  la  forma  en  la  que  orquesta la lógica de la aplicación. De esta forma es menos complicado: 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                37 

  •

Detectar en que capa se esta generando un problema de la aplicación. Por ejemplo si  un  proceso  no  se  esta  ejecutando  correctamente  es  muy  probable  que  el  problema  este en el controlador. 

Si se agrega un nuevo constraint (restricción) al modelo de datos este se aplica a todo  el sistema inmediatamente. 

Si  los  diseñadores  requieren  trabajar  en  la  presentación  esto  es  posible  sin  que  se  afecte la lógica de negocio ó el modelo de datos. 

Definitivamente  la  aplicación  se  hace  más  mantenible  y  reusable  creando  unidades  que interactúan entre si y están separadas en forma lógica de manera clara. 

5.5 Arquitectura SOA La arquitectura SOA proporciona estrategias al desarrollo e integración de infraestructuras de  software que permiten utilizar la funcionalidad de un sistema como servicios interoperables.  Las  arquitecturas  SOA  permiten  el  intercambio  transparente  de  datos  entre  diferentes  aplicaciones.  Un  SOA  permite  que  haya  loose  coupling  de  servicios  entre  diferentes  aplicaciones, sistemas operativos y lenguajes de desarrollo.     Por  muchos  años  las  empresas  han  tratado  de  integrar  múltiples  aplicaciones  con  el  fin  de  apoyar  los  procesos  de  negocio  en  cada  uno  de  sus  departamentos  y  de  ofrecer  de  forma  automatizada información a sus proveedores y clientes.    Durante  estos  procesos  es  normal  encontrarse  con  inconvenientes  como  incompatibilidad  entre  lenguajes,  formatos,  plataformas,  etc.  Por  esto  la  industria  tecnológica  ha  creado  todo  tipo de estrategías que conlleven al mejoramiento y exito de este tipo de integraciones.      SOA  es  una  estrategía  que  no  es  aplicable  a  todo  tipo  de  organizaciones  pero  si  es  muy  recomendable.  En  el  mundo  PHP  esta  arquitectura  ha  sido  poco  adoptada  debido  a  su  poco  desarrollo, exploración y culturización. Actuamente PHP proporciona librerias y funcionalidad  que permite ofrecer servicios web usando diferentes protocolos, pero SOA es mucho más que  servicios web.    Los siguientes conceptos son parte de lo que representa una arquitectura SOA:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                38 

SOA  Governance:  Son  todas  las  actividades  relacionadas  a  tener  control  sobre  una  SOA.  En  términos  cortos  se  puede  decir  que  son  las  reglas  con  las  que  se  implementa  y  adopta  esta  arquitectura.    Orquestación y Coreografía de Servicios: Aunque no es directamente dependiente de una  SOA es fundamental cuando se implementan procesos de negocio complejos.    Business  Process  Management:  Permite  el  mejoramiento  y  optimización  de  procesos  de  negocio aprovechando la arquitectura en si misma.     Y  aunque  existen  muchos  más,  Kumbia  Enterprise  ha  trabajo  en  proporcionar  herramientas  que permitan la rápida adopción de un arquitectura orientada a servicios basada en PHP y su  objetivo es ofrecer un ambiente cada vez más robusto que permita lograr este objetivo. 

5.6 Beneficios de una SOA Las tres beneficios más importantes de adoptar una arquitectura SOA son:    •

Al  generar  cada  unidad  de  negocio  como  un  servicio  y  poder  usarlo  rápidamente  en  una aplicación, se promueve la agilidad al cambio en forma más efectiva que mediante  sistemas aislados . 

Al  utilizar  servicios  se  crean  abstracciones  autosuficientes  capaces  de  mejorarsen  afectando en forma positiva a sus dependencias en forma transparente. 

Los  servicios  son  en  cierta  forma  auto‐documentados  lo  cual  es  muy  importante  al  desarrollar sistemas flexibles y adaptables. 

5.7 SOA en Kumbia Enterprise En este apartado trataremos de ilustrar como Kumbia Enterprise mediante su contenedor de  servicios y aplicaciones permite la rápida adopción de SOA en una organización.    Controladores  Inteligentes:  Como  se  vió  anteriormente,  Kumbia  Enterprise  utiliza  el  concepto  de  controlador,  quienes  son  los  que  atienden  las  peticiones  realizadas  desde  el  cliente  y  ejecutan  la  lógica  de  negocio  adecuada  para  producir  una  salida  en  una  vista.  El  framework proporciona algo que hemos denominado “controladores inteligentes”.     


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                39 

Cuando  una  aplicación  en  Kumbia  Enterprise  recibe  una  petición  esta  es  analizada  para  determinar el tipo de cliente y tipo de respuesta adecuada que espera este cliente.     El siguiente diagrama muestra el funcionamiento del contenedor:   

  Según  el  diagrama  una  aplicación  puede  recibir  peticiones  de  diferentes  clientes  solicitando  respuestas adecuadas al tipo de cliente.  El diagrama separa a los clientes de las aplicaciones  en tres:    Usuarios Finales/Visitantes: Un usuario que utiliza la aplicación y que espera obtener una  respuesta humana que pueda entender para continuar realizando otro proceso.     Maquinas  Servicios  Web:  Maquinas  que  consumen  servicios  web  y  que  requieren  de  mantener sesiones conversacionales. Por ejemplo SOAP ó REST.    Maquinas  Proceso  de  Datos:  Clientes  web  que  solicitan  a  aplicaciones  datos  en  formatos  adecuados que puedan ser procesados por el mismo cliente. Por ejemplo JSON ó XML.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                40 

El contenedor de Kumbia Enterprise analiza el solicitud de respuesta  del cliente y transfiere  la  solicitud  al  controlador/accion  adecuado  que  en  cada  uno  de  los  casos  tendrá  un  tratamiento diferente.    La capa Enterprise Service Layer es opcional y cuando se accede directamente a la aplicación  esta no existe. La capa es el ESB (Enterprise Service Bus) el cual tiene un servicio registrado y  puede modificar y monitorizar el acceso a los servicios.    La capa Domain Layer es una super capa que abstrae la implementación de todos los procesos  de  negocio.  La  capa  Application  Layer  son  las  aplicaciones/controladores/servicios  como  tal  que componen el proceso de negocio requerido. 

5.8 Loose Coupling/Tight Coupling Uno  de  los  objetivos  de  diseño  de  Kumbia  Enterprise  Framework  es  buscar  que  el  arquitecto/desarrollador no tenga que integrar ningún componente para definir la estructura  de  su  aplicación  por  esta  razón  varios  componentes  son  dependientes  los  unos  de  los  otros  proporcionando un entorno ready­to­use donde sea posible desarrollar y ejecutar aplicaciones  empresariales favoreciendo principios de reusabilidad y rendimiento de cualquier aplicación.    Los  patrones  de  diseño  VirtualProxy  y  DependecyInjection  son  utilizados  para  permitirle  al  desarrollador reemplazar/integrar componentes escritos por terceros a la aplicación.    Muchos otros componentes están pensados en ser débilmente acoplados ó loose coupling de  tal forma que puedan ser integrados a otras aplicaciones escritas en otros frameworks.     Kumbia  Enterprise  Framework  ofrece  avanzada  funcionalidad  cuyo  nivel  de  madurez  es  similar ó superior al de otros frameworks PHP actuales.               


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                41 

Capítulo Tutorial   

6 Caso de Uso: Aplicación de Cajero Bancario 6.1 Introducción En  el  presente  capitulo  del  manual  de  referencia  se  tratará  de  ilustrar  con  un  ejemplo  de  aplicación las principales características del Framework en un ejemplo práctico.    La  idea  es  crear  una  aplicación  que  sirva  como  un  futuro  cajero  electrónico  virtual  para  un  banco llamado Central Bank. Las reglas del negocio son las siguientes:    •

Los  clientes  del  banco  pueden  entrar  a  la  sucursal  virtual  usando  el  número  de  su  identificación personal y la clave de alguna de sus tarjetas. 

Una vez autenticados los clientes pueden consultar sus extractos, hacer transferencias  a otras cuentas y revisar su saldo. 

  El  desarrollo  e  implementación  de  aplicaciones  bancarias  exige  requerimientos  altísimos  de  seguridad,  prestaciones,  alta  disponibilidad,    infraestructura  de  redes  y  probablemente  la  implementación de muchas reglas financieras y bancarias para que el sistema sea funcional y  usable. Sin embargo, para que nuestro ejemplo no sea eterno y no se salga de contexto, vamos  a crear un sistema muy simplificado pero que sirva para entender los conceptos y entorno de  trabajo con el Framework.    Puede que sea necesario entender los conceptos de ORM (ActiveRecord) y el funcionamiento  del componente Controller y View, para una mayor comprensión del presente Tutorial. 

6.2 Análisis de los Requerimientos Haciendo un análisis más profundo del tema identificamos las siguientes entidades:    •

Clientes: Son el usuario final de la aplicación y se asume que habrá una entidad donde  se mantendrá la información asociada a ellos. 

Cuentas:  Manejan  el  saldo  actual  de  la  cuenta,  su  saldo  en  canje  y  su  relación  a  clientes. 

Movimiento:  Almacena  un  log  de  las  operaciones  realizadas  por  el  cliente  en  sus 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                42 

cuentas y será utilizado para generar los extractos del cliente.  •

Intereses: Son los intereses ganados por el cliente cada día que tiene su dinero en el  banco. 

Sucursales: Es la ubicación en la que se realiza la transacción bancaria. 

  Para desarrollar el ejemplo se utiliza una base de datos usando el RBDM MySQL 5.0, esta base  de datos es multiplataforma y se instala fácilmente en la mayor parte de sistemas operativos.  El nombre de la base de datos será ‘bankdb’. Creamos la base de datos así:    CREATE DATABASE nombre_bd CHARACTER SET utf8;

  La estructura de las tablas será la siguiente:    Tabla Customer: Administra la información de los clientes del banco    CREATE TABLE `customer` ( `id` int(11) NOT NULL auto_increment, `identification` varchar(20) NOT NULL, `sucursal_id` int(11) NOT NULL, `name` varchar(120) NOT NULL, `email` varchar(52) default NULL, `created_at` datetime default NULL, `status` char(1) default NULL, PRIMARY KEY (`id`), KEY `sucursal_id` (`sucursal_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Descripción de los campos:  Campo 

Descripción 

id 

Es la llave primaria de la tabla y es auto numérica. 

identification 

Es el numero de identificación de la persona. 

sucursal_id 

Es el código de la sucursal donde se creó la cuenta. 

name 

Es el nombre de la persona 

email 

Es el correo electrónico del cliente 

created_at 

Es la fecha en la que se creó el cliente en la base de datos 

status 

Es el estado del cliente en el banco. (A)ctivo ó (I)nactivo 

  Tabla Account: Administra la información de las cuentas y sus saldos    CREATE TABLE `account` ( `id` int(11) NOT NULL auto_increment, `number` int(22) NOT NULL, `password` varchar(40) NOT NULL,


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                43 

`sucursal_id` int(11) NOT NULL, `customer_id` int(11) NOT NULL, `balance` decimal(30,6) NOT NULL, `swap_balance` decimal(30,6) NOT NULL, `type` char(1) NOT NULL, `created_at` datetime default NULL, `status` char(1) default NULL, PRIMARY KEY (`id`), KEY `clientes_id` (`customer_id`), KEY `sucursal_id` (`sucursal_id`), CONSTRAINT `account_ibfk_1` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`id`), CONSTRAINT `account_ibfk_2` FOREIGN KEY (`sucursal_id`) REFERENCES `sucursal` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  Descripción de los campos:    Campo 

Descripción 

id 

Es la llave primaria de la tabla y es auto numérica. 

number 

Es el número de la cuenta 

password 

Es el resumen SHA1 de la clave de la cuenta 

sucursal_id 

Es la sucursal en donde se creó la cuenta. 

customer_id 

Es el cliente al que pertenece la cuenta 

balance 

Es el saldo que tiene la cuenta. 

swap_balance 

Es el saldo que tiene en canje. 

type 

Indica si la cuenta es de ahorros ó corriente. 

created_at 

Es la fecha en la que se creó la cuenta en la base de datos 

status 

Es el estado del cliente en el banco. (A)ctivo ó (I)nactivo 

  Tabla Movement: Administra la información de los movimientos realizados en las cuentas    CREATE TABLE `movement` ( `id` int(11) NOT NULL auto_increment, `account_id` int(11) NOT NULL, `ubication_id` int(11) NOT NULL, `cash` decimal(30,6) NOT NULL, `created_at` datetime default NULL, PRIMARY KEY (`id`), KEY `account_id` (`account_id`), KEY `ubication_id` (`ubication_id`), CONSTRAINT `movement_ibfk_2` FOREIGN KEY (`ubication_id`) REFERENCES `ubication` (`id`), CONSTRAINT `movement_ibfk_1` FOREIGN KEY (`account_id`) REFERENCES `account` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  Descripción de los campos:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

Campo 

 

                                                                44 

Descripción 

id 

Es la llave primaria de la tabla y es auto numérica. 

account_id 

Es la cuenta en la que se realizó el movimiento 

ubication_id 

Es la ubicación en la que se generó el movimiento 

cash 

Es el monto por el que se realizó el movimiento 

created_at 

Es la fecha en la que se creó la cuenta en la base de datos 

  Tabla Sucursal: Administra la información de las sucursales del banco    CREATE TABLE `sucursal` ( `id` int(11) NOT NULL auto_increment, `name` varchar(120) NOT NULL, `ubication_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `id` (`id`), KEY `ubication_id` (`ubication_id`), CONSTRAINT `sucursal_ibfk_1` FOREIGN KEY (`ubication_id`) REFERENCES `ubication` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  Descripción de los campos:    Campo 

Descripción 

id 

Es la llave primaria de la tabla y es auto numérica. 

name 

Nombre  de la sucursal 

ubication_id 

Es la ubicación donde se encuentra la sucursal 

  Tabla  Ubication:  Administra  la  información  de  las  ubicaciones  donde  se  pueden  realizar  operaciones bancarias.    CREATE TABLE `ubication` ( `id` int(11) NOT NULL auto_increment, `name` varchar(120) NOT NULL, PRIMARY KEY (`id`), KEY `id` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  Descripción de los campos:  Campo 

Descripción 

id 

Es la llave primaria de la tabla y es auto numérica. 

name 

Nombre  de la Ubicación 

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                45 

6.3 Esqueleto de la Aplicación Una  vez  creado  el  modelo  de  datos  generamos  el  esqueleto  de  aplicación  donde  irá  ubicado  los  archivos  fuente  de  la  arquitectura  MVC.  Para  esto  debemos  crear  un  directorio  llamado  ‘bank’  en  apps  y  los  subdirectorios  controllers,  config,  models  y  views.  Una  forma  rapida  de  crear el esqueleto de la aplicación es utilizar el script create_application.php en modo consola:    Al ubicarse dentro del directorio donde esta la instancia del Framework usamos el comando:    php script/create_application.php –name bank

  El nombre del directorio que tiene el Framework se llama ‘example’. La siguiente estructura  de archivos se ha creado:    example/ apps/ default/ bank/ controllers/ application.php config/ boot.ini config.ini environment.ini routes.ini logs/ models/ base/ modelBase.php views layouts/ index.phtml

Una vez definida la estructura de directorios de la aplicación es posible empezar a desarrollar  sobre ella. La aplicación se encuentra en entorno de desarrollo y todo lo relacionado con ello  esta activado por defecto. 

6.4 Configurar la conexión a la base de datos Para  empezar  a  probar  los  controladores  y  la  iteración  con  los  modelos  es  necesario  configurar la conexión a la base de datos que se va a utilizar en el entorno de desarrollo. Para  esto se edita el archivo de configuración environment.ini creado en el directorio config:    [development] database.host = localhost database.username = root database.password = 2fe0517 database.name = bankdb database.type = mysql

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                46 

Estos  parámetros  serán  usados  en  toda  la  aplicación  para  conectarse  a  la  base  de  datos  de  desarrollo. Kumbia Enterprise Framework permite definir una arquitectura de 3 capas en caso  de que se necesite utilizar la base de datos en un servidor externo al de desarrollo. 

6.5 Crear los modelos de Base de Datos Un  modelo  debe  ir  ubicado  en  el  directorio  models  de  la  aplicación.  Los  nombres  de  los  archivos de modelos “deben” tener el nombre de la tabla a mapear (esto es una convención).  En  cada  archivo  debe  existir  una  sola  clase  con  el  nombre  del  modelo  usando  notación  camelizada. Las clases de modelos “deben” heredar de la clase ActiveRecord.    Un  ejemplo  de  un  modelo  de  la  tabla  ubication  es  el  archivo  models/ubication.php  que  implementa la clase Ubication así:    <?php class Ubication extends ActiveRecord { }

Al definir un modelo con una implementación de atributos ‘vacía’ se indica a ActiveRecord que  debe crear los atributos de la tabla en forma dinámica y por lo tanto la visibilidad de esta será  pública. En general esto no es una buena practica de desarrollo ya que se deja al descubierto  la  privacidad  de  los  valores  de  los  campos  sin  que  haya  ningún  control  en  su  acceso.    Para  solucionar esto e implementar un modelo más seguro se hace así:    <?php class Ubication extends ActiveRecord { protected $id; protected $name; public function getId(){ return $this->id; } public function setId($id){ $this->id = $id; } public function getName(){ return $this->name; } public function setName($name){ $this->name = $name; } }


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                47 

Los  getters  y  setters  proporcionan  puntos  unificados  para  obtener/establecer  los  valores  internos del modelo. En general, cada tabla que se utilice en la aplicación debe ser mapeada  por un modelo en la misma. El script create_all_models.php permite crear todos los modelos de  la base de datos actual implementando cada clase como se vió en el ejemplo anterior. El uso  del script es el siguiente:    php scripts/create_all_models.php –-application bank

  Adicional  a  los  getters/setters  generados,  el  script  agrega  los  PHPDocs  a  cada  método  y  atributo con lo que se mejora la documentación del sistema y si se utilizan IDEs como Zend  Studio ó Eclipse estos comentarios son leídos ayudando a autocompletar el código cuando sea  posible.    El modelo para la tabla customer generado es:    <?php class Customer extends ActiveRecord { /** * @var integer */ protected $id; /** * @var string */ protected $identification; /** * @var integer */ protected $sucursal_id; /** * @var string */ protected $name; /** * @var string */ protected $email; /** * @var Date */ protected $created_at; /** * @var string */ protected $status; /** * Metodo para establecer el valor del campo id


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                48 

* @param integer $id */ public function setId($id){ $this->id = $id; } /** * Metodo para establecer el valor del campo identification * @param string $identification */ public function setIdentification($identification){ $this->identification = $identification; } /** * Metodo para establecer el valor del campo sucursal_id * @param integer $sucursal_id */ public function setSucursalId($sucursal_id){ $this->sucursal_id = $sucursal_id; } /** * Metodo para establecer el valor del campo name * @param string $name */ public function setName($name){ $this->name = $name; } /** * Metodo para establecer el valor del campo email * @param string $email */ public function setEmail($email){ $this->email = $email; } /** * Metodo para establecer el valor del campo created_at * @param Date $created_at */ public function setCreatedAt($created_at){ $this->created_at = $created_at; } /** * Metodo para establecer el valor del campo status * @param string $status */ public function setStatus($status){ $this->status = $status; } /** * Devuelve el valor del campo id * @return integer */ public function getId(){ return $this->id; } /** * Devuelve el valor del campo identification * @return string */ public function getIdentification(){ return $this->identification; } /** * Devuelve el valor del campo sucursal_id


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                49 

* @return integer */ public function getSucursalId(){ return $this->sucursal_id; } /** * Devuelve el valor del campo name * @return string */ public function getName(){ return $this->name; } /** * Devuelve el valor del campo email * @return string */ public function getEmail(){ return $this->email; } /** * Devuelve el valor del campo created_at * @return Date */ public function getCreatedAt(){ return new Date($this->created_at); }

}

/** * Devuelve el valor del campo status * @return string */ public function getStatus(){ return $this->status; }

6.6 Crear el Inicio de Sesión El inicio de sesión para el usuario final de la sucursal virtual según los requerimientos de la  aplicación, es una pantalla en donde el cliente deberá ingresar su documento personal junto  con alguna de las claves de las cuentas asociadas a ese documento.    Según la arquitectura MVC los controladores son el punto de entrada a cualquier acción que se  realice  en  la  aplicación,  aunque  de  momento  el  primer  requerimiento  nos  hace  pensar  en  presentación  antes  de  ‘lógica  del  negocio’  empezaremos  creando  un  controlador  que  no  implemente ningún tipo de lógica por ahora:    El controlador creado se llama login y el archivo donde se implementa la clase controladora es  el archivo controllers/login_controller.php y de momento contiene lo siguiente:    <?php class LoginController extends ApplicationController { public function indexAction(){


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                50 

} }

La  implementación  ‘vacía’  de  la  acción  ‘index’  permite  que  la  presentación  (la  vista  se  visualice) en cuanto se invoca el controlador.    Ya  que  ‘login’  será  el  controlador  por  defecto  de  la  aplicación  se  implementa  el  método  ControllerBase::init de la siguiente forma:    <?php class ControllerBase { public function init(){

}

//Enrutar al controlador login Router::routeTo("controller: login"); }

Según las convenciones en la arquitectura MVC del Framework la vista para la acción ‘index’  del controlador ‘login’ se crea en el archivo views/login/index.phtml.    La interfaz presenta una campo de texto donde es posible ingresar el documento del cliente y  otra para la clave numérica de 4 dígitos.    <h1>Bienvenido a Central Bank</h1> <?php echo Tag::form("login/validateCredentials") ?> <table> <tr> <td align='right'><b>Documento Identificaci&oacute;n:</b></td> <td><?php echo Tag::textField("identification", "size: 20", "maxlength: 20") ?></td> </tr> <tr> <td align='right'><b>Contrase&ntilde;a:</b></td> <td><?php echo Tag::numericPasswordField("password", "size: 4", "maxlength: 4") ?></td> </tr> <tr> <td></td> <td><?php echo Tag::submitButton("Entrar") ?></td> </tr> </table> <?php echo Tag::endForm() ?>

Ambos campos son requeridos y por lo tanto se validan como requeridos en el controlador. La  validación  también  se  puede  hacer  en  JavaScript,  sin  embargo  estamos  haciendo  un  sistema  confiable y no podemos confiar en lo que ocurra en el cliente.  <?php

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                51 

class LoginController extends ApplicationController { public function indexAction(){ } public function validateCredentialsAction(){ $rules = array( "identification" => array( "filter" => "alpha", "message" => "Por favor indique su documento de identificación" ), "password" => array( "filter" => "int", "message" => "Por favor indique su contraseña" ), ); if($this->validateRequired($rules)==true){ //Aquí viene la autenticación } else { $this->routeTo("action: index"); } } }

  La  utilización  del  método  heredado  validateRequired  permite  validar  el  tipo  de  dato  y  comprobar si el usuario ha ingresado algún valor en estos campos. Los valores de los campos  son filtrados usando el componente Filter antes de validar si están presentes en la entrada de  usuario.    Si  la  validación  falla  el  flujo  de  ejecución  se  enruta  nuevamente  a  la  acción  index.  Ahora  se  modifica la vista para mostrar al usuario los mensajes generados en la validación.    <h1>Bienvenido a Central Bank</h1> <?php foreach(View::getValidationMessages() as $message){ Flash::error($message->getMessage()); } ?> <?php echo Tag::form("login/validateCredentials") ?> <table> <tr> <td align='right'><b>Documento Identificaci&oacute;n:</b></td> <td><?php echo Tag::textField("identification", "size: 20", "maxlength: 20") ?></td> </tr> <tr> <td align='right'><b>Contrase&ntilde;a:</b></td> <td><?php echo Tag::numericPasswordField("password", "size: 4", "maxlength: 4") ?></td> </tr> <tr> <td></td> <td><?php echo Tag::submitButton("Entrar") ?></td> </tr> </table> <?php echo Tag::endForm() ?>


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                52 

  El método estático View::getValidationMessages() permite obtener los mensajes obtenidos en  la  validación.  Cuando  el  proceso  de  validación  es  satisfactorio  se  puede  continuar  con  el  proceso de autenticación.  

6.7 Autenticando al Cliente El  requerimiento  del  banco  exige  que  la  implementación  de  la  autenticación  se  haga  de  la  siguiente forma:    •

Validar que exista un cliente con el documento ingresado 

Validar que la clave proporcionada corresponda al menos a una cuenta del cliente 

  Los modelos Customer y Account contienen los datos requeridos para efectuar esta operación.  La acción modificada validateCredentials queda así:    public function validateCredentialsAction(){ $rules = array( "identification" => array( "filter" => "alpha", "message" => "Porfavor indique su documento de identificación" ), "password" => array( "filter" => "int", "message" => "Porfavor indique su contraseña" ), ); if($this->validateRequired($rules)){ $identification = $this->getPostParam("identification", "alpha"); $password = sha1($this->getPostParam("password", "int")); $customer = $this->Customer>findFirst("identification='$identification' AND status=’A’"); if($customer!==false){ $successAuth = false; $accounts = $this->Account->find("customer_id = '{$customer>getId()}' AND status=’A’"); foreach($accounts as $account){ if($password==$account->getPassword()){ $successAuth = true; break; } } if($successAuth==false){ $this->addValidationMessage("Documento/Password Incorrectos"); $this->routeTo("action: index"); } else { Session::set(“existsValidUser”, true); $userData = SessionNamespace::add('UserData'); $userData->setCustomer($customer->getId()); $userData->setLogInTime(time()); $this->routeTo("controller: menu"); } } else { $this->addValidationMessage("Documento/Password


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                53 

Incorrectos"); $this->routeTo("action: index"); } } else { $this->routeTo("action: index"); } }

  En  el  anterior  procedimiento  se  ilustran  varios  aspectos  de  un  procedimiento  usando  el  Framework:    •

Para  recuperar  los  valores  que  vienen  del  formulario  se  utiliza  el  método  getPost.  Como  primer  parámetro  se  pasa  el  nombre  del  campo  usado  en  el  formulario.  Adicionalmente se puede aplicar un filtro para asegurar que la entrada si es segura y  corresponde al tipo de dato esperado. 

Para acceder a cualquier modelo basta con invocarlo usando $this dentro de cualquier  acción del Framework. El nombre de la variable corresponde al nombre de la clase que  utiliza el modelo. 

El método del modelo findFirst busca un registro ó como su traducción dice “buscar el  Primero”.  La  condición  permite  obtener  el  registro  deseado.  Este  método  devuelve  false cuando no encuentra registros con las condiciones indicadas. 

El  método  find  realiza  una  búsqueda  de  varios  registros,  la  condición  permite  filtrar  solo  los  registros  de  las  cuentas  asociadas  al  cliente.  Cuando  no  encuentra  registros  devuelve  un  vector  vacío,  en  caso  contrario  el  resultado  de  find  es  un  Objeto  de  la  clase  ActiveRecordResulset  que  implementa  el  patrón  Recordset,  es  decir  una  representación en memoria del resultado devuelto por la base de datos. 

La  variable  $successAuth  sirve  como  variable  bandera  para  identificar  si  se  ha  encontrado una cuenta con la contraseña proporcionada. 

Para obtener los valores de los campos del modelo es necesario usar los getters en el  caso de customer se uso getId() para obtener el id del registro que se consultó. 

Las claves en la tabla Account son resúmenes usando el algoritmo sha1. 

Para  agregar  un  mensaje  de  validación  personalizado  se  puede  usar  el  método  addValidationMessage el cual también es usado internamente por validateRequired. 

Cuando falla algún requisito del proceso se muestra el mensaje y se enruta a la acción  index lo que le permitirá al usuario final reingresar la información. 

Cuando el documento de identificación y la clave son correctos se crea una variable de  sesión mediante Session::set, esta es llamada existsValidUser y se le asigna valor “true”.  Esta  variable  indica  a  lo  largo  de  la  aplicación  que  existe  un  usuario  valido 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                54 

autenticado. 

6.8 Un Menú para la Aplicación Para organizar las opciones que utiliza el usuario final se crea un menú y se implementa de tal  forma  que  siempre  sea  visible  por  el  usuario  final  durante  todo  el  tiempo  que  ejecute  la  aplicación. Como se vió en el procedimiento de autenticación, cuando esta es satisfactoria el  flujo  de  ejecución  es  redireccionado  al  controlador  “menu”.  La  implementación  de  este  controlador  carece  de  lógica  de  negocio  alguna  y  muestra  la  vista  que  permite  al  cliente  escoger la opción que desea:    El  script  de  ayuda  del  Framework  llamado  create_controller  permite  la  creación  del  controlador:    php scripts/create_controller.php --application bank –-name menu

  Como resultado se obtiene el codigo generado:    <?php class MenuController extends ApplicationController { public function indexAction(){ } }

La  jerarquía  de  vistas  implementada  en  el  componente  View  permite  que  la  presentación  correspondiente  a  un  controlador  sea  compartida  por  otros,  por  esto  se  ha  creado  el  menú  enlazando cada opción en el layout del controlador.    El archivo views/layouts/menu.phtml queda así:    <h1>Cajero Virtual</h1> <b>Men&uacute; Principal:</b> <ul> <li><?php echo Tag::linkTo("banking/checkBalance", "Ver Saldo") ?></li> <li><?php echo Tag::linkTo("banking/showTransactionActivity", "Ver Extractos Bancarios") ?></li> <li><?php echo Tag::linkTo("transfer", "Transferencias") ?></li> <li><?php echo Tag::linkTo("logout", "Salir del Banco") ?></li> </ul>

El  uso  del  helper  Tag::linkTo  permite  crear  un  enlace  al  controlador  requerido  y  utilizar  un  label  para  indicar  el  texto  asociado  a  él.  La  ventaja  de  utilizar  este  tipo  de  helpers  es  que 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                55 

mantiene  actualizados  los  path  absolutos  a  la  aplicación  y  si  se  llegase  a  mover  a  otro  URI  automáticamente estos mantendrían las rutas correctas.  

6.9 Visualización del saldo del cliente La primera opción que presenta el menú al cliente le permite consultar el saldo de las cuentas  bancarias que tenga en el banco. Para implementar la consulta se crea el controlador ‘banking’  que consulta el saldo de cada cuenta y lo presenta en una vista.    El controlador ‘BankingController’ queda así:  <?php class BankingController extends ApplicationController { public function indexAction(){ } public function checkBalanceAction(){ $userData = SessionNamespace::get('UserData'); $customerId = $userData->getCustomer(); $accounts = $this->Account->find("customer_id='$customerId' AND status = 'A'"); $this->setParamToView("accounts", $accounts); } }

  Se  toman  los  datos  de  sesión  que  se  crearon  cuando  el  cliente  inició  sesión  desde  el  SessionNamespace. El modelo ‘Account’ es inyectado para realizar la consulta, el resultado de  esta se pasa a la vista usando el parámetro “accounts”.     En la presentación la idea es presentar una tabla con los saldos en cada cuenta junto con una  sumatoria del saldo total por cuenta y de todas las cuentas. La tabla a presentar contiene las  siguientes columnas: Número de la Cuenta, Saldo, Saldo en Canje y Total (que suma el saldo  más  el  saldo  en  canje).  Podemos  definir  el  total  como  una  columna  calculada,  obteniendola  como  una  regla  del  negocio  implementando  el  método  getBalanceTotal()  en  el  modelo  Account:    <?php class Account extends ActiveRecord { /* getters y setters */ /** * Devuelve el saldo total de la cuenta * * @return double */


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                56 

public function getBalanceTotal(){ return $this->balance+$this->swap_balance; } }

  Al  definir  este  método  se  extiende  el  modelo  y  se  cumple  con  la  regla  del  negocio.  getBalanceTotal() está disponible en cada instancia de Account en toda la aplicación.     Se  crea  la  vista  de  esta  acción  en  el  archivo  apps/bank/views/banking/checkBalance.phtml.  Notese que banking corresponde a el nombre del controlador y checkBalance al nombre de la  acción:    <?php print "<table border='1'> <thead> <tr> <th>N&uacute;mero</th> <th>Saldo</th> <th>Saldo en Canje</th> <th>Total</th> </tr> </thead> <tbody>"; foreach($accounts as $account){ print "<tr> <td>".$account->getNumber()."</td> <td align='right'>".number_format($account->getBalance(), 2)."</td> <td align='right'>".number_format($account->getSwapBalance(), 2)."</td> <td align='right'>".number_format($account->getBalanceTotal(), 2)."</td> </tr>"; } print "</tbody></table>"; ?>

El  resultado  devuelto  por  el  método  find  de  Account  es  un  objeto  ActiveRecordResulset  que  puede ser recorrido por foreach para construir la tabla de cuentas. Algun cliente puede tener  varias  cuentas  ó  tener  ninguna,  en  este  ultimo  caso,  la  aplicación  le  informará  al  cliente.  Ya  que  los  objetos  ActiveRecordResultset  implementan  la  interface  Countable  es  posible  saber  cuantos registros devolvió la consulta usando la función count():    <?php if(count($accounts)>0){ print "<table border='1' align='center'> <thead> <tr> <th>Número</th> <th>Saldo</th> <th>Saldo en Canje</th> <th>Total</th> </tr> </thead>


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                57 

<tbody>"; $total = 0; $totalBalance = 0; $totalSwapBalance = 0; foreach($accounts as $account){ print "<tr> <td>".$account->getNumber()."</td> <td align='right'>".number_format($account->getBalance(), 2)."</td> <td align='right'>".number_format($account->getSwapBalance(), 2)."</td> <td align='right'>".number_format($account>getBalanceTotal(), 2)."</td> </tr>"; $totalBalance+=$account->getBalance(); $totalSwapBalance+=$account->getSwapBalance(); $total+=$account->getBalanceTotal(); } print "<tr> <td align='right'>TOTALES</td> <td align='right'>".number_format($totalBalance, 2)."</td> <td align='right'>".number_format($totalSwapBalance, 2)."</td> <td align='right'>".number_format($total, 2)."</td> </tr>"; print "</tbody></table>"; } else { Flash::notice("No tiene cuentas activas en nuestro banco"); }

  En  este  momento  al  visualizar  los  saldos  se  puede  ver  que  el  menú  no  aparece  al  lado  izquierdo, esto se debe a que el layout del menú que se definió anteriormente solo esta activo  para el controlador del mismo nombre. Para definir el layout ‘menu’ como el del controlador  ‘banking’  se usa el método setTemplateAfter() en el inicializador del controlador.    <?php class BankingController extends ApplicationController { protected function initialize(){ $this->setTemplateAfter("menu"); } public function indexAction(){ } public function checkBalanceAction(){ $userData = SessionNamespace::get('UserData'); $customerId = $userData->getCustomer(); $accounts = $this->Account->find("customer_id='$customerId' AND status = 'A'"); $this->setParamToView("accounts", $accounts); } }

  El  layout  menú  es  modificado  para  que  muestre  tanto  el  menu  de  la  aplicación  como  el  contenido de las vistas que lo utilicen:    <h1>Cajero Virtual</h1> <table width="100%">


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                58 

<tr> <td valign="top" width="25%"> <b>Men&uacute; Principal:</b> <ul> <li><?php echo Tag::linkTo("banking/checkBalance", "Ver Saldo") ?></li> <li><?php echo Tag::linkTo("banking/showTransactionActivity", "Ver Extractos Bancarios") ?></li> <li><?php echo Tag::linkTo("transfer", "Transferencias") ?></li> <li><?php echo Tag::linkTo("logout", "Salir del Banco") ?></li> </ul> </td> <td> <?php View::getContent() ?> </td> </tr> </table>

  El  llamado  a  View::getContent()  indica  donde  se  debe  auto‐incluir  el  contenido  de  la  vista  asociada  al  layout,  en  este  caso  es  checkBalance.phtml.  Según  la  configuración  actual,  cualquier  petición  a  los  controladores  ‘menú’  y  ‘banking’  mostrarian  el  mismo  layout  del  ´menu  principal’,  con  esto  logramos  que  los  clientes  puedan  ir  de  una  opción  a  otra  sin  problemas y la aplicación obtiene un menu que se puede mantener fácilmente ya que esta en  un solo archivo, pero aplica a varios estados de la aplicación.  

6.10 Crear el TransactionActivity La  segunda  acción  que  se  debe  implementar  en  el  controlador  banking  es  ‘showTransactionActivity’ cuyo objetivo es mostrar los extractos bancarios del cliente en cada  una de sus cuentas. Para empezar, se debe permitir al cliente que seleccione las cuentas en las  que  desea  ver  sus  extractos  y  luego  mostrarlos  paginando  los  resultados  y  dar  la  opción  de  imprimirlos.    La implementación de la acción showTransactionActivity consulta las cuentas del cliente y las  visualiza en la presentación de ella. Ya que el procedimiento para obtener las cuentas activas  del  cliente  se  habia  implementado  en  la  acción  checkBalance,  se  define  el  método  privado  _getActiveAcounts()  para  hacer  reusable  el  procedimiento  mencionado  y  usarlo  en  showTransactionActivity. El controlador queda entonces así:    <?php class BankingController extends ApplicationController { protected function initialize(){ $this->setTemplateAfter("menu"); }


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                59 

public function indexAction(){ }

'A'");

private function _getActiveAccounts(){ $userData = SessionNamespace::get('UserData'); $customerId = $userData->getCustomer(); return $this->Account->find("customer_id='$customerId' AND status = } public function checkBalanceAction(){ $this->setParamToView("accounts", $this->_getActiveAccounts()); } public function showTransactionActivityAction(){ $this->setParamToView("accounts", $this->_getActiveAccounts()); } }

  La  vista  en  el  archivo  apps/bank/views/banking/showTransactionActivity.phtml  contiene  un  formulario donde el usuario selecciona las cuentas y un botón de ‘Ver extractos’:    <?php if(count($accounts)>0){ print "<p>Por favor seleccione las cuentas a consultar:</p>"; print Tag::form("banking/getSelectedActivity"); print "<table align='center' border='1'> <thead> <tr> <th></th> <th>N&uacute;mero Cuenta</th> <th>Oficina</th> </tr> </thead> <tbody>"; foreach($accounts as $account){ print "<tr> <td>".Tag::checkboxField("cuenta[]", "value: {$account>getId()}", “checked: checked”)."</td> <td align='center'>{$account->getNumber()}</td> <td align='center'>{$account->getSucursalId()}</td> </tr>"; } print "</tbody></table><p align='center'>"; print Tag::submitButton("Consultar"); print "</p>"; print Tag::endForm(); } else { Flash::notice("No tiene cuentas activas en nuestro banco"); } ?>

  La descripción de la vista anterior es la siguiente:    •

Se controla que haya cuentas activas contando los registros devueltos y presentando  un mensaje informativo en su defecto. 

El helper Tag::form(string $action) permite la creación de una etiqueta de formulario 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                60 

cuya acción es /banking/getSelectedActivity.  •

Se recorren las cuentas activas y por cada una se genera una fila con un checkbox que  por defecto esta seleccionado. 

El helper Tag::submitButton(string $caption) permite crear el botón de ‘Consultar’, al  hacer click en él se enviará la información a la acción mencionada. 

El helper Tag::endForm() cierra el formulario. 

  La columna de la sucursal visualiza el código de esta tal y como está en la tabla lo cual no es  muy amigable para el usuario final. Las asociaciones pueden resolver esto y obtener el detalle  de la sucursal por cada cuenta en forma natural. Se define una multiplicidad n a 1 en el modelo  ‘Account’ así:    <?php class Account extends ActiveRecord { /* getters y setters */ /** * Devuelve el saldo total de la cuenta * * @return double */ public function getBalanceTotal(){ return $this->balance+$this->swap_balance; } /** * Inicializa el modelo * */ public function initialize(){ $this->belongsTo("sucursal"); } }

  De  esta  forma  se  puede  reemplazar  la  línea  de  la  vista  showTransactionActivity.phtml  en  donde se imprime el codigo de la sucursal por:    <td align='center'>{$account->getSucursal()->getName()}</td>

  Al enviar los datos del formulario a la acción banking/getSelectedActivity, se recibe las cuentas  seleccionadas y consulta los movimientos asociados a estas:    <?php class BankingController extends ApplicationController { protected function initialize(){


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

}

 

                                                                61 

$this->setTemplateAfter("menu"); public function indexAction(){ } private function _getActiveAccounts(){ $userData = SessionNamespace::get('UserData'); $customerId = $userData->getCustomer(); return $this->Account->find("customer_id='$customerId' AND status='A'"); } public function checkBalanceAction(){ $this->setParamToView("accounts", $this->_getActiveAccounts()); } public function showTransactionActivityAction(){ $this->setParamToView("accounts", $this->_getActiveAccounts()); } public function getSelectedActivityAction(){ $selectedAccountsIds = $this->getPostParam("cuenta"); $customerAccounts = array(); if(is_array($selectedAccountsIds)){ $userData = SessionNamespace::get('UserData'); $customerId = $userData->getCustomer(); foreach($selectedAccountsIds as $accountId){ $accountId = $this->filter($accountId, "int"); $existsAccount = $this->Account->count("customer_id = '$customerId' AND id='$accountId' AND status='A'"); if($existsAccount==true){ $customerAccounts[] = $accountId; } else { Flash::error("Cuentas invalidas en la peticion"); return; } } } else { Flash::error("Datos invalidos en la peticion"); return; } $movements = $this->Movement->find("account_id IN (".join(", ", $customerAccounts).")", "order: created_at DESC"); $this->setParamToView("movements", $movements); } }

  La explicación del procedimiento es la siguiente:    •

Se obtienen las cuentas seleccionadas del formulario mediante $selectedAccountsIds =  $this­>getPostParam("cuenta");  

En la siguiente linea se valida que el valor obtenido sea un vector con las cuentas 

Luego se valida que cada una de las cuentas que es enviada sea realmente del cliente  activo en la sesión y que la cuenta esté activa. 

Después de filtrar las cuentas se consulta el movimiento asociado a estas, se envia los  resultados a la vista donde en una tabla paginada se presentan los registros. 

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                62 

Creación de Aplicaciones 

7 Aplicaciones en Kumbia Enterprise 7.1 Introducción Una aplicación web es una extensión dinámica de un sitio web ó un servidor de aplicaciones.  Existes 2 tipos de aplicaciones web:   

  •

Orientadas a la Presentación: Son aplicaciones que generan páginas web dinámicas  usando  diferentes  lenguajes  de  marcas  (HTML,  XML,  etc)  y  tecnologías  como  (CSS,  JavaScript,  etc)  generando  contenidos  de  respuesta  de  acuerdo  a  las  peticiones  recibidas.  

Orientadas  a  Servicios:  Implementan  endpoints  para  servicios  web.  Aplicaciones  orientadas a la presentación suelen ser clientes de las orientadas a servicios.  

  Kumbia  Enterprise  Framework  (KEF)  proporciona  un  completo  y  robusto  entorno  para  el  desarrollo,  testeo,  implementación  y  puesta  en  producción  de  ambos  tipos  de  aplicaciones  web usando tecnología PHP. 

7.2 Instancias del framework Una instancia del framework hace referencia a una distribución del framework que reside en  un  servidor  web.  Las  instancias  pueden  contener  una  ó  más  aplicaciones  compartiendo  una  misma versión del framework y un mismo directorio público.    Las instancias pueden verse también como application containers manteniendo la memoria y  recursos de las aplicaciones en forma separada pero proporcionando un entorno integrado de  operación. 

7.3 Estructura de directorios de una Instancia La estructura de archivos de una instancia de Kumbia Enterprise Framework tiene lo siguiente:    Listado: Estructura de directorios predeterminada    apps/ default/ controllers/


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                63 

application.php config/ filters/ library/ models/ base/ plugins/ validators/ views/ config/ languages/ Library/ public/ javascript/ css/ files/ temp/ img/ index.php scripts/ test/ index.php

La descripción de cada directorio es la siguiente:    Tabla: Descripción de directorios del framework  Directorio  apps 

Descripción  El  directorio  apps  contiene  todas  las  aplicaciones  que  usen  la  misma  versión del framework   Es  la  aplicación  por  defecto,  el  Front‐Controller  para  esta  aplicación 

default 

permite acceder directamente a los controladores sin indicar el nombre  de la aplicación. 

controllers  application.php 

config 

filters 

library 

Es el directorio en el que se deben ubicar todos controladores.  Contiene  la  clase  ControllerBase  de  la  cual  heredan  todos  los  controladores y en donde también definimos el método init  Contiene los archivos de configuración por aplicación y personalizada de  aplicación  Contiene filtros personalizados por usuario. Es opcional la presencia de  este directorio.  Contiene  componentes  personalizados  por  aplicación.  Es  opcional  la  presencia de este directorio.  Aquí  se  deben  ubicar  todos  los  modelos  de  la  aplicación,  Kumbia 

models 

Enterprise Framework permite organizar lógicamente en directorios los  grupos de modelos. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

views 

plugins 

validators 

 

                                                                64 

Permite  crear  la  presentación  de  aplicaciones  mediante  el  componente  View.  Es  posible  crear  plugins  que  aumenten  la  funcionalidad  de  la  implementación MVC.  Permiten crear validadores para ActiveRecord que se ayuden a validar la   lógica de datos. 

config 

Contiene la configuración general del framework 

languages 

Contiene los mensajes localizados del framework. 

Library 

Contiene al framework como tal y librerías de terceros  Hace  el  papel  de  DocumentRoot  (raíz  de  documentos)  de  la  aplicación, 

public 

todo  los  archivos  debajo  de  este  directorio  pueden  ser  accedidos  públicamente.  En  sus  subdirectorios  se  encuentra  todo  el  contenido  estático como imágenes, javascript, css y archivos descargables. 

scripts  test 

Contiene scripts que automatizan tareas en el framework y reducen la   codificación manual.  Contienen test de unidad de los framework. 

  La  estructura  de  directorios  esta  pensada  buscando  convención  sobre  configuración,  así  el  desarrollo producido es más mantenible y se hace más eficiente el desarrollo cuando todo se  encuentra en su lugar.  

7.4 Publicar contenido estático El directorio public en la estructura de archivos está destinado a publicar contenido estático  que  es  visible  públicamente.  Cualquier  archivo  ubicado  en  este  directorio  ó  en  un  subdirectorio puede ser accedido por los clientes de la aplicación.    Con el fin de establecer ubicaciones que hagan más mantenibles las aplicaciones se incluyen  por defecto los siguientes subdirectorios:    Tabla: Directorios de publicación de contenido estático   Subdirectorio 

Descripción 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

img 

 

                                                                65 

Contiene  imágenes  predefinidas  del  framework  y  su  objetivo  es  colocar aquí imagenes a ser usadas por la aplicación. 

css 

Contiene  archivos  de  estilos  CSS.  El  archivo  style.css  contiene  las  definiciones de estilos estándares para todas las aplicaciones. 

javascript 

Está  destinado  a  almacenar  archivos  JavaScript.  El  framework  coloca  en este directorio los frameworks y funciones básicas JavaScript. 

temp 

Directorio para archivos temporales. 

files 

Directorio para archivos a descargar. 

  El desarrollador debe tener en cuenta que cuando un contenido en estos directorios no existe  la petición es direccionada a la aplicación. Evitar las peticiones a archivos inexistentes es una  buena práctica en miras a mejorar el rendimiento de las aplicaciones. 

7.5 Bootstrap En cualquier estructura MVC el boostrap cumple el papel de tomar la URL reescrita e invocar  tanto el Dispatcher como los enrutadores necesarios para ejecutar la petición. Para entender  la  forma  en  la  que  el  Dispatcher  busca  el  controlador  en  las  aplicaciones  y  ejecuta  la  acción  asociada es necesario comprender la forma en la que deben formar las URLs antes de generar  una petición.    Para una estructura de directorios que incluye 2 aplicaciones, la primera default y la segunda  que se llama producción que ilustramos así:    Ejemplo: Estructura de directorios para múltiples aplicaciones    empresa/ apps/ default/ controllers/ clientes_controller.php productos_controller.php config/ models/ views/ produccion/ controllers/ compras_controller.php config/ models/ views/

Una petición al controlador clientes sería así:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                66 

Ejemplo: Acceder a las aplicaciones y controladores desde una URL  http://www.ejemplo.com/empresa/clientes/ http://www.ejemplo.com/empresa/clientes/buscar http://www.ejemplo.com/empresa/clientes/consultar/18

  En donde, el dominio del servidor es www.ejemplo.com, la ruta al framework es empresa (en  este directorio del DocumentRoot esta el framework), el nombre del controlador es clientes, la  acción en la tercera URL sería consultar y el parámetro para esta acción es el número 18.     Una  petición  para  la  aplicación  de  producción  se  coloca  el  nombre  de  esta  después  del  directorio donde esta Kumbia Enterprise Framework, así:    Ejemplo: Acceder a la aplicación de producción desde una URL  http://www.ejemplo.com/empresa/produccion/compras/ http://www.ejemplo.com/empresa/produccion/verEstado/22

  Cada  aplicación  dentro  de  apps  contiene  una  estructura  de  directorios  para  controladores,  modelos y vistas única, la forma de acceder a cada aplicación es indicando su nombre antes  del nombre del controlador.  

7.6 Crear la acción por defecto en una Aplicación La clase ControllerBase ubicada en apps/default/controllers/application.php permite definir el  método init que se ejecuta en caso que no se defina un controlador ó acción por defecto:  Ejemplo: Acción por defecto en una aplicación  <?php class ControllerBase { public function init(){ //Cargar algunas extensiones Extensions::loadExtension("Kumbia.ApplicationMonitor"); Extensions::loadExtension("Kumbia.Acl");

}

}

//Enrutar al controlador login Router::routeTo("controller: login");

7.7 Crear un procedimiento de inicialización de la aplicación El  método  ControllerBase::init  es  ejecutado  si  no  se  especifica  un  controlador  en  la  URL,  en  ciertas ocasiones puede que no sea útil si se requiere inicializar extensiones ó ejecutar algún  proceso de inicialización. El método ControllerBase::onStartApplication resulta más apropiado,  en  estos  casos.  Este  método  solo  ejecuta  un  procedimiento  en  cuanto  se  realiza  la  primera 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                67 

petición a la aplicación. El siguiente ejemplo ilustra mejor el funcionamiento de este método:    Ejemplo: Definir un procedimiento de inicialización de la aplicación  <?php class ControllerBase { public function onStartApplication(){ //Cargar algunas extensiones Extensions::loadExtension("Kumbia.Feed"); Extensions::loadExtension("Kumbia.Acl"); } public function init(){ //Enrutar al controlador login Router::routeTo("controller: login"); } }

  También se debe evitar realizar cualquier tipo de salida al explorador ya que este método es  ejecutado antes de inicializarse el contexto de sesión. 

7.8 Detectar un cambio en la ejecución de una instancia a otra En la clase ControllerBase también es posible implementar el método onChangeInstanceEvent  que es ejecutado cuando se detecta que en la misma sesión se ha ejecutado ya una aplicación  en otra instancia de Kumbia Enterprise Framework.    Ejemplo: Detectar el cambio de ejecución de una instancia a otra  <?php class ControllerBase { public function onChangeInstanceEvent(){ //Se ha cambiado la instancia } }

  Es  posible  que  este  evento  no  se  llame  correctamente  si  las  aplicaciones  e  instancias  tienen  adaptadores de sesión diferentes.           


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                68 

Parte 1: La lógica de dominio 

8 Componente Controller 8.1 Introducción El  componente  Controller  cumple  una  importante  tarea  dentro  de  la  arquitectura  MVC  de  Kumbia.  El  framework  proporciona  la  integración  de  este  componente  con  el  componente  View y ActiveRecord que realiza el papel de los modelos.    La integración de estos componentes proporciona una estructura estable y eficiente para las  aplicaciones  orientadas  a  la  Web.  Además  de  esto,  el  componente  ofrece  un  sistema  de  persistencia transparente al desarrollador que acerca las aplicaciones Web a aplicaciones de  escritorio,  eliminando  la  complejidad  de  administrar  el  estado  y  entorno  de  la  lógica  de  negocios  en  una  sesión.  Por  medio  de  plug‐ins  es  posible  extender  la  funcionalidad  de  este  componente. 

8.2 Como funciona el componente Controller? Kumbia  Enterprise  Framework  ha  implementado  una  estructura  jerárquica  de  clases  que  permiten crear diferentes tipos de servicios y desarrollar la lógica de aplicación en diferentes  niveles de flexibilidad ó practicidad.     El  componente  Controller  posee  la  siguiente  jerarquía  de  clases  e  implementación  de  servicios:    Tabla: Jerarquia de clases del componente Controller  Clase 

Ubicación 

Descripción  Es  la  clase  padre  de  todos  los  controladores, el desarrollador puede 

ControllerBase  

apps/default/controllers/  application.php  

agregar 

métodos 

que 

serán 

heredados  por  cualquier  controlador  de  la  aplicación.  Aquí  se  puede  agregar  validación  de  seguridad  ó  Auditoría de sistemas.  

Controller  

Library/Kumbia/Controller/C Es  el  componente  Controller  en  si, 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

ontroller/Controller.php  

 

                                                                69 

implementa  comunes 

todos 

para 

los 

los 

métodos  tipos 

de 

controladores del framework.   Library/Kumbia/Controller/A ApplicationController   pplication/  Application.php  

El  diseño  de  este  controlador  ayuda  al  programador  a  interactuar  con  vistas  y  modelos  de  la  forma  más  directa y flexible.   Es 

una 

implementación 

del 

componente  Controller  que  funciona  como  Scallfolding  (generador  de  Library/Kumbia/Controller/St código)  dinámico.  Busca  ayudar  al  StandardForm  

andardForm/ 

desarrollador  a  crear  capturas  de 

StandardForm.php  

limitada  personalización  pero  que  realizan  las  operaciones  de  creación,  consulta,  modificación,  reporte  y  eliminación de los datos de una tabla.   Este  tipo  de  controlador  Permite 

Library/Kumbia/Controller/ WebServiceController   WebServiceController/  ApplicationController.php  

crear  Servicios  web  basados  en  el  estándar SOAP, generar descripciones  en  WSDL  y  orquestar  el  intercambio  de  datos  entre  aplicaciones  usando  este método.   Es 

una 

sub‐implementación 

Library/Kumbia/Controller/A ApplicationController  MultiThreadController  pplication/  MultiThreadController.php  

que 

de  está   

diseñada  para  correr  procesos  de  negocio  que  requieran  seguimiento  estilo cross‐cutting. 

  El  objetivo  de  cada  controlador  es  básicamente  separar  la  lógica  de  la  presentación,  el  componente Controller implementa el patrón Front­Controller en el cual todas las peticiones a  la  aplicación  son  atendidas  inicialmente  por  él  y  luego  son  enrutadas  a  controladores  de  usuario y acciones que atienden cada una. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                70 

8.3 Crear un Controlador Los  controladores  son  clases  que  heredan  de  las  implementaciones  de  Controladores  como  ApplicationController  ó  WebServiceController  y  que  deben  ser  creados  bajo  ciertas  convenciones en el directorio apps/default/controllers/    Al  crear  un  controlador  para  la  administración  de  la  información  de  clientes  se  crea  un  archivo  llamado  customer_controller.php,  en  él  una  clase  CustomerController  heredando  de  alguna de las implementaciones del componente Controller.    La acción por defecto en el controlador debe tener visibilidad pública y llamarse indexAction  así:    Ejemplo:  Un controlador y su acción por defecto  <?php class CustomerController extends ApplicationController { public function indexAction(){ $this->renderText("Hola Mundo"); } public function getStatusAction($id){ $this->renderText("Ver el estado del cliente $id"); } }

  Para realizar una petición a la aplicación se hace mediante la siguiente URL:    Ejemplo: Acceder al controlador mediante una URL  http://www.example.com/company/customer/index http://www.example.com/company/customer/

  Ya que index es la acción por defecto no es necesario indicarla, ya que es implícita. El indicarla  produciría  el  mismo  resultado.  Para  acceder  a  la  acción  getStatus  se  hace  de  la  siguiente  forma:    Ejemplo: Acceder a una acción personalizada desde una URL  http://www.example.com/company/customer/getStatus/190

  •

El componente Controller esta integrado con el componente View que implementa el  patrón Template View. Esta integración permite que en cuanto termina la ejecución de 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                71 

la  lógica  en  la  acción  automáticamente  se  renderiza  la  presentación  ó  vista  correspondiente al controlador y acción solicitados.  •

El  funcionamiento  del  componente  Controller  se  apoya  tanto  en  Dispatcher  como  en  Router  para  realizar  todo  el  trabajo  al  atender  una  petición  a  la  aplicación.  No  es  necesario  entender  el  funcionamiento  de  estos  componentes  en  detalle  aunque  si  se  desea  extender  la  funcionalidad  de  la  arquitectura  implementada  en  Kumbia  Enterprise Framework puede resultar útil 

Primero  la  clean  URL  es  fragmentada  usando  el  método  Router::rewrite  aquí  se  determina  que  aplicación,  controlador  y  acción  se  requiere  ejecutar.  El  componente  Router es quien realiza la orquestación de todo el flujo de ejecución. 

El  componente  Dispatcher  recibe  los  parámetros  de  controlador  y  acción  y  busca  el  indicado  en  el  directorio  de  controladores  para  su  procesamiento  y  delegación  a  la  operación requerida. 

Antes  de  ejecutar  la  petición  Dispatcher  busca  si  esta  definido  el  método  ó  atributo  beforeFilter en la clase del controlador ó en su jerarquía y lo ejecuta.  

Si el flujo de la ejecución no ha sido cambiado mediante el método Controller::routeTo  entonces ejecuta la acción solicitada en el controlador. La acción tiene acceso a todo el  entorno HTTP e información enviada por métodos POST, GET, PUT, etc. 

Si  no  cambia  el  flujo  de  ejecución  Dispatcher  busca  si  esta  definido  el  método  ó  atributo afterFilter en la clase controladora en su jerarquía de clases y lo ejecuta.  

El proceso de enrutamiento es cíclico y termina solo cuando se deja ó no se invoca el  método Controller::routeTo. 

El Compontente View toma el control y recibe lo generado por Controller y visualiza la  presentación para éste, en caso de que exista.  

  El  patrón  Front­Controller  junto  con  Model­View­Controller  funciona  como  el  corazón  el  framework  e  integra  los  componentes  Controller,  Router,  Dispatcher  y  Core  para  hacerlo  funcionar. Cuando requerimos de entender ó modificar la ejecución del flujo de aplicación nos  remitimos a los servicios que estos componentes proporcionan. 

8.4 Servicios del Componente Router void Router::rewrite(string $url)  Toma  la  clean  URL  y  fragmenta  cada  componente  localizando  la  aplicación,  controlador  y  acción  solicitados,  este  método  es  llamado  automáticamente  en  el  bootstrap  del  framework 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                72 

ubicado en public/index.php. cedula     void Router::ifRouted()  Antes de la ejecución de cualquier acción busca en la tabla de enrutamiento estático generada  a partir de config/routes.ini si se debe enrutar a otra controlador ó acción dinámicamente.    boolean Router::getRouted()  Este método devuelve el estado del router que indica si es necesario hacer una enrutación ó  continuar con el flujo normal de la aplicación.    string Router::getApplication()  Devuelve el nombre de la aplicación que fue solicitada en la petición.    string Router::getModule()  Devuelve el nombre del módulo que fue solicitado en la petición.    string Router::getController()  Devuelve  el  nombre  del  controlador  que  fue  solicitado  en  la  petición.  Esta  información  adicionalmente  se  puede  obtener  usando  el  método  en  el  controlador  llamado  getControllerName().    string Router::getAction()  Devuelve  el  nombre  de  la  acción  que  fue  solicitada  en  la  petición.  Esta  información  adicionalmente  se  puede  obtener  usando  el  método  en  el  controlador  llamado  getActionName().    string Router::getId()  Devuelve el primer parámetro enviado por URL en la petición.    array Router::getParameters()  Devuelve en un array los parámetros enviados por URL en la petición, estos igualmente se les  hace binding a la acción como parámetros del método ejecutado de la clase controladora.    array Router::getAllParameters() 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                73 

Devuelve un array con todos los fragmentos de la URL solicitada en la petición.    array Router::routeTo(mixed $params)  Permite cambiar el flujo de ejecución de la aplicación transfiriéndoselo a otro controlador y/o  acción.    array Router::routeToURI(string $uri)  Permite cambiar el flujo de ejecución de la aplicación transfiriéndoselo a otro controlador y/o  acción mediante un Uniform Resource Identifier.    string Router::getActiveApplication()    Devuelve  el  nombre  de  la  aplicación  actual.  Cuando  es  la  aplicación  por  defecto  devuelve  la  palabra default.    void Router::setApplication(string $name)  Permite establecer dinámicamente el nombre de la aplicación actual.    void Router::setDefaultActionName(string $actionName)  Permite establecer el nombre de la acción por defecto en todos los controladores.    string Router::getDefaultActionName()  Devuelve el nombre de la acción por defecto en todos los controladores.     int Router::getRoutingType()  Devuelve  el  tipo  de  enrutamiento  producido  de  acuerdo  al  origen  de  la  petición.  El  valor  devuelto es la constante Router::ROUTING_NORMAL ó Router::ROUTING_OTHER. 

8.5 Servicios proporcionados por Dispatcher void Dispatcher::setControllersDir(string $directory)  Permite  establecer  el  directorio  de  controladores  usado  para  hacer  el  lookup  de  un  controlador cuando se realiza una petición.    Controller Dispatcher::getControllerInstance()  Devuelve el objeto controlador instanciado que se está ejecutando. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                74 

  int Dispatcher:.getDispatchStatus()  Devuelve el estado actual del flujo de ejecución. Puede ser alguna de las constantes de la clase  Dispatcher:    •

STATUS_UNINITIALIZED: Indica que no se ha iniciado el proceso de ejecución  

STATUS_DISPATCHING:  Indica  que  se  esta  localizando  el  controlador  y  su  acción  solicitada  

STATUS_RUNNING_BEFORE_FILTERS:  Indica  que  se  están  localizando  los  métodos  y  atributos beforeFilter y se están ejecutando.  

STATUS_RUNNING_AFTER_FILTERS:  Indica  que  se  están  localizando  los  métodos  y  atributos afterFilter y se están ejecutando.  

STATUS_RENDER_PRESENTATION:  Indica  que  el  control  de  la  aplicación  fue  transferido al componente View.  

STATUS_RUNNING_BEFORE_STORE_PERSISTENCE:  Indica  que  se  va  a  realizar  el  procedimiento de almacenamiento de los datos persistentes del controlador.  

STATUS_RUNNING_AFTER_STORE_PERSISTENCE:  Indica  que  se  ha  realizado  el  procedimiento de almacenamiento de los datos persistentes del controlador.  

STATUS_RUNNING_CONTROLLER_ACTION: Indica que el control de ejecución lo tiene  el controlador como tal y su acción solicitada.  

boolean Dispatcher::isRunningController()  Indica si el control de ejecución esta a nivel del controlador y no del framework.    boolean Dispatcher::isRunningUserLevel()  Indica si la ejecución esta a nivel de la lógica del desarrollador y no del framework.    mixed Dispatcher::getValueReturned()  Devuelve el valor que retornó la última acción ejecutada en la petición. 

8.6 Excepciones Generadas en el Dispatcher En  el  proceso  del  Dispatcher  pueden  ocurrir  excepciones  que  son  enviadas  directamente  al  cliente  si  no  se  encuentra  definido  el  método  onException  ya  sea  en  el  controlador  ó  en  ControllerBase.  Las  excepciones  ocurridas  en  Dispatcher  lanzan  una  excepción  de  clase 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                75 

DispatcherException en las siguientes circunstancias:     Tabla: Códigos y descripción de excepciones generadas en Dispatcher  Código  Dispatcher::NOT_FOUND_ACTION 

Descripción  Se  genera  cuando  no  existe  un  método  con el nombre de la acción indicado en  la  clase  controladora  y  además  no  existe la acción notFoundAction. 

Dispatcher::NOT_FOUND_CONTROLLER 

Se  genera  cuando  no  se  encuentra  el  controlador  solicitado  pero  si  existe  el  archivo correcto. 

Dispatcher::NOT_FOUND_FILE_CONTROLLER 

Ocurre  cuando  no  existe  el  archivo  del  controlador  y  por  ende  la  clase  del  mismo al solicitar la petición a este. 

Dispatcher::NOT_FOUND_INIT_ACTION 

Ocurre  cuando  se  esta  tratando  de  ejecutar 

el 

método 

init 

en 

ControllerBase  pero  este  no  se  ha  definido ó su visibilidad no es pública.  Dispacher:: INVALID_METHOD_CALLBACK 

Se  genera  cuando  se  trata  de  invocar  externamente el constructor de la clase  controladora  ó  un  método  protegido  ó  privado. 

Dispatcher::INVALID_ACTION_VALUE_PARAMETER  Se genera cuando no se ha enviado por  la  URL  ó  al  redireccionar  a  una  determinada  acción  se  ha  omitido  el  valor  para  un  parámetro  de  una  acción  en el controlador solicitado.    Como se ha mencionado anteriormente es posible definir un método que actúe como una capa  previa  al  lanzamiento  de  la  excepción  al  usuario  llamada  onException.  Esta  recibe  el  objeto  instanciado  de  la  excepción  generada,  este  método  recibe  además  cualquier  excepción  independiente de si genera en Dispatcher ó dentro del mismo controlador:    Ejemplo: Definir un método que administre las excepciones en controladores 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                76 

<?php class CustomerController extends ApplicationController { public function indexAction(){ } public function onException($e){ if($e instanceof DispatcherException){ if($e->getCode()==Dispatcher::NOT_FOUND_ACTION){ Flash::notice(“Lo sentimos la página no existe”); } } else { //Se relanza la excepción throw $e; } } }

  Nota: 

Una 

excepción 

que 

se 

presenta 

frecuentemente 

es 

la 

INVALID_ACTION_VALUE_PARAMETER,  que  se  genera  cuando  se  omite  en  la  URL  un  parámetro  del  método  de  la  acción  que  no  es  opcional  ó  que  tiene  un  valor  por  defecto.  Kumbia Enterprise Framework es estricto en este sentido y generará una excepción cuando se  omita  un  valor  aunque  PHP  en  sí  generaría  solo  una  advertencia.  La  forma  más  práctica  de  evitar  esto  es  asignar  valores  predeterminados  a  cada  parámetro  del  método  haciendo  la  lógica de aplicación más consistente evitando mensajes en la pantalla del cliente (explorador,  consola, etc). Este tipo de excepciones también se generan al realizar el enrutamiento y omitir  el valor de algún parámetro. 

8.7 Peticiones HTTP a Controladores Cuando se realiza una petición a un controlador mediante protocolo HTTP es posible crear el  objeto de petición ControllerRequest y además utilizar métodos que ayudan a interactuar con  los datos enviados a estos como por ejemplo cuando se usan formularios HTML.     La  instancia  de  ControllerRequest  se  puede  obtener  en  el  controlador  usando  el  método  Controller::getRequestInstance(), el objeto obtenido encapsula toda la información enviada en  la petición HTTP y la información de su entorno para ser utilizada dentro del controlador:    Ejemplo: Obtener un instancia de la clase ControllerRequest  <?php class CustomerController extends ApplicationController { public function indexAction(){ $request = $this->getRequestInstance();


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

POST”);

 

                                                                77 

if($request->isPost()==true){ Flash::notice(“La petición se ha realizado por método http } } /** * Devuelve el nombre del cliente usando JSON solo si la petición * fue realizada con AJAX */ public function getCustomerClientAction(){ $this->setResponse(“json”); $request = $this->getRequestInstance(); if($request->isAjax()==true){ $this->renderText($this->jsonEncode(array(“name” => “John Smith”))); } } }

  Los valores de las variables superglobales $_GET, $_POST, $_COOKIE, $_REQUEST, $_SERVER Y  $_ENV pueden ser accesados usando los métodos de ControllerRequest usando getParamGet,  getParamPost, getParamCookie, getParamServer y getParamEnv. De igual forma puede utilizar  los 

métodos 

del 

controlador 

getQueryParam, 

getPostParam, 

getRequestParam, 

getCookieParam,  getServerParam  y  getEnvParam  para  obtener  estos  valores  sin  obtener  la  instancia  de la clase ControllerRequest aunque esto se haga implícitamente.  8.7.1

Administrar archivos adjuntos en una petición 

Los  archivos  adjuntos  en  una  petición  pueden  ser  administrados  usando  los  métodos  de  ControllerRequest llamados hasFiles, getParamFile y getUploadedFiles.     Ejemplo: Tratamiento de archivos enviados en una petición  <?php class Movement extends ApplicationController { public function loadMovementAction(){

$file){

if($this->getRequestInstance()->hasFiles()==true){ foreach($this->getRequestInstance()->getUploadedFiles() as print "Nombre original del archivo: ".$file>getFileName();

} } }

}

print "Tamaño del archivo: ".$file->getFileSize(); print "MIME del archivo: ".$file->getFileType(); print "Nombre Temporal: ".$file->getTempName(); $file->moveFileTo('movement/'.$file->getFileName());


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

8.7.2

 

                                                                78 

API de ControllerRequest 

Adicional  a  los  métodos  mencionados  anteriormente  la  referencia  del  API  de  ControllerRequest además tiene:    void setParamRequest(string $index, mixed $value)  Cambia  un  valor  enviado  en  una  petición  en  la  superglobal  $_REQUEST.  Este  método  automáticamente actualiza $_POST y $_GET si es necesario.    void setParamGet(string $index, mixed $value)  Cambia un valor enviado en una petición en la superglobal $_GET.    void setParamPost(string $index, mixed $value)  Cambia un valor enviado en una petición en la superglobal $_POST.     void setParamCookie(string $index, mixed $value)  Cambia un valor enviado en una petición en la superglobal $_COOKIE.    boolean isSetRequestParam($index)  Indica si existe una llave para un valor en la superglobal $_REQUEST.    boolean isSetQueryParam($index)  Indica si existe una llave para un valor en la superglobal $_GET.    boolean isSetPostParam($index)  Indica si existe una llave para un valor en la superglobal $_POST.    boolean isSetCookieParam($index)  Indica si existe una llave para un valor en la superglobal $_COOKIE.    boolean isSetServerParam($index)  Indica si existe una llave para un valor en la superglobal $_SERVER.    boolean isSetEnvParam($index)  Indica si existe una llave para un valor en la superglobal $_ENV. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                79 

  boolean isSetRequestParam($index)  Elimina  un  valor  en  la  superglobal  $_REQUEST.  Implicitamente  elimina  el  valor  de  $_GET  y  $_POST.    boolean isSetQueryParam($index)  Elimina un valor en la superglobal $_GET.    boolean isSetPostParam($index)  Elimina un valor en la superglobal $_POST.    boolean isAjax()  Indica si la petición ha sido realizada usando AJAX. Funciona cuando se utiliza el framework  Javascript Prototype.    boolean isFlashRequested()  Indica si la petición ha sido realizada desde un objeto Macromedia Flash incrustado en un sitio  Web.    boolean isSoapRequested()  Indica  si  la  petición  ha  sido  realizada  desde  un  cliente  SOAP.  Al  solicitarsen  este  tipo  de  peticiones a la aplicación el administrador de presentación y enrutamiento se cambian para  crear una comunicación machine­to­machine.     boolean isSecure()  Indica si la petición se realiza bajo una conexión encriptada usando HTTPS.    string getRawBody()  Devuelve el cuerpo de la petición HTTP directamente.    string getHeader(string $name)  Devuelve un encabezado HTTP a partir de su nombre. Funciona anteponiendo el sufijo HTTP_  ó sin él.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                80 

string getScheme()  Devuelve el scheme (protocolo) utilizado para realizar la petición HTTP. Devuelve http ó https  generalmente.    string getHttpHost()  Devuelve el host y puerto en el que realizo la petición. Generalmente es la ip pública ó privada  del servidor donde esta instalado el interprete PHP.    string getMethod()  Devuelve el método HTTP utilizado para hacer la petición POST, GET, PUT, etc.    boolean isGet()  Devuelve true si la petición HTTP fue realizada usando método GET.    boolean isPost()  Devuelve true si la petición HTTP fue realizada usando método POST.    boolean isPut()  Devuelve true si la petición HTTP fue realizada usando método PUT. Es útil cuando se crean  aplicaciones REST.    boolean isOptions()  Devuelve  true  si  la  petición  HTTP  fue  realizada  usando  método  OPTIONS.  Es  útil  cuando  se  crean aplicaciones REST.    boolean isHead()  Devuelve true si la petición HTTP fue realizada usando método HEAD. Es útil cuando se crean  aplicaciones REST.    boolean isDelete()  Devuelve  true  si  la  petición  HTTP  fue  realizada  usando  método  DELETE.  Es  útil  cuando  se  crean aplicaciones REST.    boolean hasFiles() 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                81 

Indica si la petición incluye archivos subidos mediante método POST.    array getUploadedFiles()  Obtiene un vector con objetos ControllerUploadFile que encapsulan la información de archivos  subidos en la petición.    string getHTTPReferer()  Obtiene el HTTP referer de la petición.    array getAcceptableContent()  Obtiene un vector con los mimes del tipo de contenido aceptado por el cliente HTTP junto con  su calidad. Devuelve un array como: Array ( [0] => Array ( [accept] => text/html [quality] => 1  ) [1] => Array ( [accept] => application/xhtml+xml [quality] => 1 ) [2] => Array ( [accept] =>  application/xml [quality] => 0.9 ) [3] => Array ( [accept] => */* [quality] => 0.8 ) )    array getClientCharsets()  Devuelve la lista de idiomas soportados por el cliente HTTP junto con su calidad. Devuelve un  array  como:  Array  (  [0]  =>  Array  (  [accept]  =>  ISO‐8859‐1  [quality]  =>  1  )  [1]  =>  Array  (  [accept] => utf‐8 [quality] => 0.7 ) [2] => Array ( [accept] => * [quality] => 0.7 ) )    string getBestQualityCharset()  Obtiene el charset de mejor calidad soportado por el cliente HTTP. 

8.8 Respuestas HTTP de Controladores La respuesta que generan los controladores en una petición HTTP es encapsulada en el objeto  ControllerResponse  el  cual  funciona  como  un  Gateway  entre  la  vista  y  el  controlador.  Este  objeto esta implementado al igual que ControllerRequest con el patrón Singleton, es decir que  por  cada  petición  a  la  aplicación  solo  existirá  una  intancia  en  todo  el  contexto  de  ejecución.  Para  obtener  la  instancia  de  la  clase  ControllerResponse  se  usa  el  método  estático  getInstance().    Ejemplo:  Uso del objeto ControllerResponse  <?php class DocumentsController extends ApplicationController { public function indexAction(){


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

}

 

                                                                82 

$response = ControllerResponse::getInstance(); $response->setHeader(“Content-Type: application/pdf”); $response->setResponse(ControllerResponse::RESPONSE_OTHER); $response->setResponseAdapter(‘pdf’); }

En el ejemplo anterior la acción index visualiza un archivo en formato PDF que es leído en la  presentación,  el  método  setHeader  establece  un  encabezado  HTTP  apto  para  la  salida  y  además indica a la aplicación que no debe utilizar el adaptador de presentación por defecto  (HTML) sino debe usar ‘pdf’.   8.8.1

Establecer el tipo de salida de la Petición 

El  controlador  proporciona  el  método  Controller::setResponse  que  permite  establecer  el  tipo  de salida que se genera en la acción solicitada. Los tipos de salida que admite este método son  los siguientes:    Tabla: Tipos de respuesta que acepta el objeto ControllerResponse  Valor 

Descripción 

view 

Indica que solo la vista correspondiente a la acción solicitada será la que se  visualizará.  Usualmente  aplica  cuando  se  renderizan  vistas  parciales  ó  fragmentos AJAX. 

ajax 

Realiza lo mismo que ‘view’ pero documenta el código más claramente. 

json 

Permite  producir  salidas  usando  notación  JSON  (JavaScript  Serializable  Object Notation). 

xml 

Produce una salida XML, agrega el encabezado Content‐type: text/xml y no  muestra ningun layout asociado. 

rss 

Produce  una  salida  XML  agrega  el  encabezado  encabezado  Content‐type:  application/rss+xml  y no muestra ningun layout asociado. 

  Los valores de los tipos de salida son internamente convertidos a un tipo de salida soportado  por ControllerResponse:    Tabla: Tipos de respuesta avanzados del objeto ControllerResponse  Valor 

Descripción 

RESPONSE_NORMAL 

Es  la  respuesta  que  se  genera  normalmente.  No  es  necesario  establecerla. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

RESPONSE_OTHER 

 

                                                                83 

Indica que no se debe usar el adaptador de visualización por defecto  porque se generará una salida en otro formato. 

  En  el  siguiente  ejemplo  se  ilustra  como  generar  una  salida  usando  JSON,  la  acción  countItemsAction  implementa  una  salida  primero  estableciendo  el  tipo  de  salida    y  después  haciendo la salida de la misma, en getItemsAction se resumen los dos pasos anteriores en una  sola línea:    Ejemplo: Implementar una salida JSON desde un controlador  <?php class CartController extends ApplicationController { public $items = array(); public function addToListAction($item){ $this->ítems[] = $item; } public function countItemsAction(){ $this->setResponse(‘json’); $this->renderText($this->jsonEncode(count($this->ítems))); } public function getItemsAction(){ $this->outputJSONResponse($this->ítems); } }

Nota:  El  método  setResponse  tiene  una  funcionalidad  limitada  por  lo  cual  ha  sido  marcado  como  obsoleto,  en  vez  de  este  se  debe  usar  View::setRenderLevel  en  conjunto  con  Controller::setResponseType.  8.8.2

API de ControllerResponse 

El API de la clase ControllerResponse es:    public static ControllerResponse getInstance()  Obtiene la instancia del objeto ControllerResponse.    public void setHeader(string $header, boolean $replace=true)  Permite establecer un encabezado HTTP en la petición actual. El parámetro $replace indica si  el encabezado debe reemplazar uno del mismo tipo establecido anteriormente.    public array getHeaders(boolean $process=true) 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                84 

Obtiene  un  array  con  los  encabezados  HTTP  que    van  a  ser  enviados  en  la  respuesta  de  la  petición.  Si  el  parámetro  $process  es  true  devolvera  un  array  asociativo  cuyas  claves  corresponden a los nombres de los encabezados.    public boolean hasHeader(string $headerName)  Indica si ya se ha definido un encabezado para ser enviado en la respuesta a la petición.    public void setResponseType(int $type)  Permite  establecer  el  tipo  de  respuesta  que  debe  generar  la  petición.  El  parámetro  $type  recibe 

los 

valores 

de 

las 

constantes 

ControllerResponse::RESPONSE_NORMAL 

y  

ControllerResponse:: RESPONSE_OTHER.    public integer getResponseType()  Obtiene el tipo de respuesta que va a generar el controlador. Devuelve el valor de cualquiera  de las 3 constantes mencionadas anteriormente.    public integer setResponseAdapter(string $adapter)  Establece  el  nombre  del  adaptador  utilizado  para  procesar  la  salida  de  la  petición.  Los  posibles valores para $adapter son json, pdf y xml. En la referencia del componente View se  explica como utilizar otros adaptadores.    public function getResponseAdapter()  Devuelve el adaptador usado para generar la salida.    public function setContentType($contentType)  Establece el encabezado Content‐Type de la respuesta del controlador. 

8.9 Controlar acciones no encontradas Cuando se realiza una petición a un controlador y la acción solicitada no esta implementada se  genera  una  excepción  que  cuando  no  es  controlada  presenta  información  de  la  excepción  al  usuario de la aplicación. La información de excepciones presenta información técnica que en  manos equivocadas puede permitir facilitar el ataque a la aplicación.    El desarrollador puede implementar la acción notFoundAction ya sea en el controlador ó en la 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                85 

jerarquía  de  clases  lo  cuál  permitirá  presentar  al  usuario  un  mensaje  personalizado  y  probablemente almacenar un log de la situación ocurrida.    Ejemplo:  Definir  una  acción  que  administre  las  peticiones  a  controladotes  y  acciones  que no esten definidas  <?php class ReportsController extends ApplicationController {

}

public function notFoundAction($actionName=””){ $logger = new Logger(“File”, “notFoundReports.txt”); $logger->log(“No se encontró la acción $actionName”); }

8.10 Filtros en controladores Cada  acción  ejecutada  en  cualquier  controlador  de  la  aplicación  ejecuta,  si  están  presentes  filtros  antes  y  después  de  la  ejecución  del  método  solicitado.  Los  filtros  permiten  ejecutar  tareas de autenticación, politicas de seguridad, validación y enrutamiento, además de acceder  por completo al entorno HTTP y modificar la respuesta de la petición.    Los dos tipos de filtros son: beforeFilter que es ejecutado antes de ejecutar la acción solicitada  como tal y afterFilter que se ejecuta inmediatamente después.    Los  filtros  son  métodos  que  se  implementan  directamente  como  métodos  en  la  clase  controladora  ó  en  la  jerarquia  de  clases  del  mismo.  Usualmente  filtros  generales  para  todos  controladores  se  implementan  en  la  clase  padre  ControllerBase,  de  esta  forma  interceptan  todas las peticiones a la aplicación.    Ejemplo: Definir filtros a nivel general en la aplicación  <?php class ControllerBase { public function init(){ Router::routeTo("controller: login"); } public function beforeFilter(){ $activeRole = Session::getData("activeRole"); if(Router::getController()=="admin"&&$activeRole!="Administradores"){ Router::routeTo("controller: login", “action: index”); return false; } } }


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                86 

  Se  debe  devolver  false  desde  beforeFilter  cuando  se  realiza  un  enrutamiento  a  otro  controlador diferente al activo.    Cuando  se  implementan  múltiples  filtros  es  necesario  invocar  el  filtro  padre  en  el  momento  indicado:    Ejemplo: Definición de múltiples filtros   <?php class CustomerController extends ApplicationController { public function beforeFilter(){ /** * Algún código de filtro */ parent::beforeFilter(); } }

8.11 Enrutamiento en controladores El  componente  Router  ofrece  servicios  que  permiten  al  desarrollador  alterar  el  flujo  de  ejecución como sea necesario, ya sea reescribiendo URLs, redireccionando mediante HTTP ó  haciendo  enrutamientos  a  nivel  de  controlador.  El  proceso  de  enrutamiento  se  requiere  en  una  aplicación  cuando  es  necesario  llevar  al  usuario  a  un  controlador  y  acción  sin  que  sea  solicitado propiamente por el mismo.  8.11.1 Ciclo de enrutamiento  Por cada petición que se realiza a la aplicación se inicia un ciclo de enrutamiento que permite  ejecutar  todas  las  acciones  requeridas  en  los  controladores  según  la  lógica  de  negocio.  Este  ciclo ejecuta cada acción enrutada como si se tratara de una petición normal de usuario.    El psudo‐código del ciclo de enrutamiento es el siguiente:    Pseudocódigo:  Flujo y orden de ejecución de eventos en ciclo de enrutamiento   Intentar InvocarEventoDeControlador(“beforeDispatchLoop”) HayEnrutamiento := Verdadero Mientras HayEnrutamiento = Verdadero Hacer HayEnrutamiento := InvocarEventoDeControlador(“beforeDispatch”) HayEnrutamiento := InvocarEventoDeControlador(“beforeExecuteRoute”) EjecutarFiltroBeforeFilter() HayEnrutamiento := EjecutarAccionEnControlador() EjecutarFiltroAfterFilter() HayEnrutamiento := InvocarEventoDeControlador(“afterExecuteRoute”) HayEnrutamiento := InvocarEventoDeControlador(“afterDispatch”)


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                87 

ContinuarMientras InvocarEventoDeControlador(“afterDispatchLoop”) CapturarExcepción InvocarEventoDeControlador(“onExceptions”) FinIntentar

  Cuando  termina  el  ciclo  de  enrutamiento  se  transfiere  el  control  de  la  aplicación  a  la  presentación (vista), en donde el compontente View realiza este trabajo.  8.11.2 Enrutar usando Router::routeTo  El  Componente  Router  ofrece  el  método  estático  routeTo  que  realiza  las  tareas  de  enrutamiento  y  valida  si  existen  rutas  estáticas  predefinidas  con  la  prioridad  del  caso.  Es  posible utilizar parámetros con nombre para indicar la ruta requerida donde se desea enrutar.  El método routeTo de Controller es un proxy al método estático mencionado.    En el siguiente ejemplo se ilustra la validación de un usuario y su enrutamiento de acuerdo a  si la autenticación es exitosa ó falla:    Ejemplo:  Validación de usuario y enrutamiento condicional  <?php class LoginController extends ApplicationController { public function startSessionAction(){ $login = $this->getPostParam('login', 'alpha'); $pass = $this->getPostParam('pass', 'alpha'); if($this->Usuarios->findFirst("login = ’$login’ AND clave = '$pass'")){ Flash::success('Bienvenido '.$this->Usuarios->getNombre()); $this->routeTo('controller: menu'); } else { Flash::error('Permisos Insuficientes/Password Incorrecto'); $this->routeTo('action: startSession'); } } }

  El  método  routeTo,  gracias  a  los  parámetros  por  nombre,  puede  recibir  la  ruta  de  enrutamiento  en  cualquier  orden,  usando  las  claves:  controller,  action  e  id.  Si  es  necesario  pasar más parámetros adicionales  puede usar llaves numéricas que coincidan con el orden en  que la acción recibe los parámetros requeridos:    Router::routeTo(“controller: invoice”, “action: setMovementDate”, “id: 2008/01/12”, “1: 2008/01/17”);

  Cuando  se  solicita  un  enrutamiento  con  routeTo()  solo  es  efectivo  hasta  que  termina  la  ejecución  de  todo  el  método  de  la  acción,  es  posible  utilizar  return  para  salir  del  método 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                88 

anticipadamente.  8.11.3 Enrutar usando Router::routeToURI()  También es posible hacer enrutamientos usando un Uniform Resource Indentifier como lo es  una clean URL dentro de la misma lógica de aplicación. Para esto se recurre al método estático  Router::routeToURI  que  realiza  el  papel  del  mod_rewrite  fragmentando  la  URL  y  convirtiéndola  en  los  valores  internos  necesario  para  hacer  el  enrutamiento.  El  siguiente  ejemplo ilustra la reescritura de una fecha pasada por la URL estilo Blogger:    Ejemplo: Reescritura de URL mediante Router::routeToURI  <?php class BloggerController extends ApplicationController { public function showPostAction ($year, $month, $date, $name){ $this->routeToURI(“/blogger/showPostByDate/$year-$month$date/$name”); } public function showPostByDateAction($date, $name) { // alguna lógica aqui } }

8.12 Inicialización de Controladores Debido a que el componente Controller proporciona un entorno de estado de persistencia, los  objetos instanciados de las clases controladoras no son destruidos al terminar la sesión y son  persistidos durante toda la sesión de usuario. Según lo anterior los constructores de las clases  controladoras no son confiables para inicializar las condiciones de ejecución cada vez que se  genera  una  petición  a  los  mismos.  Por  esta  razón  se  proporciona  la  posibilidad  de  definir  el  método  protegido  ‘initialize’  con  el  fin  de  inicializar  el  objeto  desde  la  persistencia  en  cada  petición al controlador.    Ejemplo: Inicializar un controlador mediante initialize()  <?php class UsuariosController extends StandardForm { public $scaffold = true; public $template = "admin_menu"; public function beforeInsert(){ $clave = sprintf("%04s", mt_rand(0, 9999)); $this->Usuarios->clave = sha1($clave); Flash::success('La clave del Usuario es "'.$clave.'", por favor no la olvide'); } public function beforeUpdate(){ $usuario = new Usuarios();


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

}

 

                                                                89 

$usuario->find($this->getRequestParam("fl_id", "int")); $this->Usuarios->clave = $usuario->clave; public function initialize(){ $this->ignore('clave'); $this->setTextUpper("nombre"); $this->setComboStatic('perfil', array( array('Administradores', 'ADMINISTRADOR'), array('Cajeros', 'CAJERO'), array('Meseros', 'MESERO') )); $this->setComboStatic("estado", array( array("A", "ACTIVO"), array("I", "INACTIVO") )); } }

  Este método es invocado tanto en el constructor del controlador como en el evento __wakeup  que ocurre al deserializar el objeto desde la persistencia de sesión. 

8.13 Estado de persistencia de Controladores Como se menciono anteriormente Kumbia Enterprise Framework implementa persistencia del  estado de los controladores buscando aproximar el desarrollo Web a un comportamiento de  aplicación  de  escritorio.  Para  activar/desactivar  la  persistencia  es  necesario  invocar  el  método setPersistance(bool $persitence), en el método inicializador el controlador.    Gracias  a  la  implementación  del  patrón  base  Registry  en  el  componente  Dispatcher,  cada  objeto  de  una  clase  controladora  instanciada  se  almacena  temporalmente  y  si  se  realizan  enrutamientos  a  controladores  previamente  accedidos  estos  no  son  llevados  a  persistencia  por lo que el estado de sesión del controlador se mantiene intacto como la primera vez que se  invocó un método de la misma.    Al  activar  la  persistencia  el  valor  del  atributo  name  se  mantiene  entre  peticiones  al  controlador:    Ejemplo: Implementar persistencia en el controlador  <?php class ProductsController extends ApplicationController { public $name; public function indexAction(){


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

}

 

                                                                90 

$this->name = “TV 22’”; public function showProductAction(){ Flash::notice($this->name); } public function initialize(){ $this->setPersistance(true); } }

8.13.1 Ventajas del Estado de Persistencia  El estado de persistencia ó contexto de conversación permite que:      Implementar atributos modulares en los controladores de tal forma que se haga un uso más  intuitivo de los datos de sesión.    Implementar interfaces y componentes que “recuerden” el estado que se le dio la última vez  que se accedió a ellos.    Crear conversaciones con el usuario de la aplicación de tal forma que contextualmente cada  módulo  mantenga  un  flujo  de  trabajo  ó  proceso  como  parte  de  su  naturaleza  de  negocio  misma.  8.13.2 Consideraciones del estado de Persistencia  El estado de persistencia esta pensando en dar la posibilidad de mantener los valores de los  atributos  de  los  controladores  con  el  fin  de  establecer  un  contexto  de  conversación  entre  el  cliente y la aplicación.    Los  controladores  en  un  “estado”  persistente  almacenan  los  datos  en  el  administrador  de  sesiones, si el volumen de datos almacenado es elevado el rendimiento de la aplicación podría  disminuir. Instancias de entidades y otros objetos complejos que hagan parte de los datos de  persistencia  son  excluidos  de  los  datos  almacenados  debido  a  la  cantidad  de  recursos  que  consumen.  Puede  utilizar  el  componente  Cache  para  almacenar  este  tipo  de  objetos  usando  diversos backends.    En  el  capítulo    de  optimización  y  rendimiento  se  presenta  el  componente  GarbageCollector  que permite de forma controlada comprimir y/o eliminar datos de estado de persistencia que  sean utilizados por la aplicación. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                91 

8.13.3 Transacciones y Concurrencia del Estado de Persistencia  Los controladores con estado de persistencia activo generan una transacción de los atributos  de  al  iniciar  la  ejecución  de  cualquier  acción  en  el.  Mientras  se  ejecuta  la  petición  en  el  controlador  la  transacción  permanece  en  un  nivel  de  isolación  en  el  cuál  no  realiza  ningún  bloqueo sobre los datos de sesión. Se puede entender que se realizan transacciones atómicas  con estos datos persistentes. Peticiones con un alto grado de concurrencia en la misma sesión  de usuario y al mismo controlador podrían generar inconsistencias.     Cuando  se  genera  una  excepción  no  controlada  la  transacción  realiza  un  rollback  haciendo  que  los  atributos  del  controlador  permanezcan  intactos  a  su  estado  en  la  última  petición  exitosa.  8.13.4 Eventos del estado de Persistencia  Un  controlador  con  el  contexto  de  persistencia  activado  puede  implementar  eventos  que  permitan modificar la estado inicial al restaurar el objeto de su estado “dormido” y también  cual será su estado final antes de ser almacenado “dormir”:    Tabla: Tipos de respuesta que acepta el objeto ControllerResponse  Evento 

Descripción 

afterRestorePersistence  Se genera cuando despierta el controlador de su estado “dormido”  en la persistencia. Esto solo ocurre cuando se realiza una petición al  controlador.  beforeStorePersistence  Se genera cuando el objeto controlador se esta preparando para ir a  la persistencia.    En el siguiente ejemplo se implementa el evento beforeStorePersitence para evitar que un dato  de gran tamaño no relevante se lleve a la persistencia:    Ejemplo: Implementar un evento del estado de persistencia  <?php class ProductsController extends ApplicationController { public $name; public $veryLongData; public function indexAction(){ $this->name = “TV 22’”; } public function showProductAction(){


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

}

 

                                                                92 

Flash::notice($this->name);

public function initialize(){ $this->setPersistance(true); } public function beforeStorePersitence(){ $this->veryLongData = “”; } }

8.14 La Clase ControllerBase Esta clase es la padre de todos los controladores, el concepto de esta clase esta inspirado en el  patrón  “ApplicationController”  (no  esta  relacionado  con  la  clase  del  mismo  nombre),  que  es  una  extensión  al  MVC  permitiendo  que  parte  de  la  lógica  de  negocio  sea  compartida  por  un  clase de la cual heredan las demás. Esta clase además sirve de punto de intersección y permite  ajustar el flujo de ejecución de acuerdo al contexto en el que se invoque.     El desarrollador puede implementar métodos que serán heredados por cualquier controlador  de la aplicación. Es importante proteger la visibilidad de la lógica compartida en esta clase de  tal forma que solo sea utilizada internamente por los controladores. 

8.15 La Clase Controller La  clase  Controller  implementa  funcionalidad  compartida  a  todas  las  implementaciones  de  controladores.  Esta clase actúa como el corazón de la capa de lógica de dominio.   8.15.1 API de Controller  Controller implementa principalmente métodos proxy a otros componentes facilitando su uso  inmediato en un proceso de negocio.    function void routeTo()  Este método es implementado por conveniencia al desarrollador y realiza un proxy al método  Route::routeTo.    function void routeToURI()   Este método es implementado por conveniencia al desarrollador y realiza un proxy al método  Route::routeToURI.    function mixed getPostParam(string $paramName)  


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                93 

Este método es implementado por conveniencia al desarrollador y realiza un proxy al método  ControllerRequest::getParamPost.    function mixed getQueryParam(string $paramName)  Este método es implementado por conveniencia al desarrollador y realiza un proxy al método  ControllerRequest::getParamQuery.     function mixed getRequestParam(string $paramName)   Este método es implementado por conveniencia al desarrollador y realiza un proxy al método  ControllerRequest::getParamRequest.    function mixed getServer(string $paramName)  Este método es implementado por conveniencia al desarrollador y realiza un proxy al método  ControllerRequest::getParamServer.     function mixed getEnvironment(string $paramName)   Este método es implementado por conveniencia al desarrollador y realiza un proxy al método  ControllerRequest::getParamEnvironment.    function mixed filter(string $paramValue)  Este  método  es  implementado  por  conveniencia  al  desarrollador  y  permite  aplicar  un  filtro  usando el componente Filter .     function void setRequestParam(mixed $index, mixed $value)   Este método es implementado por conveniencia al desarrollador y realiza un proxy al método  ControllerRequest::setParamRequest.    function void setPostParam(mixed $index, mixed $value)  Este método es implementado por conveniencia al desarrollador y realiza un proxy al método  ControllerRequest::setParamPost.     function void setQueryParam(mixed $index, mixed $value)   Este método es implementado por conveniencia al desarrollador y realiza un proxy al método  ControllerRequest::setParamQuery. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                94 

  function void setCookie(mixed $index, mixed $value)  Este método es implementado por conveniencia al desarrollador y realiza un proxy al método  ControllerRequest::setParamCookie.     function void setPersistance(boolean $persistance)   Establece el estado conversacional del controlador. Cuando $persistance es true el estado del  controlador,  (los  valores  de  sus  atributos)  se  mantienen  entre  una  petición  y  otra  a  la  aplicación.    function boolean getPersistance()  Devuelve un valor booleano que indica si el estado conversacional del controlador está activo  ó no.     function void redirect(string $uri)   Permite realizar una redirección HTTP a una determinada  URI dentro de la aplicación actual.    function void setResponse(string $type)   Establece  el  tipo  de  respuesta  que  debe  generar  la  petición.  Consulte  la  referencia  de  ControllerResponse para obtener más información sobre el uso de este método.    function void exceptions(Exception $exception)  Al  reescribir  este  método  es  possible  administrar  las  excepciones  producidas  en  el  controlador.       function string jsonEncode(mixed $data)  Codifica una variable $data usando notación JSON para luego ser enviada al cliente.     function void outputJSONResponse(mixed $data)   Codifica una variable $data usando notación JSON y la envia directamente al cliente.    function string getControllerName()  Obtiene el nombre del controlador actualmente en ejecución.     


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                95 

function string getActionName()  Obtiene el nombre de la acción actualmente en ejecución     function void getId()  Obtiene el valor del primer parámetro adicional pasado por la URL después del nombre de la  acción.     function void getViewHandler()  Al reescribir este método es posible transferir el control de la presentación a un componente  de usuario ó según sea requerido por la aplicación.    function array getViewExceptionHandler()   Al reescribir este método es posible transferir el control de la presentación a un componente  de usuario ó según sea requerido por la aplicación cuando halla una excepción sin capturar.     function void setTemplateBefore(string|array $template)  Permite definir uno ó mas layouts que se deben incluir en la jerarquía de renderización de la  presentación. Este/estos layout(s) son visualizados antes del layout del controlador. Consulte  la referencia del componente View para obtener más información sobre el uso de este método.     function void cleanTemplateBefore()   Resetea la lista de layouts definidos a visualizar antes del layout del controlador.    function void setTemplateAfter(string|array $template)   Permite definir uno ó mas layouts que se deben incluir en la jerarquía de renderización de la  presentación. Este/estos layout(s) son visualizados antes del layout del controlador. Consulte  la referencia del componente View para obtener más información sobre el uso de este método.    function void cleanTemplateAfter()   Resetea la lista de layouts definidos a visualizar después del layout del controlador.    function string|array getTemplateBefore()  Obtiene  el  ó  los  layouts  a  renderizar  antes  del  layout  del  controlador  definidos  hasta  el  momento.  


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                96 

   function string|array getTemplateAfter()   Obtiene  el  ó  los  layouts  a  renderizar  después  del  layout  del  controlador  definidos  hasta  el  momento.     function ControllerRequest getRequestInstance()   Obtiene la instancia del objeto ControllerRequest para su uso en el controlador.    function ControllerResponse getResponseInstance()   Obtiene la instancia del objeto ControllerResponse para su uso en el controlador.    function void setParamToView(string $index,  string $value)   Transfiere un valor a la vista. El valor $value puede ser utilizado en la vista por medio de una  variable local de la vista llamada $index.    function WebServiceClient getService(string $serviceName)   Obtiene  una  instancia  de  un  servicio  del  contenedor  de  servicios  para  ser  usada  en  el  controlador. El servicio $serviceName puede también ser un nombre del Naming Directory ó  un valor obtenido de usando un UDDI. Consulte el capítulo del contenedor de servicios para  obtener más información de este método. 

8.16 Controladores usando ApplicationController La implementación de controladores ApplicationController es la principal que debe ser usada  cuando  se  requiere  dar  respuestas  a  peticiones  solicitadas  por  los  usuarios  finales  de  las  aplicaciones.    8.16.1 API de ApplicationController  function void renderText(string $text)   Envia un texto a la presentación    function boolean validateRequired(string $rules, string $base='', string $getMode='')   Valida  la  presencia  obligatoria  de  determinados  campos  recibidos  de  la  entrada  con  base  a  unas  reglas  definidas  por  el  desarrollador.  Consulte  el  componente  Validator  y  Filter  para  obtener más información. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                97 

  function void cleanValidationMessages()   Resetea los mensajes de validación producidos hasta el momento.    function void addValidationMessage(string $message, string $fieldName='')   Agrega un mensaje a la cola de validación. El Segundo parámetro opcional $fieldName permite  establecer un campo de la interfaz de usuario al que está relacionado el mensaje.    function array getValidationMessages()   Obtiene los mensajes de validación generados hasta el momento en la cola de mensajes.    function boolean isExportable()  Este método puede ser reescrito y debe devolver un valor booleano indicando si los atributos  publicos del controlador deben transferirse a la presentación como variables locales.    8.16.2 Controladores usando MultiThreadController  Este tipo de controlador es una sub‐implementación de ApplicationController cuyo objetivo es  poder  implementar  procesamiento  asimetrico  para  grandes  procesos  en  controladores.  De  esta  forma  es  posible  ejecutar  en  forma  simultanea  tareas  de  seguimiento  y  monitorización  para procesos de negocio.    Los procesos se ejecutan de forma asincrónica y en un orden que no puede ser denominado  seguro  por  lo  tanto  son  aptos  para  procesos  de  debug  ó  monitorización  y  no  para  implementar otros procesos de negocio buscando su ejecución simultánea.    En el siguiente ejemplo se simula la implementación de un proceso de negocio que debido a la  cantidad de datos que se deben procesar puede tardar un tiempo prolongado en procesarse, si  el  proceso  fuese  más  grande  y  complejo  hacer  un  seguimiento  y  monitorización  detallado  puede degradar progresivamente la lógica misma.      El controlador contiene una acción llamada hugeProcess que contiene el proceso a ejecutar, la  anotación  @synchronized  en  el  método  logProcessState  indica  que  este  método  debe  ser  ejecutado simultáneamente con cualquier acción ejecutada en el controlador:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                98 

class MyProcessController extends MultiThreadController { private $_percent; private $_customerName; /** * Realiza el log del proceso * * @synchronized */ public function logProcessState(){ if($this->_logger==null){ $this->_logger = new Logger('File', 'processLog.txt'); } $this->_logger('El cliente actual es: '.$this->_customerName. ' '.$this->_percent); } public function hugeProcessAction(){ $totalQuantity = 0; foreach($this->Movement->find() as $movement){ $customer = $movement->getCustomer(); $this->_customerName = $customer->getName(); $this->_percent = $movement->getQuantity()/ $customer->getCreditAmmount(); $product = $movement->getProduct(); if($product->getType()=='A'){ $totalQuantity+=$movement->getQuantity(); } } $this->setParamToView('totalQuantity', $totalQuantity); } }

  Múltiples métodos del controlador pueden tener la anotación @synchronized de tal forma que  sean ejecutados de manera simúltanea con cualquier acción del controlador. 

8.17 Servicios Web usando WebServiceController 8.17.1 Qué es un Web Service?  Según  la  definición  de  la  arquitectura  de  Servicios  Web  del  W3C,  un  servicio  Web  es  un  sistema  de  software  diseñado  para  soportar  interacción  interoperable  maquina  a  maquina  sobre una red de computación. Cada servicio Web contiene una descripción que otra maquina  puede  procesar  (usando  WSDL  probablemente).  Algunos  servicios  Web  pueden  interactuar  directamente usando mensajes SOAP apoyándose en serialización XML y el protocolo HTTP en  sí.     Con  Servicios  Web  es  posible  dotar  a  las  aplicaciones  de  interoperatividad  estándar  permitiendo  su  comunicación  de  forma  independiente  a  su  plataforma  tecnológica.    Kumbia  Enterprise  Framework  permite  al  desarrollador  implementar  controladores  como  Servicios  Web automatizando los procesos de publicación del servicio, administración y persistencia en  forma transparente. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                99 

  Un controlador WebServiceController funciona como un Service Provider el cual proporciona  un  contrato  de  servicio  que  lo  conforman  las  acciones  del  mismo  y  que  son  expuestas  públicamente  como  operaciones  del  mismo  de  tal  forma  que  clientes  externos  puedan  utilizarlos de manera controlada.    Los  Service  Customers  (clientes  de  servicios)  y  Services  Providers  ofrecen  funcionalidad  concreta  para  el  envío  y  recepción  de  mensajes  en  una  comunicación  maquina  a  maquina.  Esto  es  transparente  para  el  desarrollador  aunque  debe  ser  mencionado  de  manera  informativa.    Kumbia Enterprise Framework proporciona capas de Software que permiten implementar ya  sea  Service  Customers  ó  Services  Providers  en  aplicaciones  desarrolladas  con  él.    De  esta  forma  usted  puede  preocuparse  por  desarrollar  la  lógica  de  negocio  sin  preocuparse  por  la  forma en que los servicios Web vayan a interactuar a más bajo nivel.    8.17.2 Para que son necesarios los Web Services  Las aplicaciones empresariales se pueden ver muy beneficiadas con el uso de Web Services.  Crear  contratos  de  servicio  adecuados  permite  a  los  desarrolladores  extraer  en  forma  abstracta servicios que permitan el intercambio de información  con aplicaciones de terceros,  encapsulando detalles como la conexión a bases de datos, credenciales de seguridad, dominio  y control de la información entregada bajo las condiciones pactadas.     Sistemas  empresariales  ganan  nuevos  sub‐sistemas  de  comunicación  estandarizada  entre  aplicaciones de tal forma que su composición sea reutilizable y componible. Mediante el uso  de  Web  Services  se  eliminan  dependencias  del  pasado  como  el  traspaso  de  información  mediante archivos planos, vistas en las bases de datos, conexiones por FTP ó directamente a  los  RBDMs  que  carecían  de  un  control  adecuado  y  obligaban  a  implementaciones  rígidas  y  complicadas además de exigir la integración de otros componentes en su aplicación.    8.17.3 Arquitectura Orientada a Servicios (SOA)  Las  organizaciones  empresariales  de  hoy  en  dia  requieren  interconectar  procesos  e  información  entre  los  departamentos  de  las  mismas,  sus  provedores,  clientes  y  socios 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                100 

comerciales  extendiendo  sus  fronteras  y  aumentando  la  competitividad  y  capacidad  de  crecimiento.    La Arquitectura Orientada a Servicios proporciona elementos que permiten que un conjunto  de  aplicaciones  distribuidas  se  convierta  en  conjunto  de  recursos  que  puedan  ser  utilizados  tanto interna como externamente y como resultado se obtiene mayor agilidad y productividad  en la organización.     Kumbia Enterprise Framework ofrece herramientas para la construcción de una Arquitectura  Orientada  a  Servicios,  sin  embargo,  debe  ser  el  arquitecto  ó  desarrollador  quien  debe  determinar si es realmente necesario implementar esta estrategia de acuerdo a la complejidad  y objetivos del negocio.     Transformar  la  lógica  de  negocios  empresarial  a  una  arquitectura  orientada  a  servicios  incluye  implementar  contratos  de  servicio,  reusabilidad,  abstracción,  loose  coupling  (acoplamiento débil) y composibilidad. SOA es un modelo arquitectacional para plataformas  de tecnología y cada empresa puede definir los objetivos asociados a computación orientada a  servicios usando diferentes tecnologías.     Usar Web Services es probablemente uno de las mejores opciones para aplicar los principios  SOA y empezar a usar esta arquitectura.    8.17.4 Crear un Web Service  Como  se  mencionó  anteriormente  es  posible  crear  servidores  para  servicios  Web  usando  la  implementación  de  Controller  llamada  WebServiceController.  Este  tipo  de  Controlador  permite  crear  servicios  web  XML  y  encapsula  toda  la  comunicación  basada  en  el  estándar  SOAP.  Las  comunicaciones  soportan  las  especificaciones  SOAP  1.1  y  1.2  así  como  el  uso  de  descriptores WSDL.    A  pesar  que  los  mensajes  SOAP  son  complejos;  todos  estos  detalles  son  transparentemente  implementados  en  una  capa  funcional  apta  al  desarrollo  rápido  y  efectivo.  Del  lado  del  servidor  el  desarrollador  puede  implementar  servicios  usando  lenguaje  PHP  nativo  y  la  arquitectura y servicios del framework sin demasiados cambios. Del lado del cliente es posible  utilizar  servicios  Web  invocando  el  nombre  de  los  métodos/acciones  implementados  en  el 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                101 

servicio servidor.    Gracias  a  que  se  cumple  con  la  especificaciones  definidas  por  el  W3C  (Word  Wide  Web  Consortium) es posible tener independencia del lenguaje PHP tanto del lado del cliente como  del  servidor.  Lo  anterior  permite  acceder  a  servicios  Web  creados  en  otras  plataformas  y  lenguajes y que están accedan a otros creados usando PHP.    El ejemplo a continuación muestra la definición de un servicio Web simplificado que permite  chequear  la  disponibilidad  de  fechas  para  realizar  una  reserva  en  un  sistema  ficticio.  En  el  primer  método  startSession  se  recibe  como  parámetros  el  login  y  password  y  usando  el  componente Auth se autentica contra un servidor ActiveDirectory usando el adaptador LDAP,  si estas credenciales son validas entonces el resultado devuelto es devuelto y posteriormente  permite validar que el usuario este autenticado. Notese que el segundo método getAvalability  lanza  una  excepción  WebServiceControllerException  cuando  no  se  cumple  una  validación  la  cual se notifica al cliente de igual manera.     Los  valores  escalares  devueltos  por  cada  método  se  transfieren  transparentemente  entre  el  servidor  y  el  cliente,  datos  más  complejos  exigen  distribuir  componente  compartidos  de  tal  manera  que  no  haya  perdida  de  información  entre  el  Service  Provider  (servidor)  y  el  Customer (cliente).      Nótese que todos los métodos de la clase que vayan a ser accedidos remotamente deben tener  el sufijo Action.    Ejemplo: Servicio web con WebServiceController  <?php class ReservationController extends WebServiceController { public function startSessionAction($login, $password){ $password = $this->filter($password, “alpha”); $login = $this->filter($login, “alpha”); $auth = new Auth(“ldap”, “server: ldap.server.local”, “accountDomainName: server.local”, “username: CN=$login,DC=server,DC=local”, “password: $password”); if($auth->autentícate()){ return true; } else { sleep(2); return false; } } public function getAvalabilityAction($initialDate, $finalDate){


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                102 

if(Auth::isValid()==false){ return false; } if(Date::compareDates($initialDate, $finalDate)==-1){ throw new WebServiceControllerException(“Fechas incorrectas”); } else { $reserva = Reserva($initialDate, $finalDate); return $reserva->checkAvalability(); } } public function getTicketNumberAction(){ if(Auth::isValid()==false){ return false; } return “AE1872”; } }

  En  el  cliente  se  utiliza  la  clase  SoapClient  estándar  para  acceder  al  servicio  Web  Basado  en  Soap:    Ejemplo: Acceder a un servicio web usando SoapClient  <?php class VerifierController extends ApplicationController { public function validateAction(){ $initialDate = $this->getPostParam(“initialDate”, “date”); $finalDate = $this->getPostParam(“finalDate”, “date”); $reservationService = new SoapClient(null, array( 'location' => 'http://web.server.local/w/reservation', 'uri' => 'http://app-services' )); try { if($reservationService->startSession(“webserviceUser”, “2fe05187a”)==true) { if($reservationService->getAvailability($initialDate, $finalDate)==true) { $ticketNumber = $reservationService>getTicketNumber(); return $this->routeTo(“action: successChecking”, “id: $ticketNumber”); } } } catch(SoapFault $e) { Flash::error(“Ha ocurrido un error”); } } public function successCheckingAction($ticketNumber){ Flash::success(“Felicidades, esta disponible el ticket $ticketNumber”); } }

8.17.5 WebServiceClient  Kumbia Enterprise Framework también proporciona la clase WebServiceClient que extiende el  cliente  SOAP  SoapClient  y  pretende  dar  más  facilidades  al  trabajar  con  servicios  Web  con 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                103 

servidores en este framework. El primer parámetro del constructor puede ser la ubicación del  servicio (location) cuyo Uniform Resource Identificador (uri) es http://app­services:    Ejemplo: Crear un servicio web con WebServiceClient  $webService = new WebServiceClient('http://web.server.local/w/reservation');

  Es posible definir los parámetros del cliente mediante un array de esta forma:    Ejemplo: Definir parámetros extra en el servicio web con WebServiceClient  $webService = new WebServiceClient(array( ‘wdsl’ => ‘http://www.example.com/external-services/reservation.wsdl’, ‘location’ => 'http://web.server.local/w/reservation', ‘uri’ => ‘http://www.example.com/external-services’, ‘encoding’ => ‘ISO-8859-1’ ));

  El constructor establece los siguientes parámetros por defecto para el cliente SoapClient:    Tabla: Parámetros que recibe el contructor de WebServiceClient  Parámetro 

Valor 

wsdl 

null 

uri 

http://app-services 

encoding 

UTF‐8 

compression 

SOAP_COMPRESSION_ACCEPT 

SOAP_COMPRESSION_GZIP    La extensión Soap de PHP es requerida para usar este cliente.  8.17.6 Obteniendo el WSDL de un Servicio Web  Kumbia  Enterprise  Framework  puede  hacer  AutoDiscover  de  servicios  Web  basados  en  WebServiceController, en caso que no se defina un WSDL manualmente para el servicio. Para  generar  un  descriptor  WSDL  correcto  es  necesario  agregar  PHPDocs  a  cada  acción  del  controlador  y  así  poder  determinar  el  tipo  de  dato  devuelto  por  cada  operación  pública  del  Service Provider, sino se puede determinar se genera un empty type.    El mapeo de los valores escalares tanto los que se reciben como los que se envían en PHP a su  correspondiente xsd ó soap‐enc, es el siguiente:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                104 

String  :  <xsd:string>,  Integer  :  <xsd:integer>,  Float  y  Doubles  :  <xsd:float>,  Boolean:  <xsd:bool>, Array : <soap‐enc:Array> y objetos <xsd:struct>.    Los espacios de nombres XML usados son:    xsd: "http://www.w3.org/2001/XMLSchema”  soap‐enc: “http://schemas.xmlsoap.org/soap/encoding/"     Es  posible  invocar  la  acción  getWSDLDescriptor  en  el  controlador  para  obtener  una  descripción WSDL del servicio.   8.17.7 Orquestación de servicios  La lógica de negocio de los servicios web es implementada usando controladores que hacen  parte  de  la  arquitectura  MVC,  tanto  la  capa  de  lógica  de  dominio  como  la  de  datos  tienen  sentido para el desarrollador pero la presentación no existe ó no es claro su implementación  ya  que en servicios web la comunicación  se  realiza  entre  maquinas  y  no  existe  intervención  humana donde se requiera.    Al recibir una petición desde un cliente Soap la instancia del framework es capaz de enrutar a  la  acción  en  el  controlador  adecuada  examinando  el  mensaje  SOAP  enviado  a  la  aplicación.  Luego  de  ejecutar  la  lógica  de  dominio  en  la  acción  el  valor  devuelto  por  esta  es  tratado  y  convertido en un mensaje SOAP que se envia al cliente.    La  manipulación  a  bajo  nivel  de  los  mensajes  SOAP  se  le  encarga  al  componente  Soap  que  implementa los recursos necesarios para recibir y enviar comunicaciones de servicios Web y  hacerlo transparente al usuario.    En el siguiente ejemplo se ilustra como la comunicación de servicios Web es transparente al  desarrollador y como el entorno MVC facilita la orquestación de servicios:    En la maquina servidor1 se implementa el siguiente servicio web:    Ejemplo: Servicio web aritmético  <?php class AritmethicController extends WebServiceController {


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

}

 

                                                                105 

public function addAction($a, $b){ return $a + $b; }

En la maquina servidor2 se implementa un cliente del Servicio Web:    Ejemplo: Acceso al servicio web aritmético  <?php class CalculatorController extends WebServiceController {

}

public function addAction($x, $y){ $service = new WebServiceClient(“http://server1/ins/aritmethic/”); $result = $service->add($x, $y); //Realiza la suma en el servidor1 }

  Al invocarse la acción calculador/add en servidor 2 se mapean automáticamente los valores  de $x y $y a la acción add a $a y $b respectivamente en servidor1 al invocar este método en el  objeto de servicio creado.    El  mismo  ejemplo  se  puede  implementar  utilizando  un  Proxy  a  un  tercer  servidor  quien  finalmente realiza la operación.    El servicio web en el servidor2 queda así implementado:    Ejemplo: Definir un Proxy a servicios web  <?php class AritmethicController extends WebServiceController { public function addAction($a, $b){ $service = new WebServiceClient(“http://server3/ins/aritmethicserver/”); return $service->add($x, $y); //Devuelve la suma en el servidor3 } }

El servicio Web AritmethicServer implementado en el servidor3:    Ejemplo: Servicio web aritmético en el tercer servidor  <?php class AritmethicServerController extends WebServiceController { public function addAction($c, $d){ return $c + $d; } }

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                106 

Aunque no es necesario implementar este ejemplo usando 3 maquinas, permite ilustrar como  se  puede  abstraer  la  lógica  de  aplicación  en  forma  distribuida  de  tal  forma  que  múltiples  aplicaciones  accedan  a  servicios  reutilizables  que  aumentan  la  escalabilidad  de  los  sistemas  desarrollados.  8.17.8 Características de Servicios Web en Kumbia Enterprise  Al  igual  que  los  otras  implementaciones  de  controladores,  en  los  servicios  web  usando  WebServiceController se usa de forma transparente toda la funcionalidad del framework que  se usa en los controladores de aplicación, algunas de estas son:    •

Es posible acceder a los modelos como propiedades de la clase controladora 

Se  puede  implementar  persistencia  del  estado  del  controlador  entre  sesiones  y  peticiones 

Se  puede  enrutar  el  flujo  de  ejecución  a  otros  servicios  Web  dentro  de  la  misma  aplicación 

Seguridad  declarativa  y  programacional  se  puede  implementar  en  este  tipo  de  controladores 

8.18 Controladores StandardForm La implementación de controladores StandardForm es una característica heredada de Kumbia  PHP  Framework.  Por  motivos  de  compatibilidad  con  aplicaciones  existentes  en  la  versión  Enterprise  su  funcionalidad  se  mantiene  intacta.  El  objetivo  de  esta  implementación  es  la  generación dinámica de formularios que permitan administrar la información de tablas en la  conexión pretederminada del entorno actual.    El  desarrollador  debe  evaluar  si  las  limitantes  de  esta  implementación  no  afectarán  en  un  futuro los objetivos de negocio de la aplicación.    Nota:  Esta  implementación  esta  agendada  para  ser  marcada  como  obsoleta  en  versiones  posteriores  del  framework.  LouderTechnology  está  activamente  desarrollado  Louder  Application  Forms  el  cuál  genera  componentes  de  aplicación  robustos  que  aprovechan  de  manera más adecuada y flexible las posibilidades del framework.  8.18.1 Características de StandardForm  •

Generación  dinámica  de  un  CRUD  (Create,  Read,  Update,  Delete)  con  posibilidad  de 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                107 

utilizar parte de ellas ó todos.  •

De  acuerdo  a  la  información  de  los  meta‐datos  de  una  tabla  en  la  base  de  datos  generando componentes de interfaz de usuario adecuados para cada campo. 

Es posible realizar validación del lado del cliente y del servidor. 

Es posible implementar eventos de acuerdo a las acciones ejecutadas por el usuario en  el controlador. 

La información de la tabla creada puede ser exportada a PDF, HTML, Microsoft Word y  Excel. 

8.18.2 Limitantes de StandardForm  •

La  especificación  del  modelo  entidad‐relación  esta  limitada  a  tablas  y  campos  definidos mediante las convenciones del framework 

La funcionalidad de los formularios generados sobre todo la visual puede ser difícil de  personalizar con respecto a los objetivos del desarrollador. 

8.19 Plugins de Controladores En  ciertas  ocasiones  cuando  las  aplicaciones  corren  en  múltiples  entornos  con  diferentes  características,  la  funcionalidad  y  alcance  de  la  misma  aplicación  no  es  suficiente  y  se  debe  extender  automáticamente  durante  el  runtime.  La  arquitectura  de  plugins  de  Controladores  permite observar, extender y manipular el comportamiento de las clases controladoras de la  aplicación según las condiciones lo exijan.    Los  plugins  permiten  interceptar  eventos  de  los  controladores  de  tal  forma  que  estos  sean  observables  y  además  ejecutárse  uno  tras  otro  de  manera  centralizada  sin  requerir  refactorización ó reintegración en la aplicación.  8.19.1 Crear un Plugin de Controlador  Los plugins de controlador son clases que implementan eventos que son invocados a medida  que avanza la ejecución de una petición en cualquier controlador. Estas clases deben cumplir  con los siguientes requerimientos:     Deben estar ubicados en el directorio de plugins usualmente apps/app­name/plugins   El nombre del archivo que implementa la clase debe ser el nombre del plugin   El nombre de la clase debe tener la extensión Plugin   Los plugins de controlador deben heredar de la clase ControllerPlugin ó ser subclase de ella 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                108 

  Las  clases  pueden  implementar  métodos  públicos  que  referencian  los  eventos  ocurridos  en  los controladores, la lista de ellos es la siguiente:    Tabla: Eventos que se pueden implementar en plugins de Controlador  Nombre Evento  beforeDispatchLoop 

Descripción  Ocurre  antes  de  iniciar  el  ciclo  de  enrutamiento,  en  este  punto  no se ha cargado el controlador, aunque se encuentra disponible  todo el entorno de la aplicación. 

beforeDispatch 

Ocurre dentro del ciclo de enrutamiento y justo antes de invocar  el  controlador  solicitado.  Este  evento  se  invoca  por  cada  controlador usado en el flujo de ejecución. 

beforeExecuteRoute 

Ocurre  antes  de  ejecutar  la  acción  solicitada  en  el  controlador,  en  este  punto  se  puede  obtener  los  datos  de  la  petición,  controlador, acción y parámetros. 

afterExecuteRoute 

Ocurre  después  de  ejecutar  la  acción  solicitada  en  el  controlador. 

afterDispatch 

Ocurre  después  del  proceso  de  ejecución  de  la  acción  por  controlador. 

afterDispatchLoop 

Ocurre cuando termina el ciclo de enrutamiento. 

beforeNotFoundAction 

Ocurre  cuando  la  acción  ó  controlador  ejecutado  solicitado  no  esta  implementado.  Es  independiente  de  si  la  acción  notFoundAction está implementada. 

beforeUncaugthException 

Ocurre  antes  de  lanzarse  una  excepción  que  no  fue  capturada  por la aplicación. 

onControllerException 

Ocurre cuando se genera una excepción dentro del controlador.  Se ejecuta antes de beforeUncaughException 

           


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                109 

9 Componente UDDI 9.1 Introducción Este  componente  es  una  implementación  de  la  especificación  de  servicios  Web,  Universal  Description,  Discovery  and  Integration  (UDDI).  El  prinicipal  objetivo  de  este  componente  es  permitir a servicios e controladores desarrollados en Kumbia Enterprise servir como registros  de servicios permitiendo que dominios de computación heterogeneos puedan consultarlos y  conectar servicios a sistemas existentes. 

9.2 Requerimientos Se requiere tener en cuenta lo siguiente para utilizar UDDI:    

Persistencia:  El  componente  UDDI  requiere  de  un  gestor  relacional  para  almacenar 

los registros del directorio.   

Autenticación:  El  componente  Auth  es  requerido  para  ofrecer  los  servicios  de 

autenticación a los controladores de publicación de registros.                                   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                110 

10 Componente BusinessProcess 10.1 Introducción Este  componente  da  la  posibilidad  de  implementar  meta‐procesos  usando  BPEL,  de  esta  forma  se  busca  la  optimización  y  mejoramiento  de  procesos  de  negocio  en  una  aplicación  desarrollada usando Kumbia Enterprise.    Actualmente  el  lenguaje  PDL  (basado  en  el  jPDL)  es  soportado  por  este  componente  con  el  cual  se  puede  expresar  procesos  de  negocio  en  terminos  de  tareas,  estados  de  espera,  comunicación sincronica, etc.     El  componente  permite  su  integración  con  otros  componentes  permitiendo  levantar  configuración, establecer persistencia, identificación, etc.    10.1.1 ¿Que es un proceso de negocio?  Un proceso de negocio es un conjunto de actividades estructuradas y relacionadas que tienen  como objetivo prestart un servicio que satisfaga las necesidades de un cliente. Los procesos de  negocio  son  críticos  para  las  organizaciones  y  su  correcta  estructuración  y  definición  determina el éxito de una organización.    10.1.2 ¿Qué es BPEL?  BPEL  es  un  lenguaje  de  orquestación  de  servicios  web.  Los  lenguajes  de  orquestación  implicitamente  indican  la  intervención  ó  la  facilidad  de  comunicación  entre  diferentes  sistemas que puedan tener diferentes plataformas e infraestructura de sistemas. 

10.2 Job Executor El  componente  BusinessProcess  ofrece  un  entorno  de  ejecución  para  PHP  que  permite  ejecutar procesos PDL ya sea para orquestar servicios ó ejecutar procesos funcionales. 

10.3 Crear un Proceso de Negocio Un proceso de negocio se especifica utilizando una estructura XML que representa los estados  del  meta‐proceso.  Cada  uno  debe  contener  un  estado  inicial  y  uno  final  que  indique  donde  empezar y donde se debe terminar. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                111 

  En el siguiente ejemplo se ilustra un proceso BPM de un sistema de punto de venta (POS). El  estado  inicial  del  proceso  se  marca  con  el  nodo  “start‐state”.  Es  sencillo  seguir  el  flujo  del  meta‐proceso gracias a los nodos “transition” que transfieren el flujo de ejecución de un nodo  a otro.    Ejemplo: Definición de un proceso BPM en PDL  <?xml version="1.0" encoding="UTF-8"?> <process-definition name='Pedido'> <start-state> <transition to="irAlMenu"/> </start-state> <state name="irAlMenu"> <transition to="ingresarClave"/> </state> <state name="ingresarClave"> <decision handler="autenticar"> <transition condition="{#autorizado}==false" to="fin"/> <transition condition="{#autorizado}==true" to="tomarPedido"/> </decision> </state> <state name='tomarPedido'> <task-node name='Mesa y Comanda'> <task name='Ir a Mesas' handler='irAMesas'/> <task name='Escoger Mesa' handler='escogerMesa'/> <decision name='Consultar Tipo de Comanda' handler='consultarTipoComanda'> <transition condition="{#tipoComanda}=='A'" to="ingresarNumeroPersonas"/> <transition condition="{#tipoComanda}=='M'" to="ingresarComandaManual"/> </decision> </task-node> </state> <state name='ingresarComandaManual'> <decision name='Comanda Existe' handler='comandaExiste'> <transition condition="{#comandaExiste}==true" to="fin"/> <transition condition="{#comandaExiste}==false" to="estableceNumeroComanda"/> </decision> </state> <state name='estableceNumeroComanda'> <task name='Establece la comanda' handler='establecerComanda'/> <transition to='ingresarNumeroPersonas'/> </state> <state name='ingresarNumeroPersonas'> <decision name='Requiere Numero Personas' handler='requiereNumeroPersonas'> <transition condition="{#requierePersonas}==true" to="ingresarPersonas"/> <transition condition="{#requierePersonas}==false" to="seleccionarMenu"/> </decision> </state> <state name='ingresarPersonas'> <task name='Establece las Personas en la Mesa' handler='ingresarPersonas'/> <transition to='seleccionarMenu'/> </state> <state name='seleccionarMenu'> <task-node name='Seleccionar Menu'> <task name='Seleccionar un Menu' handler='escogerMenu'/> </task-node> </state>


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                112 

<state name="fin"> </state> </process-definition>

  10.3.1 Tipos de nodos de un meta­proceso PDL  Un meta‐proceso soporta los siguientes tipos de nodos:    Tabla: Tipos de nodos de un meta­proceso PDL  Tipo Nodo 

Descripción  Representa un estado del proceso. Los estados deben tener un  nombre  que  permite  identificarlos  unívocamente  en  toda  la 

state 

definición del proceso y así generar una transición a ellos. Este  tipo de nodos contienen nodos hijos que conrresponden a las  actividades  realizadas  por  el  estado.  El  nombre  del  estado  se  define con el atributo “name”.  Este tipo de nodo permite realizar una transición a otro estado  del proceso. Dependiendo del proceso la transición puede ser  condicional,  en  estos  casos  se  implementarán  2  nodos  de 

transtion 

transición  seguidos  con  el  atributo  “condition”  definido.  La  primera  transición  cuya  evaluación  resulte  verdadera  sera  quien  realice  la  transición.  El  nodo  a  recibir  el  flujo  de  ejecución se especifica con el atributo “to”.  Los  nodos  “decision”  permiten  efectuar  saltos  condicionales  usando transiciones. El parámetro “handler” indica el nombre 

decision 

de un método en el proceso PHP asociado al meta‐proceso que  tiene como objetivo cargar las condiciones para la evaluación  en las transiciones siguientes.  Este  tipo  de  nodos  tienen  un  handler  que  referencia  un 

task 

método  en  el  proceso  PHP  asociado  y  normalmente  es  usado  para  realizar  una  operación  de  negocio  parte  del  meta‐ proceso.  

task‐node 

Cuando  se  requiere  ejecutar  varios  nodos  “task”  se  usa  un  “task‐node”  el  cual  permite  asociar  varias  operaciones  de 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                113 

negocio dentro de un estado del meta‐proceso.    10.3.2 Crear los handlers del BusinessProcess  Un proceso de negocio debe ser definido el cual realizará la carga de la definición PDL para su  posterior ejecución:    Ejemplo: Crear una clase de proceso de negocio BusinessProcess  <?php class PedidoProcess extends BusinessProcess { /** * Inicializar el proceso de negocio * */ public function initialize(){ $processDefinition = ProcessDefinition::parseXMLFile("apps/pos/test/pedido.xml"); $processInstance = new ProcessInstance($processDefinition, $this); $processInstance->signal(); } }

  Enlaces externos:  

http://en.wikipedia.org/wiki/Business_Process_Management#BPM_Technology 

http://en.wikipedia.org/wiki/BPEL 

                             


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                114 

11 Componente Filter 11.1 Introducción El componente Filter proporciona un conjunto de filtros de datos y una interfase consistente  para su aplicación a datos y entrada de usuario en un proceso de negocio.    Los  filtros  están  diseñados  para  transformar  datos,  quitar  partes  indeseadas,  eliminar  espacios ó caracteres innecesarios y en resumen asegurarse que una variable contiene lo que  se espera que contenga.     El  aplicar  los  filtros  adecuados  a  la  entrada  de  usuario  constituye  el  primer  paso  para  cerciorarse que los procesos de negocio se ejecutaran utilizando datos que en cierta forma no  dañen ni alteren el flujo y estado normal de una aplicación. 

11.2 Estructura del Componente El  componente  lo  constituye  la  clase  Filter  y  una  serie  de  filtros  base  de  uso  general  que  incluye el framework para su aplicación al común de aplicaciones Web de negocios.    Los filtros base son los siguientes:    Tabla: Filtros base del componente Filter  Nombre 

Nombre Corto 

Uso/Descripción 

Alnum 

alnum 

Filtra  caracteres  alfanuméricos  (letras  y  números). 

Alpha 

alpha 

Filtra 

letras 

del 

abecedario 

occidental 

incluyendo caracteres latinos como vocales con  tilde y eñes.  AddSlaches 

addslaches 

Escapa las comillas simples y dobles para evitar  inyección de SQL. 

BaseName 

basename 

Filtra  un  path  para  obtener  el  nombre  del  archivo ó el último directorio. 

Date 

date 

Filtra  una  cadena  de  caracteres  devolviendo  una fecha que coincida con la expresión regular  '/(19|20)(\d{2})[‐\/](\d{1,2})[‐\/](\d{1,2})/' 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                115 

ó el formato YYYY‐MM‐DD.  Digits 

digits 

Filtra  una  cadena  para  que  contenga  solo  dígitos (números del 0 al 9) 

Double 

double 

Filtra  un  valor  devolviendo  un  valor  numérico  de alta precisión. 

Email 

email 

Filtra una cadena de caracteres devolviendo un  correo electrónico valido. 

Extraspaces 

extraspaces 

Filtra  una  cadena  de  caracteres  eliminando  espacios y saltos de línea al principio y final de  la cadena. 

Float 

float 

Filtra  un  valor  devolviendo  un  valor  numérico  de alta precision 

HtmlEntities 

htmlentities 

Convierte  todos  los  caracteres  aplicables  de  una cadena de caracteres a sus entidades HTML  correspondientes. 

HtmlDecode 

htmldecode 

Convierte entidades HTML a su carácter UTF‐8  correspondiente. 

Identifier 

identifier 

Filtra un valor dejando solo un identificador de  variable valido. 

Int 

int 

Filtra el valor recibido en un entero de 32bit ó  64 bit dependiendo de la plataforma. 

Ipv4 

ipv4 

Filtra  una  cadena  de  caracteres  devolviendo  una dirección IP versión 4. 

Ipv6 

ipv6 

Filtra  una  cadena  de  caracteres  devolviendo  una dirección IP versión 6. 

Lower 

lower 

Filtra  una  cadena  de  caracteres  devolviéndola  en minúsculas. Este filtro respeta el charset de  la aplicación. 

Locale 

locale 

Filtra  una  cadena  de�� definición  de  localización  UNICODE. 

Md5 

md5 

Convierte  una  cadena  de  caracteres  a  su  resumen criptográfico md5 

Numeric 

numeric 

Convierte el valor recibido en valor numérico. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

Onechar 

onechar 

Stripspace 

stripspace 

 

                                                                116 

Filtra la cadena para obtener un solo carácter.  Elimina  los  caracteres  espacios  en  toda  la  cadena de caracteres recibida. 

Striptags 

striptags 

Elimina  las  etiquetas  HTML  que  contenga  la  cadena de caracteres recibida. 

Stripslaches 

stripslaches 

Des‐escapa 

una 

cadena 

de 

carácteres 

convirtiendolos  a  sus  carácteres  de  comillas  normales.  Upper 

upper 

Filtra  una  cadena  de  caracteres  devolviéndola  en mayúsculas. Este filtro respeta el charset de  la aplicación. 

Utf8 

utf8 

Convierte  una  cadena  de  caracteres  en  ISO‐ 8859‐1 a UTF‐8 

11.3 Usar filtros en forma directa Para  aplicar  un  filtro  a  un  valor  en  forma  directa  es  necesario  instanciar  la  clase  Filter  e  invocar  el  método  applyFilters  enviando  como  primer  parámetro  el  valor  a  filtrar  y  como  parámetros siguientes los nombres cortos de los filtros a aplicar:    Ejemplo: Crear filtros en forma directa  <?php $filter = new Filter(); print $filter->applyFilter("a1b2c3d4e5", "digits"); // Imprime 12345 $filter = new Filter(); print $filter->applyFilter("<h1>Hola</h1>", "striptags", “upper”); // Imprime HOLA

  Es  necesario  crear  una  instancia  de  filter  por  cada  combinación  de  filtros  que  se  requieran  aplicar ya que cada objeto filter almacena en un buffer estos filtros:     Ejemplo: Usar el buffer de los filtros  <?php $filter = new Filter(); print $filter->applyFilter("a1b2c3d4e5", "digits"); // Imprime 12345 print $filter->applyFilter("www.radiobox77.com"); // Imprime 77

11.4 Crear chains de Filtros Es posible crear chains para la aplicación de filtros base y de usuario a un mismo valor de la 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                117 

siguiente manera:    Ejemplo: Implementar Chains de Filtros  <?php Filter::load("striptags", "email", "lower", “special”); $filter = new Filter(); $filter->addFilter(new StriptagsFilter()); $filter->addFilter(new EmailFilter()); $filter->addFilter(new LowerFilter()); $filter->addFilter(new LowerFilter()); $filter->addFilter(new SpecialFilter()); print $filter->applyFilter("<b>ANEWUSER1978@YAHOO.ES</b>")."<br>";

  El  método  estático  Filter::load  carga  uno  ó  más  filtros  ya  sean  de  usuario  ó  base  luego  se  agregan los filtros y se aplican como es estándar. Los filtros también pueden agregarse por su  nombre corto, agregar varios a la vez y mezclarlos. El orden en que se agregan indica el orden  de aplicación:    Ejemplo: Aplicar múltiples filtros a un valor  <?php Filter::load("striptags", "email", "lower", “special”); $filter = new Filter(); $filter->addFilter("striptags"); $filter->addFilter("email", new LowerFilter()); $filter->addFilter(new SpecialFilter()); print $filter->applyFilter("<b>ANEWUSER@YAHOO.ES</b>")."<br>";

11.5 Usar filtros en Controladores Los controladores son probablemente un punto donde los filtros tengan mayor participación  ya que es aquí donde se requiere asegurar que los procesos de negocio se ejecuten con datos  consistentes y confiables.    El método de Controller::filter actua como un Proxy al componente Filter permitiendo filtrar  variables sin instanciar explícitamente alguna clase adicional:    Ejemplo: Aplicar un filtro desde un controlador  <?php class InvoicesController extends ApplicationController { public function listInvoicesAction(){ //Se obtiene un valor de la entrada y se filtra $initialDate = $this->getPostParam("initialDate");


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                118 

$initialDate = $this->filter($initialDate, "date"); }

//Resto del proceso… }

  Adicional  a  lo  anterior  los  métodos  de  Controller  getPostParam,  getRequestParam  y  getQueryParam reciben como parámetros extra al valor requerido nombres cortos de filtros  los cuales se aplican en este orden y se retornan al proceso:    Ejemplo: Aplicar un filtro a la entrada de usuario  <?php class InvoicesController extends ApplicationController { public function listByNameInvoicesAction(){ //Se obtiene un valor de la entrada y se filtra directamente $name = $this->getPostParam("name", “striptags”, “extraspaces”); }

//Resto del proceso… }

11.6 Filtrar la entrada de usuario El  componente  filter  está  integrado  a  los  controladores  permitiendo  validar  la  entrada  de  usuario cuando es recibida desde un formulario ó una URL.    El siguiente ejemplo  define una serie de reglas para validar los valores recibidos desde una  entrada de usuario generando los mensajes correspondientes:    Ejemplo: Filtrar y validar la entrada de usuario desde un formulario  <?php class UsersController extends ApplicationController { public function doRegisterAction(){ $fields = array( 'username' => array( 'message' => 'Por favor indique su nombre de usuario', 'filter' => 'extraspaces|striptags' ), 'password' => array( 'message' => 'Por favor indique su contrase&ntilde;a' ), 'confirmPassword' => array( 'message' => 'Por favor indique la confirmaci&oacute;n de la contrase&ntilde;a' ), 'email' => array( 'message' => 'Por favor indique su correo electrónico', 'filter' => 'email' ),


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                119 

'confirmEmail' => array( 'message' => 'Por favor indique la confirmación de su correo electrónico', 'filter' => 'email' ), 'name' => array( 'message' => 'Por favor indique su nombre', 'filter' => 'extraspaces|striptags' ), 'lastName' => array( 'message' => 'Por favor indique sus apellidos', 'filter' => 'extraspaces|striptags' ), 'address' => array( 'message' => 'Por favor indique la dirección de su residencia', 'filter' => 'extraspaces|striptags' ), 'phone' => array( 'message' => 'Por favor indique su teléfono' ), 'city' => array( 'message' => 'Por favor indique la ciudad' ), 'company' => array( 'message' => 'Por favor indique la empresa' ) ); if($this->validateRequired($rules)==false){ foreach($this->getValidationMessages() as $message){ $message->showErrorMessage(); } $this->routeTo(array('action' => 'startSignIn')); } } }

La  propiedad  de  la  regla  ‘filter’  permite  definir  el  filtro  que  debe  ser  aplicado  a  cada  valor  recibido antes de determinar si está presente, de esta forma se controla que el valor evaluado  sea válido y se genere el mensaje correspondiente.  Si se requiere que se aplique más de un  filtro, se puede indicar una lista separada por | (pipes).    Consulte  el  componente  Validator  para  obtener  más  información  sobre  filtrar  la  entrada  de  usuario. 

11.7 Crear un filtro de usuario El  desarrollador  puede  crear  sus  propios  filtros  en  la  aplicación  e  integrarlo  al  componente  filter para su posterior utilización.    Tanto los filtros base como los de usuario deben implementar la interface FilterInterface que  tiene la siguiente estructura:    <?php interface FilterInterface {


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                120 

public function execute($value); }

11.7.1 Requerimientos de un filtro de usuario  Al crear un filtro de usuario se debe tener en cuenta lo siguiente:    •

Se crea un archivo ubicado en el directorio filters/ de la aplicación ó donde la opción  filtersDir del archivo de configuración config/config.ini indique. 

El nombre del archivo es el nombre del filtro con la primera letra en mayúscula  

El archivo debe contener una clase con el nombre del filtro y sufijo “Filter” 

La clase debe implementar la interface FilterInterface 

  En el siguiente ejemplo se crea un filtro de usuario que apartir de una URL filtra el dominio  que corresponde a ella:    Ejemplo: Filter de usuario que filtra dominios en una URL  <?php class DomainFilter implements FilterInterface { public function execute($url){ $protocol = strpos($url, "//"); if($protocol!==false){ $url = substr($url, $protocol+2); } $fisrtSlash = strpos($url, "/"); if($fisrtSlash!==false){ $url = substr($url, 0, $fisrtSlash); } return $url; } }

  En  cualquier  parte  de  la  aplicación  se  puede  utilizar  usando  su  nombre  corto  ó  cargandolo  mediante Filter::load:    Ejemplo: Aplicar un filtro de usuario  <?php $filter = new Filter(); $url = "http://www.google.com/?q=kumbia%20framework"; print $filter->applyFilter($url, "domain"); // www.google.com

     


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                121 

12 ActionHelpers 12.1 Introducción Los  ActionHelpers  son  subcomponentes  auxiliares  que  complementan  y  auxilian  a  las  implementaciones de controladores algunas veces estableciendo puentes a la presentación y  otras veces a la capa de datos. 

12.2 Mensajes usando Flash El ActionHelper Flash permite la generación de mensajes contextuales en cualquier parte de la  aplicación.    Adicional  a  esto  es  posible  almacenar  mensajes  para  ser  mostrados  cuando  se  requiera en otras peticiones.  12.2.1 Generar mensajes contextuales   Los  mensajes  contextuales  permiten  aparte  del  mensaje  por  medio  de  colores  e  iconos  informar el carácter del mismo.    Tabla: Tipos de mensajes contextuales con Flash  Método  Flash::error 

Flash::notice 

Tipo  Error 

Descripción  Informa que hay una situación de error. Por defecto se usa  fondo rosa, texto en rojo y un icono de adminiración. 

Información 

Da  el  contexto  de  información.  Por  defecto  se  usa  fondo  azul y letra azul oscuro. 

Éxito  Flash::success 

Indica que la operación tuvo éxito ó se ejecutó un proceso  satisfactoriamente.  Por  defecto  se  usa  fondo  verde  llamativo y letra verde oscura. 

Advertencia  Flash::warning 

Genera  un  mensaje  con  el  contexto  de  advertencia.  Por  defecto se usa amarillo claro en el fondo, letra en negro y  un icono de alerta. 

  Todos los métodos reciben en su parámetro el mensaje a mostrar.   12.2.2 Cambiar el estilo por defecto de los mensajes  Si se desea cambiar el estilo de los mensajes de texto se puede modificar ó sobreescribir las  clases CSS en el archivo public/css/style.css que siempre se inserta en todas las peticiones. Por 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                122 

defecto las clases tienen los siguientes estilos:    Ejemplo: Estilos CSS predefinidos para mensajes del Flash  .kumbiaDisplay { font-size: 11px; font-weight: bold; margin: 0 auto; padding: 2px 25px; background-repeat: no-repeat; background-position: 5px center; text-align: left; } .errorMessage { background-image: url("@path/img/error.gif"); background-color: #FFDDDD; color: #B30000; border: 1px solid #FFB7B7; margin: 2px; text-align: left; } .noticeMessage { background-image: url("@path/img/user.gif"); background-color: #CCDEFF; color: #004A6F; margin: 2px; border: 1px solid #004A6F; text-align: left; } .sucessMessage { background-image: url("@path/img/ok.gif"); background-color: #CCFF99; color: #008000; border: 1px solid #008000; } .warningMessage { background-image: url("@path/img/warning.gif"); background-color: #FFFFC6; color: #000000; border: 1px solid #DDDD00; }

12.2.3 Cambiar el estilo en forma dinámica  Si  se  requiere  cambiar  la  presentación  de  un  mensaje  en  forma  programacional  se  puede  enviar un listado de clases CSS como segundo parámetro.     Ejemplo: Establecer una clase CSS personalizada para Flash   Flash::notice("Esto es una información personalizada", array("mi_clase_css", "otra_clase_css"));

  12.2.4 Enviar múltiples mensajes del mismo tipo en forma simúltanea  Cuando el primer parámetro recibido por un método de mensajes es un vector con mensajes  la lista de estos es enviada una tras otra en el orden recibido.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                123 

Ejemplo: Enviar varios mensajes simultáneos  mediante un array con Flash   Flash::error(array( "Este es el primer error", "Este es el segundo error", "Este es el tercer error", ));

12.2.5 Mostrar mensajes por su tipo  El  método  de  Flash  llamado  message  permite  mostrar  un  mensaje  utilizando  una  constante  como segundo parámetro que establece el tipo a mostrar:    Flash::message("Esto es una advertencia", Flash::WARNING); Flash::message("Esto es un error", Flash::ERROR, array("my_error_css"));

  Tabla: Constantes de los tipos de mensajes  Valor 

Constante 

Descripción 

Flash::ERROR 

Mensajes de error 

Flash::NOTICE 

Mensajes de información 

Flash::SUCCESS 

Mensajes de éxito 

Flash::WARNING 

Mensajes de advertencia 

  12.2.6 Cachear mensajes para mostrarlos en la próxima petición  Si  se  requiere  mostrar  mensajes  al  usuario  después  de  realizar  una  redirección  se  puede  utilizar el método addMessage que funciona como el método message recibe el mensaje y un  código indicando el tipo. Los mensajes que se agregan de esta forma no son visualizados sino  hasta que se invoca el método getMessages().      El siguiente ejemplo ilustra el funcionamiento de este tipo de mensajes:    Ejemplo: Enviar mensajes Flash usando la cola de mensajes de próxima petición  <?php class LoginController extends ApplicationController { public function indexAction(){ Flash::addMessage("Bienvenido usuario", Flash::SUCCESS); $this->redirect("login/menu"); } public function menuAction(){ foreach(Flash::getMessages() as $message){ Flash::message($message['message'], $message['type']); } }


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                124 

}

  Los  mensajes  agregados  con  addMessage�� se  almacenan  en  un  buffer  del  contexto  de  sesión.  Cuando los mensajes se obtienen con getMessages el buffer interno se resetea. 

12.3 Condiciones SQL con FormCriteria El  actionhelper  FormCriteria  permite  crear  condiciones  SQL  a  partir  de  los  parámetros  recibidos  por  un  formulario  de  entrada  de  usuario.  De  acuerdo  a  los  parámetros  recibidos,  solo los que tengan valores no nulos se incluyen en las condiciones generadas.    En el siguiente ejemplo se muestra como crear la condición de búsqueda para diversos tipos  de datos obtenidos desde un formulario.    Los datos capturados son:    

Código: Corresponde al código del producto y es de tipo numérico. 

Nombre: El nombre del producto y es de tipo texto. 

Categoría:  Campo  de  tipo  entero  de  la  entidad  Products  que  es  relación  a  la  tabla 

ProductCategories.  Se  usa  Tag::select  para  cargar  los  datos  de  esta  tabla  y  se  indica  el  parámetro useDummy para agregar la opción ‘Seleccione…’.  

Tipo:  Combo  creado  apartir  de  un  array  con  valores  estáticos  que  corresponde  al 

campo type de la entidad Products.    El formulario en la vista views/products/index.phtml es el siguiente:    <h1>Buscar Productos</h1> <?php echo Tag::form('products/search'); ?> <table> <tr> <td align="right">Código:</td> <td><?php echo Tag::numericField('code') ?></td> </tr> <tr> <td align="right">Nombre:</td> <td><?php echo Tag::textField('name') ?></td> </tr> <tr> <td align="right">Categoría:</td> <td><?php echo Tag::select('product_category_id', $ProductsCategories->find(), 'using: id,name', 'useDummy: yes') ?></td> </tr> <tr> <td align="right">Tipo:</td> <td><?php echo Tag::selectStatic('type', array(


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

</tr> <tr>

'A' => 'B' => 'O' => ), 'useDummy:

 

                                                                125 

'ALIMIMENTOS', 'BEBIDAS', 'OTRO' yes') ?></td>

<td></td> <td><?php echo Tag::submitButton('Enviar') ?></td> </tr> </table> <?php echo Tag::endForm() ?>

  En el controlador se define la búsqueda según se envie los parámetros a la acción search:     Ejemplo: Crear un criterio de búsqueda SQL usando FormCriteria  <?php class ProductsController extends ApplicationController { public function indexAction(){ } public function searchAction(){ $criteria = new FormCriteria($_POST, array( 'code' => array( 'type' => 'integer', 'fieldName' => 'id' ), 'name' => array( 'type' => 'string' ), 'product_categories_id' => array( 'type' => 'integer', 'operator' => '=', 'nullValue' => '@' ), 'type' => array( 'type' => 'string', 'operator' => '=', 'nullValue' => '@' ) )); $this->Products->find($criteria->getConditions()); } }

  El  constructor  recibe  2  parámetros,  el  primero  corresponde  al  origen  de  los  datos  de  los  cuales se construira el criterio de búsqueda. El segundo es un descriptor con los campos que  se reciben del formulario y la forma en que debe construirse la condición para cada uno. Las  llaves  del  descriptor  son  los  nombres  de  las  variables  que  vienen  del  formulario  y  que  son  parte del origen de datos.  En el ejemplo el origen de datos es la superglobal $_POST.    La descripción de las opciones para cada campo es:    Tabla: Opciones de los campos para crear el criterio de búsqueda con FormCriteria 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

Opción  type 

 

                                                                126 

Descripción  Es  el  tipo  de  dato  que  se  espera  recibir  del  formulario.  Puede  ser  integer,  float,  double,  date  y  string.  Dependiendo  del  tipo  de  dato  es  posible que se apliquen filtros.  

operador 

Un  operador  compatible  con  el  gestor  relacional  utilizado.    Cuando  la  opción  “type”  es  integer,  float,  double  y  date  se  utiliza  el  operador  ‘=’  cuando es string se usa el operador ‘LIKE’.  

missOnNull 

Un valor booleano que determina si se debe omitir la condición  caso de  que el valor recibido sea nulo ó el valor establecido para nulo mediante  ‘nullValue’. Por defecto su valor es true. 

nullValue 

El  valor  que  debe  entenderse  como  valor  nulo  para  saber  si  se  debe  omitir al generar la condición. 

fieldName 

El nombre del atributo en la entidad. Si no se indica se usa el nombre de  la llave en el descriptor. 

  Si se envia el valor code=10 se produce la condición:    id = 10

Si se envian los valores code=10 y nombre=”cheese cake” se produce la condición:    id = 10 OR name LIKE ‘%cheese%cake%’

Si se envian los valores product_categories_id = 2 y type=’A’ (type es el nombre del campo) se  produce la condición:    product_categories_id = 2 OR type = ‘A’

  Por  defecto  el  operador  para  unir  las  condiciones  es  OR,  con  lo  que  si  cualquiera  de  las  opciones  se  cumple  entonces  se  obtiene  el  resultado.  Si  se  desea  lo  contrario  entonces  se  puede enviar el operador como parámetro de getConditions así.    $this->Products->find($criteria->getConditions(‘AND’));

12.3.1 Criterios de Rangos  Con  FormCriteria  también  es  posible  crear  criterios  de  rangos  cuyos  valores  sean  obtenidos  de un formulario de entrada de usuario.    


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                127 

Si lo que se requiere es que apartir de campos obtenidos del formulario se cree la condición  entonces debe definir de la siguiente forma:    Ejemplo: Crear un criterio basado en un rango de fechas con FormCriteria  $criteria = new FormCriteria($_POST, array( 'fechaInicial:fechaFinal' => array( 'type' => 'date', 'fieldName' => 'fecha' ) ));

  Si se envian los valores fechaInicial=”2008‐10‐20” y fechaFinal=”2008‐11‐22” se produciría la  siguiente condición:    fecha >= ‘2008-10-20’ AND fecha <= ‘2008-11-22’

  Y si lo que se requiere es que el valor de la entrada de usuario se encuentre entre 2 campos de  la tabla entonces se define así:    //La tabla es de registro de vuelos $criteria = new FormCriteria($_POST, array( ‘fecha' => array( 'type' => 'date', 'fieldName' => 'fechaLlegada:fechaSalida' ) ));

Si se envian el valor fecha=”2008‐10‐20”  se produciría la siguiente condición:    fechaLlegada >= ‘2008-10-20’ AND fechaSalida <= ‘2008-10-20’

12.3.2 Unir varias condiciones  Varias  criterios  pueden  ser  unidos  utilizando  operadores  diferentes  para  de  esta  forma  construir condiciones más complejas:    Ejemplo: Crear condiciones de búsqueda compuestas con FormCriteria::form  $criteria1 = new FormCriteria($_POST, array( 'code' => array( 'type' => 'integer', 'fieldName' => 'id' ), 'product_categories_id' => array( 'type' => 'integer', 'operator' => '=', 'nullValue' => '@' ), )); $criteria2 = new FormCriteria($_POST, array( 'code' => array( 'type' => 'integer', 'fieldName' => 'id'


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

));

 

                                                                128 

), 'name' => array( 'type' => 'string' ), $conditions = FormCriteria::join(‘OR’, array( $criteria1->getConditions(‘AND’), $criteria2->getConditions(‘AND’) ));

  El  método  estático  FormCriteria::join  puede  unir  2  ó  más  objetos  FormCriteria  con  un  operador diferente. 

12.4 Información del Navegador con Browser Este ActionHelper permite obtener información del explorador del cliente desde el cuál se está  accediendo a la aplicación.  12.4.1 API de Browser  El API es la siguiente:    public static boolean isFirefox()  Devuelve true si el explorador utilizado es Mozilla Firefox.    public static boolean isSafari()  Devuelve true si el explorador utilizado es Apple Safari.    public static boolean isCamino()  Devuelve true si el explorador utilizado es Camino.    public static boolean isInternetExplorer()  Devuelve true si el explorador utilizado es Microsoft Internet Explorer.    public static boolean isMobileSafari()  Devuelve true si el explorador utilizado es Apple Mobile Safari, el que usa el SO del iPhone y  iPod Touch.    public static boolean isIEMobile()  Devuelve  true  si  el  explorador  utilizado  es  Microsoft  Internet  Explorer  Mobile  usado  en  el  sistema operativo Windows Mobile. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                129 

  public static boolean isOperaMobile()  Devuelve  true  si  el  explorador  utilizado  es  Opera  Mobile  si  el  explorador  utilizado  es  Opera  para Windows Mobile.    public static string getVersion()  Devuelve la versión del explorador utilizado.    public static string getUserAgent()  Devuelve el User Agent del explorador cliente.    public static boolean isGecko()  Devuelve true si el motor de renderizado del explorador es Gecko.    public static boolean isWebKit()  Devuelve true si el motor de renderizado del explorador es WebKit.    public static string getAcceptEncoding()  Indica los tipo de codificación soportador por el explorador.    public static string getAcceptLanguage()  Obtiene el idioma utilizado por el explorador usando el estándar RFC.    public static boolean acceptCompressedOutput()  Indica si el explorador acepta salida comprimida ya sea usando gzip ó deflate.    public static string getBrowserAbrev()  Devuelve una abreviatura del User Agent del explorador.    public static boolean isMobile()  Indica si el explorador usado se encuentra en una plataforma móvil.    public static boolean isMacOSX()  Devuelve true si el sistema operativo del cliente es Apple Mac OS X. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                130 

  public static boolean isWindows()  Devuelve true si el sistema operativo del cliente es Microsoft Windows    public static boolean isLinux()  Devuelve true si el sistema operativo del cliente es Linux. 

12.5 Autocompletar con Scriptaculous El  helper  Scriptaculous  permite  convertir  un  conjunto  de  datos  en  el  formato  compatible  al  componente  visual  de  autocompletar  que  proporciona  el  framework  script.aculo.us.  En  el  siguiente ejemplo se muestra el uso de este:    En  la  vista  se  usa  el  helper  de  la  vista  Tag::textWithAutocomplete  para  crear  un  campo  con  autocompletar:    <?php echo Tag::textFieldWithAutocomplete('pais', 'action: paises/consultar') ?>

Según su definición cuando el usuario escriba algunos carácteres se obtendrán los datos del  resultado de la acción consultar en el controlador paises.    Si  los  datos  de  paises  se  obtienen  de  un  array  estático  entonces  el  controlador  paises  es  el  siguiente:    Ejemplo:  Obtener  los  datos  de  auto­completado  desde  una  array  usando  Scriptaculous::autocomplete  <?php class PaisesController extends ApplicationController { public function consultarAction(){ //Se indica que la respuesta es AJAX $this->setResponse('ajax'); //Se obtiene lo que digitó el usuario en la caja de texto $pais = $this->getPostParam('pais'); //Obtener los datos de un array estatico $paises = array( 'C' => 'COLOMBIA', 'E' => 'ECUADOR', 'M' => 'MEXICO', 'A' => 'ARGENTINA', 'U' => 'URUGUAY', 'B' => 'BOLIVIA' );


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                131 

//Se filtran los que coincida con la busqueda $paisesBusqueda = Scriptaculous::filter($pais, $paises); //Se genera el HTML a devolver al usuario $htmlCode = Scriptaculous::autocomplete($paisesBusqueda); $this->renderText($htmlCode); }

}

  Si los datos de paises se obtienen de una tabla entonces el controlador paises es el siguiente:    Ejemplo:  Obtener  los  datos  de  auto­completado  desde  una  tabla  usando  Scriptaculous::autocomplete  <?php class PaisesController extends ApplicationController { public function consultarAction(){ //Se indica que la respuesta es AJAX $this->setResponse('ajax'); //Campos del modelo utilizados para crear el resultado $fields = array('cod_pais', 'nombre'); //Obtener los paises requeridos $paises = Scriptaculous::querySource(‘paises’, $fields, $pais); //Se genera el HTML a devolver al usuario $htmlCode = Scriptaculous::autocomplete($paises, $fields); $this->renderText($htmlCode); } }

                       

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                132 

13 Componente Validator 13.1 Introducción Este componente está integrado a las implementaciones de controladores y permite realizar  validaciones sobre la entrada de usuario. Al ser independiente de la capa de lógica de dominio  y presentación puede ser usado en los puntos de la aplicación que se requiera sin afectar la  arquitectura de la misma.                                                       


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                133 

Parte 2: Seguridad    

14 Seguridad con Kumbia Enterprise 14.1 Introducción Las aplicaciones Web y Servicios Web creadas usando Kumbia Enterprise Framework pueden  ser distribuidas e implementadas usando diferentes entornos dentro de una misma instancia.  Cada  aplicación  puede  constituir  una  arquitectura  multicapa  independiente  con  requerimientos de seguridad diferentes.    La seguridad de una aplicación puede ser implementada de 2 formas:    •

Declarativa  Externa:  Se  definen  los  requerimientos  de  seguridad  de  una  aplicación  utilizando recursos externos a la misma sin intervenir de manera intrusiva en la lógica  de la aplicación. La descripción de esta incluye detalles sobre como los roles acceden a  los recursos de la aplicación y sus políticas.  

Programacional  Interna:  Esta  embebida  en  la  aplicación  y  esta  implementada  en  forma  de  decisiones  de  seguridad,  es  suficiente  cuando  los  requerimientos  de  seguridad son simples y no cambian con frecuencia. 

14.2 Características de Seguridad Mecanismos adecuados de seguridad ofrecen la siguiente funcionalidad:    •

Previenen acceso inautorizado a información y procesos de negocio 

Controlan  que  las  actividades  realizadas  por  un  usuario  no  interfieran  con  las  realizadas por otros impactando la integridad del sistema. 

Protegen  el  los  servicios  del  sistema  de  riesgos  que  puedan  decaer  la  calidad  del  servicio proporcionada 

  La  seguridad  de  aplicaciones  basadas  en  Kumbia  Enterprise  Framework  consiste  en  la  implementación  de  componentes  que  ayuden  a  proteger  los  recursos  de  la  misma.  Los  procesos  de  seguridad  requieren  de  la  implementación  adecuada  de  autenticación,  identificación, control de acceso, integridad de datos y calidad del servicio:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                134 

Autenticación:  La  aplicación  ejecuta  procesos  que  permiten  confiar  que  quien  hace 

uso de la misma es quien realmente se espera.  

Autorización:  Es  el  proceso  de  identificar  a  que  conjunto  de  recursos  puede 

utilizar/acceder  con  el  propósito  de  establecer  controles  adecuados  de  integridad  de  datos y limitaciones.  

Integridad  de  Datos:  Permiten  que  solo  usuarios  ó  roles  autorizados  alteren  la 

información  a  la  que  se  les  ha  permitido  el  acceso  y  que  no  intervengan  con  otros  procesos de otros usuarios autenticados.  

Confidencialidad ó Privacidad: Permite que la información solo esté disponible para 

el usuario adecuado y de la forma adecuada.  

Calidad del Servicio (QoS): Permite que se ofrezca una mejor experiencia de usuario 

aprovechando diferentes tecnologías.  

Auditoria:  Permite  almacenar  un  registro  consistente  que  permita  saber  las 

actividades que un usuario realizo y bajo que condiciones se realizaron. 

14.3 Mecanismos de Seguridad Kumbia  Enterprise  Framework  ofrece  diferentes  componentes  para  una  adecuada  implementación  de  seguridad  tanto  de  aplicaciones  Web  como  de  Servicios  Web  empresariales:    

Access  Control  List  (ACL):  Este  componente  permite  crear  listas  en  donde  se 

establece a que recursos puede acceder determinados roles.  

Auth: Permite realizar el proceso de autenticación utilizando diferentes adaptadores 

como Digest, LDAP, Bases de Datos, Kerberos5 y Radius.  

AuditLogger: Permite crear registros de auditoria de las actividades realizadas en las 

aplicaciones.  

Session:  Mantiene  la  persistencia  de  sesión  independiente  entre  aplicaciones  y 

usuarios autenticados.  

Security: Permite detectar ataques de negación de servicio ó bloquear el acceso a un 

cliente através de su dirección IP. 

14.4 Seguridad a nivel de Capa de Aplicación Los controladores en las aplicaciones son apropiados para establecer controles de seguridad  en  las  aplicaciones,  sin  embargo,  todos  los  requerimientos  de  seguridad  no  pueden  ser 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                135 

controlados  en  profundidad  desde  este  punto  y  generalmente  es  necesario  apoyarse  por  firewalls u otras técnicas para aumentar la confiabilidad de un sistema.    Como cada aplicación maneja sus propios entornos de ejecución y de memoria la información  de  seguridad  reside  en  forma  independiente  facilitando  la  administración  de  cada  entorno.  Cuando  se  utilizan  servicios  Web  con  múltiples  intermediarios  es  posible  que  haya  la  necesidad  de  implementar  mecanismos  de  seguridad  compartidos  y  transferencia  de  identidad entre aplicaciones.    Las ventajas de la seguridad a nivel de aplicación incluyen:    

La  seguridad  de  cada  aplicación  se  puede  adaptar/generar  de  acuerdo  a  las 

necesidades de cada una.  

La seguridad es optimizada con opciones especificas de cada una. 

  Las desventajas de este tipo de implementación son:    

La  aplicación  es  dependiente  de  atributos  de  seguridad  que  no  pueden  ser 

establecidos ó transferidos desde otra.  

Se  crea  un  único  punto  de  vulnerabilidad  que  de  ser  violado  expondría  muchos 

aspectos de las aplicaciones. 

14.5 Seguridad a nivel de Capa de Transporte El uso de protocolos como HTTPS/SSL puede mejorar la seguridad desde otro punto de vista  sin que pueda reemplazar la seguridad a nivel de aplicación. La seguridad a nivel de capa de  transporte  trata  de  mecanismos  uno  a  uno  en  donde  por  medio  de  llaves  criptográficas  es  posible implementar autenticación, integridad de mensajes y confidencialidad.     Certificados  digitales  son  requeridos  para  implementar  este  tipo  de  seguridad.  Estos  están  directamente asociados al servidor Web utilizado y suponen una capa de la cual el framework  no puede tener control.    Las ventajas de la seguridad en la capa de transporte son:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

Fácil de implementar. 

Esta basado en estándares 

 

                                                                136 

14.6 Implementar Seguridad Declarativa El componente de listas de control de Acceso de Kumbia Enterprise (ACL) esta integrado con  el  Core  del  framework  interceptando  cada  petición  y  validando  que  su  ejecución  este  permitida en el contexto actual. La seguridad declarativa está implementada usando listas de  control de acceso definidas en la configuración de la aplicación mediante descriptores.     Los  descriptores  permiten  definir  la  estructura  de  autorización  de  seguridad  que  incluye:  roles, control de acceso y requerimientos de autenticación en forma externa a la aplicación.    La opción securityAccessList en la sección application del archivo config.ini permite establecer  el tipo de lista de acceso que controlará la seguridad de la aplicación:    Ejemplo: Implementar seguridad declarativa desde config.ini  [application] mode = production name = "Project Name" dbdate = Y-m-d debug = Off securityAccessList = “xml:filePath=%app-base%/security/security.xml”

  Los descriptores ACL tienen el formato de un Data Source Name indicando primero el nombre  del adaptador a utilizar y luego las opciones del mismo usando punto y comas para separar las  mismas. Los descriptores deben ir entre comillas dobles con el fin de que ciertos caracteres no  causen conflictos al leer el archivo .ini.    En  el  siguiente  ejemplo  de  un  descriptor  de  una  lista  de  acceso  basada  en  XML  se  muestra  como definir los aspectos básicos de una lista. En el capítulo del componente Acl se detalla la  implementación de cada parte del archivo XML.    Ejemplo: Lista ACL en XML para control de acceso  <?xml version="1.0" encoding="UTF-8" ?> <security xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <!-- ROLES DE LA APLICACION --> <roles-collection> <role> <name>Public</name> <description>Rol para usuarios no autenticados</description> </role>


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                137 

<role> <name>EconomyCustomers</name> <description>Usuarios con plan economico</description> </role> </roles-collection> <!-- RECURSOS DE LA APLICACION --> <resources-collection> <resource> <name>banking</name> <description>Controlador para operaciones del cajero</description> </resource> <resource> <name>login</name> <description>Controlador para operaciones de inicio de sesión</description> </resource> </resources-collection> <!-- CONSTRAINTS DE ACCESO --> <access-constraint> <role-name>Public</role-name> <resource-name>*</resource-name> <action-name>*</action-name> <rule-type>deny</rule-type> </access-constraint> <access-constraint> <role-name>Public</role-name> <resource-name>login</resource-name> <action-name>validateCredentials</action-name> <rule-type>allow</rule-type> </access-constraint> <access-constraint> <role-name>EconomyCustomers</role-name> <resource-name>*</resource-name> <action-name>*</action-name> <rule-type>allow</rule-type> </access-constraint> <access-constraint> <role-name>EconomyCustomers</role-name> <resource-name>banking</resource-name> <action-name>checkBalance</action-name> <rule-type>deny</rule-type> </access-constraint> </security>

  Los  recursos  de  una  aplicación  para  la  seguridad  declarativa  son  los  controladores  de  la  misma  y  sus  nombres  coinciden  con  estos  en  las  opciones  resource­name  en  el  ejemplo.  La  asociación  recurso‐controlador  ofrece  un  potente  sistema  de  control  para  cada  petición  a  la  aplicación de forma transparente para el desarrollador.    El rol con el cual se realizan las validaciones de seguridad es el definido mediante el método  del  componente  Security  llamado  setActiveRole(string  $roleName),  cuando  el  rol  no  se  ha  definido  aún  se  usa  la  convención  para  el  rol  Public  de  tal  forma  que  se  asuma  que  la  aplicación es pública ó no se ha definido identificación de quien usa la aplicación.    Los recursos que no se han mencionado en las listas de acceso tienen por defecto la política 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                138 

‘Allow’ con lo que se hacen públicos con solo acceder a ellos.    Por cada petición a la aplicación el método Security::checkResourceAccess valida si el rol activo  tiene acceso al recurso solicitado. Cuando se tiene acceso al recurso el proceso de negocio en  la  acción  del  controlador  se  ejecuta  normalmente,  cuando  la  validación  falla,  la  aplicación  trata de enrutar a la acción del controlador llamada unauthorizedAccessAction. 

14.7 Implementar Seguridad Programacional La seguridad programacional esta embebida en la aplicación y esta implementada en forma de  decisiones de seguridad. Es más útil cuando la seguridad declarativa resulta muy básica y no  se adapta a las necesidades de negocio.     En este punto los filtros de controladores y el punto de entrada a la aplicación ControllerBase  resultan apropiados para definir las reglas de seguridad y aplicar el API de los componentes  Acl y Auth para controlar los procesos requeridos. 

14.8 Definir Realms, Usuarios y Grupos para Autenticación Los Realms son colecciones de usuarios los cuales pueden o no pertenecer a un determinado  grupo  y  son  controlados  mediante  una  misma  política  de  autenticación.  Normalmente  una  aplicación establece controles como un usuario y contraseña antes de proporcionar acceso a  un  recurso  protegido,  los  datos  proporcionados  por  un  usuario  se  validan  en  forma  de  credenciales  produciendo  un  resultado  de  éxito  del  proceso  de  autenticación.  Kumbia  Enterprise Framework ofrece diferentes adaptadores de autenticación usando el componente  Auth.    En algunos casos los usuarios de las aplicaciones tienen asignados roles, esto indica que hacen  parte de grupos con características se seguridad definidas en un dominio de aplicación.  14.8.1  Realms  Los realms son bases de datos de usuarios y grupos que contienen las credenciales necesarias  para  controlar  una  política  de  autenticación.  Debido  a  la  flexibilidad  del  componente  de  autenticación Auth es posible crear bases de datos de autenticación en varios formatos cada  uno con características distintas.  


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                139 

14.8.2  Usuarios  Los usuarios son identidades individuales que son reconocidos por la aplicación. Un usuario  puede tener roles asociados que permiten conocer que recursos pueden acceder de acuerdo a  una política de seguridad.   14.8.3  Grupos  Los  grupos  representan  una  serie  de  características  compartidas  por  uno  o  varios  usuarios.  Un  grupo  es  un  conjunto  de  usuarios  que  comparten  los  mismos  accesos  y  controles  de  seguridad en la aplicación.                                                    


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                140 

15 Componente ACL (Lista de Control de Acceso) 15.1 Introducción La Lista de Control de Acceso ó en inglés (Access Control List) es un componente de Kumbia  Enterprise  Framework  es  un  concepto  de  seguridad  informática  usado  para  fomentar  la  separación de privilegios. Es una forma de determinar los permisos de acceso apropiados a un  determinado objeto, dependiendo de ciertos aspectos del proceso que hace el pedido.   Al  igual  que  otros  componentes  del  framework  que  están  basados  en  componentes  se  implementa el patrón Virtual Proxy, una instancia de Acl solo actúa como un Proxy al objeto  real instanciado que corresponde al tipo de adaptador utilizado por el mismo. 

15.2 Estructura del Componente Kumbia  Enterprise  Framework  ha  integrado  la  siguiente  estructura  jerárquica  de  clases  que  permiten la implementación de este componente:  Tabla: Jerarquia de clases del componente Acl  Clase  Acl.php  Interface.php  Adapters/Memory.php 

Adapters/Xml.php 

Adapters/Model.php 

Resource/Resource.php 

Role/Role.php 

Descripción  Es  la  clase  constructora  de  las  listas  Acl.  Es  un  Proxy  a  la  funcionalidad implementada en cada adaptador.  Es la interfase que deben utilizar todos los adaptadores Acl .  Es  el  adaptador  que  permite  administrar  las  listas  de  acceso  en memoria.  El  Adaptador  permite  definir  listas  de  acceso  en  archivos  de  descripción en XML.  Es el adaptador permite la administración de la lista de acceso  a una base de datos como backend.  Es  la  clase  que  permite  administrar  cada  recurso  como  una  entidad independiente de su backend.  Es  la  clase  que  permite  administrar  los  roles  que  tendrán  acceso a la lista ACL independientemente de su backend. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                141 

15.3 ¿Que es un Recurso? Un recurso es cualquier elemento de una aplicación del cual se pueda controlar su acceso. Por  conveniencia  los  controladores  de  la  aplicación  son  vistos  como  recursos  con  el  objetivo  de  generar un modelo de seguridad consistente. 

15.4 ¿Que es un Rol? Un  rol  es  un  nombre  abstracto  para  el  permiso  de  usuarios  a  un  conjunto  particular  de  recursos en una aplicación. Un rol puede ser comparado a la llave que abre un candado, este  abre sin importar quien tiene la clave. Los roles están generalmente asociados a los mismos  usuarios, a los grupos de estos ó a sus perfiles. 

15.5 ¿Que es un Acceso? Los  accesos  son  las  operaciones  ó  acciones  que  se  pueden  realizar  en  los  recursos.  Niveles  más profundos de seguridad controlan hasta este nivel lo que se pueda hacer por parte de los  usuarios. 

15.6 Tipos de Reglas El acceso a un determinado recurso tiene una regla de ‘permitir’ (allow) ó ‘denegar’ (deny), no  están soportadas otros tipos de reglas de acceso. 

15.7 ACL en Acción En  el  siguiente  ejemplo  se  ilustra  como  al  definir  un  filtro  beforeFilter  en  la  clase  ControllerBase  en  apps/default/controllers/application.php  con  el  que  se  puede  implementar  el control de acceso a los recursos de la aplicación en forma programacional:    Ejemplo:  Utilizar  ACL  con  modelos  para  validar  el  acceso  a  los  recursos  de  una  aplicación  <?php class ControllerBase { public function beforeFilter(){ $role = Session::get('role'); if($role==""){ $role = 'Public'; } $acl = new Acl('Model', 'className: AccessList'); $resourceName = $this->getControllerName(); $operationName = $this->getActionName(); if($acl->isAllowed($role, $resourceName, $operationName)==false){ if($this->getControllerName()!='appmenu'){ $this->routeTo("controller: appmenu");


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

permiso

 

                                                                142 

} else { throw new ApplicationControllerException("No tiene para usar esta aplicación"); } $authLog = new Log(“File”, "auth_failed.txt"); $authLog->log("Autenticación fallo para el rol '$role' en el recurso '". $this->getControllerName()."/".$this->getActionName()."'"); return false; } } }

Gracias a que el método beforeFilter se encuentra en la jerarquía de todos los controladores  este se ejecuta previamente a cualquier acción solicitada. Se obtiene de los datos de sesión, la  variable  role  indica  el  nombre  del  rol  actualmente  logueado,  si  aun  no  hay  un  rol  activo  es  asignado por defecto Public.     Ahora es posible instanciar la clase Acl, y definir como adaptador un Modelo en donde se ha  referencia a la clase AccessList quien mapea a la tabla llamada access_list, la cual administra  los accesos a los recursos de la aplicación. La tabla contiene un Security Policy Domain de un  POS (Point Of Sale):    Ejemplo: Datos de lista ACL basada en Modelos  SQL > select * from access_list order by role; +----+-----------------+-----------------------+--------+-------+ | id | role | resource | action | allow | +----+-----------------+-----------------------+--------+-------+ | 6 | Public | * | * | Y | | 7 | Public | dinein | * | N | | 15 | Public | users | * | N | | 27 | Public | appmenu | * | Y | | 29 | Public | admin | * | Y | | 30 | Public | menus | * | N | | 9 | Administradores | * | * | Y | | 10 | Cajeros | * | * | Y | | 11 | Cajeros | ambient_items | * | N | | 12 | Cajeros | drop_invoice | * | N | | 13 | Cajeros | menus | * | N | | 14 | Cajeros | menus_items | * | N | | 16 | Cajeros | users | * | N | | 17 | Cajeros | modifiers | * | N | | 18 | Cajeros | ambient_menus_items | * | N | | 19 | Cajeros | discount | * | N | | 26 | Cajeros | data | query | N | +----+-----------------+-----------------------+--------+-------+

  El parámetro className permite establecer un modelo que contiene la estructura descrita en  la  tabla  anterior.  El  campo  resource  y  action  pueden  contener  asteriscos  (*)  que  son  usados  como comodines para cualquier criterio que coincida. El campo allow puede tener los valores  Y(es) o N(o) para indicar si le concede el acceso al recurso.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                143 

La principal ventaja de la listas ACL es que validan los accesos en forma jerárquica ya sea a  nivel de recursos ó mediante herencia de roles. En el ejemplo el acceso de jerarquía más alto  es en el que hay comodines tanto para el recurso como para la acción, el método Acl::isAllowed  busca jerárquicamente si existe un acceso ó no en la lista de acceso.    Según el ejemplo las siguientes consultas a la lista de acceso darian como resultado:    Ejemplo: Comportamiento de la lista ACL según datos de ejemplo  $acl = new Acl('Model', 'className: AccessList'); //Esta permitido el rol ‘Public’ a acceder al recurso ‘menus’ en la operación ‘index’? //No Permitido $acl->isAllowed("Public", "menus", "index") //Esta permitido el rol ‘Cajeros’ a acceder al recurso ‘dinein’ en cualquier operación? //Permitido $acl->isAllowed("Cajeros", "dinein", "*") //Esta permitido el rol ‘Cajeros a acceder al recurso ‘data’ en la operación ‘query’? //No Permitido $acl->isAllowed("Cajeros", "data", "query")

  El primer parámetro de Acl::isAllowed es el nombre del rol, el segundo el nombre del recurso y  el  tercero  el  nombre  de  la  acción.  Cuando  no  se  encuentra  una  regla  especifica  para  rol‐ recurso‐operación, se busca rol‐recurso‐cualquiera y por ultimo rol‐cualquiera‐cualquiera. 

15.8 Herencia de Roles Una de las grandes ventajas del uso de listas de control de acceso es la construcción de arboles  de  jerarquía  de  roles.  De  esta  forma  los  permisos  de  acceso  pueden  ser  heredados  ó  compartidos entre varios roles sin que haya redundancia de información proporcionando a la  aplicación capacidades de control de acceso potentes y flexibles. 

15.9 Adaptadores de ACL Kumbia  Enterprise  Framework  permite  utilizar  varios  backends  para  almacenar  listas  Acl.  Cada adaptador implementa la interface AclInterface:    <?php interface AclAdapter { public public public public

function function function function

addRole(AclRole $roleObject, $accessInherits=''); addInherit($role, $roleToInherit); isRole($role_name); isResource($resource_name);


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

public public public public public public

function function function function function function

 

                                                                144 

addResource(AclResource $resource); addResourceAccess($resource, $accessList); dropResourceAccess($resource, $accessList); allow($role, $resource, $access); deny($role, $resource, $access); isAllowed($role, $resource, $accessList);

}

  A continuación se explican las consideraciones de uso de cada adaptador:  15.9.1 AclModel  La  lista  de  accesos  también  puede  ser  administrada  usando  modelos  disponibles  en  la  aplicación.  Para esto es necesario crear una entidad con la siguiente estructura:    Ejemplo: Estructura de una tabla apta para almacenar una lista ACL  CREATE TABLE `access_list` ( `id` int(11) NOT NULL, `role` varchar(24) NOT NULL, `resource` varchar(32) NOT NULL, `action` varchar(32) NOT NULL, `allow` char(1) default NULL, PRIMARY KEY (`id`), )

  Al  instanciar  el  objeto  Acl  se  debe  indicar  el  modelo  a  utilizar  mediante  el  parámetro  className, luego el comportamiento y utilización es el normal:    Ejemplo: Uso de listas ACL con Modelos  $acl = new Acl('Model', 'className: AccessList'); $acl->isAllowed("Administrators", "customers", "create")

  15.9.2 AclMemory  El  adaptador  AclMemory  almacena  los  permisos  en  memoria.  La  lista  de  control  de  acceso  puede  construirse  en  un  proceso  inicializador  y  almacenarse  en  un  backend  de  cache  para  usarse en otras peticiones. Para aplicaciones con requerimientos de validación de control de  acceso reducidos este adaptador puede ser una opción a tener en cuenta.  15.9.3 AclXML  Este  adaptador  permite  crear  listas  de  control  de  acceso  en  archivos  XML.  Estos  archivos  mantienen los controles de forma estructurada haciendo sencilla su manipulación desde otros  lenguajes y aplicaciones.    El archivo debe contener la siguiente estructura: 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                145 

    Un nodo raíz ‘security’ que contendrá la lista en sí    Un solo nodo ‘roles‐collection’ que contiene nodos ‘role’ con información de roles    Los  nodos  ‘role’  deben  tener  los  sub‐nodos  ‘name’  y  ‘description’  con  el  nombre  y  descripción  del rol respectivamente.    Un  solo  nodo  ‘resources‐collection’  que  contiene  nodos  ‘resource’  con  información  de  los  recursos en la lista.    Los  nodos  ‘resource’  deben  tener  los  sub‐nodos  ‘name’  y  ‘description’  con  el  nombre  y  descripción del recurso respectivamente.    Múltiples  nodos  ‘access‐constraint’  con  las  reglas  de  acceso.  El  orden  de  estas  indica  la  prioridad de cada una.    Cada  nodo  ‘access‐constraint’  contiene  los  nodos  ‘role‐name’  que  es  nombre  del  rol,  ‘resource‐name’  que  es  el  nombre  del  recurso,  ‘action‐name’  que  es  nombre  del  acceso  y  ‘rule‐type’ que contiene ‘allow’ si tiene acceso al recurso y ‘deny’ de lo contrario.    El siguiente es el ejemplo de una lista ACL en XML:    Ejemplo: Lista ACL usando una definición en XML  <?xml version="1.0" encoding="UTF-8" ?> <security xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<role>

<!-- ROLES DE LA APLICACION --> <roles-collection> <role> <name>Public</name> <description>Rol para usuarios no autenticados</description> </role> <role> <name>Customers</name> <description>Usuarios clientes de la empresa</description> </role>

<name>QueryOnly</name> <description>Usuarios con permisos de solo lectura</description> </role> </roles-collection> <!-- RECURSOS DE LA APLICACION --> <resources-collection> <resource> <name>banking</name> <description>Controlador para operaciones del cajero</description> </resource> <resource> <name>login</name> <description>Controlador para operaciones de inicio de sesión</description> </resource> </resources-collection>


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                146 

<!-- CONSTRAINTS DE ACCESO --> <access-constraint> <role-name>Public</role-name> <resource-name>*</resource-name> <action-name>*</action-name> <rule-type>deny</rule-type> </access-constraint> <access-constraint> <role-name>Public</role-name> <resource-name>login</resource-name> <action-name>validateCredentials</action-name> <rule-type>allow</rule-type> </access-constraint> <access-constraint> </security>

15.10 API de un Adaptador public boolean addRole(AclRole $roleObject, mixed $accessInherits)  Agrega un rol a la lista de roles de la lista de Acceso. En este tipo de Adaptador el rol se crea en  la entidad definida en el constructor de la lista en el parámetro: rolesClassName.    public void addInherit($role, $roleToInherit)  Agrega una herencia a la lista en la que el rol $role hereda todos los constraints de acceso que  tiene el rol $roleToInherit.    public boolean isRole(string $roleName)  Permite saber si $roleName esta presente en la lista ACL    public boolean isResource(string $resourceName)  Permite saber si un recurso existe ó no en la lista de acceso actual.    public boolean addResource(AclResource $resource)  Agrega un recurso para ser administrador por la lista de control de acceso.    public void addResourceAccess(string $resource, mixed $accessList)  Agrega una operación/acción a un recurso de la lista ACL. El parámetro $accessList puede ser  un string ó un vector.    public void dropResourceAccess($resource, $accessList)  Elimina una operación/acción de un recurso de la lista ACL. El parámetro $accessList puede  ser un string ó un vector.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                147 

public void allow(string $role, string $resource, mixed $access)  Agrega una regla que da acceso a un determinado rol a un recurso.    public void deny(string $role, string $resource, mixed $access)  Agrega una regla denegando el acceso de un determinado rol a un recurso.    public boolean isAllowed(string $role, string $resource, array $accessList)  Realiza una consulta en la lista ACL  

15.11 API de AclResource public void getName()  Obtener el nombre del recurso    public void getDescription()  Obtener la descripción del recurso 

15.12 API de AclRole public void getName()  Obtener el nombre del Role    public void getDescription()  Obtener la descripción del Role, usualmente el nombre extendido del rol.                       


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                148 

16 Componente Auth 16.1 Introducción El  componente  Auth  esta  diseñado  para  permitir  la  autenticación  y  administración  de  la  entidad  de  los  usuarios  en  una  aplicación  ya  sea  de  forma  independiente  ó  de  manera  compartida.     Este  componente  accede  a  sus  adaptadores  usando  el  patrón  Virtual  Proxy,  es  decir,  una  instancia de Auth solo actúa como un Proxy al objeto real instanciado que corresponde al tipo  de adaptador utilizado por el mismo. Esta implementación permite crear un punto de entrada  único par la utilización de adaptadores del framework ó de usuario.    La 

instancia 

interna 

del 

adaptador 

se��

puede 

obtener 

usando 

el 

método 

Auth::getAdapterInstance(). 

16.2 Adaptadores de Auth El  componente  implementa  una  arquitectura  de  adaptadores  de  autenticación,  estos  establecen interfaces consistentes a diferentes proveedores de identificación bajo una misma  interfaz  de  aplicación.  Cada  adaptador  requiere  de  diferentes  parámetros  solicitados  por  el  servicio de autenticación utilizado.    Los adaptadores disponibles son:    Tabla: Adaptadores de Auth disponibles  Adaptador 

Descripción 

Digest 

Permite la  autenticación  usando  un  realm  basado  en un  archivo plano  de texto. 

Radius 

Implementa autenticación usando protocolo Radius Autentication RFC‐ 2865. 

Kerberos V 

Autentica usando servidores Kerberos 5 y además permite obtener las  politicas asociadas al usuario identidad. 

Model 

Usa  un  modelo  de  la  aplicación  en  donde  los  atributos  de  esta  actuan  como credenciales en la autenticación. 

LDAP 

Permite  utilizar  servidores  LDAP  como  ActiveDirectory  para 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                149 

autenticarse en una aplicación.    Todos los adaptadores de Auth implementan la interface AuthInterface:    interface AuthInterface { public function __construct($auth, $extraArgs); public function getIdentity(); public function authenticate(); }

16.3 Administración de Identidad La  administración  de  identidad  es  uno  de  los  procesos  más  usuales  en  cualquier  aplicación  Web, una vez se produce la autenticación e identificación del usuario es necesario conocer la  identidad durante toda la sesión del mismo en la aplicación.    Al  realizar  una  autenticación  satisfactoria  con  el  componente  Auth  automáticamente  se  crea  un  registro  de  la  identidad  de  quien  inició  sesión  y  poder  cumplir  con  objetivos  de  la  aplicación como personalización ó confidencialidad.    El  método  estático  de  Auth  llamado  getActiveIdentity()  devuelve  la  identidad  creada  en  la  autenticación  en  cualquier  parte  de  la  aplicación.  Para  destruir  la  identidad  activa  se  usa  el  también método estático destroyIdentity().    Para  conocer  si  existe  una  identidad  valida  en  la  aplicación  se  usa  el  método  Auth::isValid()  que devuelve un valor boleano correspondiente a esa información. 

16.4 Expiración de Sesión El  componente  Auth  soporta  expiración  de  la  sesión  con  lo  que  es  posible  controlar  que  un  usuario autenticado solamente pueda utilizar la aplicación durante un determinado rango de  tiempo.     En estos casos se debe establecer el tiempo en segundos que debe durar la sesión mediante el  método del objeto Auth llamado setExpireTime después de la autenticación del usuario. 

16.5 Control de Autenticación concurrente Las reglas del negocio en una aplicación podrían contemplar que un usuario este autenticado 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                150 

en una aplicación solamente desde una terminal de trabajo. En otros casos cuando se genere  una autenticación del usuario desde otra maquina se requiera que se cierre ó se invaliden las  sesiones abiertas en otras terminales. 

16.6 Autenticación con Modelos El  adaptador  Model  permite  realizar  la  autenticación  mediante  un  realm  en  una  entidad  del  gestor relacional por defecto en config/environment.ini. La principal ventaja de este adaptador  es  que  aprovecha  las  capacidades  para  atender  múltiples  peticiones  concurrentes  de  autenticaciónn que pueda tener el gestor relacional.    El siguiente ejemplo ilustra como realizar una autenticación através usando este adaptador:    Ejemplo: Uso del componente Auth con modelos  <?php class LoginController extends ApplicationController { public function indexAction(){ } public function authSessionAction(){ $login = $this->getPostParam("login"); $password = sha1($this->getPostParam("password")); $auth = new Auth('model', "class: Usuarios", "login: $login", "password: $password"); if($auth->authenticate()==false){ Flash::error("Usuario/clave incorrectos"); $this->routeTo("action: index"); } else { $this->routeTo("controller: menu"); } $this->setRequest("password", ""); } }

  Tabla: Parámetros que requiere el adaptador Auth con modelos  Nombre  class 

Descripción  Nombre de la clase del modelo que servira como realm. 

  Los campos que conforman la clave de identidad deben ser pasados como parámetros con su  respectivo valor.    La  identidad  se  construye  apartir  de  los  atributos  de  la  entidad  exceptuando  los  campos  de  password ó contraseña. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                151 

16.7 Autenticación con KerberosV Este adaptador permite autenticarse usando servidores administrativos Kerberos 5 así como  obtener las politicas asociadas a los usuarios autenticados.    Puede 

obtener 

más 

información 

sobre 

servidores 

Kerberos 

en 

http://web.mit.edu/kerberos/www/krb5‐1.2/krb5‐1.2.8/doc/admin_toc.html.    El siguiente ejemplo ilustra como realizar una autenticación através usando este adaptador:    Ejemplo: Uso del componente Auth con un servidor KerberosV  <?php class LoginController extends ApplicationController { public function startSessionAction(){ $login = $this->getPostParam("login"); $password = $this->getPostParam("password"); $auth = new Auth('kerberos5', "realm: GONICUS.LOCAL", "username: admin/admin", "password: 12345"); if($auth->authenticate()==true){ $identity = $auth->getIdentity(); $policies = $auth->getPolicies(); Flash::success("Bienvenido {$identity['username']}"); foreach($policies as $policy){ Flash::notice($policy); } } else { Flash::error("Fallo autenticacion. Credenciales invalidas"); } } }

  Tabla: Parámetros que requiere el adaptador Auth con KerberosV  Nombre  server 

Descripción  Es  el  nombre  de  dominio  ó  dirección  IP  del  servidor  Kerberos  V.  Este  parámetro es obligatorio. 

realm 

El  nombre  de  la  base  de  datos  con  la  politica  de  autenticación  en  el  servidor K5. 

principal 

Una combinación usuario/grupo con el que se hará la autenticación 

password 

Contraseña del usuario usado en principal. 

  La identidad devuelta está consta de los campos realm y username.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                152 

Advertencia:  El  uso  de  este  adaptador  requiere  que  este  presente  la  extensión  de  PHP  llamada php_kadm5. 

16.8 Autenticación con Radius Este  adaptador  permite  la  autenticación  mediante  protocolo  Radius  (RFC2865  ‐  http://www.faqs.org/rfcs/rfc2865). Este adaptador requiere de la extensión php_radius que 

se encuentra disponible en plataformas Unix (FreeBSD, Linux) y Windows.    El siguiente ejemplo ilustra como realizar una autenticación através usando este adaptador:    Ejemplo: Uso del componente Auth con un servidor Radius  <?php class LoginController extends ApplicationController { public function startSessionAction(){ $login = $this->getPostParam("login"); $password = $this->getPostParam("password"); $auth = new Auth('radius', "server: 172.16.2.10", "port: 1821", "secret: a1b2c3d4", "username: tierry", "password: henry" ); if($auth->authenticate()==true){ $identity = $auth->getIdentity(); Flash::success("Bienvenido {$identity['username']}");

}

} else { Flash::error("Fallo autenticacion. Credenciales invalidas"); } }

  Tabla: Parámetros que requiere el adaptador Auth con Radius  Nombre  server 

Descripción  Es  el  nombre  de  dominio  ó  dirección  IP  del  servidor  Radius  V.  Este  parámetro es obligatorio. 

port 

Puerto  UDP  donde  escucha  el  servicio  Radius.  Si  el  puerto  es  0  el  adaptador  localiza  el  servicio  mediante  el  archivo  /etc/services  y  como  última opción el puerto estándar 1812. 

secret 

La clave compartida que se pasará al servidor Radius.  

timeout 

Número de segundos que el adaptador espera por obtener respuesta del  servidor. 

max_retries 

Número de intentos que realiza para tratar de autenticarse. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

username 

Nombre de usuario a autenticar. 

password 

Password el usuario a autenticar. 

 

                                                                153 

  La identidad se construye con el campo username. 

16.9 Autenticación con Digest El  adaptador  de  autenticación  Digest  permite  utilizar  archivos  planos  de  texto  como  realms  para la comprobación de identidad de los usuarios de una aplicación.  Un archivo Digest tiene  la siguiente estructura:    nombreusuario:nombrerealm:resumenpassword otronombreusuario:nombrerealm:otroresumenpassword

  Cada línea del archivo constituye una identidad. Los campos de la identidad están separados  por  “:”  (dos  puntos).  El  primer  campo  es  el  nombre  del  usuario,  este  puede  tener  la  forma  john.smith. El segundo campo es el realm al que pertenece el usuario, un archivo digest puede  tener  varios  realms  en  él.  Por  último  el  tercer  campo  es  un  resúmen  criptográfico  correspondiente  al  password  del  usuario.  El  algoritmo  estándar  de  una  sola  vía  utilizado  es  MD5  pero  es  posible  utilizar  otro  mediante  la  opción  de  configuración  algorithm.  Para  un  archivo digest como el siguiente:    john.smith:Production:5ebe2294ecd0e0f08eab7690d2a6ee69

  El siguiente proceso de autenticación es satisfactorio:    Ejemplo: Autenticación usando el adaptador Digest  <?php class LoginController extends ApplicationController { public function startSessionAction(){ $auth = new Auth('digest', "filename: auth/passwd.txt", "username: john.smith", "password: secret", "realm: Production" ); if($auth->authenticate()==true){ $identity = $auth->getIdentity(); Flash::success("Bienvenido {$identity['username']}"); } else { Flash::error("Falló autenticación. Credenciales invalidas"); } } }


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                154 

Ejemplo: Autenticación usando un archivo con otro charset diferente al de entrada  <?php class LoginController extends ApplicationController { public function startSessionAction(){ $auth = new Auth('digest', "filename: auth/passwd.txt", "username: お読みください", "password: secret", "realm: フォルダに入れてください", “charset: EUC-JP” ); if($auth->authenticate()==true){ $identity = $auth->getIdentity(); Flash::success("Bienvenido {$identity['username']}"); } else { Flash::error("Falló autenticación. Credenciales invalidas"); } } }

Tabla: Parámetros que requiere el adaptador Auth con Digest  Nombre  filename 

Descripción  Ruta al archivo digest. El archivo debe ser de texto, si está disponible la  extensión de PHP Multibyte Strings su codificación puede ser cualquiera  que soporte ésta.  

username 

Nombre del usuario a autenticar 

password 

Password plano del usuario 

realm 

Realm al que pertenece el usuario a autenticar 

algorithm 

Callback  del  algoritmo  que  se  utilizará  para  comparar  el  password  del  usuario con los del archivo digest. Por defecto es MD5.  

charset 

Codificación  que  tiene  el  archivo  de  identidades  digest.  El  valor  por  defecto es UTF‐8. 

  La identidad se construye a partir de los campos username y realm del usuario encontrado. 

16.10 Autenticación con LDAP El  protocolo  LDAP  “Lightweight  Directory  Access  Protocol”  es  utilizado  para  acceder  a  servidores  de  directorios.  Estos  son  estructuras  que  almacenan  datos  en  una  jerarquia  de  arbol.    El adaptador de autenticación LDAP soporta autenticación con servidores de directorios como  Microsoft Active Directory, OpenLDAP, Sun OpenDS ó Mac OS X Server LDAP Service.  


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                155 

  La notación DN ó “Distinguished Name” representan rutas a objetos alojados en un servidor  LDAP. Cada atributo esta indicado con su nombre estandar, un igual y su valor.  Los atributos  están  separados  por  comas  y  el  orden  de  lectura  de  los  atributos  se  realiza  de  derecha  a  izquierda.     En  el  siguiente  ejemplo  se  ilustra  la  autenticación  a  un  servidor  LDAP  a  partir  de  los  parámetros de un formulario:    Ejemplo: Uso del componente Auth con un servidor LDAP  <?php class LoginController extends ApplicationController { public function startSessionAction(){ $login = $this->getPostParam("login"); $password = $this->getPostParam("password"); $auth = new Auth('ldap', "server: server.local", "accountDomainName: example.com", "baseDN: dc=example,dc=com", "username: uid=$login,dc=example,dc=com", "password: $password", "identityAttributes: cn,uid", "port: 1389" ); if($auth->authenticate()==true){ $identity = $auth->getIdentity(); Flash::success("Bienvenido {$identity['username']}"); } else { Flash::error("Falló autenticación. Credenciales invalidas"); } } }

  Los  siguientes  parámetros  deben  ser  indicados  para  realizar  una  autenticación  satisfactoria  en un servidor LDAP:    Tabla: Parámetros que recibe el adaptador Auth con LDAP  Nombre  server 

Descripción  Es  el  nombre  de  dominio  ó  dirección  IP  del  servidor  LDAP.  Este  parámetro es obligatorio. 

accountDomainName 

Nombre del dominio al que pertenece la cuenta a autenticar. 

username 

DN del usuario que se va a autenticar en el servidor. Este parámetro  es obligatorio. 

password 

Contraseña del usuario que se va a autenticar. Si el parámetro no es  indicado se produce un intento de autenticación anónimo. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

baseDN 

 

                                                                156 

DN base donde se hace la búsqueda de la identidad del usuario. Es el  DN del servidor donde la cuenta se encuentra ubicada. 

port 

Puerto del servidor donde escucha el LDAP Server. 

identityAttributes 

Atributos  de  la  entrada  del  servidor  LDAP  que  serán  usados  para  construir la identidad del usuario autenticado. 

accountCanonicalForm  Indica  la  forma  en  la  que  el  nombre  de  usuario  esta  canonizado,  dependiendo  del  tipo  de  servidor  LDAP  el  adaptador  traduce  este  nombre automáticamente al adecuado. Un valor de 2 indica la forma  normal,  3  usa  la  forma  \\SERVIDOR\usuario  y  la  4  usuario@servidor.    La identidad se construye apartir de los campos del registro del nombre canonico del usuario  en el servidor LDAP.    Advertencia:  El  uso  de  este  adaptador  requiere  que  este  presente  la  extensión  de  PHP  llamada php_ldap.                               


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                157 

17 Componente AuditLogger 17.1 Introducción El  componente  AuditLogger  esta  diseñado  para    asistir  las  tareas  de  auditoria  de  sistemas  creando logs que lleven el registro de las actividades realizadas en una aplicación de negocios  por parte de cada uno de los roles que la utilizan.  

17.2 Crear un componente de control Ejemplo: Crear un componente de usuario para la auditoría de sistemas  <?php class MyApplicationAudit extends AuditLogger { public function __construct($note, $transaction=null){ parent::__construct("Audit"); $this->bindToField("USER_ID", "usuarios_id"); $this->bindToField("USERNAME", "nombre"); $this->bindToField("NOTE", "nota"); $this->bindToField("IP_ADDRESS", "ipaddress"); $this->setFieldData("controller", Router::getController()); $this->setFieldData("action", Router::getAction()); $this->setFieldData("USER_ID", Session::get("usuariosId")); $this->setFieldData("USERNAME", Session::get("usuariosNombre")); $this->setFieldData("NOTE", $note); if($transaction!=null){ $this->setTransaction($transaction); } } }

                           

$this->commit();


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                158 

18 Componente Security 18.1 Introducción El objetivo de este componente es ofrecer funcionalidades varias de seguridad a aplicaciones  web  empresariales.  Una  característica  importante  de  este  componente  es  un  Firewall  que  permite definir reglas de acceso estilo firewall a una aplicación.  

18.2 Subcomponente SecurityFirewall 18.2.1 Introducción  El objetivo del subcomponente SecurityFirewall es el de permitir al desarrollador analizar el  entorno  desde  el  cual  se  accede  a  un  determinado  punto  de  la  aplicación  y  validar  si  se  permite el acceso ó no.    Las reglas se definen en un archivo XML en el orden de prioridad como deben ser evaluadas.  Un ejemplo es el siguiente documento XML:    Ejemplo: Definición XML de reglas para SecurityFirewall  <?xml version="1.0" encoding="UTF-8"?> <firewallRules> <hostTraslation> <hostname>localhost</hostname> <address>::1</address> </hostTraslation> <rule> <source>localhost</source> <controller>products</controller> <action>*</action> <target>reject</target> </rule> <rule> <source>192.168.10.120</source> <controller>admin</controller> <action>*</action> <target>reject</target> </rule> <rule> <source>localhost</source> <controller>*</controller> <action>*</action> <target>accept</target> </rule> </firewallRules>

  El  nodo  raiz  firewallRules  abre  el  documento.  Los  nodos  hostTraslation  contienen  traducciones  predefinidas  para  nombres‐de‐maquina/direcciones‐ip,  así  es  posible  indicarle  al  firewall  que  un  mismo  nombre  de  maquina  tiene  varias  direcciones  IP  asignadas.  En  el  ejemplo la dirección ::1 del loopback de una maquina Mac OS X es agregada como localhost. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                159 

  Los nodos rule permiten definir las reglas del firewall. Por obligación estos nodos deben tener  un atributo target que indica que el tipo de acción a ejecutar cuando se cumple la regla.    18.2.2 Como se evaluan las reglas  Las reglas son evaluadas  en el orden en el que se definieron en el archivo XML. Si una regla  cumple  con  las  condiciones  del  entorno  de  la  petición  entonces  las  demás  reglas  no  son  evaluadas.    Es  necesario  tener  en  cuenta  el  orden  en  el  que  se  definen  para  evitar  que  una  regla  sobreescriba a otras y no se logre el objetivo esperado.  18.2.3 Tipos de Atributos de una Regla  Una regla del SecurityFirewall puede tener los siguientes tipos de atributos:    Tabla: Tipos de atributos de una regla en SecurityFirewall  Nombre  source 

Descripción  El origen de la petición. Puede ser un nombre de maquina en la red,  un  nombre  de  dominio  ó  una  dirección  IP.  Cuando  se  establece  un  nombre  de  maquina  se  utilizan  las  capacidades  de  resolución  de  nombres que tenga la maquina actual para obtener las direcciones IP  correspondientes.  La  dirección  IP  del  cliente  se  obtiene  incluso  cuando el acceso se realiza mediante un proxy transparente. Las IPs  no pueden ser obtenidas cuando se usa un proxy anónimo. 

mac 

La NIC de la tarjeta de red puede ser obtenida cuando la aplicación  es  ejecutada  en  sistemas  Linux/Unix  y  cuando  los  clientes  se  encuentran en la mismo rango de red del servidor. 

controller 

El  nombre  del  controlador  de  aplicación  ó  servicio  web  en  la  aplicación  activa  que  se  está  tratando  de  acceder.    Se  puede  usar  *  como comodín que coincida con cualquier controlador. 

action 

El  nombre  de  la  acción  en  el  controlador  solicitado  que  se  está  tratando  de  acceder.  Se  puede  usar  *  como  comodín  que  coincida  con cualquier nombre de acción. 

isAjaxRequested 

Indica si la petición se está tratando de hacer usando AJAX. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                160 

isSoapRequested 

Indica si la petición se está tratando de hacer desde un cliente Soap. 

isSecure 

Indica si la conexión se realiza usando una conexión segura. 

isFlashRequested 

Indica si la conexión se realiza desde un plug‐in de Adobe Flash. 

hasHeader 

Si  la  petición  contiene  un  determinado  encabezado.  Múltiples  encabezados pueden definirse separandolos por pipes (|). 

method 

Permite  indicar  el  tipo  de  método  HTTP  utilizado  para  solicitar  la  petición. 

                                         


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                161 

Parte 3: La lógica de datos   

19 Persistencia, Transacciones y Concurrencia 19.1 Introducción El papel de la capa de persistencia en una aplicación es traer y llevar los datos requeridos para  que  la  lógica  de  dominio  en  los  controladores  puede  realizar  su  trabajo  correctamente.  Cuando  se  habla  de  persistencia  se  piensa  normalmente  en  bases  de  datos  relacionales  y  el  tratamiento  de  estas  generalmente  conlleva  a  tratar  inconvenientes  de  bajo  nivel  como  conexiones ó incompatibilidad de la sintaxis de lenguaje SQL.     Kumbia  Enterprise  Framework  ofrece  una  variedad  de  componentes  para  acceder  a  gestores  relacionales a bajo ó alto nivel.   

20 Componente Db 20.1 Introducción Kumbia  Enterprise  Framework  implementa  una  doble  capa  de  abstracción  para  la  manipulación  de  la  persistencia  de  la  aplicación  cuando  se  utilizan  bases  de  datos.  El  componente Db administra todo lo relacionado con la interacción a bajo nivel con los gestores  relacionales  de  base  de  datos,  esto  incluye  abstraer  detalles  de  conexión,  utilización  de  lenguaje SQL, cursores, transacciones, etc.     Esta independencia se logra mediante la implementación de adaptadores que crean puntos de  compatibilidad  a  los  motores  de  bases  de  datos  de  tal  forma  que  sin  importar  el  gestor  utilizado  se  garantice  que  las  operaciones  sobre  ellos  va  a  ser  consistente  logrando  el  resultado esperado.    Mientras que el Kumbia PHP Framework ofrece múltiples opciones para conectarse a bases de  datos, Kumbia Enterprise Framework recomienda su uso en producción a los adaptadores de  MySQL y Oracle, aunque algunos otros tienen una madurez aceptable. 

20.2 Capas de acceso El  componente  Db  puede  utilizar  multiples  capas  de  abstracción  existentes  para  el  acceso  a 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                162 

gestores  relacionales,  de  esta  forma  se  aumentan  las  posibilidades  y  capacidades  de  aprovechar la funcionalidad del motor desde una aplicación.    Las capas de acceso soportadas son las siguientes:    Tabla: Capas de acceso a gestores relacionales soportadas por Kumbia Enterprise  Nombre  Native 

Descripción  Sin  capa  intermedia.  Utiliza  las  extensiones  PHP  escritas  en  lenguaje  C  que  implementan  acceso  directo  a  los  motores  de  base de datos. 

PDO 

Utiliza la capa PHP Data Objects (PDO) escrita en lenguaje C que  implementa  acceso  uniforme  a  los  principales  motores  de  base  de datos de código abierto y cerrado.  

JDBC 

Utiliza  la  capa  de  acceso  a  bases  de  datos  Java  Database  Connectivity  (JDBC)  de  Java.  Con  lo  que  es  possible  utilizar  drivers JDBC y la funcionalidad de estos. Solo disponible cuando  se usa IBM WebSphere sMash. 

 

20.3 Adaptadores del componente Db En  la  siguiente  tabla  se  detalla  los  adaptadores  de  la  distribución  de  Kumbia  Enterprise  Framework junto con sus características y estado de madurez:    Tabla: Adaptadores del componente Db y madurez actual  Nombre 

Capa de Acceso 

Estado de Madurez 

MySQL 

Nativo (MySQL) 

Estable 

MySQLi 

Nativo (MySQLi) 

Estable 

Oracle 

Nativo (oci8) 

Estable 

PostgreSQL 

Nativo 

Beta 

Microsoft SQL Server 

PDO 

Beta 

IBM Informix 

PDO 

Beta 

SQLite 

PDO 

Beta 

Oracle 

PDO 

Beta 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

Oracle 

 

JDBC 

                                                                163 

Estable 

  Cada  adaptador  nativo  hereda  de  la  clase DbBase  la  cual  implementa  métodos  utiles  validos  para  cualquier  gestor  relacional  en  forma  de  capa  de  abstracción  intermedia.  La  interface  DbBaseInterface  es  implementada  por  cada  adaptador  de  tal  forma  que  cada  uno  mantenga  una estructura consistente que permita efectuar operaciones básicas  y avanzadas sin incurrir  en detalles de bajo nivel ó dependientes de cada gestor relacional.    La estructura de la interface DbBaseInterface es la siguiente:  interface DbBaseInterface { public function __construct($descriptor=''); public function connect($descriptor=''); public function query($sqlStatement); public function fetchArray($resultQuery='', $opt=''); public function close(); public function numRows($resultQuery=''); public function fieldName($position, $resultQuery=''); public function dataSeek($position, $resultQuery=''); public function affectedRows($resultQuery=''); public function error($errorInfo='', $resultQuery=''); public function noError($resultQuery=''); public function inQuery($sqlStatement, $type=db::DB_BOTH); public function inQueryAssoc($sql); public function inQueryNum($sql); public function fetchOne($sql); public function fetchAll($sql); public function insert($tableName, $values, $fields='', $automaticQuotes=true); public function update($tableName, $fields, $values, $whereCondition=null, $automaticQuotes=true); public function delete($tableName, $whereCondition=''); public function limit($sqlStatement, $number); public function forUpdate($sqlQuery); public function sharedLock($sqlQuery); public function begin(); public function rollback(); public function commit(); public function listTables($schemaName=''); public function describeTable($tableName, $schemaName=''); public function getRequiredSequence($tableName='', $identityColumn='', $sequenceName=''); public function lastInsertId($tableName='', $identityColumn='', $sequenceName=''); public function createTable($tableName, $definition, $index=array(), $tableOptions=array()); public function dropTable($tableName, $ifExists=false); public function tableExists($tableName, $schema=''); public function getDateUsingFormat($date, $format='YYYY-MM-DD'); public function getHaveAutoCommit(); public function setIsolationLevel($isolationLevel); public function getCurrentDate(); public function getLastResultQuery(); public function getConnectionId(); public function getDatabaseName(); public function getUsername(); public function getHostName(); }


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                164 

20.4 Generación de SQL Cada  gestor  relacional  sigue  estándares  del  lenguaje  SQL,  principalmente  de  las  especificaciones ANSI92 y ANSI99. Muchos motores de base de datos agregan extensiones al  lenguaje ó no implementan adecuadamente los estándares establecidos por diversas razones.  Cuando se escriben aplicaciones multi‐motor es posible encontrar ciertas incompatibilidades  que  podrían  conllevar  a  reescrituras  de  código  que  reabren  el  ciclo  del  software  y  podrian  generar sobrecostos. La capa de abstracción de Kumbia Enterprise Framework se encarga de  los  detalles  y  genera  la  mayor  parte  de  las  sentencias  de  DML  que  soporta  un  gestor  relacional.    A nivel de aplicación el lenguaje PHP ofrece una extensa biblioteca de funciones que permiten  conectarse  y  efectuar  operaciones  sobre  una  gran  variedad  de  gestores  relacionales.  Sin  embargo, la forma en que estan implementadas estas funciones no es estándar  y consistente  por  lo  que  el  cambio  de  un  gestor  a  otro  conlleva  a  reescribir  código  y  se  presentan  las  situaciones mencionadas��anteriormente.    Ejemplo: Conexión tradicional a gestores relacionales usando PHP  //Conexión a Oracle $connId = oci_connect("scott", "tiger", "//192.168.0.40/XE"); //Conexión a Informix $connId = ifx_connect("stores@ol_srv1", "informix", "pass"); //Conexión en PostgreSQL $connId = pg_connect("host=192.62.10.1 port=5432 dbname=bankdb user=dma password=2fe051871");

Clausulas  que  extendienden  el  lenguaje  SQL  como  LIMIT  en  SELECT,  estan  soportadas  por  algunos  gestores  relacionales  y  en  otros  es  necesario  implementarlos  de  tal  forma  que  sea  transparente y funcionen como se espera.    Ejemplo:  Incompatibilidad  de  algunas  extensiones  del  lenguage  SQL  en  gestores  relacionales  //LIMIT en SQLServer ó Sybase SELECT * FROM (SELECT TOP 10 * FROM (SELECT TOP 10 customers.categoryId FROM customers) AS itable) AS otable //LIMIT en MySQL SELECT customers.categoryId FROM customers LIMIT 10

El  componente  DBR  implementa  en  cada  uno  de  los  adaptadores  métodos  que  generan  SQL  optimizado  para  cada  gestor  relacional  soportado  aumentando  las  capacidades  de  cada  aplicación desarrollada con el mismo. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                165 

20.5 Conexiones a gestores relacionales por defecto Cada aplicación proporciona el archivo de configuración environment.ini en donde se pueden  establecer los parámetros de conexión de acuerdo a los entornos de las fases de desarrollo de  la aplicación.    El archivo de configuración environment.ini predeterminado tiene la siguiente estructura:    Ejemplo: Archivo de configuración enviroment.ini predeterminado  [development] database.type = mysql database.host = localhost database.username = root database.password = database.name = development_db [production] database.type = mysql database.host = localhost database.username = root database.password = database.name = production_db [test] database.type = mysql database.host = localhost database.username = root database.password = database.name = test_db

  Los  parámetros  de  conexión  tienen  el  prefijo  databse  y  pueden  variar  de  acuerdo  al  gestor  relacional utilizado. Para indicar el adaptador a usar se utiliza el parámetro database.type. A  continuación se explican las consideraciones de conexión para los motores soportados:  20.5.1 Consideraciones para Oracle  Oracle  es  muy  conocido  por  sus  capacidades  de  escalamiento  y  características,  además  es  lider en bases de datos y está disponible en varias plataformas.    El  adaptador  de  conexión  a  Oracle  requiere  que  la  extensión  de  PHP  oci8  este  disponible,  mediante  esta  es  posible  conectarse  a  Oracle  en  sus  versiones  8i,  9i,  10g  y  11g.  Adicional  a  esto es necesario instalar el Oracle Instant Client apropiado a la plataforma requerida.     Estas 

librerias 

pueden 

ser 

descargadas 

en 

la 

siguiente 

URL: 

http://www.oracle.com/technology/tech/oci/instantclient/instantclient.html. 

  Las  variables  de  entorno  ORACLE_HOME,  ORACLE_SID,  LD_PRELOAD  Y  NLS_LANG  deben 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                166 

estar definidas para realizar la conexión a Oracle.     Parámetros  de  configuración  de  la  extensión  OCI8  como  oci8.max_persistent,  oci8.persistent_timeout y oci8.default_prefetch también deberían tenerse en cuenta.    De acuerdo a la versión de la extensión OCI8 podría ó no haber compatibilidad con el gestor  relacional  requerido.  En  la  siguiente  tabla  se  presenta  la  compatibilidad  de  acuerdo  a  la  versión de OCI8:    Tabla: Matriz de compatibilidad entre PHP, OCI8 y cliente Oracle  Distribución 

Versión PHP 

Versión de OCI8 

Versiones del  cliente Oracle  soportado 

PHP CVS  PHP 

Binario 

5.2.7+ 

1.2.5 

8i, 9i, 10g, 11g 

para  5.27+ 

1.2.5 

10g, 11g 

Windows  PECL OCI8 CVS 

Se  puede  construir  1.3.4 

9iR2, 10g, 11g 

desde PHP 4.3.9   Zend Core for Oracle 2.5 

5.2.5 

1.2.3 

Incluye 

el 

Oracle 

Instant  Client  10  por  lo  que  se  soportan:  8i, 9i, 10g, 11g    Este adaptador no soporta múltiples transacciones simultaneas, esto quiere decir que al tratar  de crear una transacción cuando ya hay una activa se generará una excepción.     Los parámetros de conexión al conectarse a Oracle son:    [production] database.type = oracle database.host = 127.0.0.1 database.username = scott database.password = tiger database.instance = XE database.port = 1521 database.territory = spain database.sort = spanish_m database.comp = linguistic database.charset = AL32UTF8


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                167 

La descripción de los parámetros es la siguiente:    Tabla: Parámetros de conexión a Oracle usando adaptador Nativo  Parámetro  database.username 

Descripción  Los  usuarios  en  Oracle  son  propiedad  de  schemas  que  tienen  el mismo nombre del usuario. Este parámetro permite indicar  el nombre del usuario ó ambiguamente el schema. 

database.host 

Nombre  de  la  maquina  ó  dirección  IP  donde  se  encuentra  el  servidor Oracle. 

database.password 

Contraseña del usuario con el que se realiza la conexión. 

database.instance 

Nombre  de  la  instancia  de  Oracle  ó  del  servicio  del  TNS  Listener.  Cuando  se  usa  Oracle  Database  Express  este  es  ‘XE’  por defecto. 

database.port 

Puerto del servicio TNS Listener. Por defecto es 1521. 

database.sort 

Este  parámetro  permite  establecer  como  se  hará  el  ordenamiento 

de 

columnas 

que 

contengan 

valores 

alfanuméricos como CHAR ó VARCHAR2. Su valor por defecto  es spanish_m. En paises hispano‐hablantes las letras ch, ll y  ñ  son  consideradas  parte  del  alfabeto  y  esta  variable  permite  que el ordenamiento sea adecuado a la localización utilizada.  database.comp 

Es  la  forma  en  la  que  se  realizan  las  comparaciones  entre  valores  constantes  y  columnas  de  las  tablas.  El  valor  por  defecto  linguistic  permite  que  las  comparaciones  no  sean  sensibles a mayúsculas/minúsculas. 

database.charset 

Permite 

establecer 

el 

charset 

en 

el 

que 

se 

almacenan/devolveran valores en las bases de datos. El valor  Al32UTF8 es el nombre de Oracle para el charset UTF8.  database.territory 

Permite  establecer  el  territorio  en  el  que  se  encuentra  la  aplicación.  Dependiendo  de  este  los  formatos  de  fechas  y  de  valores  númericos  se  ajusta  a  la  localización  requerida.  Por  defecto es ‘spain’. 

database.language 

El  idioma  en  el  que  se  presentarán  los  mensajes  de  error  del  motor y se formatearán los resultados numéricos y de fechas. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                168 

Por defecto es ‘spanish’.    20.5.1.1 Conectar a Oracle mediante JDBC  También  es  posible  realizar  conexiones  a  Oracle  usando  el  adaptador  JDBC  cuando  la  aplicación ha sido implementada en un contenedor de aplicaciones IBM WebSphere sMash.    El  archivo  JAR  ojdbc14.jar  debe  estar  ubicado  en  el  directorio  lib  de  la  aplicación  sMash  siguiendo las convenciones de arquitectura de la maquina. Por ejemplo si se ejecuta en Linux  sobre un procesador arquitectura x86 entonces la ubicación es:    lib/x86/linux/ojdbc14.jar

  Los parámetros en enviroment.ini deben ser:    [production] database.layer = jdbc database.type = oracle database.driver = "oracle.jdbc.driver.OracleDriver" database.dsn = "thin:@192.168.151.12:1521:XE" database.username = scott database.password = tiger

20.5.2 Consideraciones para Microsoft SQL Server  SQL Server  es el motor de base de datos relacional de Microsoft. La conexión a este motor es  realizada via PHP Data Objects (PDO). Este adaptador solo soporta conexiones a SQL Server  desde Windows usando conexiones ODBC mediante el driver php_pdo_odbc. Las versiones de  SQL Server soportadas van desde la 7.x hasta la 2008.    20.5.2.1 Creación de un DSN ODBC para SQL Server  A  continuación  se  ilustra  el  proceso  de  creación  de  una  conexión  a  SQL  Server  mediante  ODBC.  Utilizando  un  usuario  con  credenciales  administrativas  se  abre  el  Administrador  de  Origenes de Datos ODBC desde Panel de Control ‐> Herramientas Administrativas.    En esta pantalla se selecciona la pestaña ‘DSN de usuario’ y se da click en el botón ‘Agregar…’  para crear una nuevo origen de datos:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                169 

    A continuación se selecciona el tipo de driver utilizado, se busca ‘SQL Server’ y se da click en  siguiente:   

   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                170 

Se  da  click  en  ‘Finalizar’  para  abrir  el  asistente  de  origenes  de  datos  para  SQLServer.  Se  presenta la siguiente pantalla:   

    El campo nombre hace referencia nombre al origen de datos ó Data Source Name (DSN) que  será  utilizado  luego  para  realizar  la  conexión  en  la  aplicación.  El  campo  servidor  indica  el  nombre  de  la  instancia  y  maquina  donde  está  instalado  SQL  Server.  Se  da  click  en  siguiente  para continuar.     


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                171 

    El tipo de autenticación se debe tener en cuenta cuando se realice la conexión desde Kumbia  Enterprise.  Si  se  selecciona  autenticaciónn  de  Windows  NT  no  será  necesario  indicar  el  parámetro UID y PWD del usuario de conexión. En este caso el usuario con el que se ejecute el  proceso  del  servidor  web  se  utilizará  para  autenticarse  en  SQL  Server.  Si  se  selecciona  autenticación de SQL Server se deben indicar los parámetros mencionados anteriormente.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                172 

    En la siguiente pantalla se puede configurar la base de datos predeterminada. Las opciones  ‘Usar identificadores entrecomillados ANSI’ y ‘Usar nulos, rellenos y advertencias ANSI’ deben  estar seleccionados.    En esta pantalla se pueden activar otras opciones, al terminar se da click en ‘Finalizar’:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                173 

    La última pantalla permite probar la conexión, si todo esta bien no habrá problema al efectuar  una conexión desde Kumbia Enterprise.   

   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                174 

Los parámetros requeridos de conexión al conectarse con el adaptador “mssql” son:    [production] database.layer = “pdo” database.type = mssql database.dsn = "DRIVER={SQL Server};SERVER=SQLEXPRESS;DATABASE=test"

  Usando un DSN de Usuario:    Ejemplo: Conexión a SQL Server estableciendo un DSN  [production] database.layer = “pdo” database.type = mssql database.dsn = "bankdb"

  Estableciendo el usuario y contraseña:    Ejemplo: Conexión a SQL Server estableciendo usuario y contraseña con DSN  [production] database.layer = “pdo” database.type = mssql database.dsn = "bankdb;UID=sa;PWD=mypass"

  Estableciendo el usuario y contraseña sin DSN:    Ejemplo: Conexión a SQL Server estableciendo usuario y contraseña sin DSN  [production] database.layer = “pdo” database.type = mssql database.dsn = "DRIVER={SQL Server};SERVER=SQLEXPRESS;DATABASE=test;UID=sa;PWD=pass

  Tabla: Parámetros de conexión a Microsoft SQL Server usando PDO  Parámetro  database.pdo 

Descripción  Indica  que  se  debe  cargar  un  Adaptador  PDO.  Su  valor  debe  ser On para que tenga efecto. 

database.dsn 

Indica los parámetros del Data Source Name (DSN) del origen  datos. SERVER es la maquina donde está instalada la instancia  del framework. DATABASE es el nombre de la base de datos de  trabajo.  UID  es  el  nombre  del  usuario  con  el  que  se  hará  la  conexión.  PWD  es  el  password  del  usuario.  DRIVER  es  el  nombre  del  driver  ODBC  para  SQL  Server,  normalmente  es  ‘SQL Server’. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                175 

  20.5.3 Consideraciones para MySQL  MySQL  es  uno  de  los  motores  Open  Source  más  populares  y  con  mayor  presencia  en  aplicaciones  para  Internet.  Existen  2  adaptadores  que  permiten  la  conexión  a  MySQL,  el  primero es “mysql“ que usa la extensión de PHP nativa del mismo nombre y que permite la  conexión  usando  librerias  cliente  desde  la  versión  4.1.  La  segunda  es  “mysqli”  que  utiliza  la  extensión del mismo nombre y que tiene una funcionalidad y rendimiento superior a la de la  extensión  “mysql”.  Ambos  adaptadores  soportan  transacciones  en  sesiones  de  conexión  diferentes.    Kumbia Enterprise Framework puede trabajar con MySQL cuando está en modo SQL estricto y  no estricto. En modo estricto se generarán excepciones DbInvalidFormatException cuando se  trate de insertar un valor que no tenga un formato adecuado al tipo de dato requierido de la  columna de este.    Los parámetros requeridos de conexión al conectarse con el adaptador “mysql” son:    Ejemplo: Parámetros de conexión requeridos usando el adaptador nativo de mysql  [production] database.type = mysqli database.host = localhost database.username = root database.password = my_password database.name = production_db

  Los posibles parámetros de conexión al conectarse con el adaptador “mysql” son:    Ejemplo: Posibles parámetros de conexión a mysql  [production] database.type = mysql database.host = localhost database.username = root database.password = my_password database.name = production_db database.port = 3306 database.autocommit = Off database.compression = Off database.ssl = Off database.interactive = Off

  La descripción de los parámetros anteriores es la siguiente:    Tabla: Parámetros de conexión a MySQL usando el adaptador “mysql” 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

Parámetro  database.username 

 

                                                                176 

Descripción  El  nombre  de  usuario  de  MySQL  con  el  que  se  efectuará  la  conexión. 

database.password 

El password del usuario de MySQL. 

database.host 

Servidor  de  MySQL.  Se  puede  utilizar  el  string  de  conexión  hostname:puerto  ó  :/path/al/socket  cuando  se  trata  de  localhost. 

database.name 

Nombre de la base de datos. 

database.port 

Puerto  del  servidor  de  MySQL  al  especificarse  se  hace  la  conexión por TCP/IP. 

database.autocommit 

Cuando  el  valor  es  On.  Indica  si  la  sesión  de  MySQL  debe  establecerse  en  modo  AUTOCOMMIT,  esto  significa  que  se  debe  hacer  un  COMMIT  obligatoriamente  para  que  se  tenga  efecto  los  cambios  realizados  sobre  la  base  de  datos.  Por  defecto es Off. 

database.compression 

Indica  si  el  cliente  MySQL  debe  comprimir  todo  el  tráfico  de  red  entre  la  aplicación  y  el  servidor  de  base  de  datos.  Por  defecto es Off 

database.ssl 

Indica  si  se  debe  encriptar  el  tráfico  entre  la  aplicación  y  el  servidor de base de datos mediante SSL. Por defecto es Off. 

database.interactive 

Indica  si  se  debe  crear  una  sesión  interactiva  en  vez  de  una  conexión temporal. Por defecto es Off. 

  Los parámetros requeridos de conexión al conectarse con el adaptador “mysqli” son:    Ejemplo: Parámetros de conexión requeridos para mysqli  [production] database.type = mysqli database.host = localhost database.username = root database.password = my_password database.name = production_db

  Los posibles parámetros de conexión al conectarse con el adaptador “mysqli” son:    Ejemplo: Configuración de la conexión usando mysqli  [production] database.type = mysqli


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                177 

database.host = localhost database.socket = /tmp/mysql.sock database.username = root database.password = my_password database.name = production_db database.port = 3306 database.autocommit = Off database.compression = Off database.ssl = Off database.interactive = Off database.charset = utf8 database.key = “/home/user/key.pem” database.cert = “/home/user/ca.crt” database.ca = “/home/user/ca_file” database.capath = “/home/user/capath” database.cipher = “aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192cbc,aes256-cbc”

  Los parámetros adicionales que soporta el adaptador “mysqli” son:    Tabla: Parámetros de conexión soportados usando mysqli  Parámetro  database.socket 

Descripción  Aplica cuando el host el localhost y permite establecer el path  al socket UNIX ó al named pipe en Windows. 

database.charset 

Permite  establecer  el  charset  utilizado  por  el  cliente  MySQL  para enviar la información al servidor. 

database.key 

La  ruta  a  donde  se  encuentra  el  archivo  de  llave  compartida.  Este parámetro solo aplica cuando la opción SSL está On. Por  defecto su valor es NULL. 

database.cert 

La  ruta  al  archivo  de  certificado.  Este  parámetro  solo  aplica  cuando la opción SSL está On. Por defecto su valor es NULL. 

database.ca 

La  ruta  al  archivo  certificate  authority.  Este  parámetro  solo  aplica  cuando  la  opción  SSL  está  On.  Por  defecto  su  valor  es  NULL. 

database.capath 

La  ruta  al  archivo  que  contiene  certificados  SSL  validos  en  formato PEM. Este parámetro solo aplica cuando la opción SSL  está On. Por defecto su valor es NULL. Por defecto su valor es  NULL. 

database.cipher 

Una  lista  de  métodos  de  cifrado  para  usar  en  la  encriptación  SSL. Este parámetro solo aplica cuando la opción SSL está On.  Por defecto su valor es NULL. 

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                178 

20.5.4 Consideraciones para IBM Informix  Kumbia Enterprise utiliza PHP Data Objects (PDO) para acceder a bases de datos IBM Informix.   Es  posible  realizar  conexiones  a  Informix  (IDS)    versión  7.x,  Universal  Server  (IUS)  9.x  y  a  Informix Dynamic Server 2000, 10 y 11. Los siguientes requisitos son necesarios para realizar  una conexión satisfactoria a este motor:    •

PHP debe estar compilado con la extensión pdo_informix, esta puede ser obtenida via  PECL ó al compilar PHP desde el código fuente. 

Cuando  se  compila  desde  el  código  fuente  la  opción  de  configuración  debe  incluir  ./configure --with-pdo-informix=/path/to/SDK[,shared] 

La  extensión  PECL  puede  ser  instalada  usando  el  comando  pecl

install

pdo_informix  en entornos Unix. Para una compilación satisfactoria de la extensión 

el cliente SDK de IBM para Informix debe estar instalado en la maquina ó el servidor  Informix en si mismo.  •

La  variable  de  entorno  INFORMIXDIR  debe  apuntar  al  directorio  de  instalación  de  informix ó del client SDK. 

ESQL/C es necesario para trabajar con informix. El Informix Client SDK contiene este  software. El client SDK para IBM Informix puede ser descargado desde el sitio web de  soporte de IBM en  http://www-306.ibm.com/software/data/informix/tools/csdk/ .  Si está utilizando Informix versión 10 ó 11 no es necesario instalar CSDK ya que este  viene incluido en la distribución del servidor. 

El servidor de Informix debe estar configurado para aceptar conexiones mediante tcp  mediante el módulo onsoctcp. 

  Una  vez  las  extensiones  php_pdo  y  php_pdo_informix  se  encuentren  disponibles  la  conexión  puede realizarse de la siguiente forma:    Ejemplo: Configuración de la conexión a IBM Informix  [development] database.layer = “pdo” database.type = informix database.dsn = "host=127.0.0.1;service=9800;database=bankdb;server=ids_server; protocol=onsoctcp;EnableScrollableCursors=1" database.username = informix database.password = bypass

  Parámetros de conexión con Informix:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                179 

Tabla:Parámetros de conexión a IBM Informix con PDO  Parámetro  database.pdo 

Descripción  Indica  que  se  debe  cargar  un  adaptador  PDO.  Su  valor  debe  ser  On para que tenga efecto. 

database.dsn 

Los parámetros de conexión del Data Source Name. El parámetro  host  indica  el  nombre  del  maquina  ó  dirección  IP  donde  está  instalado  el  Informix.  Service  es  el  puerto  donde  se  realizará  la  conexión  TCP/IP.  Database  es  el  nombre  de  la  base  de  datos.  Server  es  nombre  de  la  instancia  de  informix.  Protocol  debe  ser  siempre  onsoctcp.  EnableScrollableCursors  debe  ser  igual  a  1  para  permitir  el  uso  de  cursores  que  se  pueden  recorrer  en  cualquier  orden,  esto  puede  mejorar  el  rendimiento  cuando  se  usan paginadores por ejemplo.    Otras  opciones  que  se  pueden  enviar  en  el  DSN  son:  TraslationOption,  permite  utilizar  una  librería  de  traducción  de  mensajes, con valor 0 permite solucionar un problema común en  unixODBC.    IsolationLevel:  Indica  el  nivel  de  isolación  de  la  conexión.  0  es  Predeterminado, 1 es Read Uncommited, 2 es Read Commited, 3  es Repeteable Read, 4 es Serializable y 5 es LastCommited.    CursorBehavior: Cuando es 0 el cursor se cierra automáticamente  al recorrer los registros, cuando es 1 se preserva.    ClienteLocale:  Permite  establecer  la  localización  del  cliente.  Por  defecto es en_US.CP1251    DatabaseLocale:  Permite  establecer  la  localización  de  la  base  datos por defecto es: en_US.819    AutoCommitOptimization:  Indica  si  el  driver  debe  efectuar  optimización para conexiones no‐transaccionales. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                180 

database.username 

Nombre del usuario que realizará la conexión. 

database.password 

Contraseña del usuario. 

20.5.4.1 Configuración del Servidor  Es posible que deba cambiar el usuario con el que se ejecutan los procesos del servidor web al  usuario  informix  ó  un  usuario  del  grupo  informix.  En  el  caso  de  Apache  Web  Server  puede  modificar esto cambiando los parámetros User y Group así:    User informix Group informix

  Si el servidor está instalado en Windows y se usa Microsoft IIS se debe entrar a la consola de  administración  de  servicios.  Puede  ingresar  a  ella  mediante  el  comando  services.msc  en  el  cuadro de dialogo ejecutar. Se da click derecho en el servicio “Informix IDS – Nombre” y luego  en propiedades. En la pestaña inicio de sesión se coloca el usuario con permisos del motor y  luego click en ‘Aceptar’.    La siguiente es una configuración de las variables de entorno para un profile para el usuario  “informix” en un servidor Unix ó Windows:    Ejemplo:  Variables  de  entorno  recomendadas  para  realizar  una  conexión  a  IBM  Informix  export INFORMIXDIR=/opt/IBM/informix export INFORMIXTMP=/opt/IBM/informix/tmp export INFORMIXSERVER=ol_server export INFORMIXSQLHOSTS=$INFORMIXDIR/etc/sqlhosts export ONCONFIG=onconfig export TERMCAP=/home/informix/etc/termcap export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/IBM/informix/lib:/opt/IBM/informix/etc/lib :/opt/IBM/informix/lib/esql export DBDATE=y4md export DB_LOCALE=en_US.819 export SERVER_LOCALE=en_US.819 export CLIENT_LOCALE=en_US.819 export TERM=ansi export PATH=$PATH:$HOME/bin:$INFORMIXDIR/bin

  El archivo INFORMIXSQLHOSTS debe tener al menos un servicio tcp/ip disponible:     ol_server onsoctcp

localhost

informixserver

  El archivo /etc/services debe incluir la descripción TCP para el servicio creado:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

informixserver

 

                                                                181 

9800/tcp # Informix Dynamic Server

20.5.4.2 Consideraciones con Transacciones  El desarrollador debe activar el logging de la base de datos a Unbuffered Logging ó Buffered  Logging  usando  la  herramienta  onmonitor  ó  mediante  el  comando  ontape  –B  dbname,  de  lo  contrario el adaptador generará una excepción al tratar de realizar un commit ó un rollback a  una transacción.    Informix no genera un timeout cuando registros que se vayan a modificar ó leer esten siendo  modificados  en  otra  transacción.  Kumbia  Enterprise  generará  una  excepción  como  [Informix][Informix ODBC Driver][Informix]Could not do a physical‐order read to fetch next  row.  sqlerrm(t)  (SQLFetchScroll[‐244]  at  /root/PDO_INFORMIX/informix_statement.c:889)]  (‐244)  de tipo DbLockAdquisitionTimeout.    Todos  los  niveles  de  isolación  son  soportados  en  runtime.  El  nivel  de  isolación  CURSOR  SCALABILITY es validado con ISOLATION_SERIALIZABLE.    Nota:  IBM  Informix  no  soporta  la  extensión  del  lenguaje  SQL  LIMIT  por  lo  que  el  desarrollador debe asegurarse que los resultados devuelva el número de registros requeridos  via condiciones en la clausula WHERE.    20.5.5 Consideraciones con SQLite  SQLite  es  un  motor  de  base  de  datos  escrito  en  C  que  es  embebible  en  aplicaciones  web  de  baja concurrencia. La librería SQLite permite administrar bases de datos que se crean en un  solo archivo y que se pueden distribuir junto con la aplicación.    Como  se  mencionó  anteriormente  las  bases  de  datos  SQLite  no  están  recomendadas  para  grandes aplicaciones con alto tráfico y acceso concurrente elevado.     Kumbia Enterprise soporta SQLite versión 3 mediante la capa de abstracción PDO (PHP Data  Objects) por lo que se requiere que las extensiones de PHP pdo y pdo_sqlite esten disponibles  por la aplicación. Este adaptador no soporta múltiples transacciones simultáneas.    Los parámetros de Conexión a SQLite son:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                182 

Ejemplo: Definir una conexión a SQLite con PDO  [development] database.layer = “pdo” database.dsn = "data/company.db" database.type = sqlite

  Tabla: Parámetros de conexión del adaptador de SQLite con PDO  Parámetro  database.layer 

Descripción  Indica  que  se  debe  cargar  un  Adaptador  PDO.  Su  valor  debe  ser “pdo” para que tenga efecto. 

database.dsn 

Cuando  se  trata  de  SQLite  indica  la  ruta  al  archivo  base  de  datos. La extensión .db es opcional pero es más representativa.  El  PATH  del  archivo  puede  ser  un  path  absoluto  desde  el  directorio donde está instalada la instancia ó un path relativo. 

20.6 Pool de Conexiones El componente DbBase mediante la implementación de un Singleton controla que cada vez que  se solicite la conexión a la base de datos se devuelva la misma conexión evitando la creación  de  múltiples  conexiones  al  gestor  relacional  de  forma  innecesaria  aumentando  los  recursos  requeridos por la aplicación.    El método estático Database::rawConnect() devuelve la misma conexión activa sin importar el  número  de  veces  que  sea  invocado,  si  aun  no  existe  una  conexión  entonces  la  crea.  Los  parámetros  de  conexión  son  los  establecidos  por  entorno  activo  en  environment.ini.  Si  se  requiere  una  nueva  conexión  al  gestor  se  puede  enviar  true  como  primer  parámetro  y  si  se  requiere renovar la conexión es decir reemplazar la conexión del Singleton se envia true como  segundo parámetro.  20.6.1 Conexiones de Bajo Nivel  Es  posible  establecer  conexiones  de  bajo  nivel  a  múltiples  motores  independientemente  del  gestor  relacional  requerido.  El  subcomponente  DbLoader  permite  tanto  cargar  el  adaptador  activo establecido en enviroment.ini como uno cualquiera usando el método estático factory.    El  primer  parámetro  corresponde  al  nombre  del  adaptador  requerido  para  efectuar  la  conexión, el segundo es un vector que contiene las opciones de conexión. Estas son las mismas  utilizadas en una sección de un archivo de configuración enviroment.ini.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                183 

Ejemplo: Establecer una conexión a un gestor relacional mediante DbLoader::factory  <?php $db = DbLoader::factory('MySQL', array( "host" => "localhost", "username" => "root", "password" => "mypass", "name" => "bankdb" )); print_r($db->fetchAll(“SELECT * FROM accounts”));

  Si se desea usar los adaptadores PDO hay que indicar la opción adicional “pdo” => true en el  vector de configuración.     Ejemplo: Establecer una conexión a un gestor relacional mediante un adaptador PDO  <?php $db = DbLoader::factory('MySQL', array( "pdo" => true, "host" => "localhost", "username" => "root", "password" => "mypass", "name" => "bankdb" )); $db->fetchAll("SELECT * FROM account");

Un  descriptor  string  también  puede  ser  usado  para  establecer  una  conexión.  Estos  tienen  el  mismo formato que un DSN de PDO.  Ejemplo: Establecer una conexión mediante un descriptor string  $descriptor = “mysql:host=localhost;username=root;password=mypass;name=bankdb”; $db = DbLoader::factoryFromDescriptor($descriptor);

  20.6.2 Trazar Conexiones  La  propiedad  de  las  conexiones  de  generar  trazas  permite  obtener  una  lista  de  todas  las  operaciones SQL de bajo nivel ejecutadas en una sessión al gestor relacional.    Para activar la traza en una conexión se debe llamar al método setTracing con parámetro true  apartir del momento donde se desea empezar la traza:    Ejemplo:  Activar  y  obtener  la  traza  de  seguimiento  en  un  procedimiento  con  gestores  relacionales  <?php $db = DbBase::rawConnect(); $db->setTracing(true); $results1 = $db->fetchAll(“SELECT * FROM customers”);


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                184 

$results2 = $db->fetchAll(“SELECT * FROM customers WHERE status = ‘Active’”); foreach($db->getTracedSQL() as $sqlStatement){ echo $sqlStatement.”\n”; }

20.7 Generar Profiles de ejecución de SQL Los objetos del componente Db permiten generar Profiles de la ejecución de sentencias SQL  que  se  envian  al  gestor  relacional.  La  información  generada  incluye  los  tiempos  en  milisegundos que duró la ejecución de cada sentencia y así poder identificar cuellos de botella  en la aplicación.    Ejemplo: Activar el profiling desde objeto de conexión a un gestor relacional  <?php $db = DbBase::rawConnect(); $db->setProfiling(true);

  Internamente  una  instancia  de  DbProfiler  es  instanciada  para  generar  los  profiles  de  las  operaciones  SQL.  El  desarrollador  puede  definir  su  propio  profiler  estableciendo  una  instancia  de  la  clase  que  implemente  la  interfaz  DbProfilerInterface  como  parámetro  de  setProfiling().    Ejemplo: Definir una clase de profile personalizada  <?php $db = DbBase::rawConnect(); $db->setProfiling(new MyProfiler());

  La interface DbProfilerInterface exige la implementación de:    interface DbProfileInterface { public public public public public public public

function function function function function function function

startProfile($sqlStatement); stopProfile(); getNumberTotalStatements(); getTotalElapsedSeconds(); getProfiles(); reset(); getLastProfile();

}

20.8 Manejar Excepciones de Db Crear  la  instancia  del  adaptador  ó  directamente  en  el  constructor  del  mismo  crea  automáticamente una conexión a la base de datos. Si ocurren problemas al hacer la conexión ó  alguno  de  los  parámetros  es  invalido  se  genera  una  excepción  en  la  misma  la  cual  debe  ser  controlada por el desarrollador. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                185 

  Las excepciones son controladas mediante un bloque try/catch que capture una excepción del  tipo DbException:    Ejemplo: Capturar una excepción DbException generada por el adaptador de conexión  al gestor relacional  <?php try { $db = DbLoader::factory('MySQL', array( "pdo" => true, "host" => "localhost", "username" => "root", "password" => "hea101", "name" => "bankdb" )); } catch(DbException $e){ //No se pudo cargar el adaptador }

20.8.1 Tipos de Excepciones lanzadas por el componente Db  Excepción  DbException 

Descripción  Excepción generica lanzada por adaptador  de conexión al gestor relacional utilizado. 

DbLockAdquisitionException 

Excepción  lanzada  cuando  la  transacción  actual en la conexión no puede efectuar un  bloqueo  sobre  algún  recurso  por  ejemplo  una tabla ó una serie de registros. 

DbSQLGrammarException 

Excepción  lanzada  cuando  se  envia  una  sentencia  SQL  mal  formada  ó  con  errores  de sintaxis. 

DbContraintViolationException 

Excepción  lanzada  cuando  la  operación  de  modificación  ó  actualización  viola  un  constraint de  llave foránea. 

DbInvalidFormatException 

Excepción  lanzada  cuando  se  trata  de  insertar ó actualizar un valor en una tabla  con un formato erroneo. 

  20.8.2 Información extendida de excepciones generadas por Db  Las  excepciones  generadas  por  el  componente  Db  ofrecen  información  extendida  del  origen 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                186 

de  una  excepción.  Cuando  la  aplicación  se  encuentra  en  modo  debug  esta  información  se  puede visualizar en pantalla. La referencia de la pantalla de excepciones es la siguiente:    En la esquina superior derecha se presenta el tipo de excepción generada:   

    Después de esta el mensaje que ha enviado el gestor relacional y la sentencia SQL que generó  la excepción. En este caso tanto el tipo de excepción como el mensaje de error indica que la  sentencia SQL esta mal formada ó tiene errores de sintaxis.    El  id  de  conexión  es  un  código  interno  que  identifica  el  recurso  utilizado  para  conectarse  al  motor  de  base  de  datos.  El  mensaje  de  la  excepción  informa  que  conexión  estaba  activa  cuando se produjo la excepción. El id aparece al final como “Resource id #64”.    El  codigo  de  error  enviado  por  el  motor  también  puede  resultar  de  ayuda  en  algunos  casos.  Este se muestra al final del mensaje de error entre paréntesis.   

    Como  la  aplicación  se  encuentra  en  modo  debug  se  visualiza  la  traza  de  ejecución  de  la  excepción. Si Kumbia Enteprise detecta que la excepción se ha generado en un archivo de la  aplicación  entonces  se  muestra  el  fragmento  de  código  resaltando  la  línea  exacta  donde  se  generó la excepción: 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                187 

 

    Debajo de la traza se encuentra el cuadro “Datos de la conexión activa” y presenta atributos  del estado de la conexión en el momento de la excepción:   

    En este caso la traza se encuentra desactivada, al activarla se obtendría todas las intrucciones  SQL que se ejecutaron en la misma conexión previamente a que se produjera la excepción. La  traza  se  puede  activar  declarativamente  en  el  modo  activo  en  config/environment.ini  ó  programacionalmente  pasando  el  parámetro  “tracing”  =>  true  al  constructor  del  objeto  conexión.     El archivo config/environment.ini  entonces quedaría así:    Ejemplo: Activar la traza en el archivo config/environment.ini  [development] database.host = 127.0.0.1 database.username = my_user database.password = my_password database.name = bankdb database.type = mysql database.tracing = true

  Al ejecutar nuevamente el procedimiento se puede visualizar la traza de la conexión: 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                188 

    El campo “Traza” dice “SI” y debajo de este el nuevo campo “Contenido de la Traza” muestra  en orden cronológico las sentencias SQL generadas en la conexión activa.    Más  debajo  se  visualiza  el  cuadro  datos  de  entrada,  en  él  se  detalla  la  información  que  fue  enviada  al  procedimiento  desde  el  formulario  ó  enlace  anterior.  El  objetivo  del  cuadro  es  identificar si los datos de entrada pueden ser los causantes del problema:        Los valores de entrada se muestran en modo detallado ayudando así a conocer su contenido  más fácilmente.    Si  la  información  generada  no  es  suficiente  para  identificar  la  causa  de  la  excepción  puede  utilizar  el  componente  Debug  el  cual  proporciona  ayudas  para  realizar  procedimientos  tradicionales de rastreo de procesos. 

20.9 Tipos de Resultado al Obtener de Registros Cada adaptador implementa los mismos tipos de vector al obtener registros, esto se refiere a  la  forma  en  la  que  los  vectores  devueltos  estan  indexados.  Los  métodos  inQuery,  fetchOne  y  fetchAll  permiten  establecer  en  su  segundo  parámetro  los  valores  de  las  constantes  que  permiten cambiar la forma en la que estan dispuestos los resultados al obtenerlos.    Tabla: Tipos de constantes para obtener los registros de un resultado  Constante 

Descripción 

Db::DB_NUM 

Devuelve  cada  registro  como  un  vector  indexado  solamente  numéricamente. 

Db::DB_ASSOC 

Devuelve  cada  registro  como  un  vector  indexado  solamente  asociativamente.  Las  claves  utilizadas  como  indices  corresponden  a  los  nombres  de  las  columnas  de  la  sentencia  SELECT  ejecutada. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                189 

Cuando se realizan JOINs en múltiples tablas es posible que el nombre  de los indices se repita por lo cual es necesario implementar alias para  las columnas repetidas.    Para  todos  los  gestores  relacionales  los  indices  se  encuentran  en  minúsculas.  Db::DB_BOTH 

Devuelve  cada  registro  indexado  tanto  numéricamente  como  asociativamente.  El  número  de  elementos  por  vector  resultado  es  el  doble del número de columnas devuelto en la sentencia SELECT. 

 

20.10 Leer registros Los siguientes métodos corresponden al API del componente Db que permiten leer registros  de las entidades:    public resource|false query(string $sqlQuery)  Envia  una  sentencia  SQL  al  gestor  relacional.  La  sentencia  puede  devolver  registros  o  no  devolverlos.    Ejemplo: Enviar una sentencia SQL al gestor relacional mediante el método query()  <?php $db = DbLoader::factory('Oracle', array( "host" => "192.168.2.140", "username" => "scott", "password" => "tiger", "instance" => "XE" )); $result = $db->query("SELECT id, name FROM customer WHERE category_id = 1"); while($row = $db->fetchArray($result)){ print $row['name']."\n"; }

  public array find(string $tableName, string $whereClause, string $fields=””, string $orderBy=”1”)  Realiza una consulta SELECT en una tabla en forma abstraida.     Ejemplo: Realizar una búsqueda usando el método find()  <?php //Mostrar todos los clientes activos $db = DbBase::rawConnect(); $resultset = $db->find(“customers”, “status = ‘Active’”); foreach($resulset as $row){ print $row[‘name’].”\n”; }


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                190 

public array inQuery(string $sqlQuery, int $fetchType=db::DB_BOTH)  Devuelve los resultados de una consulta SQL en un array. El parámetro $fetchType se refiere a  las constantes db::DB_ASSOC, db::DB_NUM y db::DB_BOTH que es el tipo de indexamiento del  vector devuelto por registro.    public array fetchAll(string $sqlQuery, int $fetchType=db::DB_BOTH)  Obtiene  todos  los  resultados  de  una  consulta  SQL  en  un  array.  Es  un  alias  para  el  método  inQuery.    public array inQueryAssoc(string $sqlQuery)  Obtiene  todos  los  resultados  de  una  consulta  SQL  en  un  array.  Cada  registro  es  un  array  indexado asociativamente.    Ejemplo:  Realizar  un  consulta  que  devuelve  los  registros  como  vectores  indexados  asociativamente    <?php $db = db::rawConnect(); $customers = $db->inQueryAssoc(“SELECT id, name FROM customers ORDER BY id”); foreach($customers as $customer) { print $customer[‘name’].”\n”; }

  public array inQueryNum(string $sqlQuery)  Obtiene  todos  los  resultados  de  una  consulta  SQL  en  un  array.  Cada  registro  es  un  array  indexado numéricamente.    Ejemplo:  Realizar  un  consulta  que  devuelve  los  registros  como  vectores  indexados  numéricamente  <?php $db = db::rawConnect(); $customers = $db->inQueryNum(“SELECT id, name FROM customers ORDER BY id”); foreach($customers as $customer) { print $customer[1].”\n”; //Imprime el nombre }

  public array fetchOne(string $sqlQuery, int $fetchType=db::DB_BOTH)  Devuelve un solo registro en un array de la consulta SELECT en $sqlQuery. El parámetro $type  se  refiere  a  las  constantes  db::DB_ASSOC,  db::DB_NUM  y  db::DB_BOTH  que  es  el  tipo  de 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                191 

indexamiento del array devuelto por registro.    Ejemplo: Obtener un resultado para consultas que devuelven un solo registro    <?php $db = DbBase::rawConnect(); $customer = $db->fetchOne(“SELECT * FROM customers WHERE id = 124”);

  public array fetchArray(resource $resultQuery)  Obtiene  un  registro  del  ultimo  recurso  de  consulta  generado  en  el  objeto  adaptador  ó  el  indicado  mediante  el  recurso  $resultQuery.    El  resultado  devuelto  depende  del  fetchMode  establecido con setFetchMode.     public void numRows(resource $resultQuery=null)  Devuelve  el  número  de  filas  obtenidas  en  la  ultima  consulta  SQL  ejecutada  en  el  objeto  adaptador.  Es  posible  establecer  el  recurso  devuelto  por  el  método  query  para  obtener  esta  información.    Ejemplo: Obtener el número de registros que devuelve una consulta   <?php $db = Db::rawConnect(); $result = $db->query("SELECT id, name FROM customer WHERE status = 'Active'"); print "Hay ".$result->numRows($result)." clientes activos";

  public boolean dataSeek(int $number, resource $resultQuery=null)  Permite establecer la posición en el cursor interno ó el establecido por $resultQuery haciendo  que el próximo registro que obtenga fetchArray sea el número $number.    Ejemplo: Mover el puntero del resultado de una consulta  <?php $db = DbLoader::factory('MySQL', array( "host" => "127.0.0.1", "username" => "root", "password" => "hea101", "name" => "bankdb" )); $db->query("SELECT id, name FROM customer WHERE category_id = 1"); if($db->numRows()>10){ //Empezar desde el 10 registro $db->dataSeek(10); while($row = $db->fetchArray()){ print $row['name']."\n"; } }

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                192 

public resource getLastResultQuery()  Obtiene el último recurso generado en una consulta SQL mediante el objeto.    Ejemplo: Obtener el último resulset generado con Db::getLastResultQuery  <?php $db = Db::rawConnect(); $db->query("SELECT id, name FROM customer WHERE status = 'A'"); $result = $db->getLastResultQuery(); while($row = $db->fetchArray()){ print $row['name']."\n"; }

  public string limit(string $sqlQuery, int $number)  La  extensión  del  la  sentencia  SQL  SELECT  llamada  LIMIT  permite  especificar  al  gestor  relacional que no debe devolver más del numero de registros limitados a $number. No todos  los  gestores  relacionales  implementan  esta  extensión  y  otros  permiten  hacerlo  utilizando  otros procedimientos.    Este  método  permite  crear  una  sentencia  SQL  que  reproduzca  la  funcionalidad  LIMIT  en  forma transparente.    Ejemplo: Aplicar la extensión del lenguaje SQL LIMIT a una consulta  <?php $db = Db::rawConnect(); $sqlQuery = $db->limit("SELECT id, name FROM customer WHERE status = 'A'", 10); $db->query($sqlQuery); $result = $db->getLastResult(); while($row = $db->fetchArray()){ print $row['name']."\n"; }

20.11 Manipular Registros Los siguientes métodos permiten la generación y ejecución de sentencias SQL que permiten la  manipulación de registros:    public  boolean  insert(string  $table,  array  $values,  array  $fields=array(),  boolean  $automaticQuotes=false)  Permite realizar una inserción sin usar SQL directamente. El SQL es generado está de acuerdo  al  gestor  relacional  utilizado.  Notese  que  por  defecto  el  método  espera  que  los  valores  a  insertar  esten  correctamente  escapados,  el  parámetro  $automaticQuotes  permite  que  se  agregen  comillas  simples  y  se  escapen  los  valores  usando  la  función  addslaches()  en  forma 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                193 

automática.    Las  columnas  que  son  omitidas  se  les  aplica  la  regla  del  gestor  relacional  DEFAULT  si  esta  existe, en caso contrario se insertan valores nulos.    Ejemplo: Realizar una inserción con $automaticQuotes y sin ellas  <?php $db = DbBase::rawConnect(); //Usando Quotes Manualmente $values = array(“’0044’”, “’England’”); $fields = array(“code”, “name); if($db->insert(“countries”, $values, $fields)){ Flash::success(“Se insertó correctamente el registro”); } //Usando Quotes en forma automática $values = array(“0044”, “England”); $fields = array(“code”, “name); if($db->insert(“countries”, $values, $fields, true)){ Flash::success(“Se insertó correctamente el registro”); }

  Cuando  se  agrega  el  parámetro  $automaticQuotes  y  se  requiere  insertar  expresiones  ó  ejecución de funciones de la base de datos es necesario indicar estos usando instancias de la  clase DbRawValue.    Ejemplo: Insertar un valor expresión de la base de datos    <?php $db = DbBase::rawConnect(); $values = array(“John Smith”, new DbRawValue(“current_date()”)); $fields = array(‘name’, ‘created_at’); if($db->insert(“employees”, $values, $fields, true)){ Flash::success(“Se insertó correctamente el registro”); }

  public  boolean  update(string  $table,  array  $fields,  array  $values,  string  $whereClause=null,  boolean $automaticQuotes=false)  Permite realizar una actualización sin usar SQL directamente. El SQL es generado de acuerdo  al  gestor  relacional  utilizado.  Notese  que  por  defecto  el  método  espera  que  los  valores  a  actualizar  esten  correctamente  escapados,  el  parámetro  $automaticQuotes  permite  que  se  agregen comillas simples y se escapen los valores usando la función addslaches().    Ejemplo: Realizar una actualización de datos  <?php


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                194 

$db = DbBase::rawConnect(); $fields = array(“code”, “name); $values = array(“’0044’”, “’England’”); if($db->update(“countries”, $fields, $values)){ Flash::success(“Se actualizó correctamente el registro”); } $fields = array(“code”, “name); $values = array(“0044”, “England”); if($db->update(“countries”, $fields, $values, true)){ Flash::success(“Se actualizó correctamente el registro”); }

  public void delete(string $table, string $whereCondition=””)  Permite realizar una eliminación de registros sin usar SQL directamente. El SQL es generado  de acuerdo al gestor relacional utilizado.    Ejemplo: Realizar una eliminación de datos  <?php $db = DbBase::rawConnect(); //Eliminar todos los registros de la tabla customer if($db->delete(“customer”)==true){ Flash::success(“Se eliminaron correctamente todos los registros”); } //Eliminar usando condiciones if($db->delete(“customer”, “status = ‘Active’”)==true){ Flash::success(“Se eliminaron correctamente los registros”); }

  public integer affectedRows(Resource $resultQuery=null)  Devuelve  el  numero  de  filas  afectadas  por  una  operación  de  inserción,  actualización  ó  borrado.  El  parámetro  $resultQuery  permite  cambiar  el  recurso  devuelto  por  otra  ejecución  del método query ó exec.    Ejemplo:  Obtener  información  de  los  registros  afectados  en  una  operación  de  manipulación de datos  <?php $db = Db::rawConnect(); $db->query("DELETE FROM customer WHERE status = 'I'"); print "Filas borradas = ".$db->affectedRows();

20.12 Administrar Transacciones public boolean begin()  Permite iniciar una transacción en la conexión utilizada.     Ejemplo: Uso de transacciones a bajo nivel  


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                195 

  <?php $db = DbBase::rawConnect(); $db->begin(); $fields = array("name", "createdAt"); $values = array("John Smith", "2007-10-21"); if($db->insert("customer", $values, $fields, true)==false){ $values = array("Darren Davison", "2007-12-02"); if($db->insert("customer", $values, $fields, true)==false){ $db->commit(); } else { $db->rollback(); } } else { $db->rollback(); }

  public boolean rollback()  Permite anular una transacción en la conexión utilizada.    public boolean commit()  Permite hacer commit a una transacción pendiente en la conexión actual.    public string forUpdate(string $sqlQuery)  Genera un SQL que efectúa un bloqueo no‐compartido del grupo de registros seleccionados.    public string sharedLock(string $sqlQuery)  Genera un SQL que efectúa un bloqueo compartido del grupo de registros seleccionados.    public void setIsolationLevel(int $isolationLevel)  Permite  establecer  el  nivel  de  isolación  de  la  conexión.  Los  niveles  de  isolación  deben  estar  disponibles en el gestor relacional, consulte la documentación si tiene dudas de ello. El valor  del parámetro $isolationLevel es alguna de las constantes:    Tabla: Descripción de constantes de niveles de Isolación  Valor  1 

Nombre  ISOLATION_READ_UNCOMMITED 

Descripción  Los SELECTs se ejecutan en un  modo de no‐bloqueo. 

ISOLATION_READ_COMMITED 

Las  consultas  se  ejecutan  un  un 

modo 

de 

lecturas 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                196 

consistentes con no‐bloqueo.  3 

ISOLATION_REPEATABLE_READ 

Gestores 

transaccionales 

normalmente  trabajan  sobre  este modo de isolación.  4 

ISOLATION_SERIALIZABLE 

Algunos  gestores  relacionales  como 

Oracle 

soportan 

nativamente  este  modo,  otros  como  MySQL  convierten  todas  las  instrucciones  SELECT  en  SELECT  …  LOCK  IN  SHARE  MODE bloqueando el grupo de  registros  obtenidos  en  una  consulta a modo‐solo lectura.    public boolean isUnderTransaction()  Permite conocer si la conexión se encuentra bajo una transacción activa.    public void getHaveAutoCommit()  Permite conocer si la conexión tiene auto‐commit ó nivel de isolación READ UNCOMMITED. 

20.13 Crear, Cerrar y obtener información de conexiones public Db rawConnect(boolean $newConnection=false, boolean $renovate=false)  Obtiene  un  objeto  conexión  a  la  base  de  datos  del  entorno  actual  con  los  parámetros  establecidos en el archivo config/enviroment.ini. Este método implementa el patrón Singleton  controlando que solo una instancia de la conexión se cree cada vez que se hace el llamado al  mismo desde cualquier parte de la aplicación.    Ejemplo: Obtener la conexión por defecto al gestor relacional  <?php //Crear o obtener la última conexión creada $db = DbBase::rawConnect(); //Crear una nueva conexión sin cambiar la conexión del Singleton $db = DbBase::rawConnect(true); //Crear una nueva conexión renovando la conexión del Singleton $db = DbBase::rawConnect(true, true);

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                197 

public ResourceConnection connect(stdClass $descriptor)  Establece la conexión al gestor relacional.    Ejemplo: Crear una conexión usando el método Db::connect  <?php $db = new Db(); $db->connect("192.168.2.140", "scott", "tiger", "bankdb"); $result = $db->query("SELECT * FROM customer"); while($row = $db->fetchArray($result)){ print $row['name']."\n"; }

  public resource getConnectionId()  Obtiene  el  recurso  interno  de  bajo  nivel  con  el  que  se  identifica  la  conexión  al  gestor  relacional.    public void close()  Cierra la conexión actual con el gestor relacional. Si la conexión es persistente no se cerrará.    public void setReadOnly(boolean $readOnly)  Establece si la conexión será de solo lectura. En este estado se generará una excepción cuando  se trate de realizar una inserción, modificación ó eliminación de datos.    public void isReadOnly()  Permite saber si la conexión es de solo lectura ó no. 

20.14 Información de Errores public string error(string $errorString=’’, resource $resultQuery=null)  Devuelve información del último error generado en el adaptador.    public integer noError(resource $resultQuery=null)  Devuelve el número del último error generado. 

20.15 Obtener el valor de la columna identidad Algunos  gestores  relacionales  soportan  columnas  identidad,  es  decir,  que  manejan  un  consecutivo auto‐numérico para diferenciar unívocamente cada registro en una tabla.     public integer lastInsertId(string $table=’’, string $identityField=””) 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                198 

Obtiene el último valor insertado en una columna identidad. Algunos gestores relacionales no  soportan este tipo de columnas y por ello es necesario obtener el valor buscando el máximo  valor insertado en el campo llave primaria.     public boolean tableExists(string $table, string $schema=””)  Permite  consultar  si  una  relación  con  el  nombre  $table  existe  en  el  schema  de  la  conexión  actual ó el indicado usando el parámetro $schema. 

20.16 Obtener información de Tablas public array getFieldsFromTable(string $tableName)  Este  método  obtiene  los  campos  de  una  tabla  en  un  vector.  El  vector  puede  ser  indexado  numéricamente ó asociativamente:    Ejemplo: Obtener los campos de una tabla con Db::getFieldsFromTable  <?php

  $db = DbBase::rawConnect(); $fields = $db->getFieldsFromTable(“customer”);

  public string fieldName(int $number, Resource $resultQuery=null)  Obtiene  el  nombre  de  un  campo  en  la  posición  establecida  por  $number  del  resultado  $resultQuery.    public array listTables(string $schemaName=’’)  Devuelve  un  array  con  las  tablas  que  hay  en  la  schema  actual  ó  en  el  que  se  indique  en  $schemaName.  En  algunos  gestores  relacionales  también  se  devuelven  las  vistas  a  las  que  tenga acceso el usuario de la conexión activa.    public array describeTable(string $tableName=’’, string $schemaName=’’)  Devuelve un array con la descripción de los campos de una tabla junto con sus tipos de datos. 

20.17 Crear y Eliminar Tablas public  boolean  createTable(string  $tableName,  array  $definition,  array  $index=array(),  array  $tableOptions=array())  Permite crear��tablas físicas ó temporales en la conexión activa. El parámetro $definition es un  vector con la lista de campos de la tabla y sus atributos. El parámetro $index permite indicar 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                199 

indices  que  se  deban  crear  junto  con  la  tabla  y  por  último  $tableOptions  permite  indicar  opciones  de  la  tabla  a  crear  tales  como  el  Engine  en  el  caso  de  MySQL,  el  charset  ó  el  tablespace en el caso de Oracle. Devuelve un valor booleano indicando el éxito de la operación.    Ejemplo: Crear una tabla usando un adaptador en especial  <?php $db = DbLoader::factory('MySQL', array( 'hostname' => 'localhost', 'username' => 'root', 'password' => '', 'name' => 'test' )); $db->createTable(“example”, array( "id" => array( "type" => DbMySQL::TYPE_INTEGER, "notNull" => true, "primary" => true, "auto" => true ), "nombre" => array( "type" => DbMySQL::TYPE_VARCHAR, "notNull" => true, "size" => 120 ), "texto" => array( "type" => DbMySQL::TYPE_TEXT, "notNull" => true ), "cantidad" => array( "type" => DbMySQL::TYPE_INTEGER, "notNull" => true, "size" => 11 ), "fecha" => array( "type" => DbMySQL::TYPE_DATETIME, "notNull" => true ), "fecha_at" => array( "type" => DbMySQL::TYPE_DATE ), "fecha_in" => array( "type" => DbMySQL::TYPE_DATE ), "estado" => array( "type" => DbMySQL::TYPE_CHAR , "notNull" => true, "size" => 1 ) ), array( “ix1” => “nombre”, “ix2” => array(“fecha”, “estado”) ));

  También es posible crear la tabla usando la conexión predeterminada del entorno actual:    Ejemplo: Crear una tabla usando la conexión predeterminada  <?php $db = Db::rawConnect(); $db->createTable(“example”, array( "id" => array(


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

),

));

"type" => "notNull" "primary" "auto" =>

 

                                                                200 

Db::TYPE_INTEGER, => true, => true, true

"nombre" => array( "type" => Db::TYPE_VARCHAR, "notNull" => true, "size" => 120 )

  Los  tipos  de  atributos  con  los  que  se  puede  describir  un  campo  en  la  definición  de  las  columnas es la siguiente:    Tabla: Tipos de atributos para describir una tabla con Db::createTable  Atributo  type 

Descripción  El tipo de dato que se almacenará en la columna, se puede utilizar un  string con el tipo de dato ó usar las constantes del adaptador lo que es  más recomendable. 

notNull 

Indica si la columna debe permitir nulos o no. 

primary 

Indica si el campo hace parte de la llave primaria de la tabla. 

auto 

Indica si el campo es identidad. Solo puede haber un campo  autonumérico en la tabla. 

size 

Tamaño del campo. 

scale 

Permite establecer la escala del campo. 

precision  default 

Permite establecer la precisión del campo.  Permite establecer el valor por defecto de la columna cuando se  inserta un valor nulo en ella. 

  public boolean dropTable(string $tableName, $ifExists=false)  Elimina una tabla del schema actual de la conexión. El parámetro $ifExists permite establecer  si  se  debe  comprobar  que  la  tabla  exista  antes  de  ser  eliminada  lo  que  evita  una  excepción  generada  por  el  gestor  relacional.  Devuelve  un  valor  booleano  indicando  el  éxito  de  la  operación.    Ejemplo: Eliminar una tabla con Db::dropTable  <?php $db = DbBase::rawConnect(); $db->dropTable(“customer”);


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                201 

20.18 Fecha del gestor relacional public string getDateUsingFormat(string $date, string $format=”YYYY­MM­DD”)  Devuelve la fecha del gestor relacional en un determinado formato.    public string getCurrentDate()  Obtiene la fecha actual desde el gestor relacional.    public string addQuotes(string $value)  Agrega comillas especiales soportadas por el gestor relacional a un valor $value. 

20.19 Debug, Seguimiento y Traza protected void log(string $msg, int $type=Logger::DEBUG)  Envia un valor al log interno del objeto conexión. La variable $type debe tener el valor de una  de las constantes del componente Logger.    protected void debug(string $sqlStatement)  Realiza un debug de la instrucción SQL $sqlStatement enviandola a pantalla. Generalmente no  es usado externamente y se invoca cuando la conexión se encuentra en modo debug.    public void setDebug(boolean $debug)  Permite imprimir en pantalla las operaciones internas de SQL generadas en el objeto.    public void setTracing(boolean $tracing)  Establece si el objeto está en modo traza ó no.    public array getTracedSQL()  Devuelve un vector con las operaciones SQL ejecutadas en la conexión mientras se encontraba  en modo traza.    public void setLogger(mixed $logger)  Establece  el  nombre  del  archivo  con  el  que  se  hará  seguimiento  a  las  operaciones  SQL  generadas en la conexión. Si se envia true como parámetro se creará un log con la convención  dbYYYYMMDD.txt. Si se establece una instancia de un adaptador de logger este es tomado para  hacer el seguimiento. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                202 

21 Componente Active Record - ORM 21.1 Introducción Muchos  de  los  procesos  críticos  del  software  en  una  empresa  están  relacionados  con  el  funcionamiento, desarrollo y mantenimiento de los datos que representan la información, un  activo muy valioso de una organización. Los entornos empresariales actuales requieren de la  integración  continua  de  requerimientos  dadas  las  condiciones  de  un  mundo  cambiante  y  evolutivo. Las aplicaciones desarrolladas bajo un componente de acceso a la información poco  escalable ó demasiado dependiente de componentes y proveedores tecnológicos, puede llevar  a  que  una  organización  pierda  clientes  ó  dinero  debido  a  la  imposibilidad  de  adaptarse  rápidamente a las necesidades requeridas sin perder estabilidad ó requiriendo mayor tiempo  de desarrollo e implementación generando sobre costos.    Un componente importante en Kumbia Enterprise Framework es el componente ActiveRecord.  Este es el encargado de realizar el mapeo objeto‐relacional y de encargarse de los modelos en  la  arquitectura  MVC  de  las  aplicaciones.  El  concepto  de  ORM  se  refiere  a  una  técnica  de  mapear las relaciones de una base de datos a objetos nativos del lenguaje utilizado (PHP en  este caso), de tal forma que se pueda interactuar con ellos en forma más natural. Los objetivos  de este componente van más allá de mapear tablas y convertirlas en clases (incluyendo tipos  de  datos,  constraints,  lógica  de  dominio,  etc.)  ó  de  convertir  registros  en  objetos.  La  idea  es  reducir los detalles de la interacción con las bases de datos en gran medida mediante varias  capas  de  abstracción,  incluyendo  reducir  el  uso  de  SQL  ó  lidiar  con  conexiones  y  sintaxis  programacional de bajo nivel.    Al implementar el acceso a las bases de datos usando un ORM se gana:    •

Independencia  de  la  base  de  datos  utilizada  en  gran  medida,  esto  aumenta  las  características comerciales de un software ya que es posible cambiar de RBDM con un  menor impacto sobre las áreas implicadas al uso e implementación del mismo. 

Reducción del tamaño del código haciendo más simple el uso y entendimiento a nivel  de desarrollo de sistemas que utilicen bases de datos. 

La  capa  intermedia  de  acceso  a  loas  RBDMs  proporciona  un  método  potente    de  interceptación de cualquier evento relacionado con las bases de datos, lo cual facilita  la validación de la lógica de dominio, integridad de datos, definir niveles de seguridad, 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                203 

logging , auditoria de sistemas, etc.  •

El ORM permite administrar las asociaciones de las entidades del modelo incluso si el  backend de almacenamiento es distinto.  

ActiveRecord  proporciona  event  handling  en  la  capa  intermedia,  lo  cual  permite  notificar cambios en el modelo de forma uniforme y consistente. 

  La mayor parte de la implementación de ActiveRecord se basa en el patrón de diseño del tipo  Data  Source  Architectural  del  mismo  nombre.  En  conjunto  con  el  almacenamiento  de  meta‐ datos y la administración de transacciones se realizan los procesos de interacción con bases  de datos a más alto nivel. 

21.2 Cuando usar ActiveRecord ActiveRecord  es  un  patrón  de  diseño  en  los  cual  los  datos  y  la  estructura  de  los  mismos  se  encuentran asociados en una misma clase. Los datos generalmente son persistentes, es decir  que están almacenados en algún gestor relacional, archivo ó medio físico. La lógica de acceso a  los datos es fácilmente implementable usando ActiveRecord y además la convierte en parte de  la lógica de dominio de la aplicación.    ActiveRecord es una buena opción cuando la lógica de dominio no es muy compleja, es decir se  implementa  un  modelo  isomorfico,  se  usan  derivaciones,  colecciones  ó  herencia  no‐sencilla.  Modelos entidad‐relación con un diseño consistente ayudan a mejorar la implementación de  patrón de diseño. 

21.3 Entidades Las entidades son objetos persistentes ligeros que normalmente representan una tabla en una  base  de  datos  relacional.  El  estado  persistente  de  una  entidad  este  representado  usando  atributos persistentes asociados a los campos de las tablas. Cada entidad se implementa en un  modelo que es una clase en un archivo en el directorio models/.  21.3.1 Requerimientos de las Clases de Entidades    Las clases deben tener los siguientes requerimientos:    •

Cada archivo debe tener el nombre de la tabla y la extensión .php 

Debe haber una entidad por archivo 

La clase debe ser subclase (heredar) de la clase ActiveRecord 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                204 

La clase no debe tener constructores 

La clases que representen entidades finales no debe ser abstracta 

  21.3.2 Atributos de las Entidades  Debido a que PHP es un lenguaje con tipificación dinámica los atributos de las clases entidad  no representan el tipo de dato real del campo en la base de datos. Con objetivos funcionales  los  getters  de  algunos  campos  crean  objetos  asociados  al  tipo  de  dato  real,  por  ejemplo,  los  campos tipo fecha devuelven un objeto de la clase Date con el valor del campo.    Es  posible  agregar  casting  al  valor  de  cada  objeto  usando  la  opción  del  script  que  crea  modelos así:    php scripts/create_model.php –-table-name customers –-enable-casting yes

  Los tipos de datos a los que les aplica casting son los siguientes:    Tabla: Relación de casting entre tipo de dato de la base de datos y tipo de dato de PHP  Tipo Dato BD 

Tipo Dato PHP/Kumbia  Enterprise 

Varchar, Char, Text, Blob 

String 

Integer, smallint, tinyint 

Integer 

decimal, float, Money 

double 

date 

Date 

time 

Time 

  Adicional  a  lo  anterior  es  recomendable  inicializar  los  atributos  del  modelo  a  un  valor  adecuado  a  su  tipo  de  dato,  de  esta  forma  se  evitan  inconvientes  con  la  ampliamente  construcción del framework isset usada por el framework, ya que algunas veces considera que  un campo no está definido pero en realidad tiene un valor nulo (null). 

21.4 Atributos y Campos persistentes La  implementación  de  los  atributos  de  las  entidades  en  las  clases  se  puede  realizar  estáticamente  ó  dinámicamente  dependiendo  de  los  requerimientos  de  la  aplicación.  En  general una implementación estática propende por mejores practicas de desarrollo y software 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                205 

más seguro.    En la forma estática se definen los campos de la tabla como atributos protegidos de la clase.  Esto permite encapsular el estado interno de cada propiedad y evitar que sea cambiada por  equivocación  ó  a  propósito  en  lógica  de  la  aplicación.  En  estos  casos  también  es  necesario  implementar  métodos  get/set  para  poder  obtener/establecer  el  valor  de  los  atributos.  Los  métodos  de  ActiveRecord  isAttribute($property),  writeAttribute($property,  $value)  y  readAttribute($property)  permiten  dinámicamente  conocer  si  existe  un  atributo,  obtener  y  devolver  su  valor  en  forma  pública.  Por  ejemplo  isName(),  getName()  y  setName()  es  una  implementación estática para el atributo ‘name’ de una entidad Customer.    La forma general en la que los getters/setters deben ser implementados es la siguiente:    public function getProperty(); public function setProperty($valueOfProperty);

  El método protegido setTrasient($attribute) permite establecer que campos de la entidad no  deben  ser  persistidos.  Las  operaciones  de  inserción  y  actualización  omiten  los  atributos  marcados como Trasient.    Ejemplo: Establecer un campo trasient en el modelo  protected function initialize(){ $this->setTransient(“user_code”); }

  Cuando los campos se mapean dinámicamente su visibilidad queda establecida como pública  por defecto.  

21.5 Llaves Primarias Generalmente  de  entidades  tienen  una  llave  primaria  que  permite  identificar  un  registro  en  forma  única.  Kumbia  Enterprise  Framework  lee  los  meta‐datos  de  la  tabla  mapeada  directamente  del  gestor  relacional  e  identifica  la  llave  primaria  con  sus  características:  simples, compuestas y/o auto‐numéricas.    El tipo de dato de llaves primarias debe ser un tipo de dato integral, en general se debe evitar  el  uso  de  campos  con  tipo  de  dato  flotante,  decimal  ó  Money,  ya  que  pueden  variar  ligeramente y no ofrecen seguridad en que un registro sea univoco. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                206 

  Los accesores (métodos get) de los atributos que pertenezcan a una llave primaria compuesta  ó simple deben ser todos públicos.  

21.6 Convenciones en llaves primarias Kumbia Enterprise Framework soporta convención en llave primaria, para esto debe tener los  siguientes requisitos:    •

El campo debe llamarse ‘id’ 

El campo debe estar marcado como llave primaria en el gestor relacional 

El campo debe ser entero preferiblemente unsigned (sin signo) 

El  campo  debe  ser  una  columna  identidad  ósea  ser  autonumérico  (DB2,  MySQL,  Sybase,  Microsoft  SQL  Server)  ó  estar  asociado  a  una  secuencia  (Oracle,  DB2,  PostgreSQL, Interbase) 

  El uso de esta convención reduce la complejidad de la aplicación y reduce la codificación ya  que muchos aspectos el framework puede asumir esto.  

21.7 Fechas Auto-Asignables ActiveRecord soporta fechas auto‐asignables mediante convención mediante lo cual se puede  realizar versionamiento concurrente óptimista ó simplemente llevar un registro de fechas de  creación  y modificación de registros.    Las convenciones para fechas auto‐asignables son las siguientes:    

Para  que  un  campo  tome  automáticamente  la  fecha  del  sistema  en  la  operación  de 

insertar este debe tener el sufijo “_at” y permitir valores nulos.  

Para  que  un  campo  tome  automáticamente  la  fecha  del  sistema  en  la  operación  de 

actualizar este debe tener el sufijo “_in” y permitir valores nulos. 

21.8 Multiplicidad en Relaciones de Entidades Existen cuatro tipos de multiplicidad en relaciones: una‐a‐una, una‐a‐muchos, muchos‐a‐una y  muchos‐a‐muchos. La multiplicidad puede ser unidireccional ó bidireccional y cada una puede  ser simple ó mediante combinación de tablas. El tipo de relaciones establece como se lleva a 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                207 

persistencia  una  instancia  de  una  entidad.  Normalmente  el  gestor  relacional  administra  constraints de llave foránea correspondientes a estas relaciones, la definición de estos ayuda a  que  la  integridad  de  datos  sea  confiable  y  las  relaciones  definidas  obtengan  los  resultados  esperados. A través de la implementación de las relaciones es posible acceder a los registros  relacionados a cada registro de forma uniforme ahorrando código.  21.8.1 Convenciones en Relaciones  Los  nombres  de  campos  de  las  entidades  con  ciertas  convenciones  permiten  que  se  establezcan automáticamente los campos referencias y se automaticen tareas de codificación  mediante una estructura nemotécnica:    •

Para especificar un campo que es llave foránea a otra relación se utiliza el nombre de  campo “nombre_tabla_id” 

La  tabla  referenciada  debe  tener  un  campo  identidad  que  sea  llave  primaria  con  nombre “id”. 

Si es posible, los campos relacionados deben tener el mismo tipo de dato.   

21.8.2 Relaciones Unidireccionales  Las  relaciones  unidireccionales  son  aquellas  que  se  generan  de  una  relación  a  otra  pero  no  viceversa.  Mediante  los  métodos  belongsTo,  hasMany  ó  hasOne  se  establece  que  uno  ó  mas  campos hacen referencia a otros equivalentes en otra entidad.   21.8.3 Relaciones Bidireccionales  Las relaciones bidireccionales establecen asociaciones en las que cada una de ellas tiene una  viceversa complementaria.   21.8.4 Muchos a uno  La  asociación  unidireccional  muchos‐a‐uno  es  la  más  común  de  todas.  Para  establecer  una  relación de este tipo se utiliza el método protegido de ActiveRecord belongsTo:    Ejemplo: Multiplicidad muchos a uno relacionada con un solo campo    Para 2 Tablas:    CREATE TABLE `country` ( `code` int(11) NOT NULL, `name` varchar(20) default NULL,


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

PRIMARY KEY );

 

                                                                208 

(`code`)

CREATE TABLE `city` ( `code` int(11) NOT NULL, `country_code` int(11) default NULL, `name` varchar(80) default NULL, PRIMARY KEY (`code`) );

  El modelo de ciudades con una relación muchos‐a‐uno se implementa así:    <?php class City extends ActiveRecord { protected function initialize(){ $this->belongsTo(“country_code”, “country”, “code”); } }

  El  primer  parámetro  de  belongsTo  indica  el  campo  de  la  entidad  que  hace  la  asociación,  el  segundo indica el nombre de la entidad referenciada y el tercero el nombre del campo en la  entidad referenciada. La asociación una vez definida se puede utilizar así:    Ejemplo: Utilizar una asociación muchos a uno    $city = EntityManager::getEntityInstance(“City”); $city->findByName(“Bogotá”); $country = $city->getCountry() print $country->getNombre(); // => Colombia

  Un getter con el nombre de la relación ‘Country’ permite obtener  el registro asociado al país  en la ciudad consultada.   Relacionada con varios campos:  El siguiente ejemplo implementa una relación muchos a uno con 2 campos referencia, en este  caso los nombres de los campos son iguales en ambas tablas si fuesen diferentes se podrían  definir en el tercer parámetro de belongsTo.    Ejemplo: Utilizar una relación compuesta muchos a uno  CREATE TABLE `customer` ( `identification_type` char(3) NOT NULL default '', `number` varchar(40) NOT NULL default '', `nombre` varchar(120) default NULL, `status` char(1) default NULL, PRIMARY KEY (`identification_type`,`number`) );


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                209 

CREATE TABLE `flights` ( `flight_number` varchar(12) NOT NULL default '', `identification_type` char(3) default NULL, `number` varchar(40) default NULL, `flight_date` date default NULL, `initial_hour` time default NULL, `final_hour` time default NULL, PRIMARY KEY (`flight_number`) );

  El modelo Flights se implementa así:    Ejemplo:  Definir  una  relación  belongsTo  en  un  modelo  entidad­relación  sin  convenciones    <?php class Flights extends ActiveRecord { protected function initialize(){ $this->belongsTo(array(“identification_type”, “number”), “customer”); } }

  La relación puede ser utilizada así:    $flight = $this->Flights->findByDate(“2008-11-01”); $customer = $flight->getCustomer();

  Un getter con el nombre de la relación permite obtener  el registro asociado al cliente en el  vuelo consultado.  21.8.5 Uno a Muchos  La  asociación  unidireccional  uno‐a‐muchos  indica  que  para  cada  registro  de  una  entidad  existen uno ó más registros asociado en la entidad referenciada. Para establecer una relación  de este tipo se utiliza el método protegido de ActiveRecord hasMany.  21.8.6 Uno a Uno  La  asociación  unidireccional  uno‐a‐uno  es  la  más  inusual  de  todas.  Indica  que  para  cada  registro  de  una  entidad  existe  solo  uno  asociado  en  la  entidad  referenciada.  Para  establecer  una relación de este tipo se utiliza el método protegido de ActiveRecord hasOne.  21.8.7 Muchos a Muchos  FALTA 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                210 

21.9 API de ActiveRecord A continuación se presenta una referencia de los principales métodos de la clase ActiveRecord.  21.9.1 Origen de Datos  public void setSource($source)  Permite establecer la entidad del gestor de donde se mapearan los atributos del modelo.    public string getSource()  Devuelve el nombre de la entidad usada internamente para mapear los atributos del modelo.    public void setSchema(string $schema)  Establece el nombre del $schema en donde se encuentra la tabla donde se mapearan los datos.    public void setConnection(Db $connection)  Permite  establecer  un  objeto  Db  dinámicamente  sobrescribiendo  la  conexión  actual  del  modelo.    public DbBase getConnection()  Obtiene  el  objeto  Db  utilizado  para  realizar  las  operaciones  a  bajo  nivel  con  el  gestor  relacional.  21.9.2 Volcado de Meta­Datos  public boolean isDumped()  Indica si ya se han obtenido los meta‐datos del gestor relacional en el objeto.    public void dumpModel()  Forza al modelo a obtener los meta‐datos del gestor relacional.    protected boolean dump()  Obtiene los meta‐datos del gestor relacional. Si ya se han obtenido no se vuelven a consultar    public void resetMetaData()  Elimina los meta‐datos obtenidos del gestor‐relacional cargandolos nuevamente.  21.9.3 Debug y Seguimiento  public void setDebug(boolean $debug) 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                211 

Establece  si  el  modelo  esta  en  modo  debug.  Todas  las  operaciones  internas  de  la  conexión  activa se visualizan como Flash::notices en la salida al navegador.    public void setLogger(mixed $logger)  Establece el modelo en modo debug. Todas las operaciones internas de la conexión asociada al  modelo son almacenadas en un archivo con nombre $logger. Si el primer parámetro es true se  utiliza la convención dbYYYYMMDD.txt    //Grabar todas las operaciones SQL internas a un archivo en logs/customersDebug.txt $this->Employees->setLogger(“customersDebug.txt”);

  También  es  posible  pasar  una  instancia  de  logger  utilizando  cualquier  adaptador  disponible  utilizando como parámetro el objeto creado:    Ejemplo:  Loguear  las  operaciones  internas  de  un  modelo  a  un  logger  que  usa  compresión  $logger = new Logger(‘Compressed’, ‘log.employees.txt.gz’); $logger->setPath(“/usr/local/log/”); $this->Employees->setLogger($logger);

  El desarrollador también puede pasar una instancia de un objeto que implemente un método  log como parámetro e implementar operaciones personalizadas mediante él.    Ejemplo:  Definir  un  Logger  personalizado  para  hacer  seguimiento  a  las  operaciones  internas de un modelo    $myLog = new MyUserLog(); $this->Employees->setLogger($myLog);

  public string inspect()  Obtiene una cadena de inspección con los valores internos de cada atributo de la entidad.    21.9.4 Transacciones  public void setTransaction(ActiveRecordTransaction $transaction)  Establece la transacción utilizada para efectuar las operaciones en el modelo. La transacción  debe  haberse  inicializado  antes  de  asignarla  al  objeto  ó  generará  una  excepción  ActiveRecordException. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                212 

21.9.5 Consultar registros  public ActiveRecordResulset findAllBySql(string $sqlQuery)  Permite  realizar  una  consulta  en  el  modelo  usando  lenguaje  de  consulta  SQL.  Los  valores  obtenidos son devueltos como instancias de la clase.    public ActiveRecordResulset findBySql(string $sqlQuery)  Permite realizar una consulta en el modelo que devuelve un solo registro usando lenguaje de  consulta SQL. Los valores obtenidos son devueltos como instancias de la clase.    Ejemplo: Realizar una consulta en un modelo usando SQL    //Obtener los empleados con una condición en un subselect $empoyees = $this->Employees->findBySql(“SELECT employees.* FROM employees WHERE id NOT IN (SELECT employees_id FROM historical_data WHERE period = ‘2005-02’”);

  public DbResource sql(string $sqlQuery)  Permite  realizar  una  consulta  usando  lenguaje  SQL.  El  cursor  de  bajo  nivel  es  devuelto  directamente.    public ActiveRecord findFirst(mixed $params)  Permite  realizar  una  búsqueda  de  registros  que  devuelve  un  solo  registro  ó  el  primero  que  coincida  con  las  condiciones  indicadas.  Los  parámetros  de  consulta  se  establecen  usando  parámetros por nombre.    Ejemplo: Utilizar findFirst para obtener el primer registro de un modelo ó el primero  que cumpla determinadas condiciones  //Obtener el primer empleado que se almacenó en la entidad $employee = $this->Employees->findFirst(); //Obtener el primer usuario cuyo login sea ‘j.smith’ $user = $this->Users->findFirst(“login = ‘j.smith’”); //Obtener el ultimo producto cuyo precio sea menor a 100 y este activo $user = $this->Products->findFirst(“price < 100 AND status = ‘Active’”, “order: price DESC”);

  public ActiveRecordResulset find(mixed $params)  Permite  realizar  una  búsqueda  de  registros  que  devuelve  todos  los  que  coincidan  con  las  condiciones indicadas.    Ejemplo: Utilizar find para consultar los registros del modelo 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                213 

//Obtener todos los registros de una entidad $employees = $this->Employees->find(); //Obtener todos los registros que cumplan con una condición $employees = $this->Employees->find(“status = ‘Active’”); //Obtener todos los registros que cumplan una condición y aplicándoles un ordenamiento $employees = $this->Employees->find(“status = ‘Active’”, “order: name desc”); //Obtener todos los registros y aplicarles un ordenamiento $employees = $this->Employees->find(“order: name”); //Obtener los 20 primeros registros que cumplan con unas condiciones $employees = $this->Employees->find(“agreement_date >= ‘2008-12-31’ AND status=’Active’”, “limit: 20”);

  public ActiveRecordResulset findForUpdate($params)  Permite  realizar  una  búsqueda  de  registros  que  devuelve  todos  los  que  coincidan  con  las  condiciones indicadas. Los registros encontrados son bloqueados en modo no compartido por  lo  que  otras  sesiones  de  aplicación  que  traten  de  leer/escribir  estos  registros  resultaran  en  una espera.    Ejemplo: Bloquear un conjunto de registros en modo no compartido en una transacción  <?php class OrdersController extends ApplicationController { public function increaseQuantityAction(){ try { $transaction = new ActiveRecordTransaction(true); $this->Products->setTransaction($transaction); foreach($this->Products->findForUpdate(“quantity<100”) as $product){ $product->setQuantity($product->getMinStock()*2); if($product->save()==false){ $transaction->rollback(); } } } catch(TransactionFailed $e) { Flash::error($e->getMessage()); } } }

  public ActiveRecordResulset findWithSharedLock($params)  Permite  realizar  una  búsqueda  de  registros  que  devuelve  todos  los  que  coincidan  con  las  condiciones indicadas. Los registros encontrados son bloqueados en modo no compartido por  lo que otras sesiones de aplicación que traten de escribir en estos registros resultaran en una  espera por parte del gestor relacional.    public string convertParamsToSql(mixed $params)  Crea una consulta de SQL mediante los parámetros por nombre indicados. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                214 

  public array distinct(mixed $params)  Realiza una sentencia DISTINCT sobre una columna del modelo devolviendo un listado de los  valores diferentes encontrados.    public boolean exists(string $wherePk)    public ActiveRecordResultset findAllBy(string $field, mixed $value)    public static array singleSelect(string $sql)  Realiza una consulta SQL sobre el gestor relacional en la tabla ‘dual’ en el caso de Oracle ó solo  hace la instrucción SELECT sobre ninguna entidad en otros motores.  21.9.6 Contar registros  public integer count(mixed $params)  Devuelve un conteo de registros a partir de las condiciones indicadas.  Los parámetros pueden  ser establecidos usando parámetros por nombre ó un array cuyos indices indiquen el tipo de  parámtro  a  establecer.  El  parámetro  especial  group  modifica  el  resultado  obtenido  agrupandolo mediante otros atributos de la entidad.    Ejemplo: Realizar conteos sobre atributos del modelo    //Cuantos productos hay? $this->Products->count(); //Cuantos productos tienen categoria 1 $this->Products->count("categories_id = 1"); //Contar productos por categoria foreach($this->Products->count("group: categories_id") as $result){ print $result->categories_id." ".$result->rowcount; } // Contar productos por categoria, mostrar aquellas categorias que tienen mas de // 10 productos $resultset =$this->Products->count("group: categories_id", “having: rowcount>10”); foreach($resultset as $result){ print $result->categories_id." ".$result->rowcount; }

  public mixed countBySql(string $sqlQuery)  Realiza un conteo en el modelo mediante una sentencia SQL. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                215 

21.9.7 Promediar registros  public double average($params)  Devuelve  un  promedio  de  los  valores  de  una  columna  numérica  a  partir  de  las  condiciones  indicadas. El parámetro especial group modifica el resultado obtenido agrupándolo mediante  otros atributos de la entidad.    Ejemplo: Realizar promedios sobre atributos del modelo    //En promedio, cual es el precio de un producto $this->Products->average(“price”); //En promedio, cual es el precio de un producto activo $this->Products->average(“price”, “conditions: status=’Active’”); //Promedio de precios por categoria $averages = $this->Products->average(“price”, “group: categories_id”); foreach($averages as $result){ print $result->categories_id." ".$result->average.”\n”; }

21.9.8 Realizar sumatorias  public double sum($params)  Este método permite realizar sumatorias de los atributos de la entidad. El parámetro especial  group modifica el resultado obtenido agrupandolo mediante otros atributos de la entidad.    Ejemplo: Realizar sumatorias sobre atributos del modelo    //Cuanto suman los impuestos en las ordenes de compra? $this->Orders->sum(“taxes”); //Cuanto suman los impuestos del año 2007? $this->Orders->sum(“taxes”, “conditions: year = ‘2007’”); //Cuanto suman las cantidades en las ordenes de compra por cada cliente $summatories = $this->Orders->sum(“quantity”, “group: customers_id”); foreach($summatories as $result){ print $result->categories_id." ".$result->summatory.”\n”; }

  //Cuanto suman las cantidades en las ordenes de compra por cada cliente, cuya //cantidad sea superior a 100 unidades $summatories = $this->Orders->sum(“quantity”, “group: customers_id”, “having: summatory>100”); foreach($summatories as $result){ print $result->categories_id." ".$result->summatory.”\n”; }

  21.9.9 Obtener el valor máximo de un atributo  public mixed maximum($params) 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                216 

Devuelve un valor máximo de una columna numérica a partir de las condiciones indicadas. El  parámetro  especial  group  modifica  el  resultado  obtenido  agrupandolo  mediante  otros  atributos de la entidad.    Ejemplo: Obtener el valor máximo de un atributo de un modelo  //Quien es el empleado más antiguo? $this->Employees->maximum(“contract_date”, “conditions: status=’Active’”);

21.9.10

Obtener el valor mínimo de un atributo 

public mixed minimum($params)  Devuelve un valor mínimo de una columna numérica a partir de las condiciones indicadas. El  parámetro  especial  group  modifica  el  resultado  obtenido  agrupandolo  mediante  otros  atributos de la entidad.    Ejemplo: Obtener el valor mínimo de un atributo de un modelo  //Quien es el empleado más nuevo? $this->Employees->minimum(“contract_date”, “conditions: status=’Active’”);

  21.9.11

Asignar valores a instancias  

public ActiveRecord dumpResult(array $result)  Toma  un  vector  cuyos  indices  coinciden  con  los  nombres  de  los  atributos  del  modelo  y  los  asigna  devolviendo  un  objeto  copia  de  este  con  los  valores  asignados.  Si  algún  indice  no  corresponde a un atributo del modelo se genera una excepción.    public void dumpResultSelf(array $result)  Toma  un  vector  cuyos  indices  coinciden  con  los  nombres  de  los  atributos  del  modelo  y  los  asigna al mismo objeto. Si algún indice no corresponde a un atributo del modelo se genera una  excepción.  21.9.12

Validación 

public array getMessages()  Obtiene los mensajes de validación generados en un proceso de inserción ó actualización.    public void appendMessage(ActiveRecordMessage $message)  Agrega un mensaje al buffer de mensajes de validación del modelo. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

21.9.13

 

                                                                217 

Información de atributos 

public array getAttributes()  Obtiene un vector con los nombres de los atributos de la entidad.    public array getAttributesNames()  Obtiene  un  vector  con  los  nombres  de  los  atributos  de  la  entidad.  Es  un  alias  de  getAttributes().    public boolean hasField($string field)  Permite consultar si una entidad tiene un determinado campo $field.    public array getPrimaryKeyAttributes()  Obtiene un vector con los nombres de los atributos de la entidad que son llave primaria.    public array getNonPrimaryKeyAttributes()  Obtiene un vector con los nombres de los atributos de la entidad que no son llave primaria.    public array getNotNullAttributes()  Obtiene  un  vector  con  los  nombres  de  los  atributos  de  la  entidad  que  no  aceptan  valores  nulos.    public array getDatesAtAttributes()  Obtiene  un  vector  con  los  nombres  de  los  atributos  de  la  entidad  que  auto‐asignan  la  fecha  actual cuando se realiza una operación de inserción.    public array getDatesInAttributes()  Obtiene  un  vector  con  los  nombres  de  los  atributos  de  la  entidad  que  auto‐asignan  la  fecha  actual cuando se realiza una operación de modificación.    public boolean isANumericType(string $field)  Permite consultar si un atributo en la tabla tiene un tipo de dato númerico (int, integer, float,  number, bigint, Money, etc).   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

21.9.14

 

                                                                218 

Creación y actualización de registros 

public boolean create(array $values=array())  Este método permite la creación de un registro apartir de los valores asignados previamente a  los atributos del modelo  ó asignando  valores  a  estos  a  través  de  un  array  asociativo pasado  como parámetro. Debe usarse este método cuando el desarrollador quiera asegurarse que se  realice una actualización en vez de usar save().    public boolean update(array $values=array())  Este  método  permite  la  actualización  de  un  registro  apartir  de  los  valores  asignados  previamente  a  los  atributos  del  modelo  ó  asignando  valores  a  estos  a  través  de  un  array  asociativo pasado como parámetro. Debe usarse este método cuando el desarrollador quiera  asegurarse que se realice una actualización en vez de usar save().    public boolean save()  Este método permite crear/actualizar registros de acuerdo a si estos ya existen en la entidad  asociada  a  un  modelo.  El  método  save  es  llamado  también  internamente  por  los  métodos  create y update de ActiveRecord. Para que este método funcione como se espera es necesario  que se haya definido una llave primaria correctamente en la entidad para poder determinar si  un registro debe ser actualizado ó creado.    El método save() ejecuta los validadores asociados, llaves primarias virtuales y eventos que se  hayan definido en el modelo.  El generador de identificadores asociado también es ejecutado y  al terminar el proceso el objeto se refresca con los valores finales que quedaron en la base de  datos.    Ejemplo: Crear un registro usando el método save() de ActiveRecord  <?php $product = new Products(); $product->setName('Potattos'); $product->setType('Food'); if($product->save()==false){ foreach($product->getMessages() as $message){ Flash::error($message->getMessage()); } }

  El ejecutarse save(), este devuelve un valor booleano indicando el éxito de la operación. En el  ejemplo anterior se obtienen y muestran los mensajes de validación en pantalla cuando save() 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                219 

devuelve false.  21.9.15

Eliminación de registros 

public boolean delete($params)  Elimina el registro activo asociado al objeto ActiveRecord.   21.9.16

Operaciones en Batch 

public boolean updateAll(array $values, string $conditions=””)  Realiza  una  actualización  en  batch  de  todos  los  campos  de  una  entidad  asegurando  alto  rendimiento. El parámetro $values permite indicar, mediante un array asociativo, los valores  a  actualizar,  en  donde  los  indices  son  los  nombres  de  los  campos.  El  parámetro  $conditions  permite definir las condiciones que se deben cumplir para que el registro sea actualizado. Si  no se establece un valor para $conditions se actualizarán todos los registros de la entidad.    public boolean deleteAll($conditions=””)  Realiza una eliminación de registros en batch en una entidad asegurando alto rendimiento. El  parámetro  $conditions  permite  definir  las  condiciones  que  se  deben  cumplir  para  que  el  registro  sea  actualizado.  Si  no  se  establece  un  valor  para  $conditions  se  borrarán  todos  los  registros de la entidad.    21.9.17

Lectura/escritura de Atributos 

public mixed readAttribute(string $attribute)  Obtiene  el  valor  de  un  atributo  del  modelo  apartir  de  su  nombre.  Este  método  lee  el  valor  independiente de la visibilidad de la propiedad en la clase.    public mixed writeAttribute(string $attribute, mixed $value)  Asigna un valor a un atributo del modelo apartir de su nombre. Este método escribe el valor  independiente de la visibilidad de la propiedad en la clase.  21.9.18

Validación 

protected void validate(string $validatorClass, array $options)  Agrega  un  validador  a  un  modelo.  Consulte  el  capítulo  de  validadores  de  integridad  para  aprender más sobre este método.    public boolean validationHasFailed()  Este método puede ser usado dentro de un evento de validación para indicar si el proceso de 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                220 

completo  de  validación  ha  fallado.  Consulte  el  capítulo  de  validadores  de  integridad  para  aprender más sobre este método.  21.9.19

Multiplicidad de relaciones 

protected void hasOne(mixed $fields, string $referenceTable, mixed $referencedFields)  Crea una relación 1 a 1 con otra entidad presente en el administrador de entidades. El primer  parámetro especifica el atributo ó atributos en la entidad local y $referencedFields el atributo  ó atributos en la tabla referenciada. El parámetro $referenceTable indica la tabla referenciada.    Ejemplo: Establecer relaciones hasOne (1 a 1) de acuerdo al modelo entidad­relacion  //Relación de un campo a otro por convención $this->hasOne(“tabla_id”); //Relación de un campo a otro $this->hasOne(“campo“, “tabla_referenciada”, “campo_referenciado”); //Relación de varios campos a varios campos $this->hasOne( array(“campo1“, “campo2), “tabla_referenciada”, array(“campo_referenciado1”, “campo_referenciado2”) );

  protected void belongsTo(mixed $fields, string $referenceTable, mixed $referencedFields, string  $relationName=’’ )  Crea una relación 1 a 1 inversa con otra entidad presente en el administrador de entidades. El  primer parámetro especifica el atributo ó atributos en la entidad local y $referencedFields el  atributo  ó  atributos  en  la  tabla  referenciada.  El  parámetro  $referenceTable  indica  la  tabla  referenciada.    Ejemplo: Establecer relaciones belongsTo (muchos a 1) de acuerdo al modelo entidad­ relacion  //Relación de un campo a otro por convención $this->belongsTo(“tabla_id”); //Relación de un campo a otro $this->belongsTo(“campo“, “tabla_referenciada”, “campo_referenciado”); //Relación de varios campos a varios campos $this->belongsTo( array(“campo1“, “campo2), “tabla_referenciada”, array(“campo_referenciado1”, “campo_referenciado2”) );

  protected void hasMany(mixed $fields, string $referenceTable, mixed $referencedFields)  Crea una relación 1 a n  con otra entidad presente en el administrador de entidades. El primer  parámetro especifica el atributo ó atributos en la entidad local y $referencedFields el atributo 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                221 

ó atributos en la tabla referenciada. El parámetro $referenceTable indica la tabla referenciada.    Ejemplo:  Establecer  relaciones  hasMany  (1  a  muchos)  de  acuerdo  al  modelo  entidad­ relacion  //Relación de un campo a otro por convención $this->hasMany(“tabla_id”); //Relación de un campo a otro $this->hasMany(“campo“, “tabla_referenciada”, “campo_referenciado”); //Relación de varios campos a varios campos $this->hasMany( array(“campo1“, “campo2), “tabla_referenciada”, array(“campo_referenciado1”, “campo_referenciado2”) );

  protected void hasAndBelongsToMany(mixed $fields, string $referenceTable, string $gateTable,  mixed $referencedFields)  Crea una relación n a m inversa con otra entidad presente en el administrador de entidades. El  primer parámetro especifica el atributo ó atributos en la entidad local y $referencedFields el  atributo  ó  atributos  en  la  tabla  referenciada.  El  parámetro  $referenceTable  indica  la  tabla  referenciada y $gateTable la tabla puente para acceder a la tabla referenciada.  21.9.20

Herencia 

public void parentOf(string $parent)  Establece una relación de herencia que utiliza una estrategía de tabla por subclase mediante  un discriminador. El parámetro $parent indica la entidad padre.  21.9.21

Excepciones 

protected void exceptions($e)  Al  reescribir  este  método  es  posible  tratar  las  excepciones  generadas  dentro  de  un  modelo  antes que sean lanzadas a otras partes de la aplicación. 

21.10 Identifiers Las  clases  mapeadas  con  ActiveRecord  que  pretendan  efectuar  operaciones  de  manipulación  de  datos  deben  declarar  llaves  primarias.  Por  defecto  se  utilizan  estrategias  para  obtener  el  valor de estas al hacer una inserción.     Los tipos de identificadores soportados son:    Tabla: Tipos de generadores soportados 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                222 

  Tipo  Increment 

Descripción  Genera identificadores de tipo integer, que son únicos solo  cuando  otros  procesos  no  generar  operaciones  de  inserción  concurrentes.  Esta  opción  no  debería  ser  usada  en clusteres. 

Identity 

No  realiza  ninguna  operación  en  especial  ya  que  aprovecha  una  columna  identidad  presente  en  la  entidad.  Este  tipo  de  columnas  son  soportadas  por  MySQL,  IBM  DB2, Microsoft SQL Server, IBM Informix y SQLite. 

Sequence 

Obtiene el valor de un objeto del gestor relacional llamado  secuencias.  Las  secuencias  son  soportadas  por  Oracle,  PostgreSQL e IBM DB2. 

Hilo 

Utiliza un algoritmo tipo hi/lo para eficientemente generar  los valores únicos de tipo integer. 

UUID 

Genera  identificadores  unicos  de  128bits  tipo  string  basados en el algoritmo UUID (Universal Unique Identifier. 

Assigned  

No  aplica  ninguna  estrategía  y  utiliza  el  valor  asignado  directamente al objeto instancia del modelo. 

Uniqid 

Permite obtener identificadores únicos de 128bits usando  la función de PHP llamada uniqid. 

  21.10.1

Establecer el Generador 

Para establecer este tipo de identificadores se debe usar el método protegido de ActiveRecord  llamado  setIdGenerator.  El  primer  parámetro  indica  que  tipo  de  generador  se  usará    y  el  segundo permite establecer las opciones del generador.  21.10.2

Algoritmo Hi/Lo 

El generador Hi/Lo permite obtener el valor que deba se utilizado como llave primaria de un  campo  en  otra  entidad  en  forma  eficiente.    En  una  transacción  al  obtener  el  valor  del  identicador se efectúa (si se soporta) un bloqueo por fila en el registro para asegurarse que  ningún otro proceso obtenga el mismo valor.    Ejemplo: Establecer un generador eficiente Hi/Lo en un modelo 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                223 

<?php class Invoices extends ActiveRecord { public function initialize(){ $this->setIdGenerator("Hilo", “code”, array( "table" => "invoces_data", "column" => "consecutive", "max_lo" => 100 )); } }

La opción max_lo indica el valor mínimo que debe tomar el consecutivo.    Tabla: Parámetros del generador Hi/Lo  Tipo 

Descripción 

table  

Table donde se encuentra el consecutivo 

columna 

Columna que lleva el consecutivo 

source 

Es opcional. Permite establecer que la tabla se encuentra en otro schema. 

max_lo 

Es  opcional.  Permite  controlar  el  mínimo  valor  que  debe  almacenar  la  columna. 

number 

Es opcional. Indica cuantos consecutivos se deben generar para aumentar la  eficiencia. 

  Uno de los objetivos del algoritmo Hi/Lo es aumentar la eficiencia mediante la reducción de la  lectura/escritura  de  la  tabla  consecutivo.  Esto  solo  es  posible  cuando  la  operación  se  encuentra en medio de una transacción administrada por el TransactionManager.  21.10.3

Algoritmo UUID 

El algoritmo UUID genera identificadores únicos que pueden ser usados como llave primaria  mediante  el  algoritmo  del  mismo  nombre.    El  sistemas  UNIX  utiliza  /dev/urandom  para  generar el identificador.    Un UUID tiene la siguiente forma:     4cfce7c2-6089-102c-91cf-d8dbbe268425

  Se establece un generador UUID de esta forma:    Ejemplo: Establecer un generador de identificadores que use el algorimo UUID  <?php


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                224 

class Media extends ActiveRecord { public function initialize(){ $this->setIdGenerator("Uuid", “id”); } }

21.10.4

Generador UniqId 

El  generador  Uniqid  genera  identificadores  únicos  apartir  de  la  función  Uniqid  de  PHP.  El  valor generado es un string de 32 caracteres (un número hexadecimal de 128 bits) que es muy  difícil de repetir.    Ejemplo: Establecer un generador de identificadores que use el algoritmo uniqid  <?php class Media extends ActiveRecord { public function initialize(){ $this->setIdGenerator("Uniqid", “id”); } }

21.10.5

Generador Native 

El  generador  “Native”    debe  usarse  en  aquellos  casos  en  los  que  el  valor  de  la  columna  identidad  son  asignados  por  un  trigger  en  la  tabla  y  que  toma  el  valor  de  una  secuencia.  En  estos casos ActiveRecord no asignará ningún valor en la sentencia INSERT creada respetando  el  consecutivo  de  la  secuencia  aunque  si  consultará  su  valor  para  actualizar  el  estado  del  objeto.    El generador “Native” debe establecerse de la siguiente forma:    Ejemplo: Establecer un generador nativo en un modelo  <?php class Orders extends ActiveRecord { public function sequenceName(){ return “ORDERS_SEQ”; } public function initialize(){ $this->setIdGenerator("Native", “id”); } }

21.10.6

Columnas Identidad y Secuencias 

Para bases de datos que soporten columnas identidad el generador asigna el valor adecuado 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                225 

para que se genere valor autonumérico en la columna adecuada. En estos casos el generador  Identity se puede usar con motores como IBM DB2, MySQL y Microsoft SQL Server.     Para  los  motores  que  soportan  secuencias  como  Oracle,  PostgreSQL  e  IBM  DB2  se  debe  utilizar  el  generador  “Sequence”  ó  “Native”.  El  generador  “Sequence”  se  debe  establecer  cuando no existan triggers que asignen el valor de la columna en la tabla ya que esto hará que  se altere el consecutivo innecesariamente.    Ejemplo:  Establecer  un  generador  de  secuencias  para  un  modelo  con  un  gestor  relacional que lo soporte  <?php class Orders extends ActiveRecord { public function initialize(){ $this->setIdGenerator("Sequence", “id”, array( “name” => “ORDERS_ID” )); } }

El  nombre  de  la  secuencia  también  puede  ser  establecido  mediante  el  método  público  sequenceName tanto para los modelos con generadores como los que tienen identificador por  convención:    Ejemplo: Definir el nombre la secuencia del generador de valores identidad  <?php class Orders extends ActiveRecord { public function sequenceName(){ return “ORDERS_ID_SEQ”; } public function initialize(){ $this->setIdGenerator("Sequence", “id”); } }

21.11 Convenciones en Identificadores ActiveRecord puede automáticamente establecer el tipo de generador a Identity si en los meta‐ datos  de  la  entidad  encuentra  que  existe  una  columna  identidad.  Igualmente  si  el  campo  se  llama  explícitamente  ‘id’  igualmente  se  entenderá  la  convención  que  se  trata  de  un  campo  identidad generado por el gestor relacional ó mediante el generador Increment.    


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                226 

Requisitos para utilizar la convención en identificadores:    •

El campo debe llamarse “id” 

El campo debe tener un tipo de dato enterno (bigint, int, integer, number) 

El campo debe ser la llave primaria de la tabla 

El campo debe ser no nulo 

21.12 Los Meta-datos en ActiveRecordMetadata Gran  parte  de  la  ciencia  en  la  implementación  de  ActiveRecord  esta  relacionada  con  la  administración  de  los  metadatos  de  las  tablas  mapeadas.  El  almacenamiento  de  sus  características es punto fundamental para la utilización de los métodos que consultan, borran,  modifican,  almacenan,  etc.  El  subcomponente  ActiveRecordMetadata  implementa  el  patrón  Metadata Mapping el cual permite crear un data map por schema sobre la información de las  tablas y así reducir el consumo de memoria por objeto ActiveRecord y consolidar una base de  datos in‐memory de las características de cada entidad utilizada en la aplicación.    Normalmente  los  meta‐datos  son  escritos  manualmente  por  el  desarrollador  pero  Kumbia  Enterprise  los  toma  directamente  del  gestor  relacional,  con  esto  se  gana  eficiencia  en  el  desarrollo  generando  un  schema  auto‐actualizable  que  refleja  cualquier  cambio  en  la  estructura del modelo de datos.  21.12.1

Tipos de Meta­Datos Almacenados 

En  ActiveRecordMetaData  se  almacenan  varios  tipos  de  información  sobre  entidades  que  pretenden  acelerar  las  operaciones  de  manipulación  y  consulta  de  datos  en  ActiveRecord.  Estos tipos de datos son:    Tabla: Meta­datos almacenados para una entidad en el ActiveRecordMeta­Data  Tipo Meta­Dato 

Descripción 

Campos de la tabla 

Nombres de los campos de las tablas 

Llaves Primarias 

Campos que hacen parte de la llave primaria de las  tablas. 

Campos no llave primaria 

Conjunto de campos que no pertenece a la llave  primaria de las tablas. 

Campos No Nulos 

Campos que no permiten valores nulos 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                227 

Tipos de Datos 

Tipo de datos de cada campo en una tabla. 

Campos Fecha Auto‐

Campos que por convención asignan automáticamente 

Asignables 

la fecha del sistema al actualizar ó modificar. 

  21.12.2

Meta­Datos en etapas de Desarrollo 

Cuando  las  aplicaciones  se  encuentran  en  etapa  de  desarrollo  es  posible  que  el  los  desarrolladores encuentren que los cambios en la estructuras de la base de datos no se ven  reflejados en las aplicaciones.    Esto sucede porque los meta‐datos de las tablas son cacheados temporalmente en sesión para  evitar que la base de datos sea accedida continuamente disminuyendo el rendimiento.    Para  hacer  que  los  meta‐datos  sean  cargados  nuevamente  es  necesario  cerrar  y  abrir  el  navegador ó el cliente web y así se verán los cambios del modelo de datos reflejados.    21.12.3

API de ActiveRecordMetaData 

public void static existsMetaData(string $table, string $schema)  Permite saber si ya se ha definido los meta‐datos para una tabla y esquema en especial.    public void static createMetaData(string $table, string $schema)  Crea un registro para meta‐datos en el meta‐data store.    public void static setAttributes(string $tableName, string $schemaName, array $attributes)  Establece los nombres de los campos de una determinada tabla.    public array static getAttributes(string $tableName, string $schemaName)  Obtiene los nombres de los campos de una determinada tabla.    public  array  static  setPrimaryKeys(string  $tableName,  string  $schemaName,  array  $primaryKey)  Establece los campos que son llave primaria a una determinada tabla.    public array static getPrimaryKeys(string $tableName, string $schemaName=””) 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                228 

Obtiene los campos que son llava primaria en una determinada tabla    public  void  static  setNonPrimaryKeys(string  $tableName,  string  $schemaName,  array  $nonPrimaryKey)  Establece los campos que no son llave primaria a una determinada tabla.    public array static getNonPrimaryKeys($tableName, $schemaName)  Obtiene los campos que no son llava primaria en una determinada tabla    public void static setNotNull(string $tableName, string $schemaName, array $notNull)  Establece los campos que no pueden tener valores nulos.    public array static getNotNull($tableName, $schemaName)  Obtiene los valores que no son nulos en una tabla.    public void static setDataType(string $tableName, string $schemaName, array $dataType)  Establece los tipos de datos de una tabla.    public array static getDataTypes(string $tableName, string $schemaName)  Obtiene los tipos de datos de una determinada tabla.    public void static setDatesAt(string $tableName, string $schemaName, array $datesAt)  Establece los atributos de la tabla a los cuales se les asigna fecha automática al insertar.    public array static getDatesAt(string $tableName, string $schemaName)  Obtiene los atributos de la tabla a los cuales se les asigna fecha automática al insertar.    public void static setDatesIn(string $tableName, string $schemaName, array $datesIn)  Establece los atributos de la tabla a los cuales se les asigna fecha automática al actualizar.    public array static getDatesIn(string $tableName, string $schemaName)  Obtiene los atributos de la tabla a los cuales se les asigna fecha automática al actualizar.    public void static dumpMetaData(string $table, string $schema, array $metaData) 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                229 

Almacena los meta‐datos para una determinada tabla en el meta‐data store. 

21.13 Cursores y Resulsets de Consultas Los resultados devueltos por los métodos de consulta de ActiveRecord son objetos instancias  de la clase ActiveRecordResulset que encapsulan la manipulación y obtención de los registros  individuales en el cursor enviado por el RBDM.    La  clase  implementa  las  interfaces  Iterator,  ArrayAccess,  SeekableIterator  y  Countable  con  lo  cuál  el  objeto  se  puede  recorrer  usando  una  sentencia  como  foreach,  acceder  a  indices  individuales mediante el operador de acceso de vectores y contar el total de registros usando  funciones como count ó sizeof.    La implementación de este objeto logra una administración de memoria más eficiente ya que  solo  el  registro  activo  en  el  cursor  consume  memoria  en  el  script  actual  y  se  va  liberando  a  medida  que  se  recorren  los  registros.  Las  implementaciones  de  ORM  que  devuelven  los  registros  en  un  array  consumen  mayor  memoria  y  si  la  consulta  devuelve  una  cantidad  considerable  de  registros  es  probable  que  el  interprete  PHP  aborte  debido  al  consumo  excesivo de memoria por parte de la aplicación.  21.13.1

Utilizar el cursor como tipo Forward­Only 

Los  objetos  de  resultado  de  consulta  pueden  ser  recorridos  usando  sentencias  del  lenguaje  como foreach y while utilizandolos como cursores tipo forward­only. Al terminar de recorrer  los registros los cursores son auto‐resetados permitiendo volver a recorrerlos.    Ejemplo: Recorrer un cursor tipo forward­only  //Recorrerlo con Foreach foreach($this->Products->find() as $product){ print $product->getId()."\n"; } //Recorrerlo con While $resultSet = $this->Products->find(); while($resultSet->valid()){ $product = $resultSet->current(); print $product->getId()."\n"; }

21.13.2

Utilizar el cursor como Scrollable 

Los  resultsets  también  pueden  ser  recorridos  en  modo  scrollable  de  esta  forma  se  puede  acceder a un registro en particular usando un indice para establecer su posición.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                230 

$resultSet = $this->Products->find(); //Obtener el primer registro print $resultSet->getFirst()->id."\n"; //Obtener el segundo registro print $resultSet->offsetGet(1)->id."\n"; //Obtener el último print $resultSet->getLast()->id."\n";

21.13.3

API de ActiveRecordResulset 

public integer key()  Obtiene el número del registro que está actualmente activo en el cursor.    public boolean offsetExists(integer $index)  Permite consultar si existe un registro en una determinada posición.    public void rewind()  Devuelve el cursor interno del resulset al primer registro.    public boolean valid()  Indica la posición actual del cursor interno es valida, es decir que aun quedan más registros  para recorrer.    public void next()  Mueve el cursor interno al siguiente registro del Resultset.    public void current()  Devuelve el objeto ActiveRecord activo en el cursor.    public void seek(int $position)  Mueve  el  cursor  interno  del  resultset  a  la  posición  indicada  por  $position,  esta  debe  ser  un  número entero mayor a 0.    public integer count()  Implementa el método que exige la interface Countable el cual permite saber cuantos registros  ha devuelto el resultset.    public ActiveRecord getFirst() 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                231 

Obtiene el primer registro del cursor. Implicitamente rebobina el puntero al primer registro.    public ActiveRecord getLast()  Obtiene  el  último  registro  del  cursor.  Implicitamente  mueve  el  puntero  interno  al  último  registro.    public ActiveRecord offsetGet($index)  Obtiene el registro ubicado en la posición $index del cursor. Las posiciones empiezan en 0.    public boolean offsetExists($index)  Permite consultar si existe un registro una determinada posición del cursor.    public  string getSQLQuery()  Devuelve el SQL que produjo la consulta.    public ActiveRecord getEntity()  Devuelve la entidad que produjo la consulta. 

21.14 Mensajes de ActiveRecord ActiveRecord  tiene  un  subsistema  de  mensajes  que  permite  flexibilizar  la  forma  en  que  se  presentan  ó  almacena  la  salida  de  validación  que  se  genera  en  los  procesos  de  inserción  ó  actualización. Cada mensaje consta de una instancia de la clase ActiveRecordMessage. El grupo  de  mensajes  generado  puede  ser  recogido  usando  el  método  getMessages()  del  objeto  ActiveRecord donde se produjo la operación.    Cada mensaje ofrece información extendida como el nombre del campo que generó el mensaje  y el tipo de mensaje.    En  el  siguiente  ejemplo  se  ilustra  como  imprimir  los  mensajes  que  resultan  de  un  proceso  fallido de inserción:    Ejemplo: Obtener los mensajes de validación de un modelo  <?php $customer = new Customer(); $customer->setName("Steve Conrad"); $customer->setEmail("s.conrad@mail.com");


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                232 

if($customer->save()==false){ foreach($customer->getMessages() as $message){ Flash::error($message->getMessage()); } }

21.14.1

API de ActiveRecordMessage 

El API de la clase ActiveRecordMessage es la siguiente:    public void setType(string $type)  Establece el tipo de mensaje.    public string getType()  Obtiene el tipo de mensaje.    public void setMessage(string $message)  Establece el mensaje interno del objeto.    public string getMessage()  Obtiene el mensaje generado.    public void setField(string $field)  Establece el nombre del campo de cuyo valor se generó el mensaje.    public string getField()  Obtiene el nombre del campo que generó el mensaje. 

21.15 Transacciones en ActiveRecord Las aplicaciones empresariales generalmente administran datos cuyo valor es critico para las  organizaciones  y  su  manejo  debe  ser  seguro,  estable  y  confiable.  La  integridad  de  datos  se  pierde  cuando  las  operaciones  son  interrumpidas  y  no  se  completan  satisfactoriamente.  Las  transacciones  en  el  software  tratan  precisamente  de  evitar  estas  situaciones  buscando  que  haya integridad en los datos y que se puede recuperar la información si ocurre un estado de  fallo.    La implementación de Transacciones de Negocio para ActiveRecord esta basada en la idea del  patrón  del  grupo  Object­Relational  Behavioral  llamado  Unit  of  Work,  aunque  este  sin 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                233 

administrar el log de objetos utilizados. Su funcionamiento básicamente permite separar los  objetos ActiveRecord que pertenecen a una transacción de tal forma que todas las operaciones  efectuadas por ellos mantengan un estado de concurrencia consistente y se pueda controlar si  se altera la base de datos ó se hace rollback en caso que se requiera.     La implementación de transacciones en ActiveRecord tiene 2 ventajas principales:    •

Se encapsulan detalles sobre la implementación de transacciones del gestor relacional  utilizado. 

Soporta administración de transacciones declarativas. 

Esta  integrado  con  el  componente  TransactionManager  que  reduce  la  codificación  y  administra globalmente las transacciones.   

21.15.1

Administracion de Transacciones 

La  administración  de  transacciones  puede  ser  utilizada  a  nivel  global  ó  nivel  local,  independientemente de la forma en que se utilicen su objetivo es primordialmente controlar  la  concurrencia  a  los  recursos  de  persistencia  de  la  aplicación.  La  gestión  de  transacciones  depende explícitamente de los requisitos de la aplicación:    •

Globales: Las globales son administradas y gestionadas por la aplicación, el bloqueo  de  recursos  es  dependiente  de  la  naturaleza  de  los  mismos.  Como  el  estado  de  ejecución  de  una  aplicación  Web  duerme  entre  una  petición  y  otra  es  necesario  cancelar y/o aceptar las transacciones pendientes cada vez que terminan los hilos de  ejecución.  Las  transacciones  pueden  ser  compartidas  entre  la  ejecución  de  varias  acciones  en  un  mismo  hilo.  Kumbia  Enterprise  Framework  permite  establecer  transacciones  en  forma  automática  para  cualquier  petición  a  la  aplicación  y  cada  objeto  instanciado,  sin  embargo  esta  implementación  puede  resultar  demasiado  incondicional para las reglas de negocio de una aplicación. Su mayor ventaja es que las  operaciones  que  se  realizan  a  nivel  global  pueden  ser  replicadas  a  varios  recursos  transaccionales.   

Locales:  Permiten  al  desarrollador  establecer  modelos  de  programación  más  naturales  y  faciles  de  implementar  que  cumplen  detalladamente  con  la  lógica  de  negocio  de  la  aplicación.  La  principal  desventaja  es  que  tiene  a  invadir  el  modelo  de 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                234 

programación de la aplicación.    El  componente  TransactionManager  administra  la  creación,  cancelación,  destrucción  y  aceptación de transacciones cuando se implementan en múltiples acciones en un determinado  flujo  de  ejecución  ó  cuando  se  usan  transacciones  globales.  Este  componente  implementa  la  interfase  TransactionManagerInterface,  así  el  desarrollador  puede  implementar  un  componente propio de administración de transacciones implementando esta:    interface TransactionManagerInterface { public public public public public public public

function getUserTransaction($definition=null); function commit(); function rollback(); function initializeManager(); function rollbackPendent(); static function notifyRollback(); static function notifyCommit();

}

  El  método  TransactionManager::getUserTransaction()  devuelve  la  última  transacción  ó  crea  una si es necesario de acuerdo a la definición pasada como argumento. La definición es una  instancia  de  la  clase  TransactionDefinition.  La  definición  de  la  transacción  establece  parámetros como el nivel de isolación ó si la transacción es propagable:    Ejemplo: Establecer los parámetros de la transacción con un TransactionDefinition  <?php class AccountsController extends ApplicationController { public function createCustomerDataAction(){ try { $definition = new TransactionDefinition(); $definition-> setIsolationLevel(TransactionDefinition::ISOLATION_SERIALIZABLE); $definition->setPropagation(false); $definition->setReadOnly(false); $definition->setTimeout(0); $transaction = TransactionManager::getUserTransaction($definition); $customer = new Customer(); $customer->setTransaction($transaction); $customer->setName("John Smith"); $customer->setStatus("Active"); if($customer->save()){ $this->routeToAction("action: createAccountData"); } else { $transaction->rollback(); } } catch(TransactionFailed $e){ Flash::error($e->getMessage()); }


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                235 

} public function createCustomerDataAction($clientId){ $clientId = $this->filter($clientId, "int"); try { $transaction = TransactionManager::getUserTransaction($definition); $this->Account->setTransaction($transaction); $accounts = $this->Account>findWithSharedLock("client_id=’$clientId’"); foreach($accounts as $account){ if($account->getStatus()=='Inactive'){ $account->setBalance(0); $account->setStatus('Active'); if($account->save()==false){ foreach($account->getMessages() as $message){ Flash::error($message>getMessage()); } $transaction->rollback(); } } } if($transaction->commit()==true){ Flash::success("Se creó correctamente el cliente"); } } catch(TransactionFailed $e){ Flash::error($e->getMessage()); } } }

  El ejemplo muestra como se aplica la transacción creada mediante la definición y se reutiliza  entre las diferentes acciones que conforman la operación de negocio. Una descripción de los  parámetros que se pueden definir en TransactionDefinition es la siguiente:    •

Isolación:  Permite  establecer  el  grado  de  isolación  con  el  que  trabajaran  las  transacciones. Este se refiere al estándar SQL92  y depende de si esta soportado por el  gestor relacional. 

Propagation:  La  propagación  de  transacciones  permite  que  cuando  una  transacción  sea cancelada se cancelen��otras creadas en la misma petición a la aplicación.  

Read­Only:  Permite  establecer  una  transacción  de  solo  lectura,  cualquier  intento  de  modificación (inserción, actualización, borrado) de registros termina en la generación  de una excepción. 

Timeout: Permite establecer un tiempo en segundos después del cual la transacción  será  cancelada  automáticamente  si  no  se  ha  realizado  un  commit.  Esto  permite  controlar ciertos procesos de negocio donde el acceso a los recursos es por demanda. 

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                236 

El  método  estático  TransactionManager::getUserTransaction()  devuelve  una  instancia  de  la  clase  ActiveRecordTransaction  quien  administra  el  acceso  al  Data  Source  de  la  transacción.  Múltiples  entidades  comparten  un  mismo  DataSource  aunque  esto  sea  transparentemente  administrado.  21.15.2

Sincronización de Recursos con Transacciones 

El  desarrollador  debe  tener  cuidado  al  utilizar  transacciones,  ya  que  multiples  administradores  transaccionales  que  trabajen  sobre  un  mismo  gestor  relacional  podria  realizar bloqueos sobre recursos necesarios en una misma operación de negocio que termina  en un deadlock y una excepción.    El  uso  de  TransactionManager  permite  evitar  esto  en  cierta  medida  ya  que  este  controla  la  creación,  reutilización,  propagación,  cancelación  y  aceptación  de  los  procesos  relacionados  con transacciones así como otras operaciones.  21.15.2.1

Sincronización de Alto Nivel 

El  método  de  ActiveRecord::setTransaction()  proporciona  un  método  para  el  objeto  que  representa un registro comparta una transacción de forma transparente. La sincronización de  alto nivel permite que varios objetos ActiveRecord compartan un mismo DataSource bajo una  transacción y todas sus operaciones de bajo nivel son administradas por los componentes del  framework  lo  cual  aumenta  la  seguridad  y  confiabilidad  que  la  operación  no  se  salga  de  control y se ejecuten las tareas de finalización de transacciones requeridas.  21.15.2.2

Sincronización a Bajo Nivel 

La  conexión  al  gestor  relacional  puede  ser  obtenida  de  un  objeto  ActiveRecord  mediante  el  método  getConnection().  El  objeto  devuelto  es  una  instancia  de  la  clase  Db  que  es  quien  ejecuta  las  tareas  de  bajo  nivel  directamente  en  el  gestor  relacional.  Los  métodos  begin(),  rollback() y commit() estan presentes y permiten iniciar y terminar transacciones a bajo nivel.    Ejemplo: Utilizar transacciones a bajo nivel  $invoice = new Invoice(); $db = $invoice->getConnection(); $db->begin(); $invoice->find(124); $invoice->setStatus(“Cancelled”); $invoice->save(); $db->commit();

21.15.3

Consideraciones de Sincronización 

La importancia de la sincronización yace en la necesidad de una correcta implementación del 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                237 

proceso de negocio en donde la disponibilidad de los recursos sea consistente entre los que  son transaccionales y los que no.    Es  fundamental  entender  que  los  objetos  que  poseen  una  misma  transacción  administran  ciertos  recursos  y  se  debe  controlar  que  no  vayan  a  ser  utilizados  ó  requeridos  en  otra  transacción dentro del mismo proceso, si no se controlan estas situaciones es posible que se  presenten inconsistencias en los procesos de negocio.    En el siguiente proceso se puede comprender la situación presentada:    Ejemplo: Sincronización de recursos en controladores  <?php try { $transaction = new ActiveRecordTransaction(true); foreach($Accounts->find("status = 'P'") as $accountItem){ $accountItem->setTransaction($transaction); $accountItem->setStatus("A"); if($accountItem->save()==false){ foreach($accountItem->getMessages() as $message){ Flash::error($message->getMessage()); } $transaction->rollback(); } } foreach($Accounts->find("status = 'A' AND customer_id = '$customerId'") as $accountItem){ $accountItem->setTransaction($transaction); $accountItem->setBalance($accountItem->getBalance()$manageDiscount); if($accountItem->save()==false){ foreach($accountItem->getMessages() as $message){ Flash::error($message->getMessage()); } $transaction->rollback(); } } $transaction->commit(); } catch(TransactionFailed $e){ Flash::error($e->getMessage()); }

  En  el  primer  foreach  se  consultan  las  cuentas  cuyo  estado  sea  igual  a  ‘P’  y  se  les  cambia  el  estado  a  ‘A’,  en  el  segundo  foreach  se  consultan  las  cuentas  cuyo  estado  sea  igual  a  ‘A’  y  pertenezcan a un cliente determinado para luego aplicar un descuento sobre estas cuentas.    El  proceso  espera  que  las  cuentas  recién  actualizadas  en  el  primer  foreach  se  les  haga  igualmente  el  descuento  del  segundo,  sin  embargo  esto  no  será  así  ya  que  los  resultados 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                238 

devueltos  por  la  transacción  base  pertenecen  a  un  espejo  diferente  al  espejo  de  los  objetos  administrados por la transacción $transaction.    En resumen, los objetos que se espera que también se les aplique el descuento en el segundo  foreach quedaran sin este, ya que en el gestor relacional aún no se ha reflejado la actualización  de estados del primer foreach.    La solución a este inconveniente es seguir las siguientes consideraciones:    •

Los  procesos  de  negocio  que  accedan  a  un  mismo  recurso,  en  este  caso  la  entidad  Account deben asociar todas las instancias a una misma transacción 

Si  existe  integridad  referencial  en  el  modelo  de  datos  igualmente  es  necesario  que  todas  las  entidades  relacionadas  y  sus  procesos  estén  administradas  por  una  misma  transacción.   

Si  no  es  necesario  que  se  reflejen  los  cambios  en  el  modelo  de  datos  dentro  de  un  mismo  proceso de negocio entonces puede hacer caso omiso a estas consideraciones y utilizar tantos  administradores de transacciones como requiera.    El ejemplo presentado anteriormente sin el inconveniente mencionado se implementaría así:    Ejemplo: Sincronización de recursos en controladores  <?php try { $transaction = new ActiveRecordTransaction(true); $Accounts->setTransaction($transaction); foreach($Accounts->find("status = 'P'") as $accountItem){ $accountItem->setStatus("A"); if($accountItem->save()==false){ foreach($accountItem->getMessages() as $message){ Flash::error($message->getMessage()); } $transaction->rollback(); } } foreach($Accounts->find("status = 'A' AND customer_id = '$customerId'") as $accountItem){ $accountItem->setBalance($accountItem->getBalance()$manageDiscount); if($accountItem->save()==false){ foreach($accountItem->getMessages() as $message){ Flash::error($message->getMessage()); } $transaction->rollback(); } }


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                239 

$transaction->commit(); } catch(TransactionFailed $e){ Flash::error($e->getMessage()); }

  Cada instancia devuelta por find esta automáticamente asociada a la transacción $transaction  y se controla que todas las operaciones efectuadas sobre la entidad Accounts se refleje en todo  el proceso de negocio.  21.15.4

API de TransactionDefinition 

public void setIsolationLevel(int $isolationLevel)  Establece  el  nivel  de  Isolación  que  tendrá  la  conexión  asociada  a  la  transacción.  El  valor  del  parámetro  $isolationLevel  es  una  constante  de  TransactionDefinition  que  puede  ser  ISOLATION_DEFAULT, 

ISOLATION_READ_COMMITED, 

ISOLATION_READ_UNCOMMITED, 

ISOLATION_REPETEABLE_READ  y  ISOLATION_SERIALIZABLE.  La  disponibilidad  de  estas  depende exclusivamente de si esta soportada por el gestor relacional.    public void setPropagation(boolean $propagation)  Establece un valor booleano que indica si las transacciones creadas al cancelarse cualquiera se  propagará el estado a las demás del administrador de transacciones.    public void setTimeout(int $timeout)  Establece el tiempo máximo que pueda durar una transacción antes que sea cancelada.     public void setReadOnly(boolean $readOnly)  Establece el carácter de solo lectura de la conexión   21.15.5

API de ActiveRecordTransaction 

public __construct(boolean $autoBegin=false, TransactionDefinition $definition=null)  Constructor de la definición de la transacción.    public boolean commit()  Realiza la operación de ‘commit’ sobre la transacción administrada.    public boolean rollback()  Realiza  la  operación  de  ‘rollback’  sobre  la  transacción  administrada.  Si  la  transacción  es 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                240 

propagable cancelará otras transacciones creadas bajo el mismo TransactionManager.    public boolean begin()  Permite iniciar la transacción en la conexión activa al gestor relacional.    public DbBase getConnection()  Obtiene le objeto del adaptador al gestor relacional que administrada la transacción.    public void setIsNewTransaction(boolean $isNew)  Establece si la transacción ha creado una nueva conexión al gestor relacional ó esta reusando  una existente.    protected void setPropagation(boolean $propagation)  Establece  si  la  transacción  esta  en  modo  de  propagación.  La  propagación  solo  funciona  si  la  transacción fue creada con el TransactionManager.    public bool getPropagation()  Devuelve  el  estado  de  propagación  de  la  transacción.  La  propagación  solo  funciona  si  la  transacción fue creada con el TransactionManager.  21.15.6

Timeouts en Transacciones 

Kumbia Enterprise ofrece un entorno administrado para la implementación de transacciones  de tal forma que es posible conocer cuando ocurre alguna novedad con una transacción. Los  timeouts son un ejemplo de esto, cuando un procedimiento no puede obtener un bloqueo para  efectuar la operación una excepción de tipo DbLockAdquisitionException es generada.    Ejemplo: Capturar una excepción al no poder obtener un bloqueo en una transacción  <?php class OrdersController extends ApplicationController { public function increaseQuantityAction(){ try { $transaction = new ActiveRecordTransaction(true); $this->Products->setTransaction($transaction); foreach($this->Products->findForUpdate(“quantity<100”) as $product){ $product->setQuantity($product->getMinStock()*2); if($product->save()==false){ $transaction->rollback(); } } } catch(DbLockAdquisitionException $e){


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

}

}

 

                                                                241 

Flash::error(“No se pudo obtener el bloqueo requerido”); } catch(TransactionFailed $e){ Flash::error($e->getMessage()); }

21.16 Validadores de Integridad de Datos ActiveRecord  permite  que  los  modelos  ejecuten  tareas  de  validación  definidas  por  el  desarrollador que garanticen que los datos que se almacenen en la persistencia sean íntegros  y se evite todo lo que esto conlleva.    Los 

eventos 

del 

modelo: 

beforeValidation, 

beforeValidationOnCreate, 

beforeValidationOnUpdate y validation permiten definir reglas de validación en forma general  ó de acuerdo a la operación que se vaya a realizar sobre el modelo:    Ejemplo: Definir validadores de integridad de datos en un modelo  <?php class Customers extends ActiveRecord { protected protected protected protected

$id; $name; $e_mail; $status;

protected function setId($id){ $this->id = $id; } protected function setName($name){ $this->name = $name; } protected function setEMail($e_mail){ $this->e_mail = $e_mail; } protected function setStatus($status){ $this->status = $status; } protected function validation(){ $this->validate("Length", array("field" => "name", "minimum" => 10, "maximum" => 50)); $this->validate("Email", "e_mail"); $this->validate("InclusionIn", array("field" => "status", “domain” => array(“A”, “I”), “required” => false);

}

}

if($this->validationHasFailed()==true){ return false; }

  El método protegido de los modelos ActiveRecord::validate() recibe en su primer parámetro el  validador  con  el  que  se  efectuará  la  validación  y  como  segundo  parámetro  una  lista  de 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                242 

opciones  para  el  mismo.  Algunos  validadores  pueden  recibir  simplemente  el  nombre  del  campo a validar como segundo parámetro.  El desarrollador puede determinar si la validación  debe  cancelar  la  acción  que  se  está  ejecutando  sobre  el  modelo  mediante  el  método  ActiveRecord::validationHasFailed()  el  cuál  indica  si  se  han  generado  mensajes  de  validación  en  las  clases  validadoras.  El  devolver  false  desde  cualquiera  de  los  eventos  de  validación  conlleva a la cancelación de la acción actual y a que el método save, create ó update también  devuelvan false.      El Listado de validadores por defecto que contiene la versión estándar de Kumbia Enterprise  Framework son los siguientes:    Tabla: Validadores por defecto que hacen parte de ActiveRecord  Validador 

Descripción 

PresenceOf 

Es  un  validador  implicito  para  los  modelos  cuyas  entidades  tengan  atributos  NOT  NULL  y  sean  requeridos  al insertar ó actualizar. 

DateIn 

Valida que el valor de un atributo de la entidad tenga un  formato de fecha valido. 

Length 

Valida que el numero de caracteres  de un el valor de un  atributo de la entidad tipo String tenga un limite inferior,  superior ó ambos. 

InclusionIn  

Valida  que  el  valor  de  un  atributo  de  la  entidad  se  encuentre en un listado estático definido en un vector. El  vector se define usando la opción ‘domain’. 

ExclusionIn 

Valida  que  el  valor  de  un  atributo  de  la  entidad  no  se  encuentre en un listado estático definido en un vector. El  vector se define usando la opción ‘domain’ 

Numericality 

Valida  que  el  valor  de  un  atributo  de  la  entidad  sea  numérico. 

Format 

Valida que el valor de un atributo de la entidad tenga un  formato  establecido  en  una  expresión  regular,  esta  se  define usando la opción ‘format’. 

Email 

Valida que el valor de un atributo de la entidad tenga un  formato de e‐mail correcto. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

Uniqueness 

 

                                                                243 

Permite  validar  que  el  valor  de  un  atributo  no  exista  en  otro registro de la entidad. La opción “field” puede recibir  un  Array  cuando  se  debe  validar  combinaciones  de  campos.  

  21.16.1

Validadores para atributos No­Nulos 

Cuando se define un validador, este valida cualquier valor que se vaya a insertar ó actualizar  sobre la persistencia. Algunas veces el atributo puede permitir nulos, el valor nulo igual será  validado  por  el  Validador  y  si  no  cumple  con  las  condiciones  establecidas  generará  un  mensaje y dependiendo de las condiciones podría detener la ejecución de la operación actual.     Una  forma  de  establecer  una  regla  de  excepción  para  estos  casos  es  agregar  la  opción  ‘required’ con valor false al método validate:     Ejemplo: Establecer reglas de validación de integridad de datos en modelos  protected function validation(){ $this->validate("Numericality", array(“field" => “precio_venta", “required” => false)); if($this->validationHasFailed()==true){ return false; } }

  Ejemplo: Validar que una combinación de campos no se repita   protected function validation(){ $this->validate("Uniqueness", array( “field" => array(“invoice_number", “invoice_preffix”) ); if($this->validationHasFailed()==true){ return false; } }

21.16.2

Tratar el resultado de un proceso de Validación 

Cuando  se  ejecuta  el  método  inteligente  save()  se  ejecutan  los  procesos  de  validación  y  los  validators  asociados  al  modelo,  normalmente,  el  método  save  devuelve  un  valor  booleano  indicando  el  éxito  de  la  operación,  cuando  el  valor  devuelto  es  false  es  posible  obtener  los  mensajes que se han generado y tratarlos adecuadamente para ser presentados al usuario.    Ejemplo:  Obtener  los  mensajes  de  validación  cuando  falla  una  operación  de  manipulación de datos 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                244 

  <?php $customer = new Customer(); $customer->setName("Carl Johnson"); $customer->setEmail("c.johnson@mail.com"); $customer->setContractDate(“2009-02-01”); if($customer->save()==false){ foreach($customer->getMessages() as $message){ Flash::error($message->getMessage()); } }

  Aplicando la API de ActiveRecordMessage es posible personalizar los mensajes de validación y  la forma en que se tratan. En el siguiente ejemplo se muestra como presentar los mensajes de  validación de correo electrónico como advertencias y el resto como errores:    Ejemplo: Personalizar la presentación de los mensajes de validación mediante el API de  ActiveRecordMessage  <?php $customer = new Customer(); $customer->setName("Carl Johnson"); $customer->setEmail("c.johnson@mail.com"); $customer->setContractDate(“2009-02-01”); if($customer->save()==false){ foreach($customer->getMessages() as $message){ if($message->getType()==’Email’){ Flash::warning($message->getMessage()); } else { Flash::error($message->getMessage()); } } }

El campo que genera el mensaje también permite personalizar los mensajes generados:    Ejemplo:  Obtener  información  de  los  mensajes  de  validación  en  un  proceso  de  manipulación de datos  <?php $customer = new Customer(); $customer->setName("Carl Johnson"); $customer->setEmail("c.johnson@mail.com"); $customer->setContractDate($contractDate); if($customer->save()==false){ foreach($customer->getMessages() as $message){ if($message->getField()==’contractDate’){ Flash::warning(“La fecha de contrato no ha sido establecida”); } else { Flash::error($message->getMessage()); } } }

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

21.16.3

 

                                                                245 

Validadores de Usuario 

El desarrollador puede definir validadores de aplicación que extiendan ó se adecuen mejor a  las  reglas  de  negocio  de  la  aplicación.  Todos  los  validadores  deben  cumplir  con  unos  requisitos para su integración con ActiveRecord y su correcta ejecución:    •

El  Validador  debe  estar  ubicado  en  el  directorio  validators  en  el  directorio  de  la  aplicación. Si este directorio no existe se debe crear. 

Los  archivos  donde  se  implementan  las  clases  validadoras  deben  tener  la  siguiente  convención: NombreValidator.php 

Los validadores pueden heredar la clase ActiveRecordValidator la cual implementa una  estructura  consistente  para  el  desarrollo  de  un  validador  eliminando  detalles  poco  usables. 

Las clases validadoras deben llamarse usando la convención: NombreValidator 

Las clases validadoras deben implementar la interface ActiveRecordValidatorInterface. 

  La interface ActiveRecordValidatorInterface tiene la siguiente estructura:    interface ActiveRecordValidatorInterface { public public public public

function function function function

__construct($record, $field, $value, $options = array()); checkOptions(); getMessages(); validate();

}

  Tanto  el  constructor  como  el  método  getMessages()  se  encuentran  ya  definidos  en  la  clase  ActiveRecordValidator.  Un  validador  solo  implementa  validate  y  opcionalmente  sobrescribe  checkOptions. El primero realiza la validación en si y devuelve un valor booleano indicando si  el proceso fue satisfactorio ó no. El método checkOptions permite chequear si los parámetros  enviados en las opciones del validador son correctos.    En  el  siguiente  ejemplo  se  implementa  un  validador  que  proporciona  a  la  aplicación  un  servicio  de  validación  de  números  de  identificación  de  acuerdo  a  las  convenciones  de  algún  país.  Los  números  de  identificación  deben  ser  de  20  dígitos,  los  3  primeros  deben  ser  las  letras ABC si es una empresa ó XYZ si es una persona natural.    El archivo validators/IdentificationValidator.php queda así: 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                246 

  Ejemplo: Crear un validador para integridad de datos en modelos  <?php class IdentificationValidator extends ActiveRecordValidator implements ActiveRecordValidatorInterface { public function checkOptions(){ if($this->isSetOption('type')==false){ throw new ActiveRecordException("Debe indicar el tipo de numero de identificaci&oacute;n para IdentificationValidator"); } if(!in_array($this->getOption('type'), array('any', 'company', 'people'))){ throw new ActiveRecordException("El tipo de numero de identificaci&oacute;n no es valido, para IdentificationValidator"); } } public function validate(){ $number = $this->getValue(); $type = $this->getOption('type'); $valid = true; if($type=='any'||$type=='company'){ if(substr($number, 0, 3)=='ABZ'){ $valid = false; } } if($type=='any'||$type=='people'){ if(substr($number, 0, 3)!='XYZ'){ $valid = false; } } if(strlen($number)!=20){ $valid = false; } if(!$valid){ $this->appendMessage("El valor del campo '{$this>getFieldName()}' debe ser una identificaci&oacute;n valida"); return false; } else { return true; } } }

  Para aplicar el validador se invoca el método validate en la implementación de algún evento  del modelo de tipo ‘validation’:    Ejemplo: Implementar un evento de validación de acuerdo a la operación ejecutada  protected function beforeValidationOnCreate(){ $this->validate("Identification", array(“field" => “number_iden", “type” => “any”)); if($this->validationHasFailed()==true){ return false; } }

21.16.4

Eventos en la Validación 

Los  modelos  permiten  la  implementación  de  eventos  que  se  lanza  cuando  se  efectúa  una  operación de inserción ó actualización y que tienen como objetivo definir lógica de validación 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                247 

e integridad de datos en la aplicación.    A continuación se nombran y explican los eventos soportados así como su orden de ejecución:     Tabla: Tipos de eventos de validación y su orden de ejecución  Puede  cancelar  Operación  Inserción 

Nombre  y  beforeValidation 

operación: 

Explicación 

SI 

Se  ejecuta  antes  de 

Actualización 

que  se  validen  los  campos  no  nulos  y  se  ejecuten 

los 

validadores 

de 

integridad de datos.  Inserción 

beforeValidationOnCreate 

SI 

Se  ejecuta  antes  de  que  se  validen  los  campos  no  nulos  y  se  ejecuten 

los 

validadores 

de 

integridad  de  datos,  solo  cuando  se  realiza  una inserción sobre  el  modelo.  Actualización 

beforeValidationOnUpdate 

SI 

Se  ejecuta  antes  de  que  se  validen  los  campos  no  nulos  y  se  ejecuten 

los 

validadores 

de 

integridad  de  datos,  solo  cuando  se  realiza  una  actulización  del   modelo  Actualización  Inserción 

ó  onValidationFails 

SI (ya se ha 

Se  ejecuta  después 

detenido) 

que  un  validador  de 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                248 

integridad falla.    Inserción 

afterValidationOnCreate 

SI 

Se  ejecuta  después  de  que  se  validen  los  campos  no  nulos  y  se  ejecuten 

los 

validadores 

de 

integridad  de  datos,  solo  cuando  se  realiza  una inserción sobre  el  modelo.  Actualización 

afterValidationOnUpdate 

SI 

Se  ejecuta  después  de  que  se  validen  los  campos  no  nulos  y  se  ejecuten 

los 

validadores 

de 

integridad  de  datos,  solo  cuando  se  realiza  una  actulización  del   modelo  Inserción 

y  afterValidation 

SI 

Actualización 

Se  ejecuta  después  de  que  se  validen  los  campos  no  nulos  y  se  ejecuten 

los 

validadores 

de 

integridad de datos.  Inserción 

y  beforeSave 

SI 

Actualización 

Se  ejecuta  antes  de  realizar  la  operación  requerida  sobre  el  gestor relacional. 

Actualización 

beforeUpdate 

SI 

Se  ejecuta  antes  de  realizar 

la 

actualización  en  el  gestor relacional.  Inserción 

beforeCreate 

SI 

Se  ejecuta  antes  de 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                249 

realizar  la  inserción  en el gestor relacional.  Actualización 

afterUpdate 

NO 

Se  ejecuta  después  de  realizar 

la 

actualización  en  el  gestor relacional.  Inserción 

afterCreate 

NO 

Se  ejecuta  después  de  realizar  la  inserción  en el gestor relacional. 

Inserción 

y  afterSave 

NO 

Actualización 

Se  ejecuta  después  de  realizar  la  operación  requerida  sobre  el  gestor relacional. 

Eliminación 

beforeDelete 

SI 

Se  ejecuta  antes  de  eliminar  el  registro  del gestor relacional. 

Eliminación 

afterDelete 

NO 

Se  ejecuta  después  de  eliminar  el  registro  del gestor relacional. 

  21.16.5

Implementar un evento de validación 

Cuando  se  ejecuta  una  operación  de  inserción,  actualización  ó  eliminación  sobre  el  modelo  ActiveRecord verifica si se han definido métodos con los nombres de los eventos y en caso de  encontrarlos los ejecuta en el orden mencionado en la tabla anterior.    Los eventos de validación deben ser métodos protegidos recomendablemente para evitar que  la lógica de datos que contienen se exponga públicamente.    En  el  siguiente  ejemplo  se  implementa  un  evento  que  valida  que  la  cantidad  a  actualizar  ó  insertar sobre el modelo sea mayor a 0 según los requerimientos del negocio:    Ejemplo: Implementar un evento de validación para modelos  <?php class Products extends ActiveRecord {


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                250 

protected function beforeSave(){ if($this->quantity<0){ Flash::error("La cantidad no puede ser negativa"); return false; } } }

21.16.6

Detener/Cancelar una operación 

Si dadas las condiciones al ejecutar un evento de validación se requiere detener ó cancelar la  operación que se esta ejecutando se puede realizar si el evento lo permite y así evitar que se  almacenen datos incorrectos favoreciendo la integridad del dominio de datos.    En la tabla de eventos de validación es posible verificar si el evento permite la cancelación de  la  operación.  Un  método  que  requiera  detener  la  operación  debe  devolver  el  valor  boleano  false, en este caso los métodos save, create y update también devolveran false indicando que  no se pudo efectuar la operación.  21.16.7

Establecer un evento con un nombre no estándar 

Los  eventos  de  validación  también  pueden  ser  definidos  usando  atributos  protegidos  en  la  clase  del  modelo.  De  esta  forma  se  pueden  definir  uno  ó  más  eventos  en  forma  dinámica  flexibilizando la implementación de estos:    Ejemplo: Cambiar el nombre estándar de un evento en un modelo  <?php class Products extends ActiveRecord { protected $beforeSave = “myCustomEvent” protected function myCustomEvent(){ if($this->quantity<0){ Flash::error("La cantidad no puede ser negativa"); return false; } } }

  Si se requiere ejecutar varios métodos para un mismo evento se puede indicar un vector con  la  lista  de  métodos  en  el  orden  de  ejecución  requerido.  Si  alguno  falla  los  demás  no  serán  ejecutados.    Ejemplo: Definir múltiples callbacks para un mismo evento de un modelo   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                 ��                                              251 

<?php class Products extends ActiveRecord { protected $beforeSave = array(“myFirstEvent”, “mySecondEvent”); protected function myFirstEvent(){ if($this->quantity<0){ Flash::error("La cantidad no puede ser negativa"); return false; } } protected function mySecondEvent(){ if($this->quantity>100){ Flash::error("La cantidad no puede ser mayor a 100"); return false; } } }

  Los eventos pueden ser establecidos dinámicamente desde otros eventos ó en el inicializador  del  modelo.  De  esta  forma  se  pueden  crear  potentes  modelos  de  validación  de  la  lógica  de  datos en una aplicación:    Ejemplo: Definir eventos del modelo dinámicamente mediante atributos  <?php class Products extends ActiveRecord { protected $beforeSave; protected function beforeValidation(){ if($this->category==”Food”){ $this->beforeSave = “checkFoodQuantity”; } else { $this->beforeSave = “checkOtherQuantity”; } }

100");

protected function checkFoodQuantity(){ if($this->quantity>100){ Flash::error("La cantidad de alimentos no puede ser mayor a

}

}

return false;

protected function checkOtherQuantity(){ if($this->quantity>50){ Flash::error("La cantidad no puede ser mayor a 50"); return false; } } }

21.16.8

Evento cuando el proceso de validación detiene la operación 

Las operaciones ejecutadas en el método save pueden fallar si al menos un validador falla en  este caso develve el valor booleano false indicando este estado. Es posible definir un evento  llamado  ‘onValidationFails’  que  es  ejecutado  cuando  el  proceso  de  validación  devuelve  un 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                252 

resultado  no  satisfactorio.  En  este  evento  se  puede  definir  elementos  de  logging  ó  informativos  de  usuario  para  indicar  el  porqué  no  se  ha  podido  realizar  la  operación  requerida.    Ejemplo:  Definir  un  evento  a  la  espera  de  un  fallo  en  el  proceso  de  validación  de  un  modelo  <?php class Products extends ActiveRecord { protected function onValidationFails(){ if($this->operationWasCreate()==true){ Flash::error(“La inserción falló”); } if($this->operationWasUpdate()==true){ Flash::error(“La actualización falló”); } foreach($this->getMessages() as $message()){ Flash::error($message->getMessage()); } } }

21.16.9

Deshabilitar eventos de validación 

Los  eventos  de  validación  pueden  ser  deshabilitados  para  aumentar  el  rendimiento  en  aplicaciones  que  no  requieren  de  ellos  ó  cuando  se  ejecutan  procesos  de  manipulación  de  datos que no requieran de esta característica.    El  método  ActiveRecord::disableEvents(bool  $disable)  permite  cambiar  este  comportamiento.  Un  valor  booleano  true  los  deshabilita  y  un  valor  false  los  habilita  nuevamente.  Esta  funcionalidad actúa en forma general para cualquier modelo de la aplicación. 

21.17 Llaves Foráneas Virtuales ActiveRecord permite definir llaves primarias virtuales que validen la integridad relacional en  las operaciones de manipulación de datos asegurando que los campos llave contengan valores  que existan en las entidades referenciadas.    Ventajas sobre el control convencional a nivel de base datos:    •

Es posible validar integridad relacional sobre columnas con tipos de datos diferentes 

Se disminuye la carga del motor de base de datos 

Es  posible  controlar  la  integridad  sobre  tablas  en  diferentes  motores  ó  diferentes 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                253 

servidores  •

Se puede generar mensajes de usuario personalizados de acuerdo al intento fallido de  efectuar una operación por violación de llave foránea. 

Se puede validar la integridad  en  motores  que  no  soporten  llaves  foraneas  (MyISAM  en MySQL). 

Se  pueden  definir  llaves  foráneas  que  validen  la  integridad  en  objetos  de  la  base  de  datos como vistas y sinonimos. 

No se requieren indices en las tablas referenciadas (aunque es recomendado que los  tengan). 

  Desventajas de las llaves foráneas virtuales:    •

El  rendimiento  no  es  tan  óptimo  como  el  de  las  administradas  directamente  por  el  motor de base de datos. 

La  integridad  solo  es  validada  cuando  las  operaciones  se  realizan  mediante  eventos  realizados a través de los modelos. 

21.17.1

Crear una llave foránea virtual 

El  método  protegido  de  ActiveRecord  llamado  addForeignKey  permite  la  definición  de  llaves  foráneas virtuales en el inicializador de la clase modelo.    Mediante convenciones se coloca solamente el nombre del campo y de esta forma la tabla y  campo referenciado se intuye normalmente:    Ejemplo: Definir una llave foránea virtual por convención  <?php class Products extends ActiveRecord { protected function initialize(){ $this->addForeignKey(“categories_id”); } }

  Sino se utiliza un modelo entidad‐relación que use convenciones la forma de indicar las llaves  foráneas se realiza de esta manera:    Ejemplo: Establecer llaves foráneas de acuerdo al modelo entidad relación   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                254 

<?php class Employees extends ActiveRecord { protected function initialize(){ //Un campo a un campo $this->addForeignKey(“code_cat”, “categories”, “code”); //Varios campos a varios campos $this->addForeignKey( array(“country_born“, “city_born”), “cities”, array(“country_code”, “city_code”) ); } }

21.17.2

Opciones de las llaves foráneas 

El  cuarto  parámetro  de  addForeignKey  permite  establecer  opciones  adicionales  como  el  mensaje a generar cuando se viole la integridad y las acciones a realizar cuando se actualiza ó  borra un registro y falla el proceso de validación.    Ejemplo: Establecer acciones de una llave foránea virtual en un modelo  <?php class Employees extends ActiveRecord { protected function initialize(){ $this->addForeignKey(“office_id”, “office”, “id”, array( “message” => “La oficina %s no existe”, “on_delete” => ActiveRecord::ACTION_CASCADE, “on_update” => ActiveRecord::ACTION_RESTRICT )); } }

  Tabla: Opciones de addForeignKey  Opción  message 

Descripción  Mensaje  del  validador  cuando  se  viola  la  llave  foránea  y  la  acción efectuada debe restringir la operación. 

on_delete 

Establece una acción a ejecutar cuando una llave foránea es  violada  al  hacer  una  eliminación  de  datos  en  la  entidad.  El  valor 

es 

alguna 

de 

ActiveRecord::ACTION_CASCADE 

las 

constantes  ó 

ActiveRecord::ACTION_RESTRICT.  on_update 

Establece una acción a ejecutar cuando una llave foránea es  violada al hacer una actualización de datos en la entidad. El 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

valor 

es 

 

alguna 

                                                                255 

de 

las 

constantes 

ActiveRecord::ACTION_CASCADE 

ó 

ActiveRecord::ACTION_RESTRICT.    Tabla: Acciones dependiendo de la operación  Opción 

Descripción 

ActiveRecord::ACTION_CASCADE 

Cuando  se  realiza  una  eliminación  de  datos  indica  que  todas  los  datos  en  llaves  dependientes  deben  ser  eliminados  antes  de  efectuar  la  operación.  Esto  permite  que no queden registros huérfanos. En una actualización  se actualiza el nuevo valor en las relaciones dependientes. 

ActiveRecord::ACTION_RESTRICT  Indica que se debe cancelar la operación actual debido a  la 

violación 

de 

la 

llave 

foránea. 

El 

objeto 

ActiveRecordMessage  es  cargado  con  el  mensaje  establecido en la opción ‘message’.   

21.18 Entidades Temporales Administrar datos en una entidad  proporciona recursos importantes para las aplicaciones de  negocios. En ciertas ocasiones se requiere utilizar entidades para almacenar datos temporales  que permitan la ejecución de procesos de negocio sin que  estas afecten el dominio de datos  en forma notable.    El  componente  ActiveRecord  proporciona  el  subcomponente  TemporaryActiveRecord  el  cual  permite  crear  modelos  que  administran  sus  datos  sobre  entidades  temporales  en  el  gestor  relacional.     Este tipo de entidades pueden ser consideradas de alto rendimiento ya que no requieren de  escritura de disco además este tipo de modelos están optimizados para un procesamiento más  efectivo en memoria.    En  estos  casos  la  persistencia  es  temporal  ya  que  todos  los  datos  que  administra  el  modelo  existen  en  memoria  mientras  la  conexión  al  gestor  relacional  esta  activa.  Como  estas  conexiones se realizan en modo no‐persistente  los datos en las entidades creadas solo existen 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                256 

durante  el  tiempo  que  emplee  la  petición  en  ejecutarse  por  completo  creándose  y  destruyéndose cada vez que se utilicen.  21.18.1

Crear un TemporaryActiveRecord 

Lo siguiente se debe hacer para crear un modelo temporal:    •

Se  crea  un  modelo  que  extienda  al  subcomponente  TemporaryActiveRecord  en  el  directorio de modelos. 

Se  debe  implementar  un  método  protegido  que  se  debe  llamar  _tableDefinition  es  requerido para obtener la definición de la entidad, esta constituye un array asociativo  con las llaves attributes e indexes. 

La  llave  attributes  es  obligatoria  y  contiene  un  vector  asociativo  cuyas  llaves  corresponden a los nombres de los campos y cuyo valor es una descripción del campo  tal y como es aceptada por el método de los adaptadores del componente Db llamado  createTable. 

Cuando se definan los atributos del modelo como protegidos se deben definir con los  mismos nombres utilizados en la definición del método _tableDefinition. 

Si  no  se  definen  los  atributos  protegidos  ActiveRecord  los  definirá  como  públicos  aunque esto no es recomendable. 

Las  entidades  temporales  también  soportan  relaciones  unidireccionales  y  bidireccionales definiéndose como es usual en los modelos persistentes. 

21.18.2

Comportamiento de un TemporaryActiveRecord 

El  siguiente  comportamiento  debe  tenerse  en  cuenta  cuando  se  trabaja  con  entidades  temporales:    •

Al  instanciarse  por  primera  vez  la  clase  del  modelo  temporal  cuando  el  Facility  es  USER_LEVEL  se  crea  una  tabla  temporal  en  la  conexión  por  defecto  al  gestor  relacional. 

La  tabla  temporal  creada  tiene  el  nombre  de  la  clase  utilizada  las  limitaciones  del  gestor relacional en cuanto a los nombres de tablas y que otras entidades no existan  con este nombre deben ser tenidas en cuenta. 

Las  sentencias  de  creación  de  la  tabla  temporal  no  corresponden  a  manipulación  de  datos  por  lo  tanto  las  transacciones  globales  y  locales  no  tienen  en  cuenta  esta  operación. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                257 

Como la tabla es creada en cada petición en donde se haga uso del modelo los meta‐ datos  de  la  tabla  no  son  almacenados  así  que  no  es  posible  obtener  información  de  esta usando ActiveRecordMetaData. 

La  tabla  es  destruida  en  cuanto  se  cierra  la  conexión  con  el  gestor  relacional,  si  es  requerido destruirla desde la aplicación se puede usar el método del administrador de  entidades  EntityManager::destroyTemporaryEntity(string  $name)  donde  $name  es  el  nombre del modelo, este método destruye la tabla temporal en cada conexión al gestor  relacional donde fue creada. Si una nueva instancia del la clase modelo es invocada ó  utilizada la tabla temporal se creará nuevamente. 

21.18.3

Transacciones con Entidades Temporales 

Las  operaciones  de  manipulación  de  datos  sobre  las  entidades  temporales  soportan  transacciones  en  forma  transparente,  aunque  se  debe  tener  en  cuenta  que  no  todos  los  gestores relacionales soportan transacciones en tablas temporales.    Al  crear  una  transacción  ya  sea  directamente  con  ActiveRecordTransaction  ó  usando  TransactionManager  se  crea  una  nueva  conexión  temporal  al  gestor  relacional  y  es  posible  que la tabla temporal esté creada sobre la conexión no‐transaccional por defecto.     Cuando  esto  se  detecta,  ActiveRecord  crea  nuevamente  la  tabla  en  la  conexión  transaccional  pero es seguro que los datos que ya se hayan almacenado usando los modelos asociados a la  conexión no transaccional no esten disponibles en la nueva.   21.18.4

Usar un TemporaryActiveRecord 

En el siguiente ejemplo se ilustra como implementar una entidad temporal y como utilizarlo  en un proceso de negocio.    El modelo temporal models/product_stadistics.php queda así:    Ejemplo: Crear una entidad temporal  <?php class ProductStadistics extends TemporaryActiveRecord { protected $id; protected $product_id; protected $cantidad; public function getId(){ return $this->id;


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                258 

} public function getProductId(){ return $this->product_id; } public function getCantidad(){ return $this->cantidad; } public function setId($id){ $this->id = $id; } public function setProductId($product_id){ $this->product_id = $product_id; } public function setCantidad($cantidad){ $this->cantidad = $cantidad; } protected function _tableDefinition(){ return array( "attributes" => array( "id" => array( "type" => db::TYPE_INTEGER, "notNull" => true, "primary" => true, "auto" => true ), "product_id" => array( "type" => db::TYPE_INTEGER, "notNull" => true ), "cantidad" => array( "type" => db::TYPE_VARCHAR, "notNull" => true, "size" => 10 ) ), "indexes" => array("product_id") ); } protected function initialize(){ $this->belongsTo("product"); } }

El  modelo  anterior  permite  ingresar  una  serie  de  datos  y  aprovechar  las  capacidades  de  ordenamiento y agrupamiento para obtener las estadísticas de la venta de unos productos.    Es  necesario  que  las  entidades  relacionadas  al  proceso  de  negocio  esten  asociadas  a  la  transacción  donde  se  manipulan  los  datos  de  la  entidad  temporal  cuando  se  instancian  directamente de la clase modelo ó se inyectan en el controlador usando $this.    Ejemplo: Utilizar entidades temporales con transacciones  try {

$transaction = TransactionManager::getUserTransaction(); $this->Movement->setTransaction($transaction); $this->Cart->setTransaction($transaction); $conditions = "sellDate = '".Date::getCurrentDate()."'";


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                259 

foreach($this->Movement->find($conditions) as $movement){ $productStadistic = new ProductStatistics(); $productStadistic->setTransaction($transaction); $productStadistic->setProductId($movement->getProductId()); $productStadistic->setCantidad($movement->getQuantity()); if($productStadistic->save()==false){ foreach($productStadistic->getMessages() as $message){ Flash::error($message->getMessage()); } $transaction->rollback(); } } $transaction->commit(); $productStadistic = $this->ProductStadistics->findFirst(); print "La cantidad total de productos es: "; print $productStadistic->sum("cantidad")."<br>"; print "La cantidad minima es: "; print $productStadistic->minimum("cantidad")."<br>"; print "La cantidad máxima es: "; print $productStadistic->maximum("cantidad")."<br>"; print "El promedio de cantidad es: "; print $productStadistic->average("cantidad")."<br>"; } catch(TransactionFailed $e){ Flash::error($e->getMessage()); }

21.19 ActiveRecordJoin El  subcomponente  ActiveRecordJoin  permite  aprovechar  las  relaciones  establecidas  en  el  modelo de datos para generar consultas simples ó con agrupamientos en más de 2 entidades  relacionadas  ó  no  relacionadas,  proponiendo  una  forma  adicional  de  utilizar  el  Object­ Relational­Mapping (ORM).    El constructor de la clase acepta un vector con las opciones de la consulta. De acuerdo al tipo  (consulta simple, agrupación de conteo, sumatoria, máximo, mínimo) que se requiera utilizar  estos varian.    En  el  ejemplo  existen  4  entidades  Products  ProductCategories,  Customers,  Invoices  e  InvoicesLines:    CREATE TABLE `products_categories` ( `id` int(18) NOT NULL, `name` varchar(70) default NULL, PRIMARY KEY (`id`) ); CREATE TABLE `products` ( `id` int(18) NOT NULL, `name` varchar(100) default NULL, `products_categories_id` int(11) NOT NULL, `quantity` int(11) NOT NULL, `price` decimal(16,2) NOT NULL, PRIMARY KEY (`id`)


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                260 

); CREATE TABLE `customers` ( `id` int(18) NOT NULL, `name` varchar(20) default NULL, PRIMARY KEY (`id`) ); CREATE TABLE `invoices` ( `id` int(18) NOT NULL, `customers_id` int(18) NOT NULL, `sell_date` date NOT NULL, PRIMARY KEY (`id`) ); CREATE TABLE `invoices_lines` ( `id` int(18) NOT NULL, `invoices_id` int(18) NOT NULL, `products_id` int(18) NOT NULL, `quantity` int(11) NOT NULL, `price` decimal(16,2) NOT NULL, `taxes` decimal(16,2) NOT NULL, PRIMARY KEY (`id`) );

Los modelos de estas entidades son los siguientes, (a propósito se omiten los getters/setters):    Ejemplo: Definición de modelos y sus relaciones para uso con ActiveRecordJoin  <?php // Modelo de Categorias de Productos class ProductsCategories extends ActiveRecord { public function initialize(){ // Relación 1-n con productos $this->hasMany("products"); } } // Modelo de Productos class Products extends ActiveRecord { public function initialize(){ // Relacion 1-1 inversa con categorias de productos $this->belongsTo("products_categories"); // Relacion 1-n con lineas de facturas $this->hasMany("invoices_lines"); } } // Modelo de Clientes class Customers extends ActiveRecord { public function initialize(){ // Relacion 1-n con facturas $this->hasMany("invoices"); } } // Modelo de Facturas class Invoices extends ActiveRecord { public function initialize(){ // Relacion 1-1 inversa con clientes $this->belongsTo("customers"); }


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                261 

} // Modelo de Detalle de Facturas class InvoicesLines extends ActiveRecord { public function initialize(){ // Relacion 1-1 inversa con clientes $this->belongsTo("invoices"); // Relacion 1-1 inversa con productos $this->belongsTo("products"); } }

  Una  vez  se  definan  las  relaciones  entre  las  entidades  del  dominio  de  datos  es  posible  utilizarlas tanto para obtener registros simples ó colecciones mediante ActiveRecorJoin:    Ejemplo: Hacer un Join de tres entidades  //Listar los productos vendidos, su cantidad y la fecha en que se vendieron $query = new ActiveRecordJoin(array( "entities" => array("Invoices", "Products", "InvoicesLines"), "fields" => array( "{#Products}.name", "{#Invoices}.sell_date", "{#InvoicesLines}.quantity" ) ));

Los  resultados  de  la  consulta  pueden  ser  obtenidos  mediante  el  método  getResultSet()  del  objeto ActiveRecordJoin. El valor de cada columna de la consulta puede ser obtenido usando  un getter virtual creado implícitamente en cada objeto resultado ó mediante el nombre de la  columna como una propiedad pública.    Ejemplo: Obtener los registros generados en un Join con ActiveRecordJoin  //Mediante getters foreach($query->getResultSet() as $result){ print $result->getName()." ". $result->getSellDate()." ". $result->getQuantity()."\n"; } //Mediante atributos públicos foreach($query->getResultSet() as $result){ print $result->name." ".$result->sell_date." ".$result->quantity."\n"; }

La  consulta  interna  SQL  SELECT  puede  ser  examinada  mediante  el  método  getSQLQuery()  ActiveRecordJoin. La consulta anterior genera la siguiente sentencia:    Ejemplo: SQL generado por ActiveRecordJoin  SELECT products.name, invoices.sell_date, invoices_lines.quantity FROM invoices, products, invoices_lines WHERE products.id = invoices_lines.products_id AND invoices.id = invoices_lines.invoices_id ORDER BY 1


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                262 

Notése como las relaciones adecuadas hacen parte de la sentencia SELECT en forma dinámica.  21.19.1

Agrupamientos con ActiveRecordJoin 

ActiveRecordJoin  permite  crear  consultas  avanzadas  utilizando  agrupamientos.  Los  agrupamientos  soportados  son:  sumatorias,  conteos,  mínimos,  máximos  y  promedios.  Un  agrupamiento se establece de la siguiente forma:    Ejemplo: Agrupamientos de datos con ActiveRecordJoin  //Cuantos productos se han vendido por cada producto $query = new ActiveRecordJoin(array( "entities" => array("Invoices", "Products", "InvoicesLines"), "groupFields" => array("{#Products}.name"), "sumatory" => array("{#InvoicesLines}.quantity") )); // Cuantos productos se han vendido por cada producto, cuya cantidad vendida sea // mayor a 150 $query = new ActiveRecordJoin(array( "entities" => array("Invoices", "Products", "InvoicesLines"), "groupFields" => array("{#Products}.name"), "sumatory" => array("{#InvoicesLines}.quantity"), "having" => "quantity>10" )); //En promedio cuál ha sido el precio del producto durante el mes de octubre $query = new ActiveRecordJoin(array( "entities" => array("Invoices", "Products", "InvoicesLines"), "groupFields" => array("{#Products}.name"), "sumatory" => array("{#InvoicesLines}.price"), "conditions" => "MONTH({#Invoices}.sell_date) = 10" ));

21.19.2

Parámetros de ActiveRecordJoin 

Los parámetros soportados por ActiveRecordJoin son:    Tabla: Parámetros soportados por ActiveRecordJoin  Opción  entities 

Descripción  Un vector que indica los modelos utilizados para realizar el  join. No se debe utilizar el mismo nombre las tablas sino el  nombre  de  las  clases  usadas  como  modelos  para  acceder  a  ellas. 

conditions 

Un  string  con  condiciones  adicionales  del  join.  No  se  debe  utilizar los nombres de las tablas en las condiciones sino la  convención {#NombreClase}. (opcional) 

sumatory 

Un  vector  con  los  campos  en  los  cuales  se  debe  aplicar  un  agrupamiento de sumatoria. (opcional) 

average 

Un  vector  con  los  campos  en  los  cuales  se  debe  aplicar  un 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                263 

agrupamiento de promedio. (opcional)  count 

Un  vector  con  los  campos  en  los  cuales  se  debe  aplicar  un  agrupamiento de conteo. (opcional) 

maximum 

Un  vector  con  los  campos  en  los  cuales  se  debe  aplicar  un  agrupamiento de valor máximo. (opcional) 

minimum 

Un  vector  con  los  campos  en  los  cuales  se  debe  aplicar  un  agrupamiento de valor mínimo. (opcional) 

having 

Un string con condiciones para el agrupamiento. (opcional). 

noRelations 

Con  el  valor  true  indica  que  no  se  deben  construir  dinámicamente  las  relaciones  entre  las  entidades  del  join.  Por defecto su valor es false. (opcional). 

 

21.20 ActiveRecordUnion El  objetivo  del  subcomponente  ActiveRecordUnion  es  unir  dos  ó  más  objetos  ActiveRecordResultset ó ActiveRecordRow sin volcar a memoria los resultados producidos por  ellos consiguiendo una gestión de los recursos de la aplicación más eficiente. 

21.21 SessionRecord El subcomponente SessionRecord permite administrar entidades de persistencia de sesión de  forma  natural  como  si  fuesen  entidades  pero  destinadas  a  mantener  registros  de  manera  independiente  por  id  de  sesión.  El  estado  de  los  objetos  instanciados  es  trasient  ya  que  al  terminarse la sesión los datos se vuelven inusables.    Por defecto las entidades tipo SessionRecord localizan el campo sid que deben tener un tamaño   suficiente  para  almacenar  un  valor  de  identificador  de  sesión.  El  valor  de  la  variable  de  configuración  de  PHP  session.hash_function  establece  el  tipo  de  algoritmo  utilizado  para  generar  el  identificador  de  sesión,  si  su  valor  es  0  indica  que  se  usa  md5  de  128  bits  (35  caracteres) y cuando es 1 indica que es sha1 de 160 bits (40  caracteres).     La  siguiente  tabla  contiene  la  estructura  necesaria  para  utilizar  una  entidad  con  SessionRecord.    CREATE TABLE `cart` ( `id` int(11) NOT NULL auto_increment,


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                264 

`sid` char(35) default NULL, `product_id` int(11) NOT NULL, `quantity` int(11) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8;

  La  definición  de  la  clase  de  un  modelo  de  este  tipo  es  la  normal  pero  en  vez  de  heredar  de  ActiveRecord  debe  heredar  de  la  clase  SessionRecord.  Las  operaciones  sobre  el  modelo  se  ejecutan normalmente con la diferencia que los registros grabados y devueltos siempre harán  referencia a aquellos donde el session_id actual sea el del campo sid de la tabla. 

21.22 PropertyAccessors y Mutators ActiveRecord accede al valor de los atributos de la tabla al realizar una operación mediante los  métodos  readAttribute  y  writeAttribute  heredados  en  cualquier  modelo.  El  desarrollador  puede  sobreescribir  estos  atributos  en  la  definición  del  módelo  y  controlar  la  forma  en  que  obtienen/establecen internamente los valores de los atributos de la entidad.    Ejemplo: Sobreescribir un PropertyAccessor en un modelo  <?php class Products extends ActiveRecord { protected function readAttribute($attributeName){ if($attributeName==”very_private_field”){ return null; } else { return $this->$attributeName; } } }

21.23 DynamicUpdate y DynamicInsert Un modelo tiene la propiedad de ahorrar trabajo al gestor relacional mediante estas opciones.  En el primero al realizar una operación de actualización solo los campos que han cambiado en  la  base  de  datos  son  actualizados,  en  la  segunda  solo  los  campos  que  contienen  valores  no  nulos se insertan en la operación.    Por  defecto  ambas  propiedades  estan  desactivadas  para  cambiar  su  valor  se  deben  usar  los  métodos  protegidos  setDynamicUpdate  y  setDynamicInsert  respectivamente.  Al  activarlas  en  contra  prestación  por  ejemplo  al  actualizar  cada  registro  debe  leerse  antes  de  realizar  la  operación y compararar cada valor de los atributos con el del objeto actual.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                265 

Ejemplo: Establecer la creación de sentencias de inserción y actualización solo para los  atributos del modelo que han cambiando    <?php class Categories extends ActiveRecord { protected function initialize(){ $this->setDynamicUpdate(true); $this->setDynamicInsert(true); } }

21.24 Manejo de Excepciones Las siguientes excepciones son generadas y asociadas a operaciones con ActiveRecord:     Tabla: Excepciones generadas cuando se trabaja con ActiveRecord  Excepción  DbException 

Componente  Db 

Descripción  Excepción  generica  lanzada  por  adaptador  de  conexión  al  gestor  relacional utilizado. 

DbLockAdquisitionException 

Db 

Excepción  lanzada  cuando  la  transacción  actual  en  la  conexión  no  puede  efectuar  un  bloqueo  sobre  algún  recurso  por  ejemplo  una tabla ó una serie de registros. 

DbSQLGrammarException 

Db 

Excepción  lanzada  cuando  se  envia  una  sentencia  SQL  mal  formada ó con errores de sintaxis. 

DbInvalidFormatException 

Db 

Excepción  lanzada  cuando  se  trata  de  asignar  un  valor  con  un  formato  invalido  al  tipo  de  dato  de la columna en una una entidad. 

DbContraintViolationException  Db 

Excepción  lanzada  cuando  la  operación  de  modificación  ó  actualización  viola  un  constraint  de  llave foránea. 

ActiveRecordException 

ActiveRecord 

Excepción 

generica 

de 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                266 

ActiveRecord.  21.24.1

Capturar excepciones dentro de modelos 

Si  se  requiere  tratar  las  excepciones  generadas  dentro  de  un  modelo  en  específico  se  puede  sobreescribir  el  método  protegido  exceptions  el  cuál  recibe  las  excepciones  generadas  y  por  defecto las re‐lanza al controlador ó la vista donde se invocó el modelo.    En el siguiente ejemplo se ilustra como efectuar un procedimiento que trate las excepciones  por violación de llaves foráneas para un modelo en particular:    Ejemplo: Tratar excepciones por violación de llave foránea    <?php class Inventory extends ActiveRecord {

}

protected function exceptions($e){ if($e instanceof DbConstraintViolationException){ //Algún procedimiento } else { throw $e; } }

21.24.2

Información de Excepciones 

Las excepciones generadas por el adaptador al motor de base de datos usualmente permiten  obtener mayor información sobre el entorno de la excepción agregando datos como el código  y descripción de bajo nivel generadas por el RTP.     En  el  capítulo  del  componente  Db  se  explica  como  obtener  mayor  información  sobre  excepciones generadas en la base de datos. 

21.25 Plugins de Modelos Los Plugins de modelos ó capa de datos permiten extender la funcionalidad del componente  ActiveRecord  y  sus  subcomponentes.  La  arquitectura  de  plugins  de  ActiveRecord  permite  observar, extender y manipular el comportamiento de los modelos de la aplicación según las  condiciones lo exijan.    Los  plugins  permiten  interceptar  eventos  de  los  modelos  de  tal  forma  que  estos  sean  observables  y  además  ejecutárse  uno  tras  otro  de  manera  centralizada  sin  requerir 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                267 

refactorización ó reintegración en la aplicación.  21.25.1

Crear un Plugin de ActiveRecord 

Los plugins de ActiveRecord son clases que implementan eventos que son invocados a medida  que avanza la ejecución del proceso de acceso a la capa de datos en cualquier petición. Estas  clases deben cumplir con los siguientes requerimientos:     Deben estar ubicados en el directorio de plugins usualmente apps/app­name/plugins   El nombre del archivo que implementa la clase debe ser el nombre del plugin   El nombre de la clase debe tener la extensión Plugin   Los plugins de controlador deben heredar de la clase ModelPlugin ó ser subclase de ella    Las  clases  pueden  implementar  métodos  públicos  que  referencian  los  eventos  ocurridos  en  los controladores, la lista de ellos es la siguiente:    Tabla: Eventos que se pueden implementar en plugins de ActiveRecord  Nombre Evento  afterInitialize 

Descripción  Ocurre  después  de  inicializar  un  modelo.  Normalmente  los  modelos son inicializados solo una vez en cada petición. 

onException 

Ocurre cuando se genera una excepción dentro de un modelo. 

 

21.26 Organización de Modelos Los archivos de modelos deben estar ubicados en el directorio models/ ó donde la variable de  configuración modelsDir lo indique. Cuando los modelos se cargan en modo auto‐inicializador  es posible organizarlos en subdirectorios de tal forma que representen un grupo ó categoría  lógica al cual pertenezcan.    Un ejemplo de una organización lógica es el siguiente:    Ejemplo: Organización lógica de modelos  models/ base/ modelBase.php security/ roles.php users.php access_list.php inventory/


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                268 

references.php kardex.php orders.php movement.php

21.27 Auto-inicialización de Modelos Los  modelos  pueden  inicializarse  de  2  formas,  automáticamente  ó  dinámicamente.  Por  defecto los modelos son auto‐inicializados esto significa que en cada petición todas las clases  del directorio de modelos son leídas y se construyen las relaciones y restricciones definidas  en ellos.     El usar una forma ó la otra depende del tipo de aplicación que se tenga. Es recomendable usar  auto‐inicialización cuando:    •

El servidor donde está instalada la maquina tiene buenas prestaciones (discos duros  rápidos, procesadores de última generación, etc).  

Con relación a las prestaciones del servidor el número de modelos y su complejidad en  cuanto a relaciones y restricciones es moderado ó bajo. 

La aplicación requiere frecuentemente del acceso a la mayor parte de los modelos en  la mayor parte de los procesos de negocio. 

  Desventajas de la auto‐inicialización:    •

Dependiendo de las condiciones, el acceso a disco puede elevarse considerablemente  en cada petición 

Si  los  modelos  tienen  muchas  relaciones  y  restricciones  se  podría  aumentar  el  consumo de memoria innecesariamente   

Se recomienda utilizar inicialización dinámica cuando:    •

El servidor tiene bajas prestaciones ó una concurrencia elevada 

La aplicación requiere de modelos en forma selectiva sin que haya un patrón definido  de acceso a ellos 

El número de modelos de la aplicación es alto y hay muchas relaciones y restricciones  entre ellas.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                269 

 Desventajas de la inicialización dinámica:    •

Procesos que requieran varios modelos simultaneamente puede elevar los recursos de  procesamiento solicitados por la aplicación 

Solo los modelos inicializados son llevados a las vistas asociadas a la petición   

21.27.1

Activar inicialización dinámica 

Para  activar  la  inicialización  dinámica  se  debe  agregar  la  sección  entities  con  la  variable  de  configuración autoInitialize = Off al archivo de configuración config/config.ini de la aplicación.  Un archivo de configuración config.ini queda así:    Ejemplo: Definir autonicialización de modelos en la configuración  [application] mode = development name = "Project Name" interactive = On dbdate = YYYY-MM-DD debug = On [entities] autoInitialize = Off

                       


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                270 

 

22 Componente EntityManager 22.1 Introducción El componente EntityManager es usado internamente por el framework y principalmente por  ActiveRecord  y  Controller  para  administrar  las  entidades,  sus  relaciones  de  asociación,  relaciones  de  integridad  y  generadores  de  tal  forma  que  el  acceso  a  ellas  sea  consistente  y  uniforme.    La  clase  EntityManager  es  una  clase  abstracta  en  la  que  sus  métodos  solo  pueden  ser  invocados estáticamente, de esta forma se asegura que los datos de entidades y sus relaciones  existan solo una vez por proceso de negocio. 

22.2 Obtener una nueva instancia de un Modelo Cada vez que se llama el constructor de una clase de ActiveRecord se ejecutan procedimientos  internos  como  la  inicialización  del  modelo,  tals  como  la  localización  del  data  source,  la  definición de las relaciones con otros modelos y en algunos casos se trata de volcar los meta‐ datos de la tabla si estos no se encuentran disponibles para la aplicación.    El 

componente 

EntityManager 

proporciona 

el 

método 

getEntityInstance(string 

$instanceName) que permite obtener una instancia de la entidad ya inicializada mejorando el  rendimiento de un proceso de negocio.    En el siguiente ejemplo se muestra como se reemplaza el instanciamiento mediante new por el  método de obtener instancias ya inicializadas en blanco:    Ejemplo: Obtener instancias de modelos en forma eficiente  <?php try { $transaction = TransactionManager::getUserTransaction(); $this->Movement->setTransaction($transaction); $this->Cart->setTransaction($transaction); $conditions = "sellDate = '".Date::getCurrentDate()."'"; foreach($this->Movement->find($conditions) as $movement){ $productSt = EntityManager::getEntityInstance(“ProductStatistics”); $productSt->setTransaction($transaction); $productSt->setProductId($movement->getProductId()); $productSt->setCantidad($movement->getQuantity()); if($productSt->save()==false){ foreach($productSt->getMessages() as $message){ Flash::error($message->getMessage());


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                271 

} $transaction->rollback(); } } $transaction->commit(); } catch(TransactionFailed $e){ Flash::error($e->getMessage()); }

  Nota:  Podría  obtener  un  error  como  “Fatal  error:  Cannot  redeclare  class  Products  in  /path/to/application/instance/apps/default/models/products.php  on  line  230”  si  no  establece el parámetro de getEntityInstance usando el nombre de la clase modelo tal y como  fué definida en el archivo del modelo. 

22.3 API del Componente EntityManager El  desarrollador  no  debería  interactuar  directamente  con  este  componente  ya  que  ActiveRecord y sus subcomponentes son los encargados de utilizar este API para administrar  las  relaciones  y  la  información  de  las  entidades.  La  siguiente  API  es  presentada  buscando  ayudar a extender el core del framework ó reemplazar este componente.    22.3.1 Métodos para inicializar modelos y obtener instancias de ellos  static function array getEntities()   Obtiene un vector con todas las entidades inicializadas en la petición actual.    static function void setAutoInitialize(boolean $autoInitialize)  Establece si los modelos son auto‐inializados ó no.     static function boolean getAutoInitialize()   Indica si los modelos están siendo auto‐inicializados ó no.    static function void setModelsDirectory(string $modelsDir)   Establece el directorio desde donde deben ser cargados los modelos.    static function mixed getEntityInstance(string $entityName, boolean $newInstance=true)   Obtiene una instancia de una clase de un modelo. Si se pasa false en el segundo parámetro se  obtiene una instancia existente.   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                272 

static function void initModelBase(string $modelsDir)   Carga la clase ActiveRecord ubicada en el directorio de modelos de la aplicación.    static function void initModels(string $modelsDir)   Inicializa el directorio de modelos cargandolos e inicializandolos.    static function boolean isEntity(string $entityName)   Permite consultar si existe un determinado modelo en la petición actual.    static function boolean isModel(string $modelName)   Es un alias del método isEntity.    static function string getEntityName(string $model)   Obtiene el nombre de una entidad de acuerdo a su origen de datos (tabla).    static function void addEntityByClass(string $entityClass)   Inicializa un dinámicamente modelo por el nombre de su clase.    22.3.2 Métodos para administrar relaciones de multiplicidad  static function boolean existsBelongsTo(string $entityName, string $relationRequested)   Permite  consultar  si  una  entidad  está  relacionada  con  otra  mediante  una  relación  tipo  belongsTo (muchos a 1) al menos unidireccionalmente.    static function boolean existsHasMany(string $entityName, string $relationRequested)   Permite  consultar  si  una  entidad  está  relacionada  con  otra  mediante  una  relación  tipo  hasMany (1 a muchos) al menos unidireccionalmente.    static function boolean existsHasOne(string $entityName, string $relationRequested)   Permite consultar si una entidad está relacionada con otra mediante una relación tipo hasOne  (1 a 1) al menos unidireccionalmente.    static  function  boolean  getBelongsToRecords(string  $entityName,  string  $relationRequested,  ActiveRecord $record)   Obtiene  un  resultado  de  los  registros  relacionados  mediante  una  relación  de  multiplicidad 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                273 

belongsTo.    El  parámetro  $record  es  la  instancia  de  un  modelo  utilizada  para  efectuar  la  operación.    static  function  boolean  getHasOneRecords(string  $entityName,  string  $relationRequested,  ActiveRecord $record)   Obtiene  un  resultado  de  los  registros  relacionados  mediante  una  relación  de  multiplicidad  hasOne.    El  parámetro  $record  es  la  instancia  de  un  modelo  utilizada  para  efectuar  la  operación.    static  function  boolean  getHasManyRecords(string  $entityName,  string  $relationRequested,  ActiveRecord $record)   Obtiene  un  resultado  de  los  registros  relacionados  mediante  una  relación  de  multiplicidad  hasMany.    El  parámetro  $record  es  la  instancia  de  un  modelo  utilizada  para  efectuar  la  operación.    static 

function 

void 

addBelongsTo(string 

$entityName, 

string 

$fields='', 

string 

$referenceTable='', string $referencedFields='', string $relationName='')   Agrega una relación belongsTo al administrador de entidades en forma programacional.    static function void addHasMany(string $entityName, mixed $fields='', string $referenceTable='',  mixed $referencedFields='')   Agrega una relación belongsTo al administrador de entidades en forma programacional.    static  function  void  addHasOne(string  $entityName,  mixed  $fields='',  string  $referenceTable='',  mixed $referencedFields='')   Agrega una relación hasOne al administrador de entidades en forma programacional.    static function void addTrasientAttribute(string $entityName, string $attribute)  Agrega un atributo de una entidad que no debe ser persistido.     static function array getRelationsOf(string $entityName)   Obtiene un array con las relaciones que han sido definidas para una determinada entidad.  22.3.3 Métodos adminitrar para Entidades Temporales  static function boolean existsTemporaryEntity(string $entityName)  


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                274 

Permite consultar si una entidad temporal ya ha sido definida.    static function void addTemporaryEntity(string $entityName)   Agrega una entidad temporal al administrador de entidades.    static function void destroyTemporaryEntity(string $entityName)   Destruye una entidad temporal del administrador de entidades.    static function boolean isCreatedTemporaryEntity(DbBase $connection, string $entityName)   Consulta si una entidad temporal ya ha sido creada en una determinada conexión.    22.3.4 Origenes de datos  static function string getSourceName(string $entityName)   Obtiene el origen de datos (tabla) de una determinada entidad    22.3.5 Administrar generadores de entidades  static  function  void  setEntityGenerator(string  $entityName,  string  $adapter,  string  $column,  array $options)   Establece el generador de una determinada entidad.    static function boolean hasGenerator(string $entityName)   Indica si una entidad tiene definido algun generador.    static function ActiveRecordGenerator getEntityGenerator(string $entityName)   Obtiene el generador de una determinada entidad.    static function array getAllCreatedGenerators()   Obtiene todos los generadores definidos en la petición actual.    22.3.6 LLaves foráneas virtuales  static  function  void  addForeignKey(string  $entityName,  array  $fields='',  string  $referenceTable='', array $referencedFields='', array $options=array())   Establece una llave foránea virtual en una entidad. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                275 

  static function array getForeignKeys(string $entityName)   Obtiene las llaves foráneas virtuales definidas para una entidad.    static function boolean hasForeignKeys(string $entityName)   Permite consultar una entidad tiene llaves foráneas virtuales definidas. 

                                           


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                276 

23 Componente TransactionManager 23.1 Introducción El objetivo de este componente es administrar las transacciones globales requeridas por los  procesos de negocio de una aplicación. Su API es utilizada para acceder a un gestor relacional  en una unidad de trabajo en particular. Toda la arquitectura de este componente proporciona  a las aplicaciones desarrolladas en Kumbia Enterprise un contenedor para administración de  transacciones en PHP como los usados en Java EE.    Es  responsable  de  abrir  y  cerrar  transaciones  manteniendo  unidades  de  trabajo  en  forma  controlada. Las transacciones pueden ser creadas programacionalmente ó declarativamente.  

23.2 Contexto de Scope Persistente El  TransactionManager  es  el  puente  para  que  objetos  del  ORM  puedan  interactuar  con  su  contexto persistente adecuado.  Cada objeto que es ligado a una transacción administrada por  el contenedor es notificado de otras transacciones activas en el mismo contexto. Los objetos  mantienen su estado y este es replicado cuando se abre ó cierra la transacción informando el  estado de la misma. 

23.3 Event Listeners El  componente  TransactionManager  hace  uso  del  CommonEventInfraestructure  de  Kumbia  Enterprise  para  notificar  eventos  a  los  objetos  dependientes  de  una  transacción  y  también  entre ellos mismos.    Los eventos soportados son:    Tabla: Event Listeners de TransactionManager  Evento  delete 

Descripción  Ocurre  cuando  un  objeto  es  destruido  cuando  se  replica  el  estado  del  mismo en la persistencia. 

create 

Ocurre cuando un objeto es creado. 

update 

Ocurre cuando un objeto es actualizado. 

preInsert 

Ocurre antes de realizar una inserción de un registro. 

preDelete 

Ocurre antes de realizar una eliminación de un registro. 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                277 

preLoad 

Ocurre al crear un objeto instanciado como resultado de una consulta. 

postInsert 

Ocurre después de realizar una inserción. 

postDelete 

Ocurre después de realizar una eliminación. 

postUpdate 

Ocurre después de realizar una actualización. 

23.4 Estados de las entidades Las  entidades  pueden  tener  los  siguientes  estados  cuando  intervienen  en  procesos  transaccionales:   

Estado New: Cuando una entidad es creada mediante el operador new por defecto se 

encuentra ligada a una conexión no transaccional y no representa ningun registro de la base  de datos. 

Estado Managed: Cuando una entidad está asociada a una transacción creada por el 

TransactionManager se dice que se encuentra en estado administrado. 

Estado Detached: Cuando la entidad perteneció a una transacción administrada pero 

la transacción ya fue cerrada ó su contexto fue cambiado a la conexión no transaccional. 

Estado Removed: Cuando la entidad fue eliminada de la persistencia y por lo tanto no 

puede estar asociada a un contexto transaccional. 

23.5 Asignar el objeto al estado administrado Los  métodos  de  ActiveRecord  llamados  setTransaction()  y  detachTransaction()  permiten  cambiar programacionalmente el estado transaccional de un objeto.    Ejemplo: Cambiar un objeto ActiveRecord a un estado administrado  <?php $transaction = TransactionManager::getUserTransaction(); $customer = new Customer(); $customer->setTransaction($transaction); $customer->setName(“John”); $customer->setSurname(“Smith”); $customer->save(); $transaction->commit(); $customer->detachTransaction();

  Cuando  la  transacción  es  cerrada  ya  sea  por  un  rollback  ó  commit  los  objetos  no  son  automáticamente cambiados al estado detached. Las transacciones cerradas ya no son usables  pero la unidad de trabajo mantiene su dependencia a la transacción. El desligamiento de los  objetos  de  la  transacción  puede  realizarse  manualmente  ó  llamar  el  método 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                278 

detachDependencies() de ActiveRecordTransaction. 

23.6 API de TransactionManager static 

function 

ActiveRecordTransaction 

getUserTransaction(TransactionDefinition 

$definition='')   Crea  ó  obtiene  una  transacción  ActiveRecordTransaction.  Si  se  define  una  definición  de  transacción se crea una nueva.     static function void initializeManager()  Inicializa el administrador de transacciones. El desarrollador no debe invocar este método ya  que es automáticamente llamado por el contenedor de aplicaciones al iniciar la petición.     static function void rollbackPendent()   Realiza  un  rollback  sobre  todas  las  transacciones  administradas  por  el  TransactionManager.  Cuando  ocurre  una  excepción  no  capturada  el  framework  llama  este  método  para  cancelar  cualquier operación pendiente y así cuidar la integridad de los datos.     static function void commit()   Realiza un commit sobre todas las transacciones administradas por el TransactionManager.    static function void rollback()  Realiza un rollback sobre todas las transacciones administradas por el TransactionManager.    static function void notifyRollback(ActiveRecordTransaction $transaction)   Permite  notificar  a  otras  transacciones  administradas  por  el  TransactionManager  que  una  transacción realizo un rollback buscando que las demás también lo hagan.    static function void notifyCommit(ActiveRecordTransaction $transaction)   Permite  notificar  a  otras  transacciones  administradas  por  el  TransactionManager  que  una  transacción realizo un commit buscando que las demás también lo hagan.         


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                279 

Parte 4: La capa de presentación   

24 Presentación 24.1 Introducción La  capa  de  presentación  es  la  tercera  de  la  arquitectura  de  una  aplicación  Web  y  permite  definir  interfaces  y  métodos  para  interactuar  con  el  usuario  final  así  como  presentarle  información al mismo.                                                   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                280 

25 Componente View 25.1 Introducción El  componente  View  se  encarga  de  administrar  la  forma  estándar  en  la  que  se  genera  la  presentación al usuario final en su explorador.     La presentación estándar en una aplicación en Kumbia Enterprise se basa en varios patrones  de  diseño  que  permiten  reducir  la  codificación  y  hacer  más  mantenible  esta  parte  del  desarrollo.    El  primer  patrón  utilizado  es  Template  View  el  cuál  habla  de  utilizar  tags  personalizados  ó  marcas embebidas en el contenido dinámico proporcionando flexibilidad y poder para crear  interfaces web.    El segundo patrón es el Two State View el cual permite definir múltiples interfaces de acuerdo  al  dispositivo  ó  cliente  desde  el  cuál  se  este  se  accediendo  a  la  aplicación.  Este  tipo  de  implementación  favorece  principalmente  aplicaciones  que  accedan  desde  un  browser  ó  un  dispositivo móvil como un telefono celular, en donde es necesario personalizar detalles para  cada tipo de interfaz.    La arquitectura MVC presenta el concepto de vista la cuál actúa como puente entre el usuario  final y la lógica de dominio en los controladores. 

25.2 Jerarquía de vistas en la presentación Una jerarquía de archivos con vistas imbebibles soportadas por el componente View permite  reducir  la  codificación  creando  puntos  de  presentación  comunes  para  la  aplicación,  controladores ó mediante la implementación de plantillas.    Cada parte de la presentación se crea en un archivo ubicado en una estructura convenida de  directorios en el directorio de la aplicación llamado views/.     El  componente  View  permite  definir  la  presentación  en  varios  niveles,  cada  uno  contiene  al  siguiente:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                281 

Tabla: Niveles de presentación en el componente View  Archivo ó Ubicación  index.phtml 

Descripción  Contiene  la  vista  principal  y  encabezado  XHTML de todas las vistas. 

directorio‐con‐nombre‐del‐controlador 

Permite  establecer  archivos  con  vistas  para  cada acción del controlador. 

directorio‐con‐nombre‐del‐

Permite crear una presentación para la acción 

controlador/archivo‐con‐nombre‐de‐la‐

activa en el controlador. 

acción.phtml  layouts/archivo‐con‐nombre‐del‐

Permite  establecer  una  vista  común  para 

controlador.phtml 

todas las acciones del controlador. 

layouts/nombre‐template.phtml 

Permite  establecer  una  plantilla  común  para  varios controladores. 

directorio‐con‐nombre‐del‐

Permite  establecer  vistas  parciales  que  se 

controlador/_nombre‐vista‐parcial.phtml 

pueden  incluir  en  varias  vistas  de  acciones  del controlador activo. 

partials/_nombre‐vista‐parcial.phtml 

Permite  establecer  vistas  parciales  que  se  pueden  incluir  en  cualquier  vista  ó  template  de la aplicación. 

   El  componente  View  no  requiere  que  exista  cada  componente  de  presentación  que  se  mencionó anteriormente, el único requerido es la vista principal.  25.2.1 Vista Principal  En  el  directorio  views/  se  puede  encontrar  el  archivo  index.phtml  que  implementa  el  encabezado XHTML estándar para cualquier vista de la aplicación:    Ejemplo: Vista principal views/index.phtml por defecto  <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv='Content-type' content='text/html; charset=UTF-8' /> <title>Application Title</title> <?php Tag::stylesheetLink('style', true) ?> <?php echo Core::stylesheetLinkTags() ?> <?php echo Core::javascriptBase() ?> </head> <body> <?php echo View::getContent(); ?> </body>


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                282 

</html>

  Por  defecto  se  utiliza  un  encabezado  XHTML  1.0  Strict  el  cuál  propende  por  aplicaciones  basadas en estándares y que funcionan mejor en los navegadores más avanzados del mercado.    Los  helpers  Core::stylesheetLinkTags()  y  Core::javascriptBase()  incluyen  archivos  JavaScript  como frameworks y utilidades además de los CSS incrustados en otras vistas activas.    El XHTML generado por la vista anterior es:    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv='Content-type' content='text/html; charset=UTF-8' /> <title>Application Title</title> <link rel='stylesheet' type='text/css' href='/apppath/css.php?c=style&p=/app-path' /> <script type='text/javascript' src='/apppath/javascript/scriptaculous/protoculous.js'></script> <script type='text/javascript' src='/hfos/javascript/core/base.js'></script> <script type='text/javascript' src='/apppath/javascript/core/validations.js'></script> <script type='text/javascript' src='/app-path/javascript/core/main.php?app= &module=&path=%2Finstance-name%2F&controller=login&action=index&id='></script> </head> <body> </body> </html>

  Notese el llamado a View::getContent(), este imprime todo el contenido generado en el layout  ó vistas activas en la aplicación en el lugar que se indique.  25.2.2 Requerimientos de la Vista Principal  Es recomendable no eliminar los llamados a los helpers estándar en la vista principal ya que  esto  puede  impactar  el  comportamiento  del  framework.  En  general  los  requerimientos  del  contenido de la vista principal son los siguientes:    •

Su nombre debe ser index.phtml y mantenerse en la raíz de views/ 

Incluir los archivos JavaScript que se utilicen en cada petición a la aplicación 

Incluir los archivos CSS que se utilicen en cada petición a la aplicación 

Incluir codigo XHTML que sea común a cada controlador y acción de la aplicación 

25.2.3 Requerimientos Vistas a nivel de Controlador  Generalmente cada acción solicitada presenta ó solicita información diferente al usuario de tal  forma que el flujo de la aplicación sea consistente tanto para el desarrollador como para los 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                283 

usuarios. Los requerimientos de las vistas a nivel de controlador son:    •

Es  necesario  que  exista  un  directorio  con  el  nombre  del  controlador  donde  se  encuentre la acción 

El nombre del directorio debe ir en minúsculas y sin el sufijo “Controller”. 

El archivo de la vista debe tener la extensión .phtml y el nombre debe ser el nombre de  la acción sin el sufijo “Action”.   

25.2.4 Requerimientos de Layouts de Controladores  Los layouts de controladores son vistas que contienen fragmentos comunes de presentación  que  son  validos  para  cualquier  acción  del  controlador.  Los  requerimientos  de  los  layouts  de  controladores son:  •

Un archivo con el nombre del controlador en el directorio views/layouts debe existir. 

El nombre del archivo debe ir en minúsculas y sin el sufijo “Controller”. 

El archivo debe tener extensión .phtml.   

25.2.5 Requerimientos de Vistas Parciales en Controladores  En ocasiones fragmentos de presentación como menús, encabezados, pie de paginas, etc son  comunes  a  varias  acciones  de  un  controlador  pero  no  a  todas,  en  estos  casos  se  puede  implementar vistas parciales. Los requerimientos de las vistas parciales en controladores son:    •

Es  necesario  que  exista  un  directorio  con  el  nombre  del  controlador  donde  se  encuentre la vista parcial. 

El nombre del directorio debe ir en minúsculas y sin el sufijo “Controller”. 

El  archivo  de  la  vista  parcial  debe  tener  la  extensión  .phtml  y  el  prefijo  “_”  (underscore).   

25.2.6 Requerimientos de Vistas Parciales Generales  Al igual que las vistas parciales de controladores las generales realizan la misma tarea con la  diferencia que estan disponibles para cualquier layout, template ó vista de la aplicación.    Los requerimientos de las vistas parciales generales son:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                284 

La vista parcial debe estar ubicada en el directorio views/partials. 

El  archivo  de  la  vista  parcial  debe  tener  la  extensión  .phtml  y  el  prefijo  “_”  (underscore).   

25.2.7 Requerimientos de Plantillas ó Templates  Las plantillas permiten establecer múltiples fragmentos de presentación y aplicarsen antes ó  después del layout del controlador. Los requerimientos de las plantallas son:  •

Deben entas ubicados en el directorio views/layouts/. 

La extensión del archivo debe ser “.phtml” 

25.3 Inserción automática y manual de vistas El  componente  View  utiliza  convenciones  para  insertar  automáticamente  la  presentación  correspondiente a un controlador ó una acción, otros componentes de presentación requiere  que se establezca programacionalmente su relación con la presentación diseñada.    Si se realiza una petición a la aplicación mediante la URL:    http://172.16.5.2/company/categories/create 

  En  donde  company  es  el  nombre  de  la  instancia  del  framework,  categories  es  el  nombre  del  controlador y create la acción requerida.    Gracias  a  la  presentación  por  convención  el  componente  View  tratará    de  crear  la  presentación a partir de los archivos:    •

default/views/categories/create.phtml 

default/views/layouts/categories.phtml 

default/views/index.phtml 

  Si  alguno  de  los  archivos  mencionados  no  existe  se  trata  de  ubicar  el  siguiente  y  así  sucesivamente.    En este segundo caso la URL solicitada es:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                285 

http://172.16.5.2/company/press/categories/ 

  En  donde  company  es  el  nombre  de  la  instancia  del  framework,  press  es  el  nombre  de  la  aplicación  y  categories  es  el  nombre  del  controlador.  El  nombre  de  la  acción  no  se  ha  establecido por lo que se asume que es index.    Los archivos de presentación son los siguientes:    •

press/views/categories/index.phtml 

press/views/layouts/categories.phtml 

default/views/index.phtml 

25.4 Implementar los tipos de vistas En el siguiente ejemplo se ilustra los tipos de vistas y su integración en la presentación de una  aplicación. El controlador customers se inicializa con 3 templates:    Ejemplo: Aplicar multiples templates a un mismo controlador  <?php class CustomersController extends ApplicationController { public function initialize(){ $this->setTemplateBefore("template1"); $this->setTemplateAfter(array("template2", "template3")); } public function createAction(){ } public function updateAction(){ } }

  Los  métodos  del  controlador  setTemplate  y  setTemplateAfter  permiten  insertar  plantillas  antes  y  después  del  layout  del  controlador.  Los  templates  como  se  mencionó  deben  estar  ubicados en views/layouts.      El archivo de plantilla views/layouts/template1.phtml tiene:    <div style='background:yellow;padding:10px'> <h2>Template 1</h2> <?php View::getContent(); ?> </div>


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                286 

El  llamado  a  View::getContent()  indica  donde  se  debe  incrustar  el  contenido  de  otras  vistas  contenidas por el fragmento de presentación.    El archivo de plantilla views/layouts/template2.phtml tiene:    <div style='background:#faca22;padding:10px'> <h2>Template 2</h2> <?php View::getContent(); ?> </div>

  El archivo de plantilla views/layouts/template3.phtml tiene:  <div style='background:#ccccf2;padding:10px'> <h2>Template 3</h2> <?php View::getContent(); ?> </div>

  El archivo de layout del controlador views/layout/customers.phtml tiene:    <?php View::renderPartial('header') ?> <div style='background:orange;padding:10px'> <h2>Layout de Customers</h2> <?php View::getContent(); ?> </div> <?php View::renderPartial('footer') ?>

  El  método  View::renderPartial  inserta  una  vista  parcial  que  esta  ubicada  en  el  mismo  directorio de controlador views/customers/. Notése que el prefijo “_” de las vistas parciales es  omitido a propósito al establecer el nombre de esta.    La vista parcial views/customers/_header.phtml tiene:  <h4>Este es el encabezado</h4>

  La vista parcial views/customers/_footer.phtml tiene:  <h4>Este es el pie de página</h4>

  La vista de la acción create en el archivo views/customers/_create.phtml  tiene:  <div style='background:#eac2ff;padding:10px'> <h3>Acción Create</h3> <?php View::getContent(); ?> </div>

La vista de la acción update en el archivo views/customers/_update.phtml  tiene:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                287 

<div style='background:#cceaff;padding:10px'> <h3>Acción Update</h3> <?php View::getContent(); ?> </div>

El resultado obtenido en el explorador al invocar la acción create es:   

    El resultado obtenido al invocar la acción update en customers es:   


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                288 

    Como  se  mostró  todos  los  tipos  de  fragmentos  de  presentación  proporcionan  una  poderosa  forma de compartir el código y construir interfaces flexibles siguiendo un principio básico de  mantenibilidad de una aplicación. 

25.5 Transferir valores del controlador a la vista Existen 2 formas de transferir datos del controlador a la presentación:  25.5.1 Transferir mediante atributos públicos  Si al procesar una acción en un controlador se requiere presentar información al cliente final  esta debe ser transferida a las vistas asociadas para su posterior tratamiento. Por defecto los  atributos  públicos  de  los  controladores  son  transferidos  automáticamente  a  la  presentación  en forma de variables locales.    El siguiente controlador tiene 2 atributos públicos que se visualizan al invocar la acción info:    Ejemplo: Utilizar atributos públicos para transferir valores a la presentación  <?php class PressController extends ApplicationController { public $code; public $name;


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                289 

public function indexAction(){ } public function infoAction(){ $this->code = 100; $this->name = “Este es un nombre”; } }

  Todas las vistas asociadas a la petición tienen acceso a las variables locales $code y $name que  pueden ser usadas a conveniencia:    El archivo views/layouts/press.phtml tiene:  <h1>El código es <?php echo $code ?></h1>

  El archivo views/press/info.phtml tiene:  <p>El contenido de “name” es <?php echo $name ?></p>

  Lo que en conjunto produce en el explorador:   

    25.5.2 Transferir mediante setParamToView  La segunda forma de transferir valores desde las acciones del controlador es mediante el uso  del método setParamToView. Este método es especialmente útil cuando se requiera transferir  grandes cantidades de datos a las vistas ó datos poco relevantes que no ameriten la definición  de un atributo público en el controlador.    También si se usan controladores con el estado persistente activo es posible que también se  quiera restringir la definición de atributos públicos a los estrictamente necesarios.    Ejemplo: Transferir datos a la presentación mediante setParamToView  <?php class PressController extends ApplicationController { public function indexAction(){


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                290 

} public function showAllAction(){ $this->setParamToView(“editions”, $this->Editions>find(“status=’A’”)); } }

  En la vista se crea una variable local llamada $editions con el valor asignado en la acción. 

25.6 Controlar Niveles de Renderización En determinadas situaciones es posible que se requiera controlar el nivel de profundidad de la  visualización.  El  componente  View  permite  establecer  el  nivel  de  renderización  mediante  el  método setRenderLevel(int $level).    Esté  método  puede  ser  invocado  desde  el  controlador  ó  desde  una  capa  de  visualización  superior para evitar que otras sean presentadas.    Tabla: Niveles de renderización en View  Valor  0 

Constante  LEVEL_NO_RENDER 

Descripción  Indica  que  se  debe  evitar  generar  cualquier tipo de presentación. 

LEVEL_ACTION_VIEW 

Genera  la  presentación  hasta  la  vista  asociada a la acción. 

LEVEL_BEFORE_TEMPLATE 

Genera  la  presentación  hasta  las  plantillas  antes  de  el  layout  del  controlador. 

LEVEL_LAYOUT 

Genera  la  presentación  hasta  el  layout  del controlador. 

LEVEL_AFTER_TEMPLATE 

Genera  la  presentación  hasta  las  plantillas  después  de  el  layout  del  controlador. 

LEVEL_MAIN_VIEW 

Genera  la  presentación  hasta  la  vista  principal. Archivo views/index.phtml 

 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                291 

25.7 Utilizar modelos en la presentación Los  modelos  de  la  aplicación  siempre  están  disponibles  en  la  presentación.  Si  la  opción  de  autoinicialización de modelos está activa se creará una referencia de todos los modelos de la  aplicación  como  variables  globales  con  el  nombre  del  modelo,  si  no  está  activa  solo  los  modelos utilizados en la petición actual serán llevados a la presentación.    Dependiendo  del  caso  se  puede  usar  en  forma  natural  dentro  de  cualquier  tipo  de  vista  los  modelos de esta forma:    Ejemplo: Utilizar modelos en la presentación cuando son auto­inicializados  //Listar las ordenes de compra foreach($Orders->find() as $order){ print $order->getRecordedDate(); }

  Si  los  modelos  no  son  auto‐inicializados  se  puede  obtener  una  instancia  de  ellos  usando  el  método de EntityManager llamado getEntityInstance:    Ejemplo: Usar modelos en la presentación cuando no son auto­inicializados  $orders = EntityManager::getEntityInstance(‘Orders’); foreach($Orders->find() as $order){ print $order->getRecordedDate(); }

25.8 Plugins de View Los  Plugins  de  presentación  permiten  extender  la  funcionalidad  del  componente  View.  La  arquitectura de plugins de View permite observar, extender y manipular el comportamiento  de las vistas de la aplicación según las condiciones lo exijan.    Los plugins permiten interceptar eventos en las vistas de tal forma que estos sean observables  y  además  ejecutárse  uno  tras  otro  de  manera  centralizada  sin  requerir  refactorización  ó  reintegración en la aplicación.  25.8.1 Crear un Plugin de View  Los  plugins  de  View  son  clases  que  implementan  eventos  que  son  invocados  a  medida  que  avanza  la  ejecución  del  proceso  de  presentación  en  cualquier  petición.  Estas  clases  deben  cumplir con los siguientes requerimientos:     Deben estar ubicados en el directorio de plugins��usualmente apps/app­name/plugins 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                292 

 El nombre del archivo que implementa la clase debe ser el nombre del plugin   El nombre de la clase debe tener la extensión Plugin   Los plugins de controlador deben heredar de la clase ViewPlugin ó ser subclase de ella    Las  clases  pueden  implementar  métodos  públicos  que  referencian  los  eventos  ocurridos  en  los controladores, la lista de ellos es la siguiente:    Tabla: Eventos que se pueden implementar en plugins de View  Nombre Evento  beforeRender 

Descripción  Ocurre  antes  de  empezar  el  proceso  de  visualización  de  las  vistas  asociadas  a  la  petición.  El  evento  recibe  la  instancia  de  ControllerResponse actual 

afterRender 

Ocurre  después  de  terminar  el  proceso  de  visualización  de  las  vistas asociadas a la presentación. 

 

25.9 API del Componente View 25.9.1 Jerarquia de renderización  static function string getContent(boolean $returnContent=false)  El llamado a este método le indica al componente View donde debe insertar el siguiente nivel  de la jerarquía de renderización. Si se pasa true en $returnContent devuelve el contenido del  buffer de salida hasta el momento.    static function void setRenderLevel(int $level)   Establece hasta que nivel de renderización se debe generar la presentación. Consulte la tabla  de niveles de presentación para obtener más información sobre el uso de este método.  25.9.2 Administrar presentación  static function void handleViewRender(Controller $controller)   Este método actua como el administrador de presentación predeterminado recibiendo como  parámetro  el  último  controlador  enrutado.  No  debería  ser  invocado  directamente  por  el  desarrollador ya que es llamado por el contenedor de aplicaciones.     static function void handleViewExceptions(Exception $e, Controller $controller)   Este  método  actua  como  el  administrador  de  presentación  predeterminado  cuando  no  se 


LouderTechnology/Kumbia Enterprise Framework – Manual de Referencia 

 

                                                                293 

captura  una  excepción  recibiendo  como  parámetro  el  último  controlador  enrutado.  No  debería ser invocado directamente por el desarrollador ya que es llamado por el contenedor  de aplicaciones cuando esta situación ocurre.     25.9.3 Visualizar vistas programacionalmente  static function void renderPartial(string $_partialView,  string $_partialValue='')   Permite  visualizar  una  vista  parcial  dentro  de  otra  vista.  El  segundo  parámetro  permite  transferir un valor desde la vista donde se invoca este método al interior de la vista parcial.   La vista parcial es ubicada en el directorio de vistas del controlador actual.    El método se utiliza de la siguiente forma:  <?php View::renderPartial(“nombreVista”, “Un Valor”) ?>

  En el archivo _nombreVista.phtml el valor transferido puede ser usado así:  <?php echo $nombreVista; ?>

  Si se requiere visualizar una vista parcial en otro controlador diferente al actual debe usarse:  <?php echo View::renderPartial(“nombreVista”, “controller: nombreControlador”); ?>