Crear un proyecto de servicios web personalizados en Drupal 7

Saque ventaja del módulo flexible Services

Los servicios web son aplicaciones de software basadas en web que intercambian datos con otras aplicaciones basadas en web. Los servicios web ayudan a enlazar aplicaciones que operan en plataformas de red, hardware, software y bases de datos distintos y combinan software y servicios de distintas fuentes para proveer un servicio integrado sin problemas. Aprenda cómo crear un servicio web personalizado que le permita mostrar contenido de un sitio Drupal en otro utilizando el módulo Services.

Timi Ogunjobi, Software Engineer and Author, Xceedia Limited

Photograph of Timi OgunjobiTimi Ogunjobi es autor y desarrollador de aplicaciones web. Es CEO de Xceedia Limited, una firma de ingeniería de software interesada en las aplicaciones móviles y web. También es autor de tres libros sobre Drupal, entre muchos otros. Puede comunicarse con Timi al email timi@xceedia.co.uk.



24-07-2012

El módulo Services le permite habilitar servicios y servidores de contenido personalizados en su sitio Drupal desde un área de administración y configuración backend de módulo principal. Los servicios incluidos en el módulo le permiten llamar contenidos y arrojar datos desde los módulos predeterminados y contribuidos File, Comment, Search, User, Menu, Node, System, Taxonomy y Views de Drupal. Al llamar a estos servicios se pueden captar contenidos desde su sitio Drupal y se los puede mostrar en otro sitio Drupal, ya fuere en el mismo servidor local o desde una ubicación externa. Sin embargo, usted también puede utilizar el módulo Services para integrar las aplicaciones que no están basadas en Drupal con un servicio web externo.

La flexibilidad del módulo Services le permite crear por programa su propio módulo de servicio personalizado para integrarlo con llamados de método (como Representational State Transfer [REST], JavaScript Object Notation [JSON], and XML-remote procedure call [XML-RPC]) que vienen empaquetados con el módulo principal Services. El principal beneficio del módulo Services es que posibilita la integración de servicio web con múltiples aplicaciones mientras utiliza el código y la programación estándar del módulo Drupal. Aún más importante es que el módulo Services ayuda a reducir la cantidad de tiempo que usted le dedica a escribir sus propios módulos de servicio web, ya que provee una interfaz estándar para un número de entornos comunes de aplicación de servicio web.

Este artículo observa cómo usted puede crear un módulo de servicio web que ejecutará una devolución de llamado personalizada desde un sitio Drupal utilizando el módulo Service. Usted escribe un módulo personalizado para devolver un conjunto de datos desde el nodo de un tipo de contenido específico. También aprenderá cómo:

  • Escribir un módulo personalizado para un servicio
  • Integrar este módulo con el módulo Services y probarlo para que devuelva un resultado (éste es un ejemplo de una devolución de llamado simple que devuelve un conjunto de nodos.)

Obtener e instalar los módulos requeridos

Primero debe descargar los siguientes módulos necesarios desde el sitio Drupal.org:

  • Services. Éste es el módulo principal Services descargado de la página del proyecto (vea Recursos donde encontrará un enlace).
  • Serie de herramientas Chaos. El módulo Services depende de esta serie, por lo tanto debe instalarla primero o al mismo tiempo que el módulo Services. La serie de herramientas Chaos provee la infraestructura para que las definiciones de punto final puedan ser definidas y exportadas en cuanto a base de datos y código. Consulte Recursos para obtener un enlace al sitio de descargas.
  • Servidor REST. Usted utiliza el servidor REST, el cual está incluido en la descarga Services, para probar el servicio. También puede utilizar otros servicios, como por ejemplo, JSON y XML-RPC.
  • Auto-cargador. El servidor REST requiere este módulo de herramientas. El módulo Auto-cargador habilita otros módulos para aprovechar las capacidades de la clase de auto-cargado de PHP 5 de una manera unificada. Consulte Recursos donde encontrará un enlace.

Instale estos módulos en su carpeta /sites/all/modules. Después de cargar los servicios, si mira dentro de la carpeta encontrará que contiene dos subcarpetas: servers y services. La carpeta servers contiene el código del módulo de servicios web y el módulo central contiene soporte para el servidor XML-RPC. La carpeta services incluye módulos para proveer servicios web de contenido basado en Drupal, incluyendo archivos, comentarios, nodos, menús, búsqueda, usuarios, sistema, taxonomía y vistas (vea la Figura 1). Estas carpetas son todos los submódulos del módulo Services.

Figura 1. Contenidos de la carpeta del módulo Services
Contenidos de la carpeta del módulo Services

Cuando la instalación esté completa vaya a la lista de administración de módulos principales de su sitio Drupal y habilite el módulo principal central Services, el módulo Key Authentication, el servidor XML-RPC y el módulo Services. Después de habilitar los módulos usted podrá visualizar sus servidores y servicios instalados y activados en la página Administration junto con la configuración principal de servicios centrales. Desde la página /admin/structure/services de su sitio usted puede buscar sus módulos y servicios instalados y ver todas las claves de interfaz de programación de aplicaciones (API) que usted ha agregado en su sitio para utilizar con sus servidores y los servicios en general. La Figura 2 muestra un ejemplo de la página Browse .

Figura 2. Agregar un nuevo servicio
Agregar un nuevo servicio

Haga clic en Add para presentar y nombrar su servicio web y agregar un dominio de servidor web externo permitido con el que se comunicará. El servicio web con el que se comunica puede acceder a su sitio para utilizar estos servicios y acceder a los datos. Es posible que usted ya esté familiarizado con los sitios web de medios sociales tales como Facebook y Twitter, además de una variedad de otras aplicaciones web que permiten el intercambio y la importación de datos de usuario de manera transparente para facilitar los procedimientos de inicio de sesión. Desde la sección Admin > Configuration > Services , la página Settings muestra los métodos de autenticación y la configuración que han sido activados y pregunta si usted quiere aplicar los permisos de contenidos adicionales a su contenido cuando sea utilizado. El campo de permisos de sus tipos de contenido no se mostrará en cascada automáticamente durante un llamado de servicio web. De forma predeterminada, todos los campos de contenido se devuelven sin ninguna exclusión pero usted puede aplicar permisos a nivel de campo de contenido específico.


Crear un módulo de servicio personalizado

Un módulo Drupal es una colección de archivos escritos en PHP que extienden de manera eficaz la funcionalidad de la aplicación básica. Cuando se lo observa con más detalle, el módulo no es muy distinto, en cuanto a estructura, de cualquier otro archivo PHP, y se puede crear, probar y utilizar independientemente en varias instalaciones distintas. Generalmente, el código del módulo puede acceder a todas las variables y estructuras además de utilizar todas las funciones del núcleo de Drupal. De manera similar, el núcleo de Drupal puede llamar —a través de interfaces fijas conocidas como hooks—a aquellas funciones que han sido definidas en los módulos para mejorar su funcionalidad básica inherente.

Los hooks hacen posible que Drupal realice tareas tales como:

  • Agregar nuevos URLs y páginas a ser definidas por un módulo dentro del sitio (hook_menu)
  • Agregar contenido a páginas Drupal (hook_block, hook_footer, y demás)
  • Crear tablas de bases de datos personalizadas (hook_schema)

Observará las definiciones hook en varios lugares dentro del código de un nuevo módulo que esté creando. Al igual que la mayoría de los demás módulos Drupal, el archivo de módulo está compuesto generalmente de tres archivos básicos: modulename.info, modulename.module, y modulename.inc. Un módulo más complejo puede estar compuesto de varios archivos más.

Para comenzar a crear su propio servicio personalizado o archivos de módulo de servicios, en la carpeta /sites/all/modules/services, agregue una nueva carpeta para este módulo, con el nombre note_service.

El archivo .info

Además de la carpeta note_service, cree un nuevo archivo con el nombre note_service.info. Este archivo contendrá todos los metadatos y la información que Drupal requiere para presentar el módulo en la página de administración de los módulos principales.

En el archivo .info, ingrese el código que aparece en el Listado 1.

Listado 1. Note service .info file
name = Note Service
description = Services for the Note content type.
package = Note example
dependencies[] = services
files[] = note_service.inc
files[] = note_service.module
core = 7.x

Guarde el archivo como note_service.info. Este código describe el nombre del servicio, una descripción de qué hace, el paquete del módulo general del que forma parte el módulo personalizado, y todas las dependencias. En este caso, esto significa que para que su módulo personalizado pueda funcionar, se debe instalar y activar el módulo Services. Coloque este archivo note_service.info en su carpeta de módulo.

El archivo .install

El archivo .install le dice a Drupal cómo se debe instalar el módulo—en este caso, con la implementación del esquema hook. El archivo .install se ejecuta cuando se activa un módulo por primera vez, y su función básica es ejecutar los procedimientos de configuración requeridos por ese módulo. La tarea más común que realiza el archivo .install es crear tablas y campos de bases de datos. Las instrucciones de instalación están incluidas en una función _install() . Esta función hook es llamada cuando el módulo se activa al comienzo. El archivo también se utiliza para realizar actualizaciones cada vez que se instala una nueva versión del módulo. El archivo .install no tiene una sintaxis especial: Es simplemente un archivo PHP con una extensión de archivo distinta. Listado 2 muestra el código para el archivo note service .install.

Listado 2. Archivo note service .info
<?php
// note_service.install
/**
* Implementation of hook_schema().
*/
function note_service_schema() {
  $schema['note'] = array(
    'description' => t('Stores information about notes.'),
    'fields' => array(
      'id' => array(
        'description' => t('The primary identifier for a note.'),
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'uid' => array(
        'description' => t('The user that created the note.'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'created' => array(
        'description' => t('The timestamp for when the note was created.'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'modified' => array(
        'description' => t('The timestamp for when the note was modified.'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'subject' => array(
        'description' => t('The subject of the note'),
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
      ),
      'note' => array(
        'description' => t('The note'),
        'type' => 'text',
        'size' => 'medium',
      ),
    ),
    'primary key' => array('id'),
  );
  return $schema;
}
?>

Definiendo el servicio

Ahora, cree su archivo de módulo. Este archivo contiene la función PHP para devolver una serie de datos y arrojar los nodos de Note. Principalmente, la función implementa hook_services()de Drupal. No se necesita tener conocimientos detallados sobre desarrollo de módulo Drupal, pero sería útil. Sobra decir que como las funciones del archivo .module son funciones PHP, es importante asegurar que haya presente una etiqueta de apertura <?php en el código del archivo de módulo.

La mayoría de los servicios para el módulo Services implementa el método CRUD (create, retrieve, update, delete, index) aunque también es posible implementar acciones, acciones dirigidas y relaciones por otros medios que no están desarrollados en este artículo. El Listado 3 muestra el código para crear un archivo de módulo.

Listado 3. Archivo note service .module
<?php
// note_service.module
/** Gets a note object by id.
*
* @param int $id
* @return object
*/
function note_service_get_note($id) {
  return db_query("SELECT * FROM {note} WHERE id='".$id."'")->fetchAll();
}

/** Writes a note to the database
*
* @param object $note
* @return void
*/
function note_service_write_note($note) {
  $primary_key = !empty($note->id) ? array('id') : NULL;
  drupal_write_record('note', $note, $primary_key);
}

/**
* Deletes a note from the database.
*
* @param int $id
* @return void
*/
function note_service_delete_note($id) {
  db_query("DELETE FROM {note} WHERE id='".$id."'");
}

/**
* Implementation of hook_services_services().
*/
function note_service_services_services() {
  return array(
    'note' => array(
      'retrieve' => array(
        'help' => 'Retrieves a note',
        'file' => array('file' => 'inc', 'module' => 'note_service'),
        'callback' => '_note_service_retrieve',
        'access callback' => '_note_service_access',
        'access arguments' => array('view'),
        'access arguments append' => TRUE,
        'args' => array(
          array(
            'name' => 'id',
            'type' => 'int',
            'description' => 'The id of the note to get',
            'source' => array('path' => '0'),
            'optional' => FALSE,
          ),
        ),
      ),
      'create' => array(
        'help' => 'Creates a note',
        'file' => array('file' => 'inc', 'module' => 'note_service'),
        'callback' => '_note_service_create',
        'access arguments' => array('note service create'),
        'access arguments append' => FALSE,
        'args' => array(
          array(
            'name' => 'data',
            'type' => 'struct',
            'description' => 'The note object',
            'source' => 'data',
            'optional' => FALSE,
          ),
        ),
      ),
      'update' => array(
        'help' => 'Updates a note',
        'file' => array('file' => 'inc', 'module' => 'note_service'),
        'callback' => '_note_service_update',
        'access callback' => '_note_service_access',
        'access arguments' => array('update'),
        'access arguments append' => TRUE,
        'args' => array(
          array(
            'name' => 'id',
            'type' => 'int',
            'description' => 'The id of the node to update',
            'source' => array('path' => '0'),
            'optional' => FALSE,
          ),
          array(
            'name' => 'data',
            'type' => 'struct',
            'description' => 'The note data object',
            'source' => 'data',
            'optional' => FALSE,
          ),
        ),
      ),
      'delete' => array(
        'help' => 'Deletes a note',
        'file' => array('file' => 'inc', 'module' => 'note_service'),
        'callback' => '_note_service_delete',
        'access callback' => '_note_service_access',
        'access arguments' => array('delete'),
        'access arguments append' => TRUE,
        'args' => array(
          array(
            'name' => 'nid',
            'type' => 'int',
            'description' => 'The id of the note to delete',
            'source' => array('path' => '0'),
            'optional' => FALSE,
          ),
        ),
      ),
      'index' => array(
        'help' => 'Retrieves a listing of notes',
        'file' => array('file' => 'inc', 'module' => 'note_service'),
        'callback' => '_note_service_index',
        'access callback' => 'user_access',
        'access arguments' => array('access content'),
        'access arguments append' => FALSE,
        'args' => array(
          array(
            'name' => 'page',
            'type' => 'int',
            'description' => '',
            'source' => array(
              'params' => 'page',
            ),
            'optional' => TRUE,
            'default value' => 0,
          ),
          array(
           'name' => 'parameters',
           'type' => 'array',
           'description' => '',
           'source' => 'param',
           'optional' => TRUE,
           'default value' => array(),
          ),
        ),
      ),
    ),
  );
}
?>

Creando la devolución de llamados

Para crear devolución de llamados usted necesita crear el archivo file note_service.inc porque es allí donde usted le ha indicado a Services que puede encontrar la devolución de llamados. La devolución de llamados que se incorporará en el archivo .inc (con respecto al método CRUD) comprende:

  • Create callback
  • Retrieve callback
  • Update callback
  • Delete callback

También debe incluir un índice de devolución de llamado que capte y devuelva todas las notas de un usuario en particular. Especifique algunos argumentos aquí en el método, incluso si no se utilizan. El propósito de dichos argumentos es indicar que la página y el filtrado de un listado de índice están soportados.

Obviamente, no todos los usuarios deben tener libertad de permiso para ver los nodos Note. Es por esto que usted debe incluir devolución de llamados de acceso. Estas devoluciones de llamados de acceso, en realidad, deberían estar incluidas en el archivo del módulo principal. Note que no están representadas las funciones crear ni editar porque estas funciones utilizan directamente los argumentos user_access( ) . Además, a diferencia de otros métodos, el archivo no considera la propiedad de nota, y simplemente verifica que el servicio Note creado tenga permiso de acceso. El Listado 4 muestra el código del archivo .inc.

Listado 4. Archivo note service .inc
<?php
// note_service.inc
/**
* Callback for creating note services.
*
* @param object $data
* @return object
*/
function _note_service_create($data) {
  global $user;

  unset($data->id);
  $data->uid = $user->uid;
  $data->created = time();
  $data->modified = time();

  if (!isset($data->subject)) {
    return services_error('Missing note attribute subject', 406);
  }

  if (!isset($data->note)) {
    return services_error('Missing note attribute note', 406);
  }

  note_service_write_note($data);
  
  return (object)array(
    'id' => $data->id,
    'uri' => services_service_uri(array('note', $data->id)),
  );
}

// note_service.inc
/**
* Callback for updating note services.
*
* @param int $id
* @param object $data
* @return object
*/
function _note_service_update($id, $data) {
  global $user;
  $note = note_service_get_note($id);

  unset($data->created);
  $data->id = $id;
  $data->uid = $note->uid;
  $data->modified = time();

  note_service_write_note($data);
  
  return (object)array(
    'id' => $id,
    'uri' => services_service_uri(array('note', $id)),
  );
} 
/**
* Callback for retrieving note services.
*
* @param int $id
* @return object
*/
function _note_service_retrieve($id) {
  return note_service_get_note($id);
}

/**
* Callback for deleting note services.
*
* @param int $id
* @return object
*/
function _note_service_delete($id) {
  note_service_delete_note($id);
  
  return (object)array(
    'id' => $id,
  );
}

function _note_service_index($page, $parameters) {
  global $user;

  $notes = array();
  $res = db_query("SELECT * FROM {note} 
WHERE uid='".$user->uid."'ORDER BY modified DESC");
  foreach ($res as $note) {
    $notes[] = $note;
  }

  return $notes;
}

/**
* Access callback for the note service.
*
* @param string $op
*  The operation that's going to be performed.
* @param array $args
*  The arguments that will be passed to the callback.
* @return bool
*  Whether access is given or not.
*/

function _note_service_access($op, $args) {
  global $user;
  $access = FALSE;

  switch ($op) {
    case 'view':
      $note = note_service_get_note($args[0]);
      $access = user_access('note service view any note');
      $access = $access || $note->uid == $user->uid && 
      user_access('note service view own notes');
      break;
    case 'update':
      $note = note_service_get_note($args[0]->id);
      $access = user_access('note service edit any note');
      $access = $access || $note->uid == $user->uid &&  
      user_access('note service edit own notes');
      break;
    case 'delete':
      $note = note_service_get_note($args[0]);
      $access = user_access('note service delete any note');
      $access = $access || $note->uid == $user->uid && 
      user_access('note service delete own notes');
      break;
  }
  $access = TRUE;
  
  return $access;
}
?>

Cuando los archivos .info y .module están en orden en la nueva carpeta del módulo personalizado, usted puede activar el módulo en la página Administration de los módulos Drupal. Busque el módulo de servicio personalizado Note, seleccione la casilla de verificación que está junto al módulo para activarlo y guarde la configuración del módulo. Además, active los módulos de servidor Services y REST. Esto debería finalizar la creación de su módulo personalizado note_service.


Creando el punto final

Los servicios web representan un conjunto de herramientas de software que se pueden utilizar de varias formas, tres de las más comunes son SOA (arquitectura orientada a servicios), RPC y REST. RPC fue el foco inicial de las primeras herramientas de servicios web y por ello se convirtieron en el estilo más ampliamente desplegado y soportado, a pesar de que están acopladas de manera demasiado estrecha con llamados específicos a un lenguaje o método. En contraste, REST usa protocolos HTTP y similares, a través de operaciones conocidas como GET, POST, PUT, y DELETE, interactuando más con recursos de estado en lugar de operaciones y mensajes. Ambas herramientas de servidor están incluidas en el módulo Services (vea la carpeta Servers). Usted puede descargar otras herramientas en esta carpeta, pero este ejemplo se concentra en el método REST porque el punto final es universal.

Un punto final indica la ubicación específica donde se puede acceder a un servicio usando un protocolo específico y formato de datos. Hay dos formas de crear un punto final—ya fuere a través de código o usando la interfaz administrativa. Crear un punto final a través de una interfaz administrativa es la opción más sencilla porque de esa manera usted puede exportar y pegar el código en su módulo. Para crear un punto final, realice estos pasos:

  1. En Admin > Structure > Services, haga clic en Add.
  2. Ponga nombre a la nota de punto final.
  3. Elija REST como servidor y coloque la ruta al punto final en la nota.
  4. Deseleccione las casillas de verificación Debug Mode y Session Enabled .
  5. Haga clic en Save. La Figura 3 muestra el nuevo punto final de servicio en progreso.
    Figura 3. El nuevo punto final de servicio
    El nuevo punto final de servicio

    Ver una versión más amplia de la Figura 3.

  6. Haga clic en el enlace Services y seleccione los servicios o los grupos de servicios que desea activar. Deseleccione la casilla de verificación de las notas .
  7. Haga clic en Save.
  8. Haga clic en la pestaña Server y luego deseleccione la casilla de verificación application/x-www-form-urlencoded que está bajo Request parsing.
  9. Haga clic en Save.

Usted ha creado un punto final en correcto funcionamiento en su servidor REST.


Conclusión

En este artículo usted ha aprendido a utilizar el módulo Services de Drupal. Ha instalado y activado el módulo contribuido Services y ha observado la funcionalidad de sus servidores y la funcionalidad de sus servicios. Ha aprendido que puede agregar módulos de servidor para integrarlos con su sitio y contenido Drupal y colocar en servidor su contenido Drupal en sitios web externos utilizando los submódulos preempaquetados Services. Ha creado un módulo personalizado que se puede integrar con su módulo Services y que puede extender su funcionalidad predeterminada, y ha hecho un llamado de método para hacer una devolución de llamado que debería arrojar un listado de todos los nodos y los datos para un tipo de contenido específico.

Recursos

Aprender

Obtener los productos y tecnologías

Comentar

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=
ArticleID=827080
ArticleTitle=Crear un proyecto de servicios web personalizados en Drupal 7
publish-date=07242012