Múltiples conexiones a bases de datos

En cakephp existen gran cantidad de posibilidades desconocidas que, en algunos casos, pueden resultar útiles.
Una de ellas es la posibilidad de declarar más de una conexión a base de datos, pudiendo elegir en cada momento cuál de ellas deseamos utilizar.

Puede resultar muy cómodo para organizar nuestros proyectos, para acceder a diferentes servidores de bases de datos o acceder a diferentes gestores de bases de datos.

El proceso es sencillo, en primer lugar añadiremos al archivo database.php situado en /app/config/ una nueva configuración de base de datos.
Podremos copiar la configuración por defecto, llamada default, y cambiarle el nombre.
El fichero database.php quedará así

class DATABASE_CONFIG {

	var $default = array(
		'driver' => 'mysql',
		'persistent' => false,
		'host' => 'localhost',
		'login' => 'user',
		'password' => 'password',
		'database' => 'database',
		'prefix' => '',
	);

	var $nueva_conexion = array(
		'driver' => 'mysql',
		'persistent' => false,
		'host' => 'localhost',
		'login' => 'user',
		'password' => 'password',
		'database' => 'database_2',
		'prefix' => '',
	);

	var $test = array(
		'driver' => 'mysql',
		'persistent' => false,
		'host' => 'localhost',
		'login' => 'user',
		'password' => 'password',
		'database' => 'test_database_name',
		'prefix' => '',
	);
}

Con esto habremos declarado otra conexión a la base de datos llamada nueva_conexion.
Una de las opciones que tiene la configuración de la base de datos, es la de utilizar un prefijo, es decir, que todas las tablas de la configuración de la base de datos comiencen con una palabra, también puede ser utilizado para organizar las bases de datos.

Para utilizar la configuración de la base de datos que hemos creado, tendremos que añadir en el modelo desde donde queremos acceder a esas tablas la siguiente línea:

	var $useDbConfig ='nueva_conexion';

A partir de este momento, cada vez que accedamos a este modelo, cakephp utilizará las tablas existentes en la base de datos de esa conexión.

Localización e internacionalización

Nota: Esta modo de realizar la internacionalización en nuestras páginas es válida hasta la versión de Cakephp 1.2 RC2, próximamente escribiremos un artículo en el que se resuelva el problema para versiones posteriores.

Vamos a ver cómo realizar la internacionalización de nuestra página web. Nos fijaremos únicamente en hacer nuestra página web en varios idiomas, sin atender a otras cuestiones como puede ser el formateo de las monedas o los números.

Los pasos a realizar son los siguientes:

1. Crear tantos ficheros de idiomas como queramos tener. Estos ficheros los meteremos en la carpeta /app/locale, creando una carpeta por cada idioma que tendrá por nombre el código de 3 letras del lenguaje (ISO 639-2, lista de lenguajes). Y dentro de esta carpeta, crearemos otro subdirectorio llamado LC_MESSAGES y por último, en éste, un fichero default.po.

Ejemplo para castellano y gallego:

Jerarquia

Este fichero debe estar codificado en ISO-8859-1 y los strings no pueden tener más de 1014 caracteres. Se asocian las claves con los valores de la siguiente manera:

msgid “clave”
msgstr “valor”

Teniendo en cuenta que cada clave debe ser única.

2. Modificar el app_controller para establecer el lenguaje elegido.

uses('L10n');
class AppController extends Controller
{
   function beforeFilter() {
      $this->L10n = new L10n();
      $languages = array('es', 'gl');
      $paramLang = $this->params['plugin'];
      $lang = $this->Session->check('lang') ? $this->Session->read('lang'): 'es';
      if (isset($paramLang) && in_array($paramLang, $languages)) {
         $lang = $paramLang;
      }

      $this->Session->write('lang', $lang);
      $this->L10n->get($lang);
      Configure::write('Config.language', $lang);
   }
}

Lo que hacemos aquí es recoger el valor de la url, si existe, y si no obtenerlo de la sesión.

Recordar que el parámetro plugin de la url es el que se establece justo antes del nombre del controlador, por lo tanto las urls serán de la forma:

www.hospedaxes.com/es/controlador/accion/…
www.hospedaxes.com/gl/controlador/accion/…

3. Para usar los valores establecidos en los ficheros .po, tenemos que utilizar la función __(), al que se le pasa la clave y un booleano opcional [false si queremos que se comporte como un echo (valor por defecto), true para que devuelva únicamente una cadena].

Nueva versión de cakephp 1.2

Cada vez estamos más cerca de la versión final del framework al que dedicamos este blog.

Desde la página de cakephp se puede descargar la versión 1.2.0.7296 rc2, nueva candidata que hace que el lanzamiento de la versión definitiva se encuentre más cercano.

Como en cada actualización, corrección de bugs y pequeñas mejoras que se pueden ver en el siguiente enlace.

Actualizar el contenido de un select con ajax.

En esta entrada vamos a explicar como asociar dos selects mediante ajax y al modificar el elemento seleccionado en uno de ellos cambie el contenido del otro.

Podemos ver el ejemplo de funcionamiento aquí.

Un ejemplo muy claro para esta situación sería dos selects, uno con provincias y el otro con localidades, lo que queremos es que al cambiar de provincia varíe la lista de localidades y muestre las que están en la provincia seleccionada.

Lo haremos utilizando el ajaxHelper, para que no sea necesario la recarga de la página y quede más atractivo.

Lo primero que haremos será definir los modelos de provincias ,localidades y un tercer modelo en el que usaremos los selects, por ejemplo podría ser un modelo de cliente, en el que al insertar un nuevo cliente tendríamos que elegir la provincia y localidad a la que pertenece.

Modelos

Modelo de provincia.

/app/models/provincia.php

class Provincia extends AppModel
{
    var $name = 'Provincia';
}

Modelo de localidad.

/app/models/localidade.php

class Localidade extends AppModel
{
    var $name = 'localidade';
}

Modelo de cliente.

/app/models/cliente.php

class Cliente extends AppModel
{
    var $name = 'Cliente';
}

Controladores

Después de esto tendremos que definir los controladores.

Controlador de localidad.

/app/controllers/localidades_controller.php

class LocalidadesController extends AppController
{
	var $name = 'Localidades';
}

Controlador de provincia.

/app/controllers/provincias_controller.php

class ProvinciasController extends AppController
{
	var $name = 'Provincias';
}

Y por últino el controlador de clientes que será el que implementará la funcionalidad.

Controlador de cliente.

/app/controllers/clientes_controller.php

class ClientesController extends AppController
{
	var $name = 'Clientes';
	var $helpers = array('Ajax');
	var $uses = array('Cliente','Provincia','Localidade');

	function insertar()
	{
		$listadoProvincias = $this->Provincia->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC'));
		$this->set('provincias', Set::combine($listadoProvincias, "{n}.Provincia.id","{n}.Provincia.nombre"));
		$primera_provincia = $this->Provincia->find(null,null,'nombre ASC');
		$listadoLocalidades = $this->Localidade->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC','conditions'=>'Localidade.provincia_id='.$primera_provincia['Provincia']['id']));
		$this->set('localidades', Set::combine($listadoLocalidades, "{n}.Localidade.id","{n}.Localidade.nombre"));

		// RESTO DE LA FUNCIONALIDAD DE INSERCIÓN DE CLIENTES
	}

	function update_select()
	{
		if (!empty($this->data['Localidade']['provincia_id']))
		{
			$provincia_id = $this->data['Localidade']['provincia_id'];
			$localidades = $this->Localidade->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC','conditions'=>array('provincia_id'=>$provincia_id)));
		}
		else
		{
			$localidades = $this->Localidade->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC'));
		}
		$this->set('options', Set::combine($localidades, "{n}.Localidade.id","{n}.Localidade.nombre"));
		$this->render('/elements/update_select', 'ajax');
	}
}

Por un lado tenemos la función insertar, que será una función genérica de inserción de clientes. La parte que a nosotros nos interesa es en la que se inicializan las variables que después utilizaremos en los selects, estas deberán ser arrays en los que cada elemento tenda un identificador y su valor, para que el select pueda utilizarlos en la vista.

En la versión 1.1 de cakephp, esto se podía hacer mediante la función generateList del modelo, función que se ha eliminado en la 1.2.
Por ello ahora es necesario hacerlo en dos pasos, por un lado realizar la búsqueda con un findAll y después utilizar la función combine de la clase Set que genera un array con la estructura deseada, que será el que le pasemos a la vista.

$listadoProvincias = $this->Provincia->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC'));
$this->set('provincias', Set::combine($listadoProvincias, "{n}.Provincia.id","{n}.Provincia.nombre"));

La segunda función update_select, es a la que llamará el ajax para actualizar el listado de localidades a partir de un identificador de provincia.

Como se puede ver en el código, la función coge el identificador de provincia del select y envía a la vista los arrays actualizados de provincias y localidades.

Vistas

Localidades y provincias no tendrán vistas asociadas, ya que no hay ninguna operación en el controlador.

En clientes tendremos que crear la vista para la operación insertar del controlador, esta podría ser algo como esto:

/app/views/clientes/insertar.ctp

echo $form->create('Inscripcione',array('action'=>'insertar'));
echo $form->inputs(array('legend'=>'Actualizar Provincias',
		'Localidade.provincia_id' => array('label'=> 'Provincia','showEmpty'=>'false','id'=>'provincias'),
		'Alumno.localidade_id' => array('label'=> 'Localidad','showEmpty'=>'false','id'=>'localidades'),
			));
echo $form->end();

$options = array('url' => 'update_select','update' => 'localidades');
echo $ajax->observeField('provincias',$options);

La vista será muy sencilla, un formulario con dos selects, uno de localidades y otro de provincias y una llamada al ajaxHelper en la que se indica que cada vez que se modifique el valor del select provincias, se llame a la función update_select y actualice el select de localidades.

Este select se actualizará con los valores devueltos por la vista de update_select, que lo único que hace es imprimir todos los nombres de localidades devueltos por la función del controlador.

/app/views/elements/update_select.ctp
if(!empty($options)) {
  foreach($options as $k => $v) {
    echo "<option value='$k'>$v</option>";
  }
 }

En este enlace se puede ver un ejemplo de funcionamiento.

Nueva versión de cakephp disponible.

Desde hace unos días está disponible en la página de cakephp, una nueva versión, la 1.2.0.7125 RC1, de este framework de desarrollo escrito en php, del que hablamos en nuestro blog y en el que desarrollamos la gran mayoría de las webs que se crean en nuestra empresa.

Lo importante de esta noticia es que el framework ha abandonado la categoría de beta, pasando a ser una versión candidata, cada vez está más cerca el lanzamiento de la versión final.

En esta versión se eliminan gran cantidad de métodos deprecados y se corrigen multitud de errores.

A partir de ahora siempre que hablemos de funcionalidades del cakephp 1.2 nos referiremos a la versión RC1.

Sindicación de noticias

Hoy vamos a explicar cómo hacer en CakePHP 1.2 un canal de sindicación de noticias o sindicación web. Es una funcionalidad que utilizamos con mucha frecuencia en nuestros diseños web y para la que Cake nos ofrece un buen soporte.

Cake nos proporciona un helper, RSSHelper, que nos permite hacer en muy pocas líneas de código un RSS.

Lo primero que tenemos que hacer es una función en el controlador o bien utilizar la misma función index del controlador que queramos sindicar:

PHP:
  1. class NoticiasController extends AppController
  2. {
  3. var $helpers = array('Rss', 'Xml');
  4. var $components = array('RequestHandler');
  5.  
  6. function index()
  7. {
  8. if ($this->RequestHandler->prefers('rss'))
  9. {
  10. $this->layout = 'default';
  11. $this->set('channel',array(
  12. 'title' => 'Portal web - Noticias',
  13. 'description' => 'Sindicación de noticias de nuestro portal web',
  14. 'link' => 'http://url_al_portal.com'));
  15. $this->set('data', $this->Noticia->findAll(null, null, array('Noticia.fecha DESC'), 10));
  16. }
  17. else
  18. {
  19. // Si no es un RSS, ponemos aquí cómo queremos que se comporte el index
  20. $this->redirect("otra_funcion");
  21. }
  22. }
  23. }

Vemos que tuvimos que importar algunos helpers y componentes. Establecemos aquí ya el título, descripción y enlace del canal, y los datos que queremos sindicar.

En la capa de la vista, tenemos que definir el layout default.ctp, que estará en la carpeta views/layout/rss y será de una manera tan simple como la siguiente:

PHP:
  1. <?php
  2. echo $content_for_layout;
  3. ?>

Y también definir la vista en si, que estará en nuestro caso en la carpeta views/noticias/rss y se llamará index.ctp, y que tendrá la forma:

PHP:
  1. function convertirRSS($data)
  2. {
  3. return array(
  4. 'title' => $data['Noticia']['titulo'],
  5. 'link'  => array('action' => 'ver', $data['Noticia']['url'], $data['Noticia']['id']),
  6. 'description' => $data['Noticia']['texto'],
  7. 'pubDate' => $data['Noticia']['fecha']
  8. );
  9. }
  10. echo $xml->header(array('version'=>'1.0', 'encoding'=>'utf-8'));
  11. $document = $rss->channel(array(), $channel, $rss->items($data, 'convertirRSS'));
  12. echo $rss->document(array('version'=>'2.0'), $document);
  13. ?>

Ya por último, lo único que tenemos que hacer es meter en la cabecera de nuestro código html, el link, para que nos ponga en la barra del navegador el enlace a nuestro rss:

PHP:
  1. <link rel="alternate" type="application/rss+xml" title="Nuestro portal web RSS Feed" href="/noticias/index.rss" />

Y, como vemos, esta url no sigue el formato estándar de las urls que utiliza Cake, por lo que tenemos que definir en el archivo config/routes.php una regla para ello:

PHP:
  1. Router::parseExtensions();

Con esto ya tendríamos definido el RSS para nuestra aplicación.

Separación de funcionalidades (similar a fachadas)

CakePHP 1.2 nos proporciona un soporte con un significado similar al de las fachadas, que nos permite:

  • Separar los distintos tipos de funcionalidades en los controladores: podemos separar, por ejemplo, las funciones que corresponden al administrador, del resto de las funciones, simplemente iniciando el nombre de dicha función con la cadena "admin_".
  • Separar por urls los distintos apartados: por ejemplo, para acceder a una función de un controlador que sea "admin_listar", tendremos que escribir la url: admin/controlador/listar. De esta forma sabemos en todo momento en qué parte de nuestro proyecto nos movemos.
  • Como consecuencia y para que nuestro proyecto mucho más organizado, separaremos también las vistas en función de si estamos en la sección del administrador o en las otras secciones.
  • Esto nos permitirá también realizar un tratamiento personalizado de cada sección: por ejemplo, en el beforeFilter del AppController le podemos introducir un filtro de login.

Veamos cómo realizar la configuración de todo lo comentado. En el archivo app/config/routes.php, escribimos:

PHP:
  1. Configure::write('Routing.admin', 'admin');

En el controlador:

PHP:
  1. class UsuariosController extends AppController
  2. {
  3. var $layout = 'usuarios';
  4. function admin_listar(){ //Comandos}
  5. function listar(){ //Comandos }
  6. }

De esta manera podemos cambiar el layout en función de dónde nos encontremos y tenerlas estructuradas en distintas carpetas. Para ello, en el archivo cake/libs/controller/app_controller.php escribimos:

PHP:
  1. class AppController extends Controller
  2. {
  3. function beforeFilter()
  4. {
  5. if (isset($this->params['action']) && strstr($this->params['action'], 'admin_'))
  6. {
  7. $this->layout = 'admin/'.$this->layout;
  8. }
  9. // O bien, comparando una variable que se almacena en <em>$this->data</em>:
  10. if (isset($this->params['admin']) && $this->params['admin']==1)
  11. {
  12. $this->layout = 'admin/'.$this->layout;
  13. }
  14. // La última posibilidad es comparando la variable <em>prefix</em> de <em>$this->data</em>:
  15. if (isset($this->params['prefix'])&& $this->params['prefix']=='admin')
  16. {
  17. $this->layout = 'admin/'.$this->layout;
  18. }
  19. }
  20. }

Podríamos configurar tantas secciones como queramos simplemente añadiendo más líneas en el archivo routes.php, obteniendo un código mucho más limpio y legible.

Paginación con ordenación por columna y buscador

Hoy vamos a hablar de cómo introducir en nuestro diseño web la paginación en CakePHP 1.2, introduciéndole un buscador. Utilizaremos una tabla para visualizar los datos, añadiéndole la opción de ordenarla pinchando en las cabeceras.

Utilizaremos para ello el Paginator Helper que viene implementado en esta nueva versión y que, como veremos, hace muchísimo más fácil esta tarea.

Empezamos con el controlador. Lo primero que tenemos que hacer es añadir dos variables:

PHP:
  1. var $paginate = array('limit' =>10, 'page' =>1, 'order'=>array('Modelo.campo ASC'))
  2. var $components = array('RequestHandler');

como vemos en las opciones del array, le especificamos en la variable limit el número de elementos por página, en page la página en la que empezamos y en order la ordenación inicial. El componente RequestHandler no sería necesario si no introducimos el buscador.

El siguiente paso es crear una función de la manera siguiente:

PHP:
  1. function admin_listar()
  2. {
  3. if(!$this->RequestHandler->isAjax())
  4. {
  5. $this->set('llamada_ajax', 0);
  6. $this->Session->del($this->name.'.search');
  7. }if (isset($this->data['Modelo']['cadena_busqueda']))
  8. {
  9. $str = trim($this->data['Modelo']['cadena_busqueda']);
  10. } elseif (!empty($this->data['Modelo']['cadena_busqueda']) &&
  11. $this->data['Modelo']['cadena_busqueda'] == '')
  12. {
  13. $this->Session->del($this->name.'.search');
  14. } elseif ($this->Session->check($this->name.'.search')) {
  15. $str = $this->Session->read($this->name.'.search')
  16. }  $condicion = '';
  17. if (isset($str))
  18. {
  19. $condicion = "Modelo.campo LIKE \"%$str%\"";   // Podemos poner la condición que nos interese
  20. $this->Session->write($this->name.'.search', $str);
  21. }
  22. $this->set('resultado', $this->paginate('Modelo', $condicion));
  23.  
  24. if($this->RequestHandler->isAjax())
  25. {
  26. $this->set('llamada_ajax', 1);
  27. $this->render('admin_listar', 'ajax');
  28. }
  29. }

Utilizaremos la sesión para guardar la cadena de búsqueda y no perderla cuando pulsemos en las cabeceras para la ordenación.

Y la vista sería ("admin_listar.ctp"):

PHP:
  1. if (!$llamada_ajax)
  2. {
  3. echo $form->create('Modelo',array('action'=>'', 'id'=>'buscar'));
  4. echo $form->input('Modelo.cadena_busqueda', array('id'=>'cadena_busqueda', 'label'=>'Búsqueda'))$options = array('frequency'=>'2', 'url' => 'listar', 'update' => 'listado',
  5. 'loading' => 'Element.show(\'LoadingDiv\')',
  6. 'complete' => 'Element.hide(\'LoadingDiv\')')
  7. echo $ajax->submit('Buscar',$options);
  8.  
  9. echo $form->end();
  10.  
  11. echo $html->div(null, $html-&gt;image('ajax-loader.gif'), array('id'=>'LoadingDiv', 'style'=>'display: none;'))
  12. }
  13.  
  14. $paginator->options( array('update'=>'listado',
  15. 'url'=>array('controller'=>'nombre_controlador', 'action'=>'listar') ,
  16. 'indicator' => 'LoadingDiv'));
  17.  
  18. if (count($resultado)>0)
  19. {
  20. echo "Página ".$paginator->counter(array('separator'=>' de '));
  21.  
  22. echo $html-&gt;table('listado');
  23. echo "<thead class='cabecera'>";
  24. echo "<tr><th>".$paginator->sort('Título cabecera', 'campo_modelo')."</th></tr>";
  25. echo "</thead>";
  26. foreach ($resultado as $elemento)
  27. {
  28. echo $html->tableCells( array ($elemento['Modelo']['campo_modelo']) );
  29. }
  30. echo $html->tableEnd();
  31.  
  32. echo $paginator->prev('Página anterior');
  33. echo $paginator->numbers(array('separator'=>' - '));
  34. echo $paginator->next('Página siguiente');
  35. } else {
  36. echo $html->para('clase','No se han encontrado resultados.');
  37. }

Vemos aquí que es el propio Paginator Helper el que, con una simple llamada a la función sort, ya se encarga de hacer la ordenación de la columna alternando en cada click entre ascendente y descendente.

La función counter nos devuelve una cadena con la página en la que nos encontramos y el número total de páginas, en nuestro caso introducimos la cadena ' de ', entre ellas.

Y por último, las tres últimas funciones utilizadas, prev, numbers y next, nos muestran los enlaces a la página previa, a cada una de las páginas y a la página siguiente, respectivamente.

CakePHP 1.2 nos proporciona muchas más posibilidades y muchas otras opciones. Podemos obtener más información en la especificación de CakePHP 1.2 del Paginator Helper. Así como en la Bakery, en la que tenemos un artículo sobre la paginación básica y otro sobre la avanzada.

Validación en CakePHP 1.2

A pesar de estar todavía en la versión beta, hemos optado por hacer el desarrollo web con la versión 1.2 de CakePHP, entre otras cosas por el potente sistema de validación que posee. Explicaremos cómo realizar la validación de un formulario y los distintos tipos de validación que existen, aunque si no te gustan los que vienen ya implementados, CakePHP da soporte para poder crear tus propias reglas de validación.

Al tema... Lo primero que hay que hacer es crear las reglas de validación en el modelo, lo haremos en la variable $validate, introduciendo ya aquí los mensajes de error para no tener que preocuparnos en cada formulario de especificarlos.
En el siguiente ejemplo vemos varias reglas sencillas para un modelo que sólo tiene dos campos que queramos validar: nombre y password.

var $validate = array(
   'nombre' => array(
      'valid' => array('rule' => array('alphaNumeric'),
                       'message' => 'Nombre debe ser alfanumérico'),
      'required' => array('rule' => array('minLength', '1'),
                            'message' => 'Nombre obligatorio')),
   'password'   => array(
      'required' => array('rule' => array('minLength', '1'),
                            'message' => 'Password obligatorio'),
      'length' => array('rule' => array('minLength', 6),
                            'message' => 'Longitud mínima del password de 6 caracteres')));

Vemos ya en este ejemplo algunas de las distintas reglas que existen en CakePHP 1.2, pero tenemos muchas más. Son las siguientes:

  • alphaNumeric: campos alfanuméricos.
  • between: aunque pueda parecer que valida que un número esté en un rango, lo que en realidad hace es comprobar que la longitud de una cadena esté en un rango:
    'rule' => array('between', minVal, maxVal)
  • blank: valida que el campo esté en blanco o contenga sólo espacios o tabulaciones.
  • cc: valida que una tarjeta de crédito sea correcta:
    'rule' => array('cc', array('tipo')), donde tipo puede ser: visa, maestro...
  • comparison: para comparar valores numéricos:
    'rule' => array('comparison', 'tipo', val), donde tipo puede ser: "is greater”,“is less”, “greater or equal”, “less or equal”, “is less”, “equal to”, y “not equal”;y sus equivalentes >, <, >= ...
  • custom: sirve para definir tus propias expresiones regulares:
    'rule' => array('custom', 'expresion_regular')
  • date: valida una fecha, recibe como parámetro el formato:
    'rule' => array('date', 'ymd')
  • decimal: valida un número decimal recibiendo el número de decimales que tiene que tener:
    'rule' => array('decimal', num_decimales)
  • email: sirve para verificar que una dirección de email tiene el formato adecuado.
  • equalTo: para comprobar que un campo sea exactamente igual a otro que se le pasa como parámetro:
    'rule' => array('equalTo', val)
  • extension: sirve para validar que el campo tiene la extensión o extensiones que se le indican como parámetro:
    'rule' => array('extension', array('gif', 'jpeg', 'png', 'jpg'))
  • file: permite comprobar que es un fichero. Todavía no está implementada.
  • ip: valida que el campo es una IPv4.
  • minLength y maxLength: sirve para validar que el campo tiene la longitud mínima y máxima, respectivamente, que se le pasa como parámetro:
    'rule' => array('minLength', val)  o  'rule' => array('maxLength', val)

  • money: valida que sea una cantidad monetaria. Se le pasa como parámetro 'left' o 'right', en función de dónde le digamos que está el símbolo monetario.
  • multiple: para validar selects múltiples. Aún no está implementado.
  • numeric: se comporta igual que la función de PHP is_numeric().
  • phone: para validar un número de teléfono, se le pasa una expresión regular o null y el código del país. De momento sólo está implementado para Estados Unidos, para el resto se debe poner la expresión regular.
    'rule' => array('phone', null, 'us')
  • postal: igual que el anterior en sintaxis pero para validar códigos postales. En este caso, está implementado para Estado Unidos(us), Reino Unido(uk), Canada(ca), Italia(it) y Alemania (de).
  • ssn: lo mismo que los dos anteriores pero para números de la seguridad social. Implementado para Estados Unidos(us), Dinamarca(dk) y Holanda(nl).
  • url: para validar urls.

Y ya sólo queda hacer el formulario que incluya validación. Podemos hacer uso para ello de una nueva función que viene implementada en el Form Helper, inputs:

echo $form->inputs(array('legend'=>'Datos personales',
                  'nombre' => array('label'=>'Nombre *', 'size'=>32),
                  'password' => array('label'=>'Password *', 'type'=>'password')));

De esta forma ya se encarga CakePHP de mostrar los errores automáticamente, al hacer el save (si no le especificamos que no nos lo haga) o bien al llamar explícitamente a la función validates del modelo. Si optas por esta segunda opción, la forma de hacer la llamada cambió con la nueva versión de Cake, y ahora se realiza de la manera siguiente:

$this->Modelo->set($this->data);
$this->Modelo->validates();

Yo he optado, en el caso de no poder usar la función inputs, por no usar ninguna de las funciones del Form Helper select, dateTime, radio... y utilizar para todo la función input, a la que se le pueden pasar atributos tipo type, label, before, options, error... (para más información ver la línea 491 del Form Helper). De esta forma me muestra automáticamente los errores.

Por supuesto existe muchas más información en la propia API de CakePHP 1.2, aunque una información menos densa la encontramos en la Bakery, interesante sobre todo por los comentarios finales de la gente, que aportan muchas ideas.

Empezando…

Primer comentario de este blog dedicado al framework de desarrollo de aplicaciones web en el lenguaje php.

El objetivo de este blog es ante todo compartir nuestro conocimiento de cakePhp, con ello intentar apoyar y ayudar a todo el que lo utilice, aportando la experiencia que hemos ido adquiriendo en los últimos meses, en la que hemos desarrollado proyectos lo suficientemente serios y profesionales para encontrarnos con problemas que nos parecen que pueden ser habituales.

Invitamos a todo el que se asome por el blog que no dude en expresar sus dudas que intentaremos solventar.

[ bbPress synchronization by bobrik ]