Drupal personalizando un detalle con el resultado de una vista
Drupal tiene el módulo context, muy util al poder definir reglas para mostrar bloques por contexto. El bloque puede ser el resultado de una view. Las views pueden recibir parámetros, pero cuando es un bloque hay que hacer "ñapa" para recibir el parámetro de la url, por lo que si deseamos mostrar en el detalle del contenido un listado de otros contenidos según la regla de negocio tenemos dos opciones.
Crear una view de tipo bloque y después por context definir la regla para pintar la view o crear una variable en el preprocess del nodo con el resultado de una vista.
La ventaja de hacerlo con context, es que no tiras una línea de código pero el problema es que el bloque lo tienes que ubicar en una de las regiones definidas en el theme. Por otro lado si la vista necesita parámetros, como el $node->nid es algo más complejo.
Pongamos como ejemplo "noticia" (que original), donde va a mostrar el listado de las 5 noticias más recientes que tengan los mismos tag's que la noticia que estamos visualizando.
1.- Creamos la vista que recibe como parámetro el $node->nid para obtener los tags y luego consulta al resto de noticias para obtener el resultado de las 5 noticias a mostrar.
2.- Preprocess de nodo noticia:
function _THEMENAME_preprocess_node__noticia(&$vars){
$nid = $vars['node']->nid;
$view_name = 'noticias';
$display = 'noticias_relacionadas_por_tags';
$args = array($nid);
$view = views_get_view($view_name);
$view->set_arguments($args);
$view->build($display);
$view->execute($display);
$block = $view->render();
$vars['noticias_relacionadas'] = $block ;
}
Ahora en la plantilla de nodo noticia, tenemos una variable $noticias_relacionadas con el resultado de la vista. Esto nos da más control de personalización del detalle, ya que con context estamos "limitados" a las regiones del theme, pero de esta manera la personalización del html en el detalle de la noticia está más controlado.
Drupal crear variables en nodos para personalizar el detalle de un contenido
Cuando trabajamos en la personalización del detalle de contenido, nos puede surgir la necesidad según requisitos de crear alguna lógica para mostrar los atributos de este contenido. Es muy fácil caer en aplicar esa lógica y creación de variables en la propia plantilla php (phptemplates), pero en la medida de los posible lo correcto sería evitar "codificar" en la plantilla.
Pongamos el ejemplo de que estamos mostrando el detalle de un contenido noticia, en donde tiene dos atributos a los que hay que darle importancia:
- Imagen
- Vídeo
Requisitos:
Si la noticia tiene vídeo, mostrar el vídeo y en caso contrario pintar la imagen.
Sería muy sencillo aplicar la lógica en el phptemplate:
if($field_noticia_video_rendered){
print $field_noticia_video_rendered;
}else{
print $field_noticia_imagen_rendered;
}
Como ya sabéis, si el tipo de contenido tiene un definido el campo con nombre field_noticia_imagen y el widget del atributo es de tipo imagen, al pintar $field_noticia_imagen_rendered te pinta el html necesario para renderizar la imagen, lo mismo ocurre con el vídeo.
Bien, hasta aquí hemos cumplido la funcionalidad. Pero... ¿es la manera correcta? tal vez no debería mojarme en decir "correcta" ya que ambas funcionan, pero queda mucho más ordenado si en vez de pintar ese churro lineas en la plantilla simplemente pintamos:
print $field_noticia_multimedia_rendered;
Ahora bien, el tipo de contenido noticia no tiene el atributo multimedia y antes de que interprete la plantilla tenemos que crear la variable.
Es muy improbable que estés haciendo un tema de Drupal de cero, así que en este paso vamos a abrir template.php.
Normalmente en este fichero si partes de un tema base, ya tendrás la función:
THEMENAME_preprocess_node(&$vars, $hook){
...
$function = '_THEMENAME_preprocess_node'.'__'. $vars['node']->type;
if (function_exists($function)) {
$function(&$vars);
}
}
Antes de procesar un nodo se ejecuta esta función, en donde comprobamos si tenemos declarada una función especifica para preprocesar un nodo de un tipo de contenido determinado, como en este caso el type es "noticia" tendremos la función "_THEMENAME_preprocess_node__noticia". Al declarar la función con un guión bajo al inicio del nombre, es una manera de indicar que es una función de ámbito privado y que no es un hook que lo entienda el core.
_THEMENAME_preprocess_node__noticia($vars){
...
}
El parámetro que recibe es un array asociativo que contiene toda la información que necesitamos. Si creamos una nueva key en este array asociativo, lo que vamos a conseguir es que en la plantilla de nodo exista una variable con el nombre de la key que hemos creado en el array.
_THEMENAME_preprocess_node__noticia($vars){
if($vars['field_noticia_video][0]['value']){
$vars['field_noticia_multimedia_rendered'] = $vars['field_noticia_video'][0]['view'];
}else{
$vars['field_noticia_multimedia_rendered'] = $vars['field_noticia_imagen'][0]['view'];
}
}
Una vez creado el preprocess para el tipo de contenido noticia, en la plantilla del nodo noticia tenemos que pintar la variable $field_noticia_multimedia_rendered.
print $field_noticia_multimedia_rendered;
Nos olvidamos de la lógica en la plantilla, para cuando pase diseño a modificarla no se encuentre con esos churros que a veces metemos ![]()
La idea de llamar a la nueva variable $field_noticia_multimedia_rendered es por seguir un poco la nomenclatura de las variables que utiliza Drupal, pero puede ser sólo $multimedia ya que a otra persona que vaya a ver la plantilla le puede llevar a confusión entendiendo que es un atributo del contenido. Esto queda a elección de cada uno.
Drupal el incomprendido y desconocido CMS
Hace ya bastante tiempo, desde que me muevo en la tecnología LAMP, que conozco Drupal. Nunca le dediqué el tiempo necesario para ser conocedor de esa potencia interna que cuando miramos las tripas nos hace dudar que tenga. Drupal es un CMS agnóstico en contenido y que gracias a su extensa comunidad hay una cantidad de módulos y documentación (a veces demasiada) sobre como hacer proyectos en Drupal.
Tal vez, el problema de no haber invertido más tiempo en Drupal es por su sencillez tras la instalación y no conocer lo que realmente podía ofrecer. Una de las razones también muy importantes por las que no me decidía a investigarlo era la parte técnica, donde escasea la POO y hace algo muy raro ![]()
Recientemente en el entorno laboral nos ha surgido la oportunidad de invertir tiempo en conocerlo, realmente me ha sorprendido. La primera sensación en la toma de contacto con el CMS es que se puede desarrollar sites dinámicos sin tirar una línea de código. Esta sensación duró hasta que nos enfrentamos a un proyecto real, en donde funcionalmente podíamos atacar muchos requisitos del proyecto pero a la hora de entrar en las tripas para personalizarlo nos dimos cuenta que hay algo más allá. El código es prácticamente funciones, y el core (no se como lo hace) simula la sobrecarga de métodos pero con funciones en donde parece ser que sólo puede existir una sobre-escritura.
La verdad es que ahora mismo tengo un poco de fascinación por Drupal, y cuando hace unos 3 años un amigo me intentaba vender la "moto" de Drupal yo siempre le ignoraba
lo siento Diego! ha tenido que ser tres años más tarde.
Supongo que a partir de ahora, retomaré el blog con algún que otro artículo de Drupal.
Cambiar el path de la carpeta Web de Symfony
A veces el servidor donde vamos a hospedar el proyecto nos puede condicionar los paths del proyecto. En un hosting compartido normalmente no puedes indicar cual es el path del document_root si no que ya te ofrecen por defecto una estructura de directorios y tienes que adaptar tu desarrollo a ello.
Bien, con symfony es muy sencillo cambiar el path del web dir.
Tenemos que editar el fichero ProyectConfiguration.class.php y cambiaremos el web dir:
$this->setWebDir($this->getRootDir().'/public_html');
Teniendo en cuenta que el proyecto se encuentra en /home/projects el document_root en symfony sería /home/projects/web, pero al agregar esa línea en el fichero de configuración nos intentaría localizar en /home/projects/public_html.
Por otro lado si queremos meter toda la estructura de symfony en una carpeta, al estilo de:
public_html //El document root
source //Toda la estructura del proyecto symfony
Tendríamos que configurar el path de public_html así:
$this->setWebDir($this->getRootDir().'/../public_html');
Ya que el $this->getRootDir() ya te ubica donde tienes el código.
Aquí dejo una chuletilla
para cuando me vuelva a hacer falta, si os es de utilidad pues mejor.
$GLOBALS vs Static method en PHP 5.2.1
Hoy en el trabajo ha surgido la conversación de si es más efectivo el utilizar clases con métodos estáticos para tener una colección de objetos o variables $GLOBAL. No he utilizado en ninguno de mis desarrollos variables globales por lo que en el trayecto a casa vine dándole vueltas a como poder realizar la prueba de rendimiento entre variables globales y método estático.
Lo que se me ocurrió fue crear dos clases idénticas, a diferencia de que una tiene método estático y la otra no. La no estática la instanciaré en una variable global y entonces comprobaré el uso de memoria.
Ambas clases con una propiedad que almacena el string y con sus métodos de GET y SET. Utilizando el string " Hola Mundo! "
Resultado:
Static
54.1 Kb
Hola Mundo!
Memoria usada: 54.5 KB de 256 KB
Memoria consumida:0.4 KB
0.000107 sec
Globals
54.1 Kb
Hola Mundo!
Memoria usada: 54.8 KB de 256 KB
Memoria consumida:0.7 KB
0.000126 sec
La conclusión es clara, Globals consume 0.3Kb más que un método estático y es algo más lento. Esta prueba se ha realizado con un simple string pero si la hiciéramos en una aplicación los datos de memoria y de tiempo tendrían una diferencia más notable.
Un buen framework PHP
Desde que tomé la decisión de utilizar symfony me sorprendo cada día que voy avanzando. Te encuentras todo aquello que querías tener hecho pero nunca tuviste tiempo de hacer.
Si todavía estás dándole vueltas a que framework php utilizar deja de buscar, symfony es el framework perfecto! Por que hago esta afirmación tan rotunda... pues porque en el aprendizaje de symfony recalcan las buenas prácticas, el uso de pruebas unitarias y funcionales y la refactorización de código. Tal vez estés pensando en utilizar Zend Framework porque tiene unos componentes que son realmente interesantes, no te preocupes! con symfony puedes hacerlo!
La filosofía de los creadores del framework es de "no reinventar la rueda" y si algo está bien hecho y funciona lo utilizan. Antes de embarcarse en el desarrollo de algo nuevo comprueban si existe. De hecho, el core de symfony está compuesto por otros proyectos open source como Creole, Prado, Spyc y Pake.
Tienes todavía dudas de si debes usarlo o no, el libro y la documentación es extensa (es una buena señal), entonces ponte a realizar la práctica de Jobeet! verás lo que se puede hacer y como! la potencia de symfony es importante!
Yahoo news y del.icio.us son proyectos construidos con symfony por lo que se puede garantizar el desarrollo de aplicaciones con carga extrema.
Optimiza tu desarrollo web en php con KCachegrind – PHP Profiler con Xdebug
La descripción encontrada en wikipedia de "profiling":
Un "profiler" es una herramienta de análisis de performance que mide el comportamiento del programa mientras este está corriendo, particularmente la frecuencia y duración de las llamadas a funciones. La salida es un rastro (stream) de eventos o un sumario estático de los eventos observados (un "profile", perfil o reseña). Los profilers usan una amplia variedad de técnicas para recolectar datos, incluyendo interrupciones por hardware, instrumentos de código, ganchos (hooks) del sistema operativo.
El uso de profilers es usado en el proceso de ingeniería de performance. Un profile generalmente es realizado relacionado la posición del código fuente donde suceden los eventos y el tamaño de las medidas de los datos que es proporcional al tamaño del código del programa. En contraste, el tamaño de un rastro es proporcional al tiempo de ejecución de un programa, haciéndolo impracticable. Para programas secuenciales, un profile, es generalmente suficiente, pero los problemas de pefrormance en programas paralelos (que esperan mensajes o temas de sincronismo) generalmente depende del tiempo de relación de los eventos, de esta forma requieren la localización total para tener un entendimiento del problema
Para ello tenemos que instalar php5-xdebug:
sudo aptitude install php5-xdebug
Una vez instalado el módulo Xdebug tenemos que editar su fichero de configuración que encontraremos en:
/etc/php5/apache2/conf.d/xdebug.ini
En ese fichero agregaremos las siguientes lineas:
xdebug.profiler_enabled = 1
xdebug.profiler_output_dir = (path de salida) "/home/usuario/tmp/"
xdebug.profiler_output_name = cachegrind.out. %R
Tras reiniciar el apache comprobaremos en un fichero php el resultado de phpinfo() para comprobar que el modulo xdebug está operativo.
Más parámetros de configuración: xdebug profiler
Al poner %R en el nombre de salida conseguimos que si estamos analizando el domonio localhost guarde los ficheros como: cachegrind.out.localhost
Para conocer más opciones de parametrización de xdebug.profiler_output_name en: http://www.xdebug.org/docs/all_settings#trace_output_name
De esta manera conseguimos que se vayan creando los ficheros que después leeremos con KCachegrind.
Instalamos Kcachegrind:
sudo aptitude kcachegrind kcachegrind-converters
Ahora solo tendremos que lanzar el programa Kcachegrind y abrir el fichero cachegrind.out.localhost. En el mismo directorio encontraremos más ficheros pero tenemos que abrir el fichero principal que es el que no tiene concatenado a su nombre con un punto una secuencia numérica.

El programa analizará los logs de xdebug y nos lo mostrará con una interfaz gráfica intuitiva y no muy complicada de entender:
De esta manera podremos analizar si nuestra aplicación web pierde mucho tiempo en algún proceso en el que no hayamos reparado con anterioridad, el uso de memoria y las llamadas que se realizan a funciones y/o métodos.
Esta configuración está pensada para probarla en la máquina local de desarrollo, en ese caso en el path de salida que hemos configurado en el xdebug.ini tenemos que asignarle los permisos necesarios para que el usuario de apache www-data pueda escribir los logs.
Una vez finalizado su uso, es recomendable desactivar el profile de xdebug para que no nos sature de logs a los que no vamos a hacer caso.
Aunque el pantallazo es de un entorno KDE esta configuración y software se ha realizado en: Ubuntu 9.04 Gnome.
Si tu entorno de desarrollo es Windows, también puedes activar el módulo php_xdebug.dll en tu php.ini y seguir los mismos parámetros de configuración en tu fichero php.ini. Como herramienta para examinar los logs del profile xdebug puedes utilizar WinCacheGrind.
Espero que os sea de utilidad, si conocéis alguna herramienta y/o utilidad que os facilite la tarea de realizar aplicaciones ligeras agradecería el comentario.
Framework :: Probando la vista
Bien, hasta ahora el código que estaba publicado en el repositorio no era de mucha utilidad si no había un caso de ejemplo para probar el funcionamiento de la vista.
A tener en cuenta para pruebas:
- Document root: html
- Código donde se monta la vista: proyecto/php/portada/portada.php
- Tipo de contenido de pruebas: demo
El resultado de la prueba es un listado de 10 elementos de tipo "demo" con una paginación de 2 páginas, ya que cuando preguntamos por el total, el método devuelve directamente 20. Las clases del tipo de contendo Demo son clases de prueba, todavía falta la definición de como construir los tipos de contenido.
La idea de la vista, es un gestor de plantillas por sustitución de tag omitiendo cualquier tipo de lógica en la propia plantilla. El objetivo es tener un motor de plantillas de fácil uso a la hora de montar pantallas teniendo en cuenta que en la propia plantilla el diseñador no se tendrá que econtrar código alguno que implique lógica. Entendiendo lógica como boucles, condiciones...
Framework :: descargando el código de SVN
Para descargar el código del subversion tenemos que utilizar un cliente de subversion
"me he lucido". Tirando de la blogosfera podemos obtener manuales de como utiluzar diferentes clientes de subversion.
- TortoiseSVN en Windows
- Subclipse para usarlo en eclipse
- SscriptSVN en Gnome
También me ha parecido de interés el exponer una explicación del servicio de Subversion para aquellos que no lo conozcan. Este servicio sirve para tener un control de versiones y desarrollar en equipo. Para esto podemos acceder al blog de Manuel Recena que en su post de Algunas ideas de como usar subversion lo describe con detalle.
Si tenéis algún problema para la descarga avisarme para poder solucionarlo. El proyecto está en modo lectura para todos y para poder participar hace falta una cuenta de usuario, por lo que no podréis realizar un commit si no os he dado de alta.
Feliz descarga! ![]()
Framework :: El comienzo
Hace ya un tiempo que llevo dandole vueltas a la idea de comenzar a desarrollar un framework para desarrollar en PHP. Es cierto que en internet existen para escoger unos cuantos, unos más conocidos que otros y un sin fin de clases para utilizar en los desarrollos de cada uno.
Aunque dispongo de algo más de código que el expuesto en el respositorio de subversion que he montado para el proyecto tengo que "limpiarlo" un poco para subirlo al repositorio.
Ahora tengo un gestor de plantillas, cuya idea principal es el montar la página gestionando formularios, paginaciones y demás elementos que vaya incorporando al desarrollo. Ahora será dificil poder comprobar el funcionamiento de las clases a no ser que le dediques un poco de tiempo a leer el código pero en cuanto pueda tener código suficiente para que se pueda ir evaluando pasará un tiempecito ^_^ esperemos que no mucho.
Un punto importante en el proyecto es la documentación y en unos dias montaré un wiki para ir documentando las clases publicadas en el repositorio, por lo que se intentará mantener la publicación de documentación con la publicación de código nuevo.
El proyecto es ambicioso para una sola persona pero sin tener la obligación de alcanzar una fecha de fin no hay presión ![]()
Una de las asignaturas pendientes para este proyecto es licenciarlo bajo GPL, pero aunque ahora el código no haga referencia a esta licencia así estará en el momento que me sea posible.