text: The Services module allows you to enable custom-built content servers and services on your Drupal site from one main module back-end configuration and administration area. The services included in the module allow you to call content and output data from Drupal's default and contributed File, Comment, Search, User, Menu, Node, System, Taxonomy, and Views modules. By calling these services, content can be fetched from your Drupal site and displayed on another Drupal site, either on the same local server or from an external location. However, you can also use the Services module to integrate applications that are not Drupal based with an external web service.
  The Services module's flexibly permits you to programmatically create your own custom service module and integrate it with method calls (such as Representational State Transfer [REST], JavaScript Object Notation [JSON], and XML-remote procedure call [XML-RPC]) that come packaged with the main Services module. The main benefit of the Services module is that it enables web service integration with multiple applications while using the standard Drupal module code and programming. More importantly, the Services module helps to reduce the amount of time spent writing your own web service modules, as it provides a standard interface for a number of the common web service application environments.
  This article looks at how you can create a web service module that will run a custom callback from a Drupal site using the Service module. You write a custom module to return a set of data from a node of a specific content type. You'll also learn how to:
  - Write a custom module for a service
  - Integrate this module with the Services module and test it to return an output (This is an example of a simple callback that returns a set of nodes.)
  Obtaining and installing the required modules
  First, you must download the following necessary modules from the Drupal.org site:
  - Services. This is the main Services module downloaded from the project page (see Resources for a link).
  - Chaos tool suite. The Services module depends on this suite, so you must actually install it first or at the same time as the Services module. The Chaos tool suite provides the framework for the endpoint definitions so that they can be defined and exported in both database and code. See Resources for a link to the download site.
  - REST server. You use the REST server, which is included in the Services download, to test the service. You can use other services, such as JSON and XML-RPC, as well.
  - Autoload. The REST server requires this utilities module. The Autoload module enables other modules to leverage PHP 5's
  autoloadingclass capabilities in a unified fashion. See Resources for a link.
  Install these modules to your /sites/all/modules folder. After uploading the services, if you look inside the folder, you will find that it contains two subfolders: servers and services. The servers folder contains the web services module code and the core module contains support for the XML-RPC server. The services folder includes modules for providing web services of Drupal-based content, including files, comments, nodes, menus, search, users, system, taxonomy, and views (see Figure 1). These folders are all submodules of the Services module.
  Figure 1. Contents of the Services module folder
  When installation is complete, go to the main modules administration list in your Drupal site and enable the main core Services module, the Key Authentication module, the XML-RPC server, and the Services module. After enabling the modules, you will be able to view your installed and enabled servers and services on the Administration page along with the main core services settings. From the /admin/structure/services page of your site, you can easily browse your installed servers and services modules and view any application programming interface (API) keys you have added to your site to use with your servers and overall services. Figure 2 shows an example Browse page.
  Figure 2. Adding a new service
  Click Add to list and title your web service and add an allowed external web server domain with which you will be communicating. The web service you're communicating with can then access your site to consume these services and access the data. You may already be conversant with social media websites such as Facebook and Twitter as well as a host of other web applications that enable seamless exchange and import of user date to facilitate login procedures. From the Admin > Configuration > Services section, the Settings page shows authentication methods and settings that have been enabled and asks whether you want to apply additional content permissions to your content when it is consumed. The field permissions on your content types will not automatically cascade during a web service call. By default, all content fields are returned without any exclusion, but you can apply specific content field-level permissions.
  Creating a custom service module
  A Drupal module is a collection of files written in PHP that effectively extend the functionality of the basic application. When viewed more closely, a module is no different in structure from any other PHP file and can be independently created, tested, and used in several different installations. The module code can typically access all variables and structures as well as use all the functions of the Drupal core. Similarly, the Drupal core can call—through fixed interfaces known as hooks—those functions that have been defined in modules to enhance its inherent basic functionality.
  Hooks make it possible for Drupal to do perform such tasks as:
  - Add new URLs and pages to be defined by a module within the site (
  hook_menu)
  - Add content to Drupal pages (
  hook_block,
  hook_footer, and so on)
  - Create custom database tables (
  hook_schema)
  You will see hook definitions in several places within the code of the new module you'll be creating. Like most other Drupal modules, the module file typically consists of three basic files: modulename.info, modulename.module, and modulename.inc. A more complex module may consist of several more files.
  To begin creating your custom service or services module files, in the /sites/all/modules/services folder, add a new folder for this module named note_service.
  The .info file
  In addition to the note_service folder, create a new file named note_service.info. This file will contain all the metadata and information Drupal requires to list the module in the main modules administration page.
  In the .info file, enter the code shown in Listing 1.
  Listing 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
  Save the file as note_service.info. This code describes the name of the service, a description of what it does, the overall module package the custom module is part of, and the dependencies. In this case, this means that for your custom module to work at all, the Services module must be installed and enabled. Put this note_service.info file in your module folder.
  The .install file
  The .install file tells Drupal how the module is to be installed—in
  this case, by implementation of the hook schema. The .install file runs
  when a module is enabled for the first time, and its basic function is to
  run the setup procedures required by that module. The most common task the
  .install file performs is to create database tables and fields. The
  installation instructions are included in a
  _install() function. This hook function is
  called when the module is initially enabled. The file is also used to
  perform updates whenever a new version of a module is installed. The
  .install file has no special syntax: It is merely a PHP file with a
  different file extension. Listing 2 shows the code
  for the note service .install file.
  Listing 2. Note service .install file
  <?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('), ); return $schema; } ?>
  Defining the service
  Now, you create your module file. This file contains the PHP function to
  return a data array and output the Note nodes. The function mainly
  implements Drupal's
  hook_services(). A detailed
  understanding of Drupal module development is not required, although it's
  helpful. Needless to say, as the functions in the .module file are PHP
  functions, it is important to ensure that an opening
  <?php tag is present in the module file
  code.
  Most services for the Services module implement the create, retrieve, update, delete, index (CRUD) method, though it is also possible to implement actions, targeted actions, and relationships by other means not covered in this article. Listing 3 shows the code to create a module file.
  Listing 3. Note service .module file
  <?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('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(), ), ), ), ), ); } ?>
  Creating the callbacks
  To create callbacks, you need to create the file note_service.inc file, as this is where you have told Services the callbacks can be found. The callbacks that will be incorporated in the .inc file (with respect to the CRUD method) include:
  - Create callback
  - Retrieve callback
  - Update callback
  - Delete callback
  You should also include an index callback that fetches and returns all of a particular user's notes. Specify some arguments here in the method, even if they aren't used. The purpose of such arguments is to indicate that paging and filtering of an index listing are supported.
  Obviously, not all users should have unhindered permission to view the Note
  nodes. This is why you should include access callbacks. These access
  callbacks ought actually to be included in the main module file. Note that
  neither create nor edit functions are represented, because these functions
  directly use
  user_access( ) statements. Also,
  unlike other methods, the file does not consider note ownership, it merely checks the Note service created for access
  permission. Listing 4 shows the .inc file code.
  Listing 4. Note service .inc file
  <?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; } ?>
  When the .info and .module files are in place in the new custom module folder, you can enable the module on the Drupal modules Administration page. Look for the custom Note service module, select the check box next to the module to enable it, and save the module configuration. Also, enable the Services and REST server modules. This should finalize the creation of your custom note_service module.
  Creating the endpoint
  Web services represent a set of software tools that can be used in several
  ways, the three most common of which are service-oriented architecture
  (SOA), RPC, and REST. RPC was the initial focus of the first web services
  tools and thus became the style more widely deployed and supported, even
  though it's too tightly coupled to language-specific or method calls. In
  contrast, REST uses HTTP and similar protocols through familiar operations
  such as
  GET,
  PUT, and
  DELETE,
  thus interacting more with stateful resources rather than with operations
  and messages. Both server tools are included in the Services module (see
  the Servers folder). You can download other tools into this folder, but
  this example focuses on the REST method, because the endpoint is universal.
  An endpoint indicates the specific location where a service can be accessed by using a specific protocol and data format. There are two ways to create an endpoint—either through code or by using the administrative interface. Creating an endpoint through the administrative interface is the easier option, as you can then export and paste the code into your module. To create an endpoint, perform the following steps:
  - In Admin > Structure > Services, click Add.
  - Name the endpoint
  note.
  - Choose REST as your server, and place the path to endpoint at note.
  - Clear the Debug Mode and Session Enabled check boxes.
  - Click Save. Figure 3 shows the new service endpoint in progress.
  Figure 3. The new service endpoint
  View a larger version of Figure 3.
  - Click the Services link, and select the services or service groups you want to enable. Clear the notes check box.
  - Click Save.
  - Click the Server tab, and then clear the application/x-www-form-urlencoded check box under Request parsing.
  - Click Save.
  You have now created a proper working endpoint in your REST server.
  Conclusion
  In this article, you learned how to use the Drupal Services module. You installed and enabled the contributed Services module and looked at the functionality of its servers and services functionality. You learned that you can add server modules to integrate with your Drupal site and content and serve your Drupal content to external websites using the prepackaged Services submodules. You have created a custom module that can integrate with your Services module and extend its default functionality and made a method call to return a callback that should output a listing all of the nodes and data for a specific content type.
  Resources
  Learn
  - The Open Source developerWorks zone provides a wealth of information on open source tools and using open source technologies.
  - Visit the Safari bookstore e-reference library to find specific technical resources.
  - Follow developerWorks on Twitter.
  - Explore more about Drupal on developerworks.
  Get products and technologies
  - Get more information on Drupal 7.
  - Download the Drupal Services module.
  - Download the Chaos tool suite
  - Download the Autoload module.
  Discuss
  - Check.