Consultas “tipo CakePHP” en CodeIgniter
Una de las mayores facilidades con la que cuenta CakePHP es la forma en que maneja los modelos y las búsquedas en ellos. En este artículo vamos a tomar el núcleo de los modelos de CakePHP para aplicarlo a CodeIgniter y así obtener búsquedas más sencillas en este último framework.
Los Modelos de CakePHP
El concepto de CakePHP es simple: Los módelos no son archivos de funciones que consultan la base de datos si no que son mapas de datos, clases que contienen arreglos cuya estructura es una abstracción de los campos, restricciones y relaciones de las tablas en la base de datos.
Todos los modelos heredan el método find de la clase Model de CakePHP. El find es una función super poderosa que permite hacer casi cualquier consulta a la base de datos solamente variando los parámetros que se envían. Acá está la magia. El find de CakePHP evita tener que hacer una función distinta en el modelo para cada consulta que vayamos a hacer sobre cada tabla de la base de datos, y eso nos puede ahorrar muchísimo tiempo de desarrollo.
Traduciendo a CodeIgniter
En CodeIgniter (CI, para abreviar), los modelos son simples clases que deberían tener las funciones que realizarán consultas directas a la base de datos. Estas clases extienden a la librería CI_Model del núcleo de CI. Así, si tenemos una tabla usuarios y otra tabla publicaciones y queremos una consulta que nos traiga todos los elementos de cada tabla, tendríamos que crear la misma función en dos archivos diferentes, en dos modelos diferentes, con la única diferencia de la tabla a la cual consultan.
Podemos evitar esto usando Mapeo de Datos. Solamente tenemos que modificar la clase CI_Model del núcleo de CI para agregarle funciones que mediante parámentros reciban toda la información y puedan actuar sobre las distintas tablas de la base de datos.
Sin embargo, es cierto que modificar el núcelo de un framework (y en general de cualquier sistema que no hayamos creado) nunca es una buena idea. Afortunadamente, CI permite crear extensiones o reemplazar del todo sus librerías del núcleo de una forma sencilla: Si queremos extender la librería del núcleo CI_Model simplemente se coloca en la carpeta application/core un archivo llamado MY_Model (el prefijo MY_ es configurable). Este archivo debe contener una clase que extienda a CI_Model y ahí podemos agregar nuestras funciones.
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class KAPS_Model extends CI_Model
{
private $_table_prefix;
function __construct()
{
$this->_table_prefix = 'my_table_prefix_';
//IMPORTANT: runs the constructor of the CI_Model class
parent::__construct();
}
/**
*
* create a query to de database and return it's results
* @param String $type [all|first|count|list]
* @param Array $params array([conditions|fields|order|limit|join])
* @return Object or Array
*/
function find($type,$params=array())
{
//result of the query
$result = FALSE;
//set the name of the table where the query will run
$this->db->from($this->_table_prefix.$this->table);
//creates the where clause if $params['conditions'] is defined
if(isset($params['conditions']))
{
//where options => array('name !=' => $name, 'id <' => $id, 'date >' => $date, 'field'=>$value);
$this->db->where($params['conditions']);
}
//creates the join clause if $params['join'] is defined
if(isset($params['join']))
{
foreach($params['join']['clause'] as $join_table => $join_conditions)
{
if(isset($params['join']['type']))
$this->db->join($join_table, $join_conditions, $params['join']['type']);
else
$this->db->join($join_table, $join_conditions);
}
}
//creates the fields clause if $params['fields'] is defined
if(isset($params['fields']))
{
$this->db->select($params['fields']);
}
//creates the order clause if $params['order'] is defined
if(isset($params['order']))
{
foreach($params['order'] as $field => $sort)
{
$this->db->order_by($field,$sort);
}
}
//creates the group clause if $params['group'] is defined
if(isset($params['group']))
{
$this->db->group_by($params['group']);
}
if($type=='count')
$result = $this->db->count_all_results();
else
{
//creates the limit clause if $params['limit'] is defined and type!=first
if($type=='first')
$this->db->limit(1);
else if(isset($params['limit']) && !empty($params['limit']))
{
if(is_array($params['limit']))
{
$cnt_params = count($params['limit']);
if($cnt_params)
{
if($cnt_params==1)
$this->db->limit($params['limit'][0]);
else
$this->db->limit($params['limit'][0],$params['limit'][1]);
}
}
else
$this->db->limit($params['limit']);
}
$query = $this->db->get();
switch($type)
{
case 'list':
{
$result = array();
//return the result in array format
$tmp_result = $query->result_array();
$keys = array_values($params['fields']);
foreach($tmp_result as $tmp)
{
$result[$tmp[$keys[0]]] = $tmp[$keys[1]];
}
break;
}
case 'first':
{
//return just the first result in object format
Page 1 of 3 | Next page