Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough
Nov 28 2016
Nov 28

This article assumes you are familiar with what RESTful is & what do we mean when we use the term REST API. Some of you might have already worked with RESTful Web Services module in D7, it exposes all entity types as web services using REST architecture. Drupal 8 out of the box is RESTful with core support. All entities (provided by core + ones created using Entity API) are RESTful resources.

To explore the RESTful nature of Drupal 8, we will need to enable the following modules:

In Core

  • HAL - Serializes entities using Hypertext Application Language.
  • HTTP Basic Authentication - Provides the HTTP Basic authentication provider.
  • RESTful Web Services - Exposes entities and other resources as RESTful web API
  • Serialization - Provides a service for (de)serializing data to/from formats such as JSON and XML.

Contributed

  • REST UI - Provides a user interface to manage REST resources.

RESTful Resources

Every entity in D8 is a resource, which has an end point. Since, its RESTful, the same end-point is used for CRUD (Create, Read, Update, Delete) operations with different HTTP verbs. Postman is an excellent tool to explore / test RESTful services.  Drupal 8 allows you to selectively choose & enable a REST API. e.g., we can choose to expose only nodes via a REST API & not other entities like users, taxonomy, comments etc.

After enabling REST_UI module we can see list of all RESTful resources at /admin/config/services/rest. In addition to ability to choose the entity one can enable, we can also choose the authentication method per resource & enable specific CRUD operations per resource.

Resource Settings

Let us take a look at what the REST APIs for User entity would be after we save the configuration in the above screenshot.

User

POST

http:
{
 "_links": {
   "type": {
     "href": "http://domain.com/rest/type/user/user"
   }
 },
 "name": {
   "value":"testuser"
 },
 "mail":{
   "value":"[email protected]"
 },
 "pass":{
   "value":"testpass"
 },
 "status": {
   "value": 1
 }
}

Header

X-CSRF-Token: Get from http://domain.com/rest/session/token
Content-Type: application/hal+json
Accept: application/hal+json
Authorization: Basic (hashed username and password)

Note: Drupal 8 doesn't allow anonymous user to send a POST on user resource. It is already fixed in 8.3.x branch but for now we can pass the credentials of the user who have permission to create users. If you are interested in taking a deeper look at the issue, you can follow https://www.drupal.org/node/2291055.

Response: You will get a user object with "200 OK" response code

 

PATCH

http:
{
 "_links": {
   "type": {
     "href": "http://domain.com/rest/type/user/user"
   }
 },
 "pass":[{"existing":"testpass"}],
 "mail":{
   "value":"[email protected]"
 }
}

Note: Now as user have permission to update his own profile so we can pass current user's credentials in authentication header.

Response: You will get "204 No Content" in response code.

 

GET

http:

Response: You will get a user object with "200 OK" response code.

 

DELETE

http:

Response: You will get "204 No Content" in response code.

RESTful Views and Authentication

Drupal 8 also allows us to export views as a REST service. It allows you to use all the available authentication mechanism in views itself.

JSON API Module

JSON API module provides a new format called "api_json" which is soon becoming the de-facto standard for Javascript Frontend frameworks, If you plan to use completely de-coupled Drupal with frontend framework like Angular / React / Ember then its worth a look. To read more about JSON API you can visit the site.

Nov 28 2016
Nov 28

This article assumes you are familiar with what RESTful is & what do we mean when we use the term REST API. Some of you might have already worked with RESTful Web Services module in D7, it exposes all entity types as web services using REST architecture. Drupal 8 out of the box is RESTful with core support. All entities (provided by core + ones created using Entity API) are RESTful resources.

To explore the RESTful nature of Drupal 8, we will need to enable the following modules:

In Core

  • HAL - Serializes entities using Hypertext Application Language.
  • HTTP Basic Authentication - Provides the HTTP Basic authentication provider.
  • RESTful Web Services - Exposes entities and other resources as RESTful web API
  • Serialization - Provides a service for (de)serializing data to/from formats such as JSON and XML.

Contributed

  • REST UI - Provides a user interface to manage REST resources.

RESTful Resources

Every entity in D8 is a resource, which has an end point. Since, its RESTful, the same end-point is used for CRUD (Create, Read, Update, Delete) operations with different HTTP verbs. Postman is an excellent tool to explore / test RESTful services.  Drupal 8 allows you to selectively choose & enable a REST API. e.g., we can choose to expose only nodes via a REST API & not other entities like users, taxonomy, comments etc.

After enabling REST_UI module we can see list of all RESTful resources at /admin/config/services/rest. In addition to ability to choose the entity one can enable, we can also choose the authentication method per resource & enable specific CRUD operations per resource.

Resource Settings

Let us take a look at what the REST APIs for User entity would be after we save the configuration in the above screenshot.

User

POST

http:
{
 "_links": {
   "type": {
     "href": "http://domain.com/rest/type/user/user"
   }
 },
 "name": {
   "value":"testuser"
 },
 "mail":{
   "value":"[email protected]"
 },
 "pass":{
   "value":"testpass"
 },
 "status": {
   "value": 1
 }
}

Header

X-CSRF-Token: Get from http://domain.com/rest/session/token
Content-Type: application/hal+json
Accept: application/hal+json
Authorization: Basic (hashed username and password)

Note: Drupal 8 doesn't allow anonymous user to send a POST on user resource. It is already fixed in 8.3.x branch but for now we can pass the credentials of the user who have permission to create users. If you are interested in taking a deeper look at the issue, you can follow https://www.drupal.org/node/2291055.

Response: You will get a user object with "200 OK" response code

 

PATCH

http:
{
 "_links": {
   "type": {
     "href": "http://domain.com/rest/type/user/user"
   }
 },
 "pass":[{"existing":"testpass"}],
 "mail":{
   "value":"[email protected]"
 }
}

Note: Now as user have permission to update his own profile so we can pass current user's credentials in authentication header.

Response: You will get "204 No Content" in response code.

 

GET

http:

Response: You will get a user object with "200 OK" response code.

 

DELETE

http:

Response: You will get "204 No Content" in response code.

RESTful Views and Authentication

Drupal 8 also allows us to export views as a REST service. It allows you to use all the available authentication mechanism in views itself.

JSON API Module

JSON API module provides a new format called "api_json" which is soon becoming the de-facto standard for Javascript Frontend frameworks, If you plan to use completely de-coupled Drupal with frontend framework like Angular / React / Ember then its worth a look. To read more about JSON API you can visit the site.

Jun 24 2015
Jun 24

Menu upcasting means converting a menu argument to anything. It can be an object or an array. In this article, we will look at how it used to be done in Drupal 7 codebase & how should we port this into Drupal 8 codebase.


Lets take an example of the following code in Drupal 7:

function my_module_menu() {
  $items['node/%my_menu/mytab'] = array(
    // ...
    // ...
  );
}

The my_module_menu() function implementing hook_menu() shows a menu item with an argument %my_menu. Suppose we want the callback function for this menu item to recieve an object after doing some processing on the value passed from the url. e.g., we want to load a specific field of node with nid 1 when we hit node/1/mytab. 

To accopmplish the above in Drupal 7, would require us to create a loader function like the one below:

 
function my_menu_load($arg) {
  // Do whatever with argument and return your values
}

The page callback for the menu would recieve whatever is returned from the loader function defined above.

However, when it comes to Drupal 8, we all know the shift is towards configuration in yaml files & Object-oriented structure of the code. Drupal 8 construct to achieve this is making use of ParamConverter interface. To port the example mentioned above, we will need to do the following:

  1. Create my_module.routing.yml
  2. Create my_module.services.yml describing metadata for your custom paramconverter implementing the paramconverter interface
  3. Implement the custom paramconverter in a PHP class namespaced in my_module.services.yml
  4. Implement the callback for your menu item defined in my_module.routing.yml

Porting your menu item into Drupal 8 codebase:

my_module.mymenu:
  path: '/node/{my_menu}/mytab'
  defaults:
    _title: 'My Title'
    _form: '\Drupal\mymodule\Form\MyModuleformControllerForm'
  options:
    parameters:
      my_menu:
        type: my_menu

This is how a typical route would look like in Drupal 8. The route described above is going to render a form on the page depending on the my_menu argument passed down to it. 

NOTE: Its very important that the name of the parameter matches the variable in the page callback arguments. e.g., if the parameter name is declared as my_menu in routing.yml file, the callback function would receive the upcasted value in $my_menu variable.

Creating my_module.services.yml:

services:
  my_menu:
    class: Drupal\mymodule\ParamConverter\MyModuleParamConverter
    tags:
      - { name: paramconverter }

Make sure the tag value says paramconverter. This helps Drupal while rebuilding its cache to compile the services accordingly.

Creating MyModuleParamConverter as defined in the namespace above:

namespace Drupal\mymodule\ParamConverter;

use Drupal\Core\ParamConverter\ParamConverterInterface;
use Drupal\node\Entity\Node;
use Symfony\Component\Routing\Route;

class MyModuleParamConverter implements ParamConverterInterface {
  public function convert($value, $definition, $name, array $defaults) {
    return Node::load($value);
  }

  public function applies($definition, $name, Route $route) {
    return (!empty($definition['type']) && $definition['type'] == 'my_menu');
  }
}

This class implements ParamConverterInterface provided by Drupal 8 core. There are 2 functions implemented above:

  1. public function convert(): All your logic related to processing of the url argument goes in here. In the example above, we are converting the value picked up from the url into a node object.
  2. public function applies(): This is a validation function describing where the param convertion will be applicable. Definition variable recieves the definition for the menu parameter as defined in the routing.yml file. Since we want this convertion to be applicable only for parameters of type my_menu, the check is applied accordingly.

And, now at the last, our Callback class for the menu item:

.
.
.
Class MyModuleformControllerForm extends FormBase{
  .
  .
  .
  public function buildForm(array $form, FormStateInterface $form_state, NodeInterface $my_menu = NULL) {
    // $my_menu will be converted object from convert function above.
  }
  .
  .
  .
}

The callback above is focussed only on the buildForm function, since that is where the upcasted argument will be recieved. 

NOTE: The variable name must match the parameter value {my_menu}. The data type of the argument will depend on the return value from the convert function in MyModuleParamConverter.php.

These small chunks of code & you are all set to convert your menu parameters into almost anything required by your custom or contrib modules.

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web