jueves, 24 de diciembre de 2009

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.

<?php

class test {

var $prueba;
var $control;

function __construct() {

$array = array(
'prueba' => 'Hola',
'control' => 'amigos'
);
foreach ($array as $key => $value) {
$this->{$key} = $value;
}
}
}

$test = new test();
print_r($test);
?>

martes, 22 de diciembre de 2009

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).

Si los datos vienen de un read (o un find('first')) podemos convertirlos en array numérico con un simple $datos = array($datos), y luego procesar con un foreach. La ventaja es que el mismo código nos vale luego para ambos casos.

Yo voy a usar esta idea para un uploadable behavior en el que estoy trabajando.

viernes, 11 de diciembre de 2009

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.

martes, 8 de diciembre de 2009

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:

$action = $this->params['action'];
list($prefix, $actionName) = explode('_', $action);
if(!$actionName) {
    $actionName = $prefix;
   $prefix = '';
}

viernes, 4 de diciembre de 2009

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

<?php
App::import('Core', 'Folder');
$folder =& new Folder();
$folder->cd(APP . 'plugins');
$files = $folder->findRecursive('bootstrap\.php');
foreach ($files as $file) {
include_once($file);
}
?>

La explicación es bastante sencilla. La clase Folder nos permite apuntar a un directorio, en este caso plugins, y obtener todos los archivos cuyo nombre se ajuste a un patrón grep, cuyos paths se obtienen en un array. Luego no tenemos más que hacer include de cada uno de los archivos y ya tenemos nuestros bootstrapping.