Español

HTML5 reset

Se trata de todo un paquete completo de archivos html, css y javascript con los cuales iniciar un proyecto desarrollado en HTML 5, compatible con Internet Explorer.Tiene muy buena pinta para empezar y no parece muy difícil de integrar en CakePHP.HTML5 Reset

Hacer tests de un método que crea un objeto que debemos simular (una alternativa a los partial Mock)

Supongamos que tenemos un método en una clase y que dentro de ese método se crea un objeto, el cual debemos simular para hacer el test. Algo así como esto:public function getFeed($url) {    $Socket = ClassRegistry::init('HttpSocket');    $Socket->reset(false);    $response = $Socket->get($url);    ...}

Simulando objetos con Mock Objects

Entre otras facilidades, la Test Suite de CakePHP utiliza la capacidad de SimpleTest de crear Mock Objects, o lo que es lo mismo, simulaciones de objetos que no hacen nada, pero que reproducen todos los métodos de los objetos simulados y que puedes programar para que tengan un comportamiento determinado que te interese.Esto es útil cuando quieres probar una clase que usa otras clases. En lugar de emplear las clases reales, utilizamos sus simulaciones. De este modo, nos evitamos las posibles interferencias de su funcionamiento sobre los resultados del test y garantizamos que sólo probamos el código de la clase en cuestión.Un ejemplo sencillo típico sería tratar de probar un Controller que usa un Component.Lo que tenemos que hacer son básicamente dos cosas:

  • Crear una simulación o Mock del Component
  • Asociar el Component simulado al Controller

BeforeRedirect

Un recordatorio por si usas el callback beforeRedirect en un Component: recuerda que debe devolver una URL, de otro modo los resultados pueden ser absolutamente desquiciantes.

Model->displayField en plugins

Al menos en CakePHP 1.3 (me imagino que puede pasar en 1.2) la propiedad displayField de los modelos puede tener un comportamiento un poco errático si te has olvidado de especificar correctamente las relaciones con modelos que están en plugins.En otras palabras. Si tienes un modelo relacionado con otro que se encuentra en un plugin, no olvides indicarlo "prefijándolo" con el nombre del plugin. Por ejemplo, si tienes un modelo que tiene una relación hasMany con el modelo Item que está en el plugin Contents debes expresarlo así:var $hasMany = array('Item' => array('className' => 'Contents.Item'));Si no lo haces, métodos como find('list') no serán capaces de usar correctamente la propiedad displayField del modelo relacionado.

Yo, la autorización y Cake (II): Entendiendo los sistemas de autorización

Sistemas de permisos "a la Unix"Una forma de afrontar al problema de la autorización es partir del sistema de permisos Unix. En este sistema, cada recurso tiene asociados varios permisos (lectura, escritura, ejecución) que se asignan a un usuario, a un grupo y al resto del mundo. Es bastante fácil empaquetar estos permisos en un sólo atributos y chequearlos usando operaciones binarias (and, or...).Puedes incorporar esta información de permisos en la propia tabla del modelo que quieres controlar, o normalizarlo y guardar la información en una tabla de permisos, lo que te permite hacerlo más flexible.La dificultad puede estar en cómo relacionar esta información de permisos con las acciones de los controladores de tu sistema. Una opción es a través de un mapeado acción-tipo de permiso, o bien creando un permiso específico para cada acción.

Yo, la autorización y Cake (I)

Una de las bases de una aplicación corporativa es un buen sistema de autentificación y de autorización. Este último es uno de los aspectos que me resulta más complicado resolver al desarrollar una aplicación. Hasta ahora mis soluciones en este campo han sido funcionales, pero difíciles de mantener y de escalar.Conceptualmente son procesos bastante sencillos de entender:Autentificación es el proceso por el que el sistema determina que un usuario es quien dice ser, o por lo menos que presenta las credenciales correctas. Un sistema de autentificación básicamente toma las credenciales aportadas (habitualmente un usuario y contraseña) y las contrasta con alguna fuente de referencia, que puede ser una tabla de una base de datos, un servidor de autentificación, etc.

Forzar la actualización de un registro de un Model

Mi vida como desarrollador es un poco caótica, ya que no me dedico a tiempo completo y últimamente otras demandas me quitan montones de tiempo y toneladas de concentración. Por eso, a pesar de llevar trabajando con CakePHP desde hace ya un par de años, tengo dudas en conceptos básicos o tengo que empezar desde cero con algunos proyectos ya que "pierdo el hilo".Un ejemplo de estos conceptos básicos que tenía dudosos es lo que pasa cuando creas registros en un modelo y cuando manipulas sus id.Cuando haces un Model->save() sin indicar un id para el modelo, se crea un nuevo registro. Por tanto, para actualizar un registro existente debes indicar un id.Esto lo puedes hacer tanto en la propiedad Model->id, como en el array de datos que pases a create o a save. Por ejemplo:array('Model' => array('id' => 12));Además, se siguen unas cuantas reglas más:

Pregunta abierta: ¿conoces alternativas a getID3?

Funciona bien y td eso, ¿pero conoces alguna alternativa para extraer metadatos de archivos multimedia?

Obtener la extensión de un archivo

Esta línea nos proporciona la extensión de un archivo conociendo su nombre o su path$extension = substr($filename, strrpos($filename, '.') + 1);

Valores por defecto para parámetros de un Element

Esta es una técnica sencilla que nos servirá para definir valores por defecto (y también documentarlos) para los parámetros que pasamos a un element.Como sabrás, los parámetros pasados a los element, están disponibles como variables en el mismo. La idea es definir un array asociativo con los valores por defecto y luego extraer las claves a variables.El quid de la cuestión es usar el parámetro EXTR_SKIP para que extract no extraiga del array los parámetros que han sido pasados. Es decir, en caso de conflicto, el Element debe quedarse con el parámetro pasado y si no ha sido pasado, toma el valor por defecto.Esto nos evita una serie de if(isset(...)), y hace muy legible el código y muy fácil documentar los parámetros del Element.$defaults = array(    'channel' => false,    'count' => 1,    'mode' => 'public',    'type' => 'full'    );  

CakePHP, MAMP y el socket de Mysql (actualizado)

ActualizaciónComo comenta Nigeon, basta con poner el path al socket en el parámetro port de la configuración de la conexión.Al que, por cierto, viene documentado en el manual.'connect' => 'mysql_connect','host' => 'localhost','port' => '/Applications/MAMP/tmp/mysql/mysql.sock',Dejo la entrada anterior porque puede ser útil en algunos casos.En una entrada anterior ya he comentado el tema de como ajustar las cosas para que CakePHP pueda comunicarse con Mysql. Para ello, hay que crear un enlace simbólico del socket /Applications/MAMP/tmp/mysql/mysql.sock en el lugar adecuado, que en el artículo señalado era /var/mysql/mysql.sock.

Validación: comparar con otro campo

En la validación de datos de formularios, muchas veces nos gustaría comprobar que dos campos coinciden, como pueden ser los casos de contraseñas, emails, etc.Para ello, en los formularios ponemos un segundo campo similar al que queremos comparar a fin de que el usuario introduzca dos veces el valor. Así, por ejemplo, tendríamos el campo User.password y el campo User.confirm_password, o bien User.emal y User.confirm_email.Yo recomendaría que en el formulario usaras los campos de confirmación como si fuesen campos del modelo. A la hora de guardar (save), CakePHP los va a ignorar pues no están en el schema del modelo y nos resulta bastante fácil manipularlos.No hay una regla de validación por defecto para esto, así que me he escrito mi propio método match para hacerlo.La comparación de contraseñas

Micro-dispatching in CakePHP 1.3

One of the cool features CakePHP 1.3 introduced is the ability to have custom route classes to parse URLs. Mark Story has written a very good article showing the potential for this enhancement.
To be honest, I haven’t tried it until today, when I came up with a very crazy idea after reading this hilarious post [...]

Lögica de negocio y lógica de aplicación

Cuando se habla del patrón Modelo-Vista-Controlador a veces no queda claro cuál es el papel del Controlador.Veamos:El Modelo lleva la lógica de negocio, que básicamente es la representación de las entidades que la aplicación ha de manejar y sus relaciones. Así en una aplicación de gestión de bibliotecas tendremos modelos para los libros, socios, préstamos, etc., así como métodos para prestar libros, devolverlos, y otros muchos.La Vista lleva la lógica de presentación y cada vista sabe mostrar unos datos que recibe y nada más.¿Y el controlador? Solemos decir que el controlador pide datos al modelo y se los pasa a la vista, pero eso creo que no deja suficientemente claro su papel.

Una idea para no redirigir tanto

Estaba escribiendo el esqueleto de unas acciones para gestionar el registro y confirmación de usuarios cuando me di cuenta de que hay situaciones en las que puede ser buena idea usar Controller->render() para dirigir al usuario a páginas que le informen sobre el resultado de sus acciones, en lugar de Controller->redirect() para hacer lo mismo.Por ejemplo:function register() { if ($this->data) { if ($this->User->register($this->data)) { $this->render('registration_ok'); } }}

Paginación y find personalizado. Un problema y ¿una solución?

Uno de los temas más habituales en los foros relacionados con CakePHP es el de la paginación de resultados. Surgen bastantes problemas cuando queremos ir un poco más allá de lo básico.En mi caso, el problema que más fastidiado me tiene es la paginación con métodos find personalizados, ya que, por lo que he podido descubrir, cuando CakePHP calcula el número de registros totales no construye la petición correcta y, con frecuencia, ésta falla y o bien no devuelve la cuenta correcta o incluso el SQL falla porque no se incluyen las columnas adecuadas.Esto es especialmente molesto cuando usas los métodos personalizados para hacer búsquedas a través de tablas relacionadas, por ejemplo, forzando los join necesarios, o añadiendo claves 'contain'.Paginación y find personalizadosEs fácil paginar con métodos find personalizados. Basta indicarlo en la variable del controlador paginate, bajo la clave del modelo:

Join con relaciones muchos a muchos

En la entrada anterior dejaba pendiente el tema de las relaciones muchos a muchos, aunque es probable que ya te hayas dado cuenta de como combinar tablas relacionadas de esta manera.Este tipo de relaciones requiere una tabla intermedia (o join table) que nos permita asociar las parejas de registros. Las tablas izquierda y derecha se relacionan de uno a muchos con la join table. Por lo tanto tendremos que "unir" la tabla izquierda con la join table y ésta con la tabla derecha.Etiquetar librosVamos a seguir con nuestro ejemplo y vamos a añadir una tabla tags a nuestro sistema para poder etiquetar cada libro con diversas palabras clave descriptoras. Por ejemplo, así:CREATE TABLE `tags` (  `id` int(11) NOT NULL auto_increment,  `tag` varchar(200) default NULL,  PRIMARY KEY  (`id`))Y vamos a introducir algunos valores, para que la tabla quede así:

Uniendo tablas con Join

En la entrada anterior dejé caer que explicaría un poco más a fondo los tipos de JOIN que se pueden hacer y qué diferencias hay entre ellos.Una buena manera de entenderlo es practicando, por lo que es recomendable que crees algunas tablas sencillas y lances las querys como forma de ver en vivo los resultados de cada tipo de JOIN y así entender para qué casos te pueden servir. No hace falta que tengan muchos campos, ni muchos registros.Un buen ejemplo puede ser una tabla de libros y una de autores, como las que siguen (en este ejemplo estoy usando MySQL): CREATE TABLE `books` (`id` int(11) NOT NULL auto_increment,`title` varchar(200) default NULL,`author_id` int(11) default NULL,PRIMARY KEY (`id`))CREATE TABLE `authors` (`id` int(11) NOT NULL auto_increment,`author` varchar(200) default NULL,

Joins en CakePHP: buscar con registros relacionados

Voy a intentar escribir varias entradas sobre el uso de JOIN con CakePHP, porque me parece un tema interesante, demandado, y relativamente poco conocido en el framework.Que es eso de JOINEn SQL la cláusula JOIN nos permite hacer búsquedas en varias tablas de la base de datos que estén relacionadas entre sí.Así, por ejemplo, si tenemos el típico caso de Post hasAndBelongsToMany Tag, usando JOINS podemos hacer una búsqueda de aquellos Post que hayan sido etiquetados con una Tag determinada.Para entender el concepto de JOIN puedes imaginarte que tomas cada registro de la tabla "principal" y le añades los campos del registro relacionado en otra tabla, quedándote una especie de "supertabla", y en ella puedes realizar búsquedas sobre cualquier campo de ambas tablas.

Syndicate content