borrame.com - Colección particular de recortes de código y documentación para programación web

Canales RSS

Lo más fresco

  1. Enlaces sobre desarrollo web Modificado
  2. Cadena aleatoria en PHP Modificado
  3. Recortar texto Nuevo

Sugerencias del chef

Lo más visitado

  1. Canales RSS
  2. Formato condicional según el día de la semana
  3. Enlaces sobre desarrollo web
  4. Recortar texto
  5. Convertir de minutos a horas
Compartir esta página

Recetario básico para CakePHP/2

Estos son algunos trucos básicos que me suelen venir bien cuando me toca trabajar con la cada vez más añeja versión 2 de CakePHP.

MySQL

Fijar un modo SQL a nivel de aplicación ayuda a prevenir errores sutiles (o no tan sutiles) al subir a producción —cuando son más difíciles de solucionar— y fijar un valor estricto desde el principio ahorra no pocos quebraderos de cabeza:

<?php // app/Config/database.php class DATABASE_CONFIG { public $default = array( 'datasource' => 'Database/Mysql', 'persistent' => false, 'host' => 'localhost', 'login' => 'user', 'password' => 'password', 'database' => 'database_name', 'prefix' => '', 'encoding' => 'utf8mb4', 'settings' => array( '@@SESSION.sql_mode' => "'TRADITIONAL,NO_AUTO_VALUE_ON_ZERO'", ), ); }

Alternativamente, al trabajar sobre código ajeno puede ser necesario relajar el modo para que la aplicación no explote:

'@@SESSION.sql_mode' => "''"

Esquema

Los callbacks de CakeSchema no permiten algo tan básico como ejecutar código al principio y al final del todo y el constructor es casi inútil por las mil formas en que se instancia la clase. Al final me he acabado ingeniando lo que muestro a continuación:

<?php // app/Config/Schema/schema.php class AppSchema extends CakeSchema { public function before($event = array()) { static $inicializado = false; if (!$inicializado) { $this->_tareasIniciales(); $inicializado = true; } return true; } public function after($event = array()) { static $tablas_creadas = array(); if( isset($event['create']) ){ $tablas_creadas[] = $event['create']; // ¿Ya se han creado todas las tablas? if (count($tablas_creadas)===count($this->tables)) { $this->_tareasFinales(); } } } }

DebugKit

DebugKit guarda en la caché de CakePHP un historial con la información de depuración de las últimas páginas vistas. En algunos casos en que dicha información es enorme (a mí me ha pasado al generar CSV) la caché alcanza tal tamaño que ralentiza progresivamente la aplicación hasta que llega un momento en que PHP no dispone de suficiente memoria para deserializar la caché. Si tal cosa sucediere, se puede reducir la longitud del historial:

<?php // app/Controller/AppController.php class AppController extends Controller { public $components = array( 'DebugKit.Toolbar' => array( 'history' => 2, ), ); }

… o deshabilitarlo por completo:

<?php // app/Controller/AppController.php class AppController extends Controller { public $components = array( 'DebugKit.Toolbar' => array( 'panels' => array( 'history' => false, ), ), ); }

SQL

Creo que no he visto prácticamente nunca hacer una consulta SQL con LIKE texto dinámico que se preocupe de los comodines. CakePHP ni siquiera dispone de las funcionalidad así que siempre me tengo que escribir la mía:

<?php // app/Model/AppModel.php class AppModel extends Model { /** * Escapa los caracteres que son comodines en expresiones LIKE * * @param string $text * @param string $caracter_escape * @return string * * @version 2018-11-20 * @link https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like */ protected function escapeLike($text, $caracter_escape = '\\') { if (mb_strlen($caracter_escape) !== 1) { throw new InvalidArgumentException('El carácter de escape debe ser un único carácter'); } return strtr($text, array( '%' => $caracter_escape . '%', '_' => $caracter_escape . '_', $caracter_escape => $caracter_escape . $caracter_escape, )); } }

… que se puede usar tal que así (¡sólo es un ejemplo!):

<?php // app/Model/Cliente.php class Cliente extends AppModel { public function busquedaPorNombre(array $datos) { return array( "{$this->alias}.nombre LIKE ?" => array('%' . $this->escapeLike($datos['nombre']) . '%'), ); } }

Para la gente que prefiere siempre la alternativa más larga y redundante:

<?php // app/Model/Cliente.php class Cliente extends AppModel { public function busquedaPorNombre(array $datos) { return array( "{$this->alias}.nombre LIKE ? ESCAPE ?" => array( '%' . $this->escapeLike($datos['nombre'], '|') . '%', '|' ), ); } }

Historial

v2018-11-20
Esquema: faltaba poner $inicializado a true.
SQL: hacer realmente opcional la cláusula ESCAPE.
v2017-03-28
Primera versión.

Esta página ha sido impresa el miércoles 12 de agosto de 2026 (13:51:23 +0200) desde https://borrame.com/recortes/php/cakephp2.html. La última vez que miré contenía HTML válido con CSS fresquito y si tiene flatas de ortografía ha sido sin querer.

Lorem ipsum dolor sit amet.

© 2005-2026 by Álvaro González (alvaro.es) • Burgos (España) • borrame.com