Getting started with the Drupal RESTful module

The need to make Drupal content available through a RESTful Web Service is becoming more and common. This enables the content from your Drupal site to be exposed as an API and consumed by a 'headless' application using a modern frontend framework such as AngularJS or Backbone.js.

The Services module is not always the answer

The Services module has always been a popular way to achieve this however one if its drawbacks is that it tries to cater for every possible use case with numerous web services and data formats supported. It also returns rather big and unwieldy data objects for even the most basic of requests.

Enter the RESTful module

I was listening to the Drupalize.me podcast last month where Mateu Aguiló Bosch and Amitai Burstein were discussing the RESTful module that they've been developing over the past year. Whist the use case is narrower in that it is for creating a RESTful web service and only supports the JSON data format out of the box, this should still cater for the majority of people building headless Drupal applications.

Defining our RESTful Plugin

Unlike the Services module where resources can be enabled by simply clicking a checkbox on the configuration page, the RESTful module requires that you create a plugin using code. But don't worry, this is actually very straightforward to do!

The first step is to create a module that declares the location of our RESTful plugins. This goes in the .module file.

/**
  * Implements hook_ctools_plugin_directory().
  */
function my_module_ctools_plugin_directory($module, $plugin) {
  if ($module == 'restful') {
    return 'plugins/' . $plugin;
  }
}

You then need to create a directory named 'restful' that sits within this 'plugins' directory. Although not required, it also helps organise things to create a seperate directory for each plugin and a directory for each version number. We therefore end up with something like this:

my_module/plugins/restful/articles/1.0

Within this directory you should then define the resource plugin in a .inc file. Here I've created a file named articles.inc that will be used to expose the article nodes on our site:

$plugin = array(
  'label' => t('Articles'),
  'resource' => 'articles',
  'name' => 'articles',
  'entity_type' => 'node',
  'bundle' => 'article',
  'description' => t('Resource used to expose articles content from our site.'),
  'class' => 'RestfulArticlesResource',
);
  • The label can be anything but it's easiest to just name this the same as the resource.
  • The resource is what will be used in the URL that exposes the data.
  • The name should match the name of the file.
  • The entity_type and bundle define where we're pulling the content from.
  • The description can be anything.
  • The class should be the name of the resource class that we're going to create next.

Examining the node's properties

We now need to decide which properties form our article nodes we are are going to expose in our API. I find the easiest way to get a list of the properties available is to use the Devel module and call the getPropertyInfo() method on the entity wrapper:

Creating the resource class

We're now going to create a file in the same directory named RestfulArticlesResouce.inc. As we're exposing content from a node, we should create a class that extends the RestfulEntityBaseNode class. You can view other the classes that can be extended by going to the plugins/restful directory of the RESTful module. We can then declare the fields to be made available by overriding the publicFieldsInfo() function.

class RestfulArticlesResource extends RestfulEntityBaseNode {

  /**
    * Overrides RestfulEntityBaseNode::publicFieldsInfo().
    */
  public function publicFieldsInfo() {

    $public_fields = parent::publicFieldsInfo();

    $public_fields['body'] = array(
      'property' => 'body',
      'sub_property' => 'value',
    );

    $public_fields['category'] = array(
      'property' => 'field_category',
      'sub_property' => 'tid',
    );

    $public_fields['author'] = array(
      'property' => 'author',
      'sub_property' => 'name',
    );

    $public_fields['created'] = array(
      'property' => 'created',
      'process_callbacks' => array(
        array($this, 'formatCreatedDate'),
      ),
    );

    return $public_fields;
  }

  /**
    * Format created date.
    */
  protected function formatCreatedDate($value) {
    return date ('j F Y', $value);
  }

}

You can see that we're using sub properties for both the body and category fields. Specifying 'value' as the sub_property for the body field means that the entire field will be returned however we could have also specified 'summary'. Using the 'name' sub_property for the category field provides us with the taxonomy term name but we could have also used 'tid' to get the term's ID. For the created field we use a process_callback function to format the date in a readable format rather than just showing a timestamp.

Viewing our resource

Once this is all done the resource can then then be accessed by going to [site url]/api/v1.0/articles in the browser. The result is shown below:

If we wanted to just return a specific node then we could just call [site url]/api/v1.0/articles/[node id].

The RESTful module provides us with a much cleaner object containing only the data we want to expose and also allows us to name each item however we like.

The module itself includes a restful_example submodule so the best place to start is to enable this on your Drupal site and go from there. You can find documentation within the docs directory of the RESTful module.

There's also a couple of patches that need to be applied to the Entity API module so be sure to do this before you start.

Example module

comments powered by Disqus