Using the new Drupal 8 REST api with serialization we were trying to use Drupal 8 views "REST Export" pane on a content type with an entity reference field with the 'unlimited' possible values set. For example a
Customer content type, which may have many
To make life easier for front-end development, or other websites consuming the data, clients need only call the endpoint once because all the information needed would be in the first response thanks to the use of Entity Reference and it being set to unlimited.
Drupal 8 REST Endpoint Example With Entity Reference Using REST Views
This is an example endpoint configured with a context of customer id past in the url, and what you can achieve:
The objective is to have a simple endpoint like this, and receive a JSON response listing the customer and their contacts, all JSON encoded in one
Above we see a JSON response showing the
Customer, complete with a JSON array for each
Contact attached to this Customer. The
Contact entity reference field is set to 'Unlimited', so that add new Contacts are added and removed, the REST Endpoint adapts accordingly.
How to render / serialize entity reference fields with Drupal 8 Rest Export like this?
Out the box the Views REST export works fine if your content type doesn't have entity reference fields. To quote "":
When you create a view with a REST Export display, you will quickly encounter
hard limitations on the data structure, imposed by the Views module's reliance on the Render API:
- You may want to export a field with multiple values as an array.
By default, this is only possible by exporting the raw field, as the rendering
process also concatenates the output into a single string.
- An entity reference can only be exported as a fully rendered string,
and not as a nested structure with multiple individual fields.
- Boolean and numeric fields can only be exported as strings, rather than
the appropriate JSON primitives.
The Views and Field plugins in the Rest Views module add all of these features.
- Credit Christoph Burschka
We needed to show all fields of the referenced entity, and an expose these
n referenced entities as a JSON array.
Essentially we needed Drupal 8 to serialize the rendered entity, but Drupal Views core cannot serialize a rendered entity in this way. What we wanted was to answer the question: 'how to do Drupal views group by entity reference?' and out a JSON rest endpoint.
If this was a web view, we'd simply use rendered entity, with a custom display mode. However, just choosing 'rendered entity' in a REST endpoint doesn't work as Burschka points out. To achieve a REST Export of entity reference fields in views, Drupal's REST export by default doesn't serialize the entity reference; it only pulls in the entity reference title.
Thankfully, after much trial and error we found REST Views written by Christoph Burschka (cburschka). Rest Views allows us to create a JSON formatted endpoint including the serialization of all entity references and their fields. This works even when the entity reference field has unlimited values permitted. REST views can be configured to merge unlimited field values into a JSON array.
There's also a project 'rest-export nested' but we haven't experimented with this.
Eilyin's post on 'Rest API through views drupal 8 how to modify serializer' provides good backgroupd to creating your own serializer. Burschka's REST Views module goes all the way providing a very intuitive solution.
How to use REST Views Module
Here's an example of how to use the REST Views module. The scenario is:
Imagine you're building a CRM and your Customers have many Contacts for example:
- Joe from Marketing
- Clare from Sales
- Sally the Director
These people are all stored in a Contact types and attached to a Customer content type via an Entity reference field set to 'unlimited'.
You want to create a REST endpoint which when called, spits back your Customer entity, and all associated Contacts in one request.
1. Create a Contact content type
Create a basic
Contact content type. For example first name/last name and an email address. This will be the references entity for when a Customer has many contacts.
(You may want to use an actual user account if this if your exact use-case)
2. Create a customer content type
Customer content type, and add a field of type Entity Reference named
Set the allowed number of values to unlimited:
Set reference type to
3. Create a new REST Export View called 'Customer'
Create a new view, but choose "REST EXPORT", and check 'Provide a REST export.
We've set the endpoint path to
api/customer/% because we want the client to supply a customer id when making the request.
We could, for example, go further and create another endpoint called
/customers which listed all customers or paginated the result showing all possible customer Ids.
4. Choose Show Fields on REST Export
By default the view will output the entire entity, we want to select show 'fields'.
On all fields, click them and unckeck "Link to the Content" because this will clean up the REST endpoint output. Do this for every field you add. You don't need a link to the content without your JSON response, if you do, add an
id field instead and create another endpoint for that content type.
We now have clean JSON output, showing just the
title field of the
Customer content type. Next we need to add our
Contacts unlimited entity reference field to the view.
5. Add Serializable Entity Reference Field (Unlimited values) To View
Click 'add fields' to your view and search for the
'Customer Contacts (serializable) field to your view. Notice the serializable appended to the field name. This has been made available to you thanks to the REST Views module (make sure it's installed).
Press 'Add and configure fields', then choose the correct formatter (next step).
6. Choose 'Export Rendered Entity' Formatter
The REST Views module makes available the 'Export rendered entity' formatter. Choose this, and leave the default 'Multiple Field Settings' as they are.
Press apply and you now have a fully serialized JSON enpoint for getting customers and their associated contacts via the entity reference!
To finish off, add a contextual filter to your view to filter on Customer id because at the moment the view will send back all customers and their associates contacts.
7. Add contextual filter (Optional)
The objective is to be able to pass a customer id to
example.com/api/customer/<customer-id> and have the endpoint only send back data related to that customer. Do this by adding contextual filter:
Set your view path to allow a customer ID to be passed to endpoint
We set it to
Add contextual filter based on Customer id
Search and select "ID" based on the ID of Customer:
ID Means the node id of the Customer content type. So if our customer has an ID of 15, our REST call would be
Add some basic filter validation (optional)
Here we've set: If a customer ID is not given, then we show
Access Denied. Also we validate the customer ID to be numeric:
Finally, remember to enable authentication on your endpoints. Drupal's REST web services API does respect node access settings, but it's easy to mistakenly give access to resources. Be careful. For example, look into using Drupal's built-in Basic Auth (and use over SSL).
Completed Restful Enpoint using Rest Views
Using a tool like Advanced Rest Client developers can easily play with the endpoint and inspect the response visually: