Skip to content

Using a different field for URL ID

jeff-h edited this page Oct 16, 2015 · 1 revision

In some cases you may wish to use something other than the Drupal entity IDs as the IDs in your API URLs (if, for example, you wish to use some sort of FQN, UUID, or similar for an API that needs to be integrated with other systems that are not aware of the Drupal ID system and have other constraints on IDs).

This can be easily done with restful, though it does take implementing the correct API methods.

By default, restful supports only numeric IDs in URLs. To change this, implement getControllers in your plugin class:

/**
 * Overrides \RestfulEntityBase::getControllers().
 */
public function getControllers() {
  return array('\w+' => array(
    \RestfulInterface::GET => 'viewEntities',
  ));
}

This tells the process method to use viewEntities for IDs that are composed of any alphanumeric characters. (You'd need to extend this to cover the POST, PUT, etc. cases).

That's all that's needed to accept non-numeric IDs in our API URLs. We can now use any logic we wish to load entities based on the ID we are given. We can use the title, for example:

  /**
   * Overrides \RestfulEntityBase::viewEntity().
   *
   * Wrap viewEntity to load the node via title. So we can use 
   * the fully qualified name (FQN) as the ID.
   */
  public function viewEntity($label) {
    $query = new EntityFieldQuery();
    $result = $query
      ->entityCondition('entity_type', 'node')
      ->entityCondition('bundle', $this->getBundle())
      ->propertyCondition('title', $label)
      ->propertyCondition('status', NODE_PUBLISHED)
      // There can be only a single item with this label.
      ->range(0, 1)
      ->execute();
    
    if (empty($result['node'])) {
      throw new \RestfulBadRequestException(format_string('Label @label is not a valid entity ID.', array('@label' => $label));
    }

    $id = key($result["node"]);
    return parent::viewEntity($id);
  }
Clone this wiki locally