Monthly Archives: June 2009

Concatenar o separar segmentos de documentos PDF

Cómo concatenar archivos PDF ?

$ pdftk (<archivos a concatenar>)+ cat output <archivo resultante>

$ pdftk a.pdf b.pdf c.pdf cat output all.pdf

Cómo extraer un segmento de un archivo PDF ?

$ pdftk (NOMBRE=archivo.pdf)+ cat (NOMBRE{RangoInicial}-{RangoFinal})+ output <archivo resultante>

$ pdftk A=one.pdf B=two.pdf cat A1-5 B10-20 output section.pdf

Enlaces.

"Entrepreneurs can change the world"

Enlaces.

Los componentes en Yii

Introducción.

  • Son objetos escritos basados en una especificación.
  • Heredan de la clase CComponent.
  • Es posible acceder y modificar sus propiedades así como lanzar y manejar sus eventos.

Propiedades.

  • Son atributos públicos de lectura y escritura.
  • Pueden definirse de dos maneras.
    • Declarando un atributo público en el componente.
      • En este caso el nombre de la propiedad es sensible a mayúsculas.
    • Definiendo los métodos setter y getter correspondientes.
      • En este caso el nombre de la propiedad no es sensible a mayúsculas.
      • Para implementar la propiedad imageType es necesario implementar los siguientes métodos.
        public function getImageType()
        {
            return $this -> _imageType;
        }
        public function setImageType($value)
        {
            $this -> _imageType = $value;
        }
      • Este método es mas flexible ya que permite definir una lógica del negocio que condicione el acceso a las propiedades.
      • De igual manera es posible implementar propiedades de sólo lectura (sin setter) o de sólo escritura (sin getter).

Eventos.

  • Los eventos del componente son propiedades que toman referencias a métodos (event handlers) como valores.
  • Estos métodos son invocados automáticamente cuando sucede el evento asociado.
  • Un evento del componente es definido por la implementación de un método cuyo nombre empieza por on y termina con el nombre del evento asociado (no es sensible a mayúsculas).
    • Para el evento click -> el método deberá ser entonces: onClicked.
      public function onClicked($event)
      {
          // ...
      }
  • Los eventos ($event) son instancias de la clase CEvent.
  • Los manejadores de evento se asginan de la siguiente manera.
    $component -> onClicked = $callback;
    • $callback deberá ser una referencia válida en PHP según las siguientes opciones.
      • El nombre de una función global.
      • Un método de una clase, para este caso deberá ser de la forma array($objeto, 'nombreMétodo').
  • Varios manejadores de evento pueden asociarse a un mismo evento, estos se ejecutarán en el orden en que fueron creados.
  • Un manejador de eventos puede evitar que se invoquen los demás manejadores de eventos al realizar la siguiente modificación.
    $event -> handled = true;

Comportamientos.

  • Un comportamiento es un objeto cuyos métodos pueden ser transferidos a los componentes que se le agreguen.
  • Es decir, reune funcionalidades en lugar de realizar una especialización como lo hace la herencia convencional.
  • Es posible agregar múltiples comportamientos lo que se asemeja a la herencia múltiple.
  • Son análogos a los mixins que incluyen otros lenguajes orientados a objetos (como Ruby) o que implementan otros frameworks (como Symfony).
  • Existen varias maneras de implementar un comportamiento.
    • Como una clase que implementa a la interfaz IBehavior.
    • Como una clase que hereda de CBehavior.
    • Si va a ser agregado a un modelo puede ser una clase que herede de CModelBehavior o CActiveRecordBehavior según corresponda.
  • Para utilizar un comportamiento primero debe ser agregado a un componente.
    $comportamiento -> attach($nombre, $componente);
    $componente -> métodoDelComportamiento();
  • Los comportamientos pueden ser activados y desactivados según se desee en cada componente.
    $componente -> enableBehavior($nombre);
    $componente -> disableBehavior($nombre);
  • Si dos o mas comportamientos agregados a un componente entran en conflicto porque tienen métodos con igual nombre, la precedencia la tendrá el comportamiento que haya sido agregado primero.

Enlaces.

Los módulos en Yii

Introducción.

  • Son unidades autocontenidas de software.
  • Tienen sus propios modelos, vistas, controladores y demás componentes de soporte.
  • Se asemejan a una aplicación pero no pueden ser desplegados individualmente, deben residir como parte de  una aplicación.
  • Los usuarios acceeden a los controladores de los módulos de la misma forma como se acceden los controladores convencionales.
  • Son útiles para dividir el desarrollo y mantenimiento de aplicaciones muy grandes en módulos independientes.
  • Facilitan la reutilización de código a alto nivel.
  • Se utilizan para implementar funcionalidades como autenticación, manejo de usuarios, manejo de comentarios, etc.

Estructura.

  • Cada módulo tiene una clase principal que hereda de CWebModule.
  • El nombre de la clase se determina de la siguiente manera: ucfirst(IdentificadorMódulo) . 'Module'.
    • Ejemplo, la clase del módulo gallery debe llamarse GalleryModule.
  • Esta clase se utiliza para almacenar información y características que son comúnes a todo el módulo.
    • CWebModule::params almacena los parámetros del módulo.
    • CWebModule:: components comparte componentes de aplicación a nivel del módulo.

Creación.

Utilizando yiic.

yiic permite crear fácilmente un esqueleto básico del módulo para empezar a trabajar sobre él.

$ cd WebRoot/MiAplicacion
$ protected/yiic shell

Yii Interactive Tool v1.0
Please type 'help' for help.  Type 'exito' to quit.

>> module gallery

Uso.

  • Copie el directorio del módulo en el directorio modules de la aplicación.
  • Declare el módulo (con su identificador) en la propiedad modules de la configuración de la aplicación de la siguiente manera.
    return array (
        // ...
        'modules' => array('gallery', /* ... */),
        // ...
    );
  • Es posible especificar valores iniciales para las propiedades del módulo de la siguiente manera.
    return array (
        // ...
        'modules' => array(
            'gallery' => array(
                'fileType' => 'png',
                'rows' => 10,
                'cols' => 3
            ),
            /* ... */
         ),
        // ...
    );
  • La instancia del módulo puede ser accedida a través de la propiedad module del controlador acrivo.
    $rows = Yii::app() -> controller -> module -> rows;
  • Los módulos se acceden con la ruta módulo/controlador/acción.
    • Para el ejemplo, gallery/image/add corresponderá entonces con el URL http://www.servidor.com/index.php?r=gallery/image/add.
  • Un módulo puede contener a su vez a otros módulos los cuales pueden ser accedidos de manera similar: móduloPadre/móduloHijo/controlador/acción.

Enlaces.

Plantillas para documentos XHTML y otros recursos web

En el sitio de WebStandards se puede encontrar un listado con las plantillas base para los documentos XHTML 1.0/1.1 y HTML4.

Además de estos documentos encontré otros recursos interesantes relacionados con el desarrollo web.

http://www.webstandards.org/learn/tutorials/accessible-forms/

Remover estilos CSS por defecto

Introducción.

El primer paso para desarrollar cualquier interfaz de usuario basada en HTML debería ser el remover los estilos introducidos por defecto por el navegador web, con esto podríamos estar [un poco mas] seguros que los estilos implementados van a tener un igual comportamiento entre los diferentes tipos de navegadores web.

Hacer esto es muy fácil, sólo es necesario incluír el siguiente estilo provisto por Yahoo! al inicio de la hoja de estilos principal (la primera que se carga).

/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.7.0
*/
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}body{text-align:center;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main,.yui-g .yui-u .yui-g{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:14.8461em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-g .yui-u{width:48.1%;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;}.yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#hd:after,#bd:after,#ft:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#hd,#bd,#ft,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;}

Otra forma de hacerlo es simplemente hacer una referencia a esta hoja de estilos desde los servidores de Yahoo!.

<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.7.0/build/reset-fonts-grids/reset-fonts-grids.css">

Enlaces.

Agregar soporte de MP3 en Ubuntu 9.04

Introducción.

Por defecto, la instalación de Ubuntu no incluye el soporte para el formato MP3 así que sólo es posible codificar archivos en formato OGG que es mejor pero la gran mayoría de los reproductores [físicos] de audio aún no lo soportan.  Por suerte la instalación del soporte para el formato es muy sencilla.

Instalación.

$ sudo aptitude install gstreamer0.10-plugins-ugly-multiverse

Extracción y codificación de MP3.

Iniciar Applications > Sound & Video > Rhythmbox Music Player.

Configurar a Rhythmbox para que se utilice a MP3 como formato por defecto.

Seleccionar el menú Edit > Preferences y seleccione la etiqueta Music.

En el campo Preferred format elija la opción CD Quality, MP3 (.mp3 type).

MusicPreferences

Si desea modificar la calidad del archivo MP3 generado realice los siguientes pasos adicionales.  Por defecto se generan con un bitrate de 128 Kbps.

Presione el botón Edit para modificar el formato seleccionado: MP3.

Seleccione el perfil CD Quality, MP3 o cree uno nuevo.  Presione el botón Edit del diálogo.

Modifique el campo GStreamer pipeline con la siguiente cadena.

audio/x-raw-int,rate=44100,channels=2 ! lame name=enc mode=0 vbr-quality=6 bitrate=192 ! id3v2mux

Edite los valores de las variables rate, channels y bitrate según sus preferencias.

Seleccione las canciones que se desean codificar.

Presione el botón de extracción: ExtractButton

Los archivos de las canciones codificadas se almacenan en la ubicación especificada en las preferencias bajo Library Location > Music files are placed in, cuya ruta es por defecto: ~/Music.

Enlaces.

Creación de contenido traducido en Drupal 6

Introducción.

Este procedimiento permite mantener diferentes tipos de contenido en Drupal 6 traducido en los diferentes idiomas que soporta el Portal.  En esta versión, a diferencia de la versión 5, el módulo que permite esto se incluye en la distribución de core.

Configuración.

Activar el módulo de traducción de contenido.

  • Acceder a http://www.servidor.com/?q=admin/build/modules.
  • Activar el módulo Content translation encontrado en la sección opcional de core.

Asignar los permisos de traducción.

  • Acceder a http://www.servidor.com/?q=admin/user/permissions.
  • Asignar el permiso Translation > traducir contenido a los roles que estarán encargados de realizar la traducción de los contenidos.

Determinar los idiomas soportados por el portal.

  • Acceder a http://www.servidor.com/?q=admin/settings/language.
  • Agregar los idiomas necesarios además del idioma predefinido para el sitio.

Determinar cuales tipos de contenido tendrán traducción.

  • Acceder a http://www.servidor.com/?q=admin/content/types.
  • Elegir los tipos que tendrán contenido traducido.
  • Editar los tipos.
  • En la sección Workflow settings > Multilingual support seleccionar la casilla de verificación Habilitado con traducción.
  • Guardar.

En mi caso personal elegí los siguientes tipos de contenido para tener traducción: Evento, Noticia, Página, Página de grupo, Tema de foro y Enlaces web.

Activar el bloque para cambio de idiomas (opcional).

  • Acceder a http://www.servidor.com/?q=admin/build/block.
  • Activar y ubicar donde se desee al bloque Language switcher.

Utilización.

Después de realizado este el procedimiento de configuración, los tipos de contenido configurados para tal fin tendrán un nuevo campo llamado Idioma el cual permitirá elegir entre Lenguaje neutral y Español (o el idioma predeterminado elgido anteriormente).

Para acceder a la traducción del contenido es necesario editar el contenido inicial y seleccionar a Español como idioma.  Al guardar este contenido aparece una nueva opción llamada Traducción (Translate) a través de la cual es posible seleccionar cualquiera de los demás idiomas configurados para crear la traducción del contenido inicial.

Cuando se consulta un nodo este muestra con enlaces cuales son las traducciones que se encuentran disponibles y permite acceder a ellas, de igual manera es posible modificar el idioma del sitio utilizando el bloque de cambio de idioma.

Enlaces.

Las vistas en Yii

Introducción.

  • Son archivos PHP convencionales.
  • Pueden incluír elementos de interfaz de usuario basados en Yii.
  • Se recomienda que las vistas accedan a la información de los modelos pero que no los modifiquen.
  • Deben permanecer lo mas simples posibles, lógicas complejas deberían llevarse hasta el controlador.
  • El nombre del archivo donde se almacena la vista corresponde con el identificador junto con la extensión .php.
    • La vista edit se almacenará en el archivo edit.php.
  • Los archivos de las vistas se almacenan bajo la ruta protected/views/<Identificador del controlador>.
  • Desde la vista es posible acceder a los atributos del controlador a través del objeto $this.
  • Para procesar una vista se debe invocar el método CController::render(<Identificador de vista>).
  • Es posible pasar explícitamente información desde el controlador a la vista en el momento de su generación.
    $this -> render('edit', array (
        'variable1' => $valor1,
        'variable2' => $valor2
    ));
    • En la vista edit se podrá acceder a $variable1 y $variable2 como variables convencionales.

Layouts (diseños).

  • El layout permite especificar el diseño común y constante de la interfaz de usuario.
  • Evita la necesidad de agregar elementos comúnes (archivos javascript y css, título, subtítulo, menú izquierdo, pies, etc) a todas las páginas en cada una de ellas.
  • El layout aplica a todo el sitio web y se aplica automáticamente al invocar el método render.
  • Para generar una vista sin el layout es necesario utilizar el método renderPartial.
  • El layout utilizado por defecto se encuentra en views/layouts/main.php.
    • Es posible modificar esto alterando CWebApplication::layout para toda la aplicación o CController::layout para todas las acciones del controlador.
  • En el layout se debe incluír la variable $content para especificar la ubicación en la que se agregará el contenido de la vista específica al controlador/acción ejecutado (parte no constante de la interfaz de usuario).

Widgets.

  • Los widgets son componentes predefinidos para la presentación de la interfaz de usuario.
  • Generalmente agregan una funcionalidad gráfica compleja, específica y autocontenida.
  • Heredan de CWidget.
  • Su forma de invocarlos depende de si tienen o no contenido en su cuerpo.
    • Sin contenido en su cuerpo.
      <? php $this -> widget('ruta.a.la.ClaseWidget'); ?>
    • Con contenido en su cuerpo.
      <? php $this -> beginWidget('ruta.a.la.ClaseWidget'); ?>
      ... contenido del cuerpo del Widget ...
      <? php $this -> endWidget(); ?>
  • Es posible definir valores iniciales para los atributos del Widget durante su invocación con widget o beginWidget.
    $this -> widget('CMaskedTextField', array (
        'mask' => '99/99/9999'
    ));

Creación de nuevos Widgets.

  • El nuevo widget debe heredar de CWidget e implementar los métodos init y run.
    class NuevoWidget extends CWidget
    {
        public function init()
        {
            // Invocado por CController::beginWidget().
        }
        public function run()
        {
            // Invocado por CController::endWidget().
        }
    }
  • Tienen sus propias vistas y se ubican por defecto en el directorio views bajo el directorio que contiene la clase del widget.
  • Estas vistas se generan invocando CWidget::render().

Vistas del sistema.

  • Estas vistas se utilizan para mostrar errores del sistema o información de registro.
  • Las excepciones de HTTP (CHTTPException) se despliegan con las vistas errorXXX donde XXX es el código del error HTTP generado.
  • Las vistas por defecto provistas por Yii se ubican en framework/views y pueden personalizarse definiéndolas en protected/views/system.

Enlaces.

Los Controladores en Yii

Introducción.

Estructura de una aplicación Yii.

Estructura de una aplicación Yii.

  • El Modelo/Vista/Controlador es un patrón de diseño.
  • Su utilidad radica en separar la lógica del negocio de la interfaz de usuario.
  • El modelo representa la información y las reglas del negocio asociadas a ella.
  • La vista representa a los componentes de la interfaz de usuario y todo lo relacionado con su presentación.
  • El controlador recibe la solicitud del usuario (controlador, acción e información) e intermedia entre la vista y los modelos para elaborar la respuesta.
  • El controlador frontal (index.php) recibe directamente la solicitud del usuario, es el único que interactúa directamente con él, y se encarga de enrrutar la solicitud al controlador y acción apropiados.
  • Consultar secuencia de procesamiento de un requerimiento.

El controlador.

  • Hereda de CController.
  • Su identificador es de la forma ruta/a/xyz (ejemplo: user).
  • Corresponde con el archivo protected/controllers/ruta/a/XyzController.php (ejemplo: protected/controllers/UserController.php).
  • Si la aplicación utiliza módulos, su identificador se incluye en la ruta del identificador del controlador.
  • Incluye una o mas acciones.
  • Incluye cero o mas filtros para sus acciones.
  • La instanciación de un controlador puede realizarse de la siguientes maneras según el contexto.
    • Si se define CWebApplication::catchAllRequest, todas las solicitudes serán redireccionadas al controlador indicado ignorándose el solicitado.  Es útil para poner el sitio fuera de línea.
    • Si el identificador del controlador solicitado se encuentra en CWebApplication::controllerMap se utilizará el controlador asociado en la conversión.
    • Se busca el controlador en la ubicación específica según su ruta.
    • Si el controlador no existe se lanza una CHttpException 404.

Las acciones.

  • Definen (implementan) que hacer ante el requerimiento específico de un usuario.
  • Si no se especifica una acción se utiliza la acción por defecto (index) que puede configurarse con CController::defaultAction.
  • Pueden implementarse de dos maneras.
    • Como un método del controlador cuyo nombre deberá ser actionIdentificador.
      • La acción add corresponderá con el método actionAdd.
    • Como una nueva clase que hereda de CAction cuyo nombre deberá ser IdentificadorAction e implementa el método run.
      • La acción add en este caso corresponderá con una instancia de la clase AddAction.
      • Para que este caso funcione se debe sobreescribir el método actions del controlador estableciendo la relación entre identificador de la acción y clase que la implementa.
        ...
        public function actions()
        {
            return array(
                'add' => 'application.controllers.post.AddAction'
            );
        }
        ...
      • Se recomienda almacenar las acciones bajo el alias de application.controllers.<identificador del controlador> que hace referencia a la ruta física protected/controllers/<identificador del controlador>.

Los filtros.

  • Permiten manipular el flujo de ejecución de la acción solicitada.
  • Se ejecutan antes y después de la acción solicitada permitiendo filtrar si esta es efectivamente invocada o no.
  • Útiles para realizar procesos previos de preparación (estadísticas, verificación de autenticación/autorización, etc.) y de limpieza (liberación de recursos, verificaciones finales, etc.).
  • Una acción puede tener cero o mas filtros.
  • Los filtros se ejecutan en el mismo orden en que fueron definidos.
  • Un filtro puede decidir si los demás filtros o la acción no deben ser ejecutados.
  • Al igual que las acciones, los filtros pueden implementarse de dos maneras.
    • Como un método del controlador cuyo nombre deberá ser filterIdentificador.
      • El filtro editPassword corresponderá con el método filterEditPassword.
        public function filterEditPassword($filterChain)
        {
            // $filterChain -> run() continúa la ejecución de los filtros.
        }
    • Como una nueva clase que hereda de CFilter cuyo nombre deberá ser IdentificadorFilter.
      • Se deben implementar los métodos preFilter y postFilter que se ejecutarán antes y después de invocarse la acción.
        class CheckAuthFilter extends CFilter
        {
            protected function preFilter($filterChain)
            {
                // Ejecutado antes de invocar la acción.
                return true;   // false si se debe abortar la ejecución de la acción.
            }
            protected function postFilter($filterChain)
            {
                // Ejecutado después de terminar la invocación de la acción.
            }
        }
  • Es necesario sobreescribir el método CController::filters() para asociar los filtros a las acciones.
    ...
    public function filters()
    {
        return array(
            'editPassword + edit, create',                               // filtro basado en un método
            array (
                 'application.filters.CheckAuthFilter - logout, index',  // filtro basado en una clase
                 'tipo' => 'usuario'
            )
        );
    }
    ...
    • El filtro editPassword está implementado por un método del controlador mientras que el filtro checkAuth está basado en una clase que hereda de CFilter.
    • El alias application.filters hace referencia a la ruta física protected/filters.
    • Es posible especificar valores para los atributos del filtro utilizando un arreglo en la definición de los filters tal y como se le asigna un valor al atributo tipo del filtro checkAuth.
    • Los operadores + y – modifican el alcance de la relación entre filtros y acciones.
      • +: el filtro se aplica a las acciones especificadas.  (incluye).
        • El filtro editPassword se aplica a las acciones edit y create únicamente.
      • -: el filtro se aplica a todas las acciones exceptuando las especificadas.  (excluye).
        • El filtro checkAuth se aplica a todas las acciones menos a logout e index.

Enlaces.

    protected function preFilter($filterChain)
    {
        // Ejecutado antes de invocar la acción.
        return true;   // false si se debe abortar la ejecución de la acción.
    }