Getting URL Alias For Referenced Entity With RESTful API in Drupal

As documented in a previous post, with RESTful, you can create a separate API endpoint to look up the base node ID from a URL alias for a specific entity. However, there are also URL aliases for other entities that are referenced from within your base entity, such as users and taxonomy terms. We don't want to have to do a separate lookup for each of these entities outside of our base entity, so the ideal situation would be to just have a field returned within our base entity lookup that contains these URL aliases.

As an example, let's say that in our Blog entity, instead of using the built in node creator for the author, we have an entity reference field called Author (field_author) that references users (this gives us flexibility in specifying the content author in allowing us to easily select other names, as well as allowing us to have multiple authors). And, as is typical in Drupal 7, we use term reference fields for taxonomy terms, and since in a decoupled front end we want to display those terms as links, we need that path. We want to be able to get these aliases as fields when we query the Blog node.

The solution to this problem in RESTful is process callbacks (see this video for examples). These work very similar to process callbacks in the Form APi in Drupal; they are simply custom callbacks that can be used to do custom manipulating of field data once it has been retrieved and before it is returned.

The callbacks are added in the field definition in the publicFields function using the process_callbacks key. Here is the definition for a user alias within the Users class:

class Users__1_1 extends Users__1_0 {

  /**
   * {@inheritdoc}
   */
  protected function publicFields() {
    $public_fields = parent::publicFields();
...
    $public_fields['alias'] = array(
      'property' => 'uid',
      'process_callbacks' => array(
        array($this, 'getAlias')
      )
    );

    return $public_fields;
  }

  public function getAlias($value) {
    return drupal_get_path_alias('user/' . $value);
  }
}

Things to note in this code:

  • The property is the data that you need to have to get the alias, and in this case it is the user id (uid).
  • We define the callback name as an array with the $this reference as the first item because we are making the callback a member function in this class. If the function were placed elsewhere (such as a .module or .inc file) or is a regular PHP function, we would just pass the function name.
  • The $value argument that is passed to the callback is the value of the field defined in the property key; in this case, the uid.

We just call drupal_get_path_alias() and pass it the uid to get the URL alias. This alias is then returned as part of the author member in the JSON object:

{
  "type": "users",
  "id": "123",
  "attributes": {
    "id": "123",
    "label": "Steve Edwards",
    "self": "http://mysite.com/api/v1.1/users/123",
    "mail": "sedwards@mysite.com",
    "name": "Steve Edwards",
    "alias": "author/steve-edwards"
}

A similar case is a taxonomy term from a term reference field. Here is an example for a Journalists vocabulary:

class Journalists__1_0 extends ResourceEntity implements ResourceInterface {

  /**
   * {@inheritdoc}
   */
  protected function publicFields() {
    $public_fields = parent::publicFields();

    $public_fields['alias'] = array(
      'property' => 'tid',
      'process_callbacks' => array(
        array($this, 'getAlias')
      )
    );

    return $public_fields;
  }

  public function getAlias($value) {
    return drupal_get_path_alias('taxonomy/term/' . $value);
  }
}

This is very similar to the Author example, with the only difference being that we are passing a term id (tid) instead of a user id. The resulting output is the same:

{	
  "type": "journalists",
  "id": "1938",
  "attributes": {
    "id": "1938",
    "label": "Jake Tapper",
    "self": "http://mysite.com/api/v1.0/journalists/1938",
    "alias": "journalists/jake-tapper"
},

As mentioned above, if you are familiar with process callbacks in Form API, then this will look very familiar.

Also, see this wiki page I created in the GitHub repo for RESTful for another example of using process callbacks to add the path for an image style derivative.

Dec26