Programando con Drupal - Mapeo de acciones

18
Programando con Drupal Mapeo de acciones En Drupal, un URL tiene la forma: app_url/a/b/c/... ó, si no se usa clean urls: app_url/?q=a/b/c/... 'a/b/c...' es la ruta de argumentos del URL. La principal forma de mapear la ruta de argumentos con acciones es usando el hook _menu. Recordando Hooks Durante el proceso que genera los menús, bloques, etc, Drupal da a los módulos la oportunidad de participar. Un hook corresponde a un tipo de participación. Básicamente, para cada hook hhh, se consulta a cada módulo mmm si ha implementado una función mmm_hhh, y se ejecuta si es así. Módulos Un módulo es un conjunto de código agrupado en un directorio, diseñado para ser reconocido por Drupal y participar en el proceso del sistema. Un módulo mmm guarda en un directorio mmm al menos dos archivos: mmm.info y mmm.module. La estructura de mmm.info es similar a: ; $Id$ name = Mmm description = Module description core = 6.x package = Group name La estructura de mmm.module es similar a: <?php

description

Cómo se hace en Drupal la correspondencia entre URL y acciones.

Transcript of Programando con Drupal - Mapeo de acciones

Page 1: Programando con Drupal - Mapeo de acciones

Programando con Drupal

Mapeo de acciones

En Drupal, un URL tiene la forma:

app_url/a/b/c/...

ó, si no se usa clean urls:

app_url/?q=a/b/c/...

'a/b/c...' es la ruta de argumentos del URL.

La principal forma de mapear la ruta de argumentos con acciones es usando el hook _menu.

Recordando

HooksDurante el proceso que genera los menús, bloques, etc, Drupal da a los módulos la oportunidad de participar.

Un hook corresponde a un tipo de participación. Básicamente, para cada hook hhh, se consulta a cada módulo mmm si ha implementado una función mmm_hhh, y se ejecuta si es así.

MódulosUn módulo es un conjunto de código agrupado en un directorio, diseñado para ser reconocido por Drupal y participar en el proceso del sistema.

Un módulo mmm guarda en un directorio mmm al menos dos archivos: mmm.info y mmm.module.

La estructura de mmm.info es similar a: ; $Id$

name = Mmm

description = Module description

core = 6.x

package = Group name

La estructura de mmm.module es similar a: <?php

Page 2: Programando con Drupal - Mapeo de acciones

// $Id$

/**

* @file

* File description

*/

/**

* Implementation of hook_hhh().

*/

function mmm_hhh() {

//...

}

//...

Hello WorldUn esquema básico de mapeo es similar a: /**

* Implementation of hook_menu().

*/

function mymodule_menu() {

$items = array();

$items['mypath_1' ] = array(

'page callback' => 'mymodule_mypath_1',

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

$items['mypath_2' ] = array(

'page callback' => 'mymodule_mypath_2',

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

return $items;

}

/**

* Page callback.

*/

function mymodule_mypath_1() {

// something

}

/**

* Page callback.

*/

function mymodule_mypath_2() {

// something

}

Es decir, el hook _menu debe devolver un array de items, cada uno de los cuales indica qué función realizará la acción correspondiente a una ruta determinada.

Esto permite implementar Hello World del siguiente modo, en el módulo helloworld:

Page 3: Programando con Drupal - Mapeo de acciones

/**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

Aquí, el item indica que al invoca al url http://myapp_url/helloworld, se llamará a la función helloword_hello, cuya salida (el resultado de t('Hello World!')) será escrita en la página (en el bloque encargado de mostrar el contenido principal).

Es posible definir cualquier ruta y mapearla a cualquier función adecuada. Por ejemplo, podemos agregar un segundo item que defina una ruta alterna que haga lo mismo: /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

$items['hello/again'] = array(

'page callback' => 'helloworld_hello',

Page 4: Programando con Drupal - Mapeo de acciones

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

El segundo item indica que al invocar al url http://myapp_url/hello/again, se llamará a tambien a la función helloword_hello, lo que producirá el mismo resultado.

Control de accesoPara que cualquiera acceda a la ruta, basta con poner access callback en TRUE (de lo contrario se obtendrá un mensaje de acceso denegado).

Pero es posible usar tambien un callback para esto: /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

'page callback' => 'helloworld_hello',

'access callback' => 'helloworld_access',

'type' => MENU_CALLBACK,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

/**

* Access callback.

*/

function helloworld_access() {

return TRUE;

}

La idea es que el access callback devuelva un booleano. Aquí simplemente se ha devuelto TRUE.

Page 5: Programando con Drupal - Mapeo de acciones

Tambien podemos usar la función drupal user_access(), indicando el permiso requerido: /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

'page callback' => 'helloworld_hello',

'access callback' => 'helloworld_access',

'type' => MENU_CALLBACK,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

/**

* Access callback.

*/

function helloworld_access() {

return user_access(array('access content'));

}

O también, de modo más compacto: /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

'page callback' => 'helloworld_hello',

'access callback' => 'user_access',

'access arguments' => array('access content'),

'type' => MENU_CALLBACK,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

Page 6: Programando con Drupal - Mapeo de acciones

Aquí se da acceso a todos los que tengan el permiso ‘access content’.

Para definir un permiso personalizado, podemos usar el hook _perm. /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

'page callback' => 'helloworld_hello',

'access callback' => 'user_access',

'access arguments' => array('helloworld access'),

'type' => MENU_CALLBACK,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

/**

* Implementation of hook_perm().

*/

function helloworld_perm() {

return array('helloworld access');

}

En el menúComo el tipo de cada item es MENU_CALLBACK, simplemente se realiza el mapeo de la ruta con la función.

Usando MENU_NORMAL_ITEM, y agregando un título, aparecerá como item del menú: /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

Page 7: Programando con Drupal - Mapeo de acciones

'title' => 'Hello World',

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_NORMAL_ITEM,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

Además, el título se usa también como título de la página y del bloque.

La línea 'type' => MENU_NORMAL_ITEM, es opcional, ya que MENU_NORMAL_ITEM es el valor por default.

La posición del item en el menú se puede afectar poniendo en weight un valor adecuado (los items con valores menores tienden a flotar y los de valores mayores a hundirse): /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

'title' => 'Hello World',

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_NORMAL_ITEM,

'weight' => 5,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

Page 8: Programando con Drupal - Mapeo de acciones

$output = t('Hello World!');

return $output;

}

Si las rutas son anidadas, los títulos aparecerán anidados en el menú: /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

'title' => 'Hello World',

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_NORMAL_ITEM,

);

$items['helloworld/again'] = array(

'title' => 'Hello World again',

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_NORMAL_ITEM,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

Opcionalmente se puede definir una descripción, que aparecerá al pasar el puntero del mouse sobre el item:

Page 9: Programando con Drupal - Mapeo de acciones

/**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

'title' => 'Hello World',

'description' => 'say Hello World',

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_NORMAL_ITEM,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

Traduciendo el menúEn helloworld_hello(), por ejemplo, se usa t() para indicar contenido traducible. Sin embargo, no se usa t() ni para title ni para description, ya que esa función se aplicará automáticamente a los valores que ahí se definan.

Para description siempre se usa t(). Pero, en el caso de title, la funcion de traducción se puede cambiar dándole un valor a title callback (que por default ‘t’): /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

'title' => 'Hello @name!',

'title callback' => 'helloworld_title',

'description' => 'say Hello World',

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_NORMAL_ITEM,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

Page 10: Programando con Drupal - Mapeo de acciones

return $output;

}

/**

* Title callback.

*/

function helloworld_title($title) {

$output = strtoupper(t($title, array('@name' => 'Antonio')));

return $output;

}

Se puede usar drupal_set_title() para que el title sólo afecte al menú: /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

Page 11: Programando con Drupal - Mapeo de acciones

'title' => 'Hello @name!',

'title callback' => 'helloworld_title',

'description' => 'say Hello World',

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_NORMAL_ITEM,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

/**

* Title callback.

*/

function helloworld_title($title) {

drupal_set_title(t('Hello World!'));

$output = strtoupper(t($title, array('@name' => 'Antonio')));

return $output;

}

Page 12: Programando con Drupal - Mapeo de acciones

Si el title callback es sólo t(), el paso de argumentos se puede escribir de modo compacto: /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['helloworld'] = array(

'title' => 'Hello @name!',

'title callback' => 'helloworld_title',

'title arguments' => array('@name' => 'Antonio'),

'description' => 'say Hello World',

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_NORMAL_ITEM,

);

return $items;

}

/**

Page 13: Programando con Drupal - Mapeo de acciones

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

Argumentos de la páginaLos argumentos adicionales en la ruta son pasados como argumentos a la función, si esta los acepta. /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['hello'] = array(

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello($name='John', $lastname='Doe') {

$output = t('Hello @name @lastname!',

array('@name' => $name, '@lastname' => $lastname));

return $output;

}

Ahora, el callback puede aceptar dos argumentos. Si no hay ninguno, usa los valores por default:

Page 14: Programando con Drupal - Mapeo de acciones

También es posible pasar los argumentos al definir el item. En ese caso, son usados antes que los pasados por el URL: /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['hello'] = array(

'page callback' => 'helloworld_hello',

'page arguments' => array('Carlos'),

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello($name='John', $lastname='Doe') {

$output = t('Hello @name @lastname!',

array('@name' => $name, '@lastname' => $lastname));

return $output;

}

Aquí, el primer argumento tomado es ‘Carlos’, que es el primer argumento pasado en la definición del item, y el segundo argumento tomado es ‘Antonio’, que es el primer argumento pasado en el URL.

Page 15: Programando con Drupal - Mapeo de acciones

También se pueden pasar los argumentos poniendo en page arguments un array con los índices de los argumentos a tomar. El orden en que aparezcan los índices es tomado en cuenta. Asi que es posible invertirlos, por ejemplo: /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['hello'] = array(

'page callback' => 'helloworld_hello',

'page arguments' => array(2, 1),

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello($name='John', $lastname='Doe') {

$output = t('Hello @name @lastname!',

array('@name' => $name, '@lastname' => $lastname));

return $output;

}

Callbacks en otro archivoAunque es necesario que las definiciones de los items estén en el archivo .module, es posible pasar las definiciones de los callback a otros archivos, para que así esas definiciones se carguen sólo cuando sean necesarias. helloworld.module

//...

/**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

Page 16: Programando con Drupal - Mapeo de acciones

$items['helloworld'] = array(

'page callback' => 'helloworld_hello',

'file' => 'helloworld.inc',

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

return $items;

}

//...

helloworld.inc

//...

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

//...

ComodinesEn la definición de una ruta se puede usar comodines. Por ejemplo, % significa ‘cualquier cosa’, hasta antes del siguiente /. /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['hello'] = array(

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

$items['hello/%'] = array(

'page callback' => 'helloworld_hellox',

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

/**

* Page callback.

Page 17: Programando con Drupal - Mapeo de acciones

*/

function helloworld_hellox($name='Anonymous') {

$output = t('Hello') . ' '. $name . '!';

return $output;

}

Así, rutas como hello/a/Antonio, hello/1/Antonio, ó hello/something/Antonio, serán procesadas por el callback helloworld_hellox().

Un item cuya ruta contenga comodines normalmente no aparecerá en el menú, aun cuando se indique que su tipo es MENU_NORMAL_ITEM.

Se puede pasar el comodín y los otros argumentos de la ruta, poniendo en page arguments, sus índices: /**

* Implementation of hook_menu().

*/

function helloworld_menu() {

$items = array();

$items['hello'] = array(

'page callback' => 'helloworld_hello',

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

$items['hello/%/a/b/c'] = array(

'page callback' => 'helloworld_hellox',

'page arguments' => array(1,2,3), // Esto pasa %, a, b

Page 18: Programando con Drupal - Mapeo de acciones

'access callback' => TRUE,

'type' => MENU_CALLBACK,

);

return $items;

}

/**

* Page callback.

*/

function helloworld_hello() {

$output = t('Hello World!');

return $output;

}

/**

* Page callback.

*/

function helloworld_hellox($something='Hello',

$a='', $b='', $name='Anonymous') {

$output = t($something) . ' '. $name . '!';

return $output;

}

page callback permite pasar tanto el comodín como los otros argumentos, si fuera necesario.

Una vez que se han pasado los argumentos indicados por page callback, el siguiente será el que aparezca en el URL después de la ruta. Por eso en este ejemplo $name=’Antonio’ y no ‘c’.

Referencias● John K. VanDyk, "Pro Drupal Development", 2ed, 2008, ISBN 978-1-4302-0989-8

Autor● Antonio Kobashikawa Carrasco

[email protected] http://www.kobaonline.com