Headless Drupal 8

Post on 29-Nov-2014

548 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

"The front-end moves faster than Drupal, whether Drupal likes it or not" This reference from "The state of the Front-end" session at DrupalCon Amsterdam explains that we need different ways to retrieve content from a Drupal site for an easy integration with new front-end frameworks. This allows non-experienced front-end developers to start theming Drupal using the tools they are used to. In this session you will learn how to enable the new Drupal 8 features that exports all the content in a front-end friendly format (JSON, HAL). Also I'll show a simple Backbone.js application that will load that content and print it using only the specific markup you need.

Transcript

Headless Drupal 8#HeadlessDrupal

DrupalCamp Göteborg 2014

Ruben Teijeiro @rteijeiro

Drupal 7 Front-end Sucks!

DIVITIS

BUT

Drupal 8 Front-end is MortenDK Certified

I love Twig!! WTF!!WTF!!

BUT

"The front-end moves faster than Drupal, whether

Drupal likes it or not"

@eatings at DrupalCon Amsterdam

https://amsterdam2014.drupal.org/session/state-front-end

"The front-end moves faster than Drupal, whether Drupal likes it or not"

We have a solution

DECOUPLING

Decoupling Drupal Front-end makes easier to get

unexperienced front-end developers involved in Drupal

projects

Headless Drupal 8

We don't need contrib anymoar!!

Headless Drupal 8 REST modules are in Core

Don't forget the permissions

A little bit of CRUD

CRUD

CreateReadUpdateDelete

curl --include --request POST--user user:password--header 'Content-type: application/hal+json'http://localhost/drupal8/entity/node--data-binary '{"_links":{"type":{"href":"http://localhost/drupal8/rest/type/node/page"}}, "title":[{"value":"Node created using curl"}], "body": [{"value":"This is the body of the node created using curl"}]}'

Sample Create Request

HTTP/1.1 201 CreatedDate: Fri, 24 Oct 2014 10:26:50 GMTServer: Apache/2.2.22 (Debian)X-Powered-By: PHP/5.4.33-1~dotdeb.1Location: http://localhost/drupal8/entity/node/2

Sample Create Response

CRUD

CreateReadUpdateDelete

Sample Read Request

curl-H "Accept:application/hal+json" --request GET http://localhost/drupal8/node/2

Sample Read Response{"_links":{"self":{"href":"http:\/\/localhost\/drupal8\/node\/2"},"type":{"href":"http:\/\/localhost\/drupal8\/rest\/type\/node\/page"},"http:\/\/localhost\/drupal8\/rest\/relation\/node\/page\/uid":[{"href":"http:\/\/localhost\/drupal8\/user\/1","lang":"en"}],"http:\/\/localhost\/drupal8\/rest\/relation\/node\/page\/revision_uid":[{"href":"http:\/\/localhost\/drupal8\/user\/1"}]},"uuid":[{"value":"f89b04b9-b2b2-4230-8e5c-92fb3856213d"}],"type":[{"target_id":"page"}],"langcode":[{"value":"en"}],"title":[{"value":"Node updated using curl","lang":"en"}],"_embedded":{"http:\/\/localhost\/drupal8\/rest\/relation\/node\/page\/uid":[{"_links":{"self":{"href":"http:\/\/localhost\/drupal8\/user\/1"},"type":{"href":"http:\/\/localhost\/drupal8\/rest\/type\/user\/user"}},"uuid":[{"value":"b3e6e828-03fa-4a19-a706-6bba6f47edc4"}],"lang":"en"}],"http:\/\/localhost\/drupal8\/rest\/relation\/node\/page\/revision_uid":[{"_links":{"self":{"href":"http:\/\/localhost\/drupal8\/user\/1"},"type":{"href":"http:\/\/localhost\/drupal8\/rest\/type\/user\/user"}},"uuid":[{"value":"b3e6e828-03fa-4a19-a706-6bba6f47edc4"}]}]},"status":[{"value":"1","lang":"en"}],"created":[{"value":"1414146410","lang":"en"}],"changed":[{"value":"1414147433","lang":"en"}],"promote":[{"value":"0","lang":"en"}],"sticky":[{"value":"0","lang":"en"}],"revision_timestamp":[{"value":"1414146410"}],"body":[{"value":"This is the body of the node updated using curl","format":null,"summary":null,"lang":"en"}]}

CRUD

CreateReadUpdateDelete

Sample Update Request

curl --include --request PATCH--user user:password--header 'Content-type: application/hal+json' http://localhost/drupal8/node/2--data-binary '{"_links":{"type":{"href":"http://localhost/drupal8/rest/type/node/page"}}, "title":[{"value":"Node updated using curl"}], "body": [{"value":"This is the body of the node updated using curl"}]}'

Sample Update Response

HTTP/1.1 204 No ContentDate: Fri, 24 Oct 2014 10:43:53 GMTServer: Apache/2.2.22 (Debian)X-Powered-By: PHP/5.4.33-1~dotdeb.1

CRUD

CreateReadUpdateDelete

Sample Delete Request

curl --include --request DELETE--user user:password--header 'Content-type: application/hal+json' http://localhost/drupal8/node/2

Sample Delete Response

HTTP/1.1 204 No ContentDate: Fri, 24 Oct 2014 10:51:04 GMTServer: Apache/2.2.22 (Debian)X-Powered-By: PHP/5.4.33-1~dotdeb.1

Views are in Core too!!

Thanks @pfrenssen forhttps://www.drupal.org/node/2317085

REST export

REST export settings

curl-H "Accept:application/hal+json" --request GET http://localhost/drupal8/node/rest

Sample Request

Sample Response[{"_links":{"self":{"href":"http:\/\/localhost\/drupal8\/node\/1"},"type":{"href":"http:\/\/localhost\/drupal8\/rest\/type\/node\/article"},"http:\/\/localhost\/drupal8\/rest\/relation\/node\/article\/uid":[{"href":"http:\/\/localhost\/drupal8\/user\/1","lang":"en"}],"http:\/\/localhost\/drupal8\/rest\/relation\/node\/article\/revision_uid":[{"href":"http:\/\/localhost\/drupal8\/user\/1"}]},"uuid":[{"value":"5fad49bf-5c70-475d-9333-51c25caf62d5"}],"type":[{"target_id":"article"}],"langcode":[{"value":"en"}],"title":[{"value":"You don't get sick, I do","lang":"en"}],"_embedded":{"http:\/\/localhost\/drupal8\/rest\/relation\/node\/article\/uid":[{"_links":{"self":{"href":"http:\/\/localhost\/drupal8\/user\/1"},"type":{"href":"http:\/\/localhost\/drupal8\/rest\/type\/user\/user"}},"uuid":[{"value":"b3e6e828-03fa-4a19-a706-6bba6f47edc4"}],"lang":"en"}],"http:\/\/localhost\/drupal8\/rest\/relation\/node\/article\/revision_uid":[{"_links":{"self":{"href":"http:\/\/localhost\/drupal8\/user\/1"},"type":{"href":"http:\/\/localhost\/drupal8\/rest\/type\/user\/user"}},"uuid":[{"value":"b3e6e828-03fa-4a19-a706-6bba6f47edc4"}]}]},"status":[{"value":"1","lang":"en"}],"created":[{"value":"1413657929","lang":"en"}],"changed":[{"value":"1413657957","lang":"en"}],"promote":[{"value":"1","lang":"en"}],"sticky":[{"value":"0","lang":"en"}],"revision_timestamp":[{"value":"1413657929"}],"revision_log":[{"value":"","lang":"en"}],"body":[{"value":"<p>Your bones don't break, mine do. That's clear. Your cells react to bacteria and viruses differently than mine. You don't get sick, I do. That's also clear. But for some reason, you and I react the exact same way to water. We swallow it too fast, we choke. We get some in our lungs, we drown. However unreal it may seem, we are connected, you and I. We're on the same curve, just on opposite ends.<\/p>\r\n","format":"basic_html","summary":"","lang":"en"}],"comment":[{"status":"2","cid":"0","last_comment_timestamp":"1413657957","last_comment_name":null,"last_comment_uid":"1","comment_count":"0","lang":"en"}]}]

vs

HAL JSON

Use HAL if you care about API definition

{ "_links": {

"self": { "href": "/your-api-links" }

},

"_embedded": {

"items": [

Array of serialized items

]

}

}

Use JSON if you only care about the content

[

{ "title": “This is your content title”,

"body": “This is your content body.”

}

]

How to enable JSON requests

Like a Ninja

Like a Ninja

core/modules/rest/config/install/rest.settings.yml

resources: entity:node: GET: supported_formats: - hal_json supported_auth: - basic_auth POST: supported_formats: - hal_json supported_auth: - basic_auth PATCH: supported_formats: - hal_json supported_auth: - basic_auth DELETE: supported_formats: - hal_json supported_auth: - basic_auth

Configuration Management – Single Import

Like a Boss

https://www.drupal.org/project/restui

Sample JSON Request

curl -H "Accept: application/json" --request GET http://localhost/drupal8/node/rest

Sample JSON Response

[{"nid":[{"value":"1"}],"uuid":[{"value":"5fad49bf-5c70-475d-9333-51c25caf62d5"}],"vid":[{"value":"1"}],"type":[{"target_id":"article"}],"langcode":[{"value":"en"}],"title":[{"value":"You don't get sick, I do"}],"uid":[{"target_id":"1"}],"status":[{"value":"1"}],"created":[{"value":"1413657929"}],"changed":[{"value":"1413657957"}],"promote":[{"value":"1"}],"sticky":[{"value":"0"}],"revision_timestamp":[{"value":"1413657929"}],"revision_uid":[{"target_id":"1"}],"revision_log":[{"value":""}],"path":[{"alias":null,"pid":null}],"body":[{"value":"<p>Your bones don't break, mine do. That's clear. Your cells react to bacteria and viruses differently than mine. You don't get sick, I do. That's also clear. But for some reason, you and I react the exact same way to water. We swallow it too fast, we choke. We get some in our lungs, we drown. However unreal it may seem, we are connected, you and I. We're on the same curve, just on opposite ends.<\/p>\r\n","format":"basic_html","summary":""}],"comment":[{"status":"2","cid":"0","last_comment_timestamp":"1413657957","last_comment_name":null,"last_comment_uid":"1","comment_count":"0"}],"field_image":[{"target_id":null,"display":null,"description":null,"alt":null,"title":null,"width":null,"height":null}],"field_tags":[{"target_id":null}]}]

BEWARE!!hal_json is the only format supported

for POST and PATCH methods

https://www.drupal.org/node/1964034

It needs work:

Getting a cleaner JSON response

Use Fields in View

Fields Raw Format

Clean JSON Response

[ { "title":"You don't get sick, I do", "body":"<p>Your bones don't break, mine do. That's clear. Your cells react to bacteria and viruses differently than mine. You don't get sick, I do. That's also clear. But for some reason, you and I react the exact same way to water. We swallow it too fast, we choke. We get some in our lungs, we drown. However unreal it may seem, we are connected, you and I. We're on the same curve, just on opposite ends.<\/p>" }]

Happy now?

DEMO

Want to contribute?

How to POST a comment and other relational entities

Add special handling for collections in REST

Support ConfigEntity via REST

[meta] REST et al

File needs CRUD permissions to make REST work on entity/file/{id}

Serialize file content (base64) to support REST GET/POST/PATCH on file entity

Join the Code Sprints!!

Questions??

Thanks!

top related