Español

CakePHP, MAMP y el socket de Mysql

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.Hace poco, tras varias actualizaciones los shells empezaron a "pedir" un socket en /tmp/mysql.sock, por lo que creé un nuevo enlace, pero olvidé la opción -s y creé un enlace duro en lugar de simbólico.Pues bien, que sepas que los enlaces duros no valen para el caso y los shells no eran capaces de conectar a la base de datos. Ha sido cambiarlo a enlace simbólico y volver a funcionar todo como es debido.

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.

Una buena guía para sumergirse en HTML5

El libro de Mark Pilgrim Dive into HTML5 tiene una pinta estupenda para empezar a familiarizarse con el nuevo (e inacabado) estándar, y empezar a usarlo en la medida en que algunas de sus novedades ya están soportadas por los navegadores modernos.Además, el autor hace varias recomendaciones prácticas acerca de cómo utilizar los nuevos elementos y características, dado a la vez soporte a navegadores que aún no las contemplan. Por ejemplo: cómo puedes empezar a utilizar ya los nuevos types del los input en los formularios, o cómo utilizar el elemento video sin dejar de lago el viejo explorer.

Diseño web con HTML y CSS

El título suena a perogrullada, pero en 24 ways han publicado un gran artículo de Meagan Fisher acerca del proceso de diseño de webs usando código y relegando la costumbre de crear los bocetos mediante un editor de imágenes.Lo cierto es que nunca fui capaz de diseñar una web mediante un editor de imágenes pues lo mío siempre ha sido lápiz y papel, aunque es una práctica muy común abrir el Photoshop o el programa equivalente y trabajar a partir de ahí.El artículo hace hincapié en las capacidades de HTML y CSS 3, cuyas propiedades más avanzadas empiezan a estar soportadas por los navegadores más importantes, ya sean de la rama Mozilla (Firefox, Flock, Camino), de la Webkit (Safari, Chrome) o de Opera. Así que quitando ese que tú sabes, un navegador moderno permite jugar con propiedades como las sombras, opacidad, tipografía e incluso animaciones.

Programar en inglés

Hace tiempo alguien preguntó en el grupo google de cakephp en español acerca de la costumbre de programar en inglés y hace un par de días volví a caer en este post de CakeBaker sobre el tema.Bien, primero habría que explicar lo que entiendo por "programar en inglés". Para empezar, PHP, como tantos otros lenguajes de programación, es una especie de dialecto del inglés. Por programar en inglés, quiero decir usar este idioma para nombres de variables, clases, funciones, comentarios e incluso para los textos iniciales de la aplicación.¿Y qué razones tendríamos para hacer esto?Hay algunas bastante prácticas, como las siguientes:

Poblar variables de clase a partir de un array

Este código nos permite poblar de valores las propiedades de una clase a partir de un array asociativo cuyas claves tengan el mismo nombre. Es algo así como un extract.Puede ser útil al pasar parámetros en forma de array asociativo, una práctica habitual en CakePHP.<?phpclass test { var $prueba; var $control; function __construct() { $array = array( 'prueba' => 'Hola',

Comprobar que un array no es asociativo

Se me ha ocurrido esta función para comprobar que un array no sea asociativo:function isList($array) { if (!is_array($array) || count($array) == 0) { return false; } return array_sum(array_keys($array)) > 0;}?>Devuelve true si el array es numérico, y false si no es un array o es asociativo.En CakePHP puede ser interesante usarlo cuando queremos diferenciar entre los datos devueltos por un read y un find('all'). En el segundo caso, el array es numérico (una clave numérica por cada registro del modelo).

Querys CakePHP con operaciones bitwise

Otro de esos títulos "sólo para iniciados"...Hoy me he encontrado con un problemilla curioso. Necesitaba definir una condición para un find en la que hay una operación bitwise en la base de datos. En concreto, un & de una máscara binaria contra un campo del modelo.Bueno, pues la forma en que he conseguido que funcione es algo así:...array('conditions' => array('12 & Rule.precedence'):...Que debe dar un WHERE más o menos así:WHERE 12 & `Rule`.`precedence`Es decir, primero pongo el valor de la máscara, luego la operación binaria y luego el campo.Si pongo primero el campo, CakePHP se empeña en hacer no sé qué y no aparece la comparación en el WHERE.

Crear un sitio CakePHP sin conexion a una base de datos

CakePHP por default asume que usaremos una base de datos para nuestra aplicación, esto trae un problema cuando intentamos crear un sitio web sin base de datos.

Encontré la solución, creando una conexión falsa que devuelva siempre TRUE. Esto lo hacemos de la siguiente manera:

- Primero creamos un datasource en app/models/datasources/dbo/dbo_fake_dbo_source.php con el siguiente contenido:


<?php
class DboFakeDboSource extends DboSource
{
function connect()
{
$this->connected = true;
return true;
}

function disconnect()
{
$this->connected = false;
return true;
}

}

Obtener el prefijo de una acción (o dividir una cadena)

Esta es una de esas cosas que siempre se me olvidan, así que voy a anotarla.He aquí una operación típica para romper un string en dos partes, sabiendo que están separadas por un carácter concreto, en este caso el socorrido "underscore".list($part1, $part2) = explode('_', $string);Aplicándolo a CakePHP, vamos a imaginar que tenemos el nombre de una acción y queremos saber si tiene prefijo y cuál es. Así que en algún sitio de nuestro Controller (probablemente en el beforeFilter) hacemos:$action = $this->params['action'];list($prefix, $actionName) = explode('_', $action);Sencillo, ¿verdad?Pero, ¿qué pasa si $action no tiene prefijo y por tanto no hay separador en la cadena?Bueno, pues en ese caso, $prefix toma el valor de la cadena y $actionName queda vacío, por lo que necesitaríamos el siguiente código para controlar la situación:

Bootstrap para plugins

El archivo APP/config/bootstrap.php de una aplicación CakePHP nos sirve como lugar donde cargar funciones, cargar configuraciones, iniciar variables o definir constantes globales para nuestra aplicación.Estos días me encontré con la necesidad de disponer de una funcionalidad parecida para los plugins. La idea es interesante, se trata de poder disponer, entre otras cosas, de ajustes de configuración y constantes definidas en los plugins pero que sean accesibles desde otras partes de la aplicación.La cuestión es cómo hacer ese "bootstrapping" para plugins de forma "automágica".A mí se me ha ocurrido usar este fragmento de código en el bootstrap de la aplicación<?phpApp::import('Core', 'Folder');$folder =& new Folder();$folder->cd(APP . 'plugins');$files = $folder->findRecursive('bootstrap\.php');foreach ($files as $file) {

Nota mental: Controller necesita $name

Pues sí, los controladores necesitan tener la propiedad $name, al menos para funcionar en los test, de otro modo se rompe todo. Incluso con PHP 5.

Cosas que hago mal

Dejando aparte errores de sintaxis y algunos fallos lógicos, más o menos normales, he estado pensando que hago algunas cosas mal en mi "estrategia" (por decir algo) de desarrollo.Una de las principales es que tiendo a centrarme demasiado en lo periférico, con lo cual avanzo relativamente poco en mis tareas, aunque teclee innumerables líneas de código.Por ejemplo, llevo unos meses trabajando (un poco irregularmente) en el desarrollo de un proyecto que, en principio, será un CMS y la base para una aplicación de Intranet para el colegio en el que trabajo.

Syndicate content