Debugging cakephp sql queries

Para los que desarrollamos con cakephp alugna vez hemos tenido la necesidad de volcar todas las consultas SQL que se ejecutan en cada petición de nuestra aplicación. Una manera rápida y efectiva de volcar y poder trazar todas las queries es editar el fichero ‘/lib/Cake/Model/Datasource/DboSource.php’ y localizar la function execute() que es la función por la que pasan todas la llamadas SQL.
La herencia de objetos que incluye DboSource, permite llamar al logger de una manera muy sencilla:
[php]
$this->log( $query );
[/php]

De forma que la función quedará así:

[php]
/**
* Queries the database with given SQL statement, and obtains some metadata about the result
* (rows affected, timing, any errors, number of rows in resultset). The query is also logged.
* If Configure::read(‘debug’) is set, the log is shown all the time, else it is only shown on errors.
*
* ### Options
*
* – log – Whether or not the query should be logged to the memory log.
*
* @param string $sql SQL statement
* @param array $options The options for executing the query.
* @param array $params values to be bound to the query.
* @return mixed Resource or object representing the result set, or false on failure
*/
public function execute($sql, $options = array(), $params = array()) {
$options += array(‘log’ => $this->fullDebug);

$this->log( $sql );

$t = microtime(true);
$this->_result = $this->_execute($sql, $params);

if ($options[‘log’]) {
$this->took = round((microtime(true) – $t) * 1000, 0);
$this->numRows = $this->affected = $this->lastAffected();
$this->logQuery($sql, $params);
}

return $this->_result;
}
[/php]

Tengo que recordar que estamos modificando directamente el core de cakephp y que no es la manera adecuada, pero para un apuro es muy rápido y eficaz y claro está que en producción esto no lo podemos poner 😀

Si fuera necesario hacer un override aquí tenemos la documentación para llevarlo a cabo
http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#overriding-classes-in-cakephp

UPDATE:
Si estás tratando de tracear la query final y estás usando ‘prepared staments‘, olvidate. Este tipo de consultas se pasan directamente al motor sql y las procesa automáticamente, con lo que te quedas igual.
Para loggear las consultas en mysql échale un vistazo a la documentación de MySQL
http://dev.mysql.com/doc/refman/5.1/en/query-log.html

cakephp testing models

Un error tonto pero tonto tonto, es crear en app/Console/Command/TestShell.php por que sobreescribe el funcionamiento de lib/Cake/Console/Command/TestShell.php que es el script que se encarga de lanzar la integración de phpunit.

Lo que sucede es no ejecuta nada, ni parámetros ni help, ni verbose ni nada, pero sí funciona vía web, me he tirado media hora traceando hasta que me he dado cuenta ! 😀

… cosas de la vida

custom error message en cakephp

Usar las convenciones en cake es muy útil y rápido, pero como toda regla, hay ocasiones en que no se cumple.

No siempre podemos usar las convenciones para crear nuestro código, en este caso hablo de la validación de formularios con elementos no convencionales.

En mi caso he tenido que crear un formulario para la validación de fechas, de forma que el elemento input del formulario no se crea automáticamente con un datetime si no con otro tipo de selectores.

Es todo genial menos a la hora de pintar los errores, para ello he buceado un poco en el código de FormHelper.php para obtener este pequeño fragmento de código  para usar en CustomHelper que nos pintará un elemento de error con la descripción

 

[php]

<?php

App::uses(‘HtmlHelper’, ‘View/Helper’);

class CustomHelper extends HtmlHelper {

public $helpers = array(‘Html’,’Form’);

/**
* Custom error field description
*/
public function errorField( $field = false ) {

$defaults = $this->Form->inputDefaults() ;
return $this->Form->error( $field  , null , $defaults[‘error’][‘attributes’]  ) ;

}

}

[/php]

 

 

mal uso de parámetros en un array con consultas preparadas con cakephp y mysql

Vaya chorro de título….. qué es esto ?

Pues explicado muy muy rápido si quiero preparar una consulta bonita para lanzar a la base de datos ( mysql ) y que tenga parámetros en vez de hacer chapuzas y guarrerías varias que se ven en muchos sitios , uniendo strings y demás…. se pueden usar parámetros.

Es muy sencillo, queda de esta forma :

[sql]

SELECT Customer.name FROM customers Customer WHERE Customer.id = :customer_id

[/sql]

Si veis ‘:customer_id’ no pertenece al standard de SQL , es un parámetro . De forma que le puedo pasar a la consulta una variable como cuando usamo printf y Mysql construirá la query completa, además de hacer cosas con los índices y demás … que no vamos a tratar ahora.

Pues bien. tengo aquí un caso real de una cosa que me ha pasado hoy, quería pasar por parámetros un array de parámetros de forma que quería buscar ‘customer.id IN ( :listaIDs ) ‘. Os adelanto ya que no se puede pasar un parámetro que sea un string de integers separados por coma.

[php]

public function getCustomersById( $objectIds = array() ) {
$sql = ‘
SELECT
Customer.*
FROM
customers Customer
WHERE
Customer.id IN ( :objectIds ) ‘;

$db = $this->getDataSource();

$objectIds= join( ‘,’, $object_id );
$params = array (
‘objectIds’ => $objectIds
);

return  $db->fetchAll($sql, $params  )

}

[/php]

Pues esta consulta sólo retorna los resultados que coincidan con el último valor del array. Si veis hago un join() para unir los valores y pasarlos como parámetro. Pues Mysql se lo come y sólo utiliza el último, tampoco da error. Qué alegrías que nos da la programación 😀

 

cakephp testing: Actualizar base de datos de test con migrations

Si estás usando las migraciones de base de datos y quieres aplicarlas a la base de datos de test debes lanzar este comando :

Console/cake schema update --connection test

update:
realmente esto no vale de nada en cakephp ya que cada vez que lanzas los tests se usan los ficheros fixtures para recrear la base de datos con lo que el contenido y estructura de la base de datos siempre se destruye y se crea de nuevo.
Para tener actualizado el contenido de la base de datos es necesario actualizar los ‘Fixtures’, lo más cómodo es usar la herramienta bake fixtures

http://book.cakephp.org/2.0/en/console-and-shells/code-generation-with-bake.html

gedit / pluma highligth ctp

Si trabajamos con gedit o pluma y con CakePHP nos interesa que los ficheros .ctp ( cake template ) se muestren con el sombreado ‘highligth’ como php y html de forma que sea más fácil trabajar con el contenido.

Por defecto este tipo de extensiones no son reconocidas por las instalaciones Debian, así que nos toca agregarlas. Para ello y basándome en este enlace he creado una pequeña modificación para que los ficheros .ctp se muestren coloreados
[shell]sudo sed -i ‘s@<glob pattern=»\*.phps»/>@<glob pattern=»*.phps»/>\n\t\t<glob pattern=»*.ctp»/>@g’ /usr/share/mime/packages/freedesktop.org.xml
sudo update-mime-database /usr/share/mime[/shell]