Desde el principio en masquemedicos.com nos hemos preocupado lo mucho por minimizar el numero de queries que se lanzan a la base datos. Nosotros hemos optado por usar memcache, el cual nos permite acceder de forma rápida y fácil a objetos cacheados en memoria.
Nuestro framework Symfony ya cuenta de por sí con integración con memcache, lo que te permite por ejemplo cachear todo o parte del contenido de una página. Para ello te recomiendo la propia documentación de Symfony sobre cache.
En este post vamos a ver cómo cachear cualquier objeto (como objetos propel resultado de una query) mediante la clase sfMemcacheCache, lo cual no es fácil de encontrar en la documentación de Symfony. Por ejemplo veamos el caso práctico en el que dispones en tu modelo de datos de la entidad provincia en la que cada provincia tiene un id y un nombre. Suele ser un caso muy habitual el que accedas muy frecuentemente a esos datos para mostrar por ejemplo un selector <select> de esas provincias.
Vamos a declarar la funcion getCacheProvincias, la cual se encarga de obtener esos datos de memcache en caso de que existan. Si no existen los cogerá de base de datos (propel) y los guardará en cache. Así la proxima vez que se soliciten ya los obtendrá de caché sin consultar la base de datos. No te tomes al pie de la letra la función, es sólo una forma de explicar la manera de proceder.
function getCacheProvincias(){
//Instancio la clase memcache de symfony. OJO, ni a mi se me ocurriría hacer esto aquí, ya que si usas varias veces esta funcion u otras
//similares estarías instanciando la clase varias veces lo cual no tiene ningun sentido
$memcache=new sfMemcacheCache();
$memcache->initialize();
//Defino la clave a la que se asociaran los datos de las provincias en memcache
//Ojo, tiene que ser clave única... aseguraté de no volver a usar "provincias"
$key=md5("provincias");
//Cojo los datos de memcache
$data=$memcache->get($key);
if ($data){ //Los datos estaban presentes en memcache, asi que basta con deveolverlos deserializados (o como se diga)
return unserialize($data);
}else{ //Los datos no están presentes en memcache. Hacemos la consulta a bbdd y los guardamos
//la consulta a bbdd
$c = new Criteria();
$c->add(lo que sea...);
$provincias = ProvinciasPeer::doSelect($c);
//la guardamos en memcache. Los objetos hay que serializarlos.
$memcache->set($key,serialize($provincias),tiempo-de-vida-de-los-dato-en-segundos);
return $provincias;
}
}
Pues con eso ya tenemos resulta la forma de coger y guardar datos en memcache, ahora ten presente que si cambia algo en la BBDD (el nombre de una provincia por ejemplo) o bien esperas a que se pase el tiempo de vida que has indicado o te preocupas tu mismo de borrar los datos de memcache. Solo tienes que borrarlos, no regenerarlos porque ya se volverán a generar en la siguiente petición. Para realizar el borrado:
$key=md5("provincias");
$memcache->remove($key);
Por remetar el ejemplo solo indicar que para usarlo solo tienes que imaginar que estas cogiendo los datos igual que si los cogieras de la BBDD con propel, por ejemplo pasándoselos a la vista en el actions:
//en actions;
$this->provincias=getCacheProvincias();
//y en la vista, lo que sea:
echo "<select>";
foreach ($provincias as $provincia){
echo "<option value=\"".$provincia->getId()."\">".$provincia->getNombre()."</option>";
}
echo "</select>";
Esto es todo por hoy, ya sabes no te tomes el código al pie de la letra, seguro que hay formas mejores, pero si te sirve la idea… eso que te llevas.
Abrazos para todos.
Gracias Carlos,
Interesante y sencilla solución
Comentario por Sergio Viteri — diciembre 4, 2009 @ 11:28 am
Gracias a tu artículo salvé un día de trabajo de una forma directa y sencilla. Muchas gracias por pensar en los demás.
Comentario por Viviana — enero 11, 2011 @ 11:06 am
Donde debo instanciar el objeto sfMemcacheCache() para no instanciarlo cada vez qe se ejecuta el action???
Comentario por Cristian — agosto 9, 2011 @ 12:40 pm