Hola Mundo, empezar a programar con Drupal 7
Este tutorial está orientado a programadores que conocen PHP, que han empezado a utilizar Drupal 7 a nivel de instalación e interfaz de administración, y que desean aprender a programar sus propios módulos. He querido empezar por el clásico “Hola Mundo” para hacer el ejemplo lo más sencillo posible conceptualmente, pero al mismo tiempo extenderlo con variantes que permitan hacerse una idea de cómo funciona Drupal y las posibilidades que nos ofrece.
A través de este tutorial podrás aprender a:
- Crear tu primer módulo
- Crear una página para decir hola mundo
- Theming: maquetar el resultado con HTML
- Programar un bloque que diga “Hola Mundo”
- Hacer el saludo configurable desde la interfaz de administración
- Saludar por su nombre al usuario que inicia sesión
- Hacer configurable en la interfaz qué eventos mostrarán el saludo
- Traducir cadenas de texto con Drupal: t(“Hello World”)
Creando tu primer módulo
Por supuesto podríamos crear el “Hola Mundo” en un bloque o una página directamente desde la interfaz, o incluso introducir un <?php echo “Hola Mundo”; ?> en una plantilla del tema, pero se trata de aprender a programar funcionalidades y en Drupal esto se hace desarrollando módulos.
Los módulos se suelen ubicar dentro del directorio /sites/all/modules. Allí creamos una carpeta para nuestro módulo que podemos llamar “saludar”. Para terminar de crear nuestro módulo necesitamos crear dentro el archivo saludar.info y el archivo saludar.module. El primero es un archivo de texto que contendrá la información de definición del archivo, y en el segundo empezaremos a programar con PHP.
saludar/saludar.info
name = Saludar description = "Módulo que dice hola mundo" package = Aprendiendo a programar con Drupal core = 7.x files[] = saludar.module
En saludar.info estamos diciendo que el módulo se llama “Saludar”, describimos lo que hace, lo clasificamos en la categoría “Aprendiendo a programar con Drupal”, especificamos que es compatible con Drupal 7 e indicamos que se compone del archivo saludar.module, que de momento hemos creado vacío.
Para comprobar que hemos creado el módulo correctamente nos vamos a la opción “Módulos” del menú de administración de nuestra web Drupal, en la ruta /admin/modules. Allí encontraremos nuestra categoría con nuestro primer módulo, y una casilla para activarlo.

Crear una página para decir hola mundo
Para crear una página, es decir, programar la respuesta para una determinada url, utilizaremos la función hook_menu(). Cuando nuestra aplicación reciba la petición de la página “/saludar/hola-mundo”, Drupal comprobará si alguno de los módulos tiene programado un nombremodulo_menu() para esta dirección. Creamos pues nuestra función saludar_menu() que servirá de índice para las direcciones a las que responderá nuestro módulo saludar.
saludar/saludar.module
<?php
/**
* @file
* Archivo para empezar a programar con Drupal
*/
/**
* Implementación del hook_menu()
*/
function saludar_menu() {
$items['saludar/hola-mundo'] = array(
'title' => 'Saludar',
'page callback' => 'saludar_hola_mundo',
'access callback' => TRUE,
);
return $items;
}
/**
* Callback que implementa la página: saludar/hola-mundo
*/
function saludar_hola_mundo() {
return "Hola Mundo";
}
Lo que hemos hecho es añadir una url al array de elementos $items, y para esa dirección elegimos un título para la página y la función que implementa el contenido, que a su vez devuelve como contenido un “Hola Mundo”. Con 'access callback' definimos con qué permisos pueden acceder a esta página, en este caso podrán todos los usuarios (TRUE).
Cada vez que implementamos un cambio en hook_menu() necesitamos vaciar la caché para poder visualizar estas modificaciones. En el menú de administración pulsamos en Configuración, y a continuación en Rendimiento (en el bloque de Desarrollo), donde podremos pulsar el botón “Vaciar todas las cachés”. Ahora sí, podemos ver nuestro primer “Hola Mundo” en la dirección “/saludar/hola-mundo” de nuestro sitio web.

Como puedes ver, además de la página se ha creado un enlace en el menú de Navegación. Esto es porque hemos obviado una de las opciones del array $items en el hook_menu(): 'type', cuyo valor por defecto es la constante MENU_NORMAL_ITEM. Si quisiéramos crear la página sin que aparezca el menú simplemente añadiríamos en el array:
'type' => MENU_CALLBACK,
¡Recuerda vaciar las cachés para ver los cambios!
Theming: maquetar el resultado con HTML
Hemos creado una página con el título Saludar y hemos mostrado en su interior el texto “Hola Mundo”. Como podéis comprobar el contenido de nuestra página se muestra dentro de un <div class=”content”>. Podríamos formatear un poco el resultado con HTML directamente en la función:
function saludar_hola_mundo() {
return '<p class="saludo"><em>Hola Mundo</em></p>';
}
Pero estaríamos mezclando contenido y presentación, así que vamos a ir un poco más allá para separarlo, maquetando el “Hola Mundo” con HTML en un archivo de plantilla aparte. Para ello devolvemos el resultado de la función theme():
function saludar_hola_mundo() {
$variables = array(
'message' => 'Hola Mundo',
);
return theme('saludar_hola_mundo', $variables);
}
Ahora estamos introduciendo “Hola Mundo” en el array de variables que le vamos a pasar a la plantilla, y a continuación utilizamos la función theme() para generar el resultado de salida. Para ello la función theme() invoca el hook_theme(), utilizando el primer parámetro 'saludar_hola_mundo' como nombre del hook.
Por tanto el siguiente paso es implementar el hook_theme() para nuestro módulo en saludar.module, indicando la plantilla que formateará la salida de 'saludar_hola_mundo'. Al igual que con hook_menu(), la función que implementa el hook_theme() en el módulo se denomina nombremodulo_theme():
/**
* Implementación del hook_theme()
*/
function saludar_theme() {
return array(
'saludar_hola_mundo' => array(
'template' => 'saludar-hola-mundo',
),
);
}
En nuestro hook_theme() estamos llamando a la plantilla (template): “saludar-hola-mundo”, para maquetar el callback: “saludar_hola_mundo”. Ahora solo falta crear la plantilla en nuestro módulo, creando un archivo con el nombre del template acabado en “.tpl.php”.
saludar/saludar-hola-mundo.tpl.php
<p class="saludo"><em><?php echo $message; ?></em></p>
Vaciamos las cachés para que coja el nuevo archivo y podemos comprobar el resultado. Como puedes ver estamos utilizando la variable “message” que definimos en la función saludar_hola_mundo(). A partir de aquí puedes añadir nuevas variables de contenido (por ejemplo la fecha) y modificar la plantilla para maquetar ese contenido con esas variables.

Al utilizar theme() estamos separando la presentación de la funcionalidad y el contenido, y permitiendo que esa presentación sea fácilmente sobreescrita en un tema. Por ejemplo un maquetador o “drupal themer” podría simplemente copiar el archivo saludar-hola-mundo.tpl.php del módulo en el tema y modificarlo, sobreescribiendo así el marcado HTML por defecto definido en nuestro módulo.
Programar un bloque que diga “Hola Mundo”
Hemos aprendido a crear nuestra primera página desde un módulo, con contenido maquetado. Ahora vamos a aprender a construir un bloque para poder colocar nuestro “Hola Mundo” en la región de la página o páginas donde queramos ubicarlo. Para crear el bloque tenemos primero que implementar en saludar.module el hook_block_info(), que define todos los bloques que nuestro módulo va a proveer:
/**
* Implementación del hook_block_info().
*/
function saludar_block_info() {
$blocks['hola_mundo'] = array(
'info' => 'Bloque para Hola Mundo',
);
return $blocks;
}
En el array $blocks definimos todos los bloques de nuestro módulo y proporcionamos las opciones por defecto de cada bloque. Aquí hemos definido solamente “info”, pero podríamos haber definido si por defecto aparece activado o no, en qué región, con qué peso, etc. Estas opciones las puede configurar el administrador del sitio web drupal desde la pantalla de Bloques en el menú Estructura (/admin/structure/block). Allí vemos nuestro bloque, en la sección “Desactivado”.

Podemos colocarlo en una región, por ejemplo en la barra lateral, pero aún no podemos verlo porque nos falta un paso, construir el bloque con el contenido, mediante hook_block_view():
/**
* Implementación del hook_block_view().
*/
function saludar_block_view($delta = '') {
switch ($delta) {
case 'hola_mundo':
$block['content'] = saludar_hola_mundo();
return $block;
}
break;
}
En esta función definimos lo que se ve en cada bloque que implementa nuestro módulo. La variable $delta es la que nos identifica el bloque, y para el caso 'hola_mundo' establecemos su contenido. Nuevamente en lugar de establecer el contenido del bloque directamente con “Hola Mundo”, estamos reutilizando la función saludar_hola_mundo() que escribimos anteriormente para utilizar la plantilla saludar-hola-mundo.tpl.php a través de hook_theme().

Ahora sí, si actualizamos cualquier página podemos ver el bloque en la barra lateral, con el mensaje “Hola Mundo”, tal y como lo maquetamos en la plantilla. A este bloque no le hemos asignado ningún título, si quisiéramos proporcionar uno por defecto bastaría con utilizar la variable $block['subject'] en el hook_block_view().
Hacer el saludo configurable desde la interfaz de administración
Drupal, además de una plataforma para desarrollo de aplicaciones, es un potente CMS o gestor de contenidos. Esto es así porque la mayoría de los módulos no solo extienden la funcionalidad aportando algo nuevo, si no que tratan de poner en manos de los usuarios administradores herramientas para configurar esa funcionalidad y gestionar su contenido. Por tanto a la hora de desarrollar un módulo para Drupal puede ser muy importante programarlo para que sea configurable, y como vamos a ver a continuación, implementar el formulario de administración de las opciones del módulo es bastante sencillo.
Vamos a crear una página donde configurar el saludo de nuestro módulo, así el administrador podrá cambiar el texto del mensaje “Hola mundo” por cualquier otro saludo. Primero Colocaremos el acceso a esta página en el menú de Configuración dentro de la zona de Administración, en la url /admin/config:

Añadimos un nuevo elemento en el array del hook_menu de nuestro módulo, en saludar.module:
$items['admin/config/content/saludar'] = array(
'title' => 'Saludar',
'description' => 'Configurar las opciones para el saludo.',
'page callback' => 'drupal_get_form',
'page arguments' => array('saludar_configuracion'),
'access arguments' => array('administer site configuration'),
'file' => 'saludar.admin.inc',
);
Al situar la página bajo la ruta “admin/config/content/” estamos ubicándola en ese menú, de título “Auditoría del contenido”, dentro de Administración – Configuración.

En esta ocasión configuramos la opción “page callback” para construir el formulario con la función drupal_get_form(), “page arguments” para establecer el id del formulario (“saludar_configuracion”) que le pasamos a drupal_get_form(), y “access arguments” para que sólo puedan acceder a la página de configuración de nuestro módulo aquellos usuarios cuyo rol tenga asignado el permiso “administer site configuration”, traducido en la página de permisos como “Administrar configuración del sitio”.
Por último hemos utilizado la opción “file” para programar el formulario de administración en un archivo diferente. Por supuesto podríamos omitirlo y seguir programando todo en saludar.module, pero a medida que el módulo empieza a crecer se hace más importante dividir la funcionalidad y dejar el .module con los hooks y funciones más generales, a modo de índice del módulo.
A continuación creamos el archivo saludar.admin.inc en nuestro módulo con tres funciones, una para definir el formulario de configuración, otra para validar dicho formulario y otra para procesar el envío del formulario ya validado.
saludar/saludar.admin.inc
<?php
/**
* @file
* Callbacks de administración del módulo saludar
*/
/**
* Definir el formulario de opciones de configuración
*/
function saludar_configuracion() {
$form['saludar_saludo'] = array(
'#title' => 'Saludo que se muestra al usuario',
'#type' => 'textfield',
'#default_value' => variable_get('saludar_saludo', 'Hola Mundo'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Guardar configuración',
);
$form['#submit'][] = 'saludar_configuracion_submit';
return $form;
}
/**
* Validar el formulario de opciones de configuración
*/
function saludar_configuracion_validate($form, &$form_state) {
if (trim($form_state['values']['saludar_saludo']) == '') {
form_set_error('saludar_saludo', 'El saludo no puede quedar vacío.');
}
}
/**
* Procesar el envío del formulario de opciones de configuración
*/
function saludar_configuracion_submit($form, $form_state) {
variable_set('saludar_saludo', $form_state['values']['saludar_saludo']);
drupal_set_message("Se han guardado las opciones de configuración.");
}
En saludar_configuracion() definimos los elementos del formulario en un array . En este caso sólo presentaremos un campo de texto “textfield” para establecer el “Saludo que se muestra al usuario”. Puedes consultar la Drupal Form Api Reference para conocer todos los elementos y sus propiedades.
Este saludo lo vamos a guardar en la base de datos con una variable que llamaremos saludar_saludo (una vez más utilizamos saludar_ como prefijo para evitar colisiones con otros módulos). Por eso definimos el valor por defecto del campo de texto mediante la función de Drupal variable_get(), que mostrará el último valor registrado por el administrador, o la cadena 'Hola Mundo' si no se ha configurado el saludo aún.
'#default_value' => variable_get('saludar_saludo', 'Hola Mundo'),
Por último la función define el botón de submit y la función que procesará el envío, y devuelve el formulario.

Como ejemplo de validación comprobamos que no se haya enviado una cadena vacía, accediendo al valor del campo que recibimos del array $form_state['values']. Si hay un error invocamos la función form_set_error(), definiendo el campo donde se ha producido y el mensaje de error correspondiente.

Finalmente en la función saludar_configuracion_submit() procesamos el envío validado guardando el saludo en la base de datos mediante la función variable_set(), y emitimios un mensaje de confirmación mediante drupal_set_message().

Hemos visto que podemos controlar la validación y el envío del formulario a través de estas dos funciones, pero para este ejemplo podríamos hacerlo mucho más sencillo y ninguna de las dos serían necesarias. Por un lado la validación de campo obligatorio se puede implementar directamente con '#required' => TRUE. Por otro lado podemos utilizar la función system_settings_form(), que añade el botón de submit, e invoca internamente tras el envío a la función system_settings_form_submit(), que ya se encarga de guardar el valor del campo en una variable con el mismo nombre que el campo, en este caso "saludar_saludo". Simplificando el ejercicio, podríamos dejar el archivo saludar.admin.inc sólo con esta función:
function saludar_configuracion() { $form['saludar_saludo'] = array( '#title' => 'Saludo que se muestra al usuario', '#type' => 'textfield', '#default_value' => variable_get('saludar_saludo', 'Hola Mundo'), '#required' => TRUE, ); return system_settings_form($form); }
Ahora solo nos queda utilizar el valor de configuración guardado para mostrarlo en el saludo. Para hacer esto modificamos la función saludar_hola_mundo() del archivo saludar.module, que quedará así:
function saludar_hola_mundo() {
$variables = array(
'message' => variable_get('saludar_saludo', 'Hola Mundo'),
);
return theme('saludar_hola_mundo', $variables);
}
Eso es todo, ahora nuestro “Hola Mundo” se ha convertido en un saludo configurable que mostraremos en la página o bloque que hemos creado para ello. Los bloques además tienen una página de configuración específica en la que podríamos haber incluido el campo para configurar el saludo, de manera similar a cómo lo hemos hecho en saludar.admin.inc, pero utilizando los hooks hook_block_configure() y hook_block_save(). Te lo dejo como ejercicio de investigación y práctica.
Saludando por su nombre al usuario que inicia sesión
Este ejercicio se puede hacer de manera muy sencilla, tan solo hay que responder al hook de inicio de sesión que se llama hook_user_login(), en nuestro saludar.module:
/**
* Implementación del hook_user_login().
*/
function saludar_user_login(&$edit, $account) {
drupal_set_message("Hola " . $account->name);
}
Ya sabemos como escribir un saludo en una página y en un bloque, ahora lo hacemos en un sitio nuevo. Estamos haciendo uso de la función drupal_set_message(), para escribir un mensaje de estado o confirmación, que también podría ser de advertencia o error, estableciendo un segundo parámetro.

El hook_user_login() nos proporciona el evento al que reaccionar y también el propio objeto usuario: $account, donde la propiedad “name” nos da su nombre. Pero... ¿y si quisiéramos saludarle también en otras ocasiones? Obviamente podemos programar el saludo o cualquier otra acción en cada hook de cada evento que deseemos, pero de nuevo vamos aprovechar la potencia de Drupal para dejar que sea el administrador y no el programador el que pueda cambiar y decidir en qué momento ejecutar esa acción.
Hacer configurable en la interfaz qué eventos mostrarán el saludo
Drupal dispone de un módulo del núcleo, Trigger, que permite desde la interfaz de administración activar ciertas acciones en determinados eventos del sistema, como cuando un usuario inicia sesión o cuando se crea contenido. Necesitamos activar este módulo porque vamos a crear una acción de saludar para que el administrador pueda decidir qué eventos van a accionar (“trigger”) el saludo, en el menú de administración Estructura – Disparadores (admin/structure/trigger).
Primero creamos la acción de saludar utilizando hook_action_info() en nuestro saludar.module:
/**
* Implementación del hook_action_info().
*/
function saludar_action_info() {
return array(
'saludar_usuario_action' => array(
'type' => 'user',
'label' => 'Saludar al usuario',
'configurable' => FALSE,
'triggers' => array('any'),
),
);
}
Cada elemento en el array que devuelve este hook define una acción, en este caso 'saludar_usuario_action', que clasificamos de tipo usuario, su etiqueta será “Saludar al usuario”, en principio no será configurable y estará disponible para cualquier disparador (se puede limitar qué disparadores tendrán la acción disponible). Con esta función implementada ya podemos seleccionar en la interfaz a qué disparadores queremos asignar esta acción, por ejemplo tras iniciar sesión.

Lo siguiente es eliminar la función saludar_user_login() que implementamos en el apartado anterior, y sustituir ese hook por la acción genérica que accionarán los disparadores asignados en la interfaz.
/**
* Acción de drupal que saluda al usuario
*/
function saludar_usuario_action() {
$message = "¡Bienvenido!";
if (user_is_logged_in()) {
$message = "Hola " . $GLOBALS['user']->name;
}
drupal_set_message($message);
}
En la acción estamos teniendo en cuenta si el usuario es anónimo o está autenticado, saludándole por su nombre en ese caso. Para ello hacemos uso de la variable global “user”, que contiene el objeto usuario actual, y su propiedad “name” solo disponible si el objeto es un usuario autenticado.
Otra opción es utilizar la función format_username(), que directamente nos da el nombre del usuario o bien el nombre usado en el sitio para indicar usuarios anónimos, generalmente “Anónimo” (se define en Configuración – Personas – Opciones de la cuenta). Como ves la API de Drupal ya cuenta con muchas funciones de utilidad implementadas que conviene conocer.
function saludar_usuario_action() {
drupal_set_message("Hola " . format_username($GLOBALS['user']));
}
Ahora puedes comprobar que el saludo se muestra correctamente para los distintos eventos que configures en la página de Disparadores, y de paso ir conociéndolos y ver cuándo se ejecutan.
Traducir cadenas de texto con Drupal: t(“Hello World”)
La función t() sirve para poder traducir la cadena en los distintos idiomas que pudiera tener la web. El idioma por defecto es el inglés y es en este idioma como deberemos crear las cadenas de texto al programar. Por tanto en los ejemplos anteriores deberíamos sustituir la cadena “Hola Mundo” por la expresión t(“Hello World”), y así con todas las expresiones de texto por su equivalente en inglés bajo la función t(). De esta manera se podrán traducir desde la interfaz estas cadenas a cualquier idioma.

Por supuesto las cadenas que contienen variables, como en el último ejemplo del saludo al usuario, también se pueden traducir. En la cadena de texto utilizamos variables con el símbolo @ delante, y definimos estas variables en un array como segundo parámetro de la función t().
$message = t("Hola @name", array('@name' => $GLOBALS['user']->name));
Aunque se pueda traducir desde la interfaz, podríamos proporcionar con nuestro módulo sus cadenas de texto ya traducidas. Para ello crearíamos en el módulo una carpeta “translations” con un archivo “general.pot” que contendría todas las cadenas a traducir, y un archivo .po para cada idioma con las cadenas traducidas, por ejemplo: “es.po”. Existen herramientas para generar este tipo de archivos, y concretamente en Drupal encontrarás de gran utilidad el módulo Translation template extractor, con el que podrás fácilmente extraer estos archivos de traducción para las cadenas de texto de un módulo específico.
En estos primeros ejemplos he utilizado el español en el código para facilitar la comprensión. Pero Drupal está desarrollado por una comunidad internacional con el inglés como idioma base. Por ello es una buena práctica escribir todo en inglés, tanto los nombres de funciones y variables como los comentarios, lo que ayudará a que cualquier otro desarrollador de Drupal pueda entenderlo. Ésta y muchas otras directrices constituyen los estándares de programación de Drupal, que conviene conocer y acostumbrarse a seguir al desarrollar código. De esta manera podrías contribuir algún día a la comunidad con tus propios módulos ¿no?
Espero que este tutorial te haya servido y animado a continuar este camino. Puedes dejar aquí tus comentarios, cualquier duda, o sugerencia para mejorar el artículo. Os dejo el enlace para descargar el código del módulo saludar.


Comentarios
Si haces uso de system_settings_form no hace falta implementar la función submit para guardar la variable, el propio system_settings_form obtiene el nombre de la variable del nombre asignado a esa variable en el form.
Respecto a la validación, tampoco haría falta si defines el elemento del formulario con '#required' => TRUE.
Por lo demás todo muy clarito y bien explicado, aunque yo intentaría educar a los programadores de desarrollar en inglés, las funciones y variables todo en inglés para que pueda ser leído por cualquier público.
Gracias por tu comentario Jaime. Quería introducir la función system_settings_form() y también dar un _validate y un _submit como ejemplo de introducción a FAPI, y quería hacer alguna cosita más para justificarlo, pero al final lo simplifiqué y así se quedó. Pero voy a aprovechar tu observación para incluir una aclaración y mejorar un poco el artículo ;)
Totalmente de acuerdo con lo del inglés, es lo que he intentado explicar justo en el último párrafo. Pero muchos programadores están acostumbrados a programar y comentar en español y quería empezar con un ejemplo sencillo en "su idioma", para tratar de convencerles después de adoptar mejores prácticas.
Muy buen artículo. Claro, completo y bien explicado.
Esperamos ansiosos futuras entregas ;)
¡Gracias! Yo también lo espero, es mi intención que esto sólo sea un punto de partida.
Me parece un tutorial magnifico claro y sencillo. Como puntualizacion sobre system_settings_form() seria bueno decir porque es algo que se suele olvidar que el nombre del campo del formulario en este caso $form['saludar_saludo'] tiene que coincidir con el nombre de la variable usada para almacenar los datos de configuración de ese campo en este caso variable_get('saludar_saludo', 'Hola Mundo')
Un saludo y enhorabuena de nuevo :)
¡Gracias Alfonso! En realidad sí que decía que system_settings_form() guarda el valor con el nombre del campo, pero tomando nota de tu comentario lo he completado y puesto en negrita para que no vuelva a pasar desapercibido ;)
Un saludo
Ups pues tenias razon, perdón por mi despiste :(
Excelente tutorial para el que quiere empezar...
Muchas gracias.
Un saludo.
Miguel.
Me agrego tu url YA!!!!
Me parece que pusiste mal el titulo del post. esto no es un "Hola mundo", es un "Hola mundo" + "chau" + "ya volví" + lorem ipsum!.
Los felicito, un trabajo de calidad. Ojalá hubiera dado con un post así hace unos años atrás, me habría ahorrado un par de quebraderos.
Muchas gracias, por favor puedes poner un ejemplo como el anterior, pero alterando un modulo o formulario?
Gracias
¿Podrías ser un poco más específico? ¿A qué te refieres con alterar un módulo? ¿Qué formulario querrías alterar y de qué forma?
Muy buen articulo.. te felicito. hay pocos tutoriales donde te enseñan de esa manera a dearrollar modulos en Drupal 7.
Bueno ahora esto me servirá para empezar a programar en Drupal.. gracias por el aporte..!
Escribe tu comentario