KevinBlanco.io

Drupal Certified Specialist and Activist. Javascript Enthusiasts and Entrepreneur

Drupal Views: The Power of Contextual Filters

On my last blog entry I talked about how to build a quick RESTful view in Drupal 8 taking advantage of the RESTful Web Services module that is now in Core. The small endpoint I built returns an array of cars in sale, with relative information about each car. You can see the endpoit working here: http://dev-cars-api.pantheonsite.io/api/cars and here’s my view configuration until now:

Very straigtforward, i’m just showing fields of the Cars content type.

What are Contextual Filters useful for?

Right now my view endpoint return all cars in sale, and there’s no chance for filtering the results. In a real life app where we would consume this API, we would want to filter them by brand or type, and even price range, etc. We can accomplish this with contextual filters.

Contextual Filters are, in scence, URL arguments that filter the content of the view, that’s the simplest explanation. So let’s say that perhaps you want to get all Land Rover cars in sale, or all Toyota and 4x4 cars, so let’s do it.


Filter car by Brand and Type

Add the contextual filter:

Go to your view and find the Advanced area, usually located right side or the screen and click on “Add” button next to the “Contextual Filters” label. Now find the field you want to add as an URL argument, in my case is called Brand and you will be prompted with some options

  • WHEN THE FILTER VALUE IS NOT AVAILABLE => What to display when the argument is not present in the URL. In my case if the argument is not sent I want all cars to be returned, but you can change it for your use case. You can provide a fixed value, or a “No results found” response, etc.
  • WHEN THE FILTER VALUE IS AVAILABLE OR A DEFAULT IS PROVIDED => Here you can define settings like overriding the view title or defining a validation criteria, this is a very powerful configuration that I won’t cover in this post, but I will expand it later.

Go ahead and click save as it is for now, save the View configuration as well. And that’s it!! Let’s give it a try, I want all Toyota cars in sale, just go to http://dev-cars-api.pantheonsite.io/api/cars/Toyota and you will see on the response only the toyota cars. If you remove the Toyota from the URL you will still get all of them. What goes after the http://dev-cars-api.pantheonsite.io/api/cars/ it’s the argument, in this case {Toyota}.

1
2
3
4
5
6
7
8
9
10
[
  {
  "name": "Toyota Vitz",
  "brand": "Toyota",
  "price": "$7500.00",
  "type": "Sedan",
  "photo": "http://dev-cars-api.pantheonsite.io/sites/default/files/styles/large/public/2016-03/Toyota_Yaris_front_20080104.jpg?itok=uJMZTbHm",
  "description": "Small and compact, cheap and fast"
  }
]

This query works as a SQL LIKE statement so you can send just a piece of the name and Views will try to find all records LIKE that argument, example, I have a brand called Land Rover but if I just send Land as an argument it will work http://dev-cars-api.pantheonsite.io/api/cars/Land

1
2
3
4
5
6
7
8
9
10
[
  {
  "name": "Land Rover Defender",
  "brand": "Land Rover",
  "price": "$15000.00",
  "type": "4X4",
  "photo": "http://dev-cars-api.pantheonsite.io/sites/default/files/styles/large/public/2016-03/L550_15ACC_EXT_LOC02_V1_04__293-111196_500x330.jpg?itok=w5Gud-8b",
  "description": "A great car in great conditions, it only has 4000miles and new whells"
  }
]

Now go ahead and do the same but this time add a Contextual Filter by Type. In this case my Type field defines the car type (sedan, 4x4, truck, etc) so it’s a very important filter I want to have.

This will be a second argument in the URL, so it will be api/cars/{brand}/{type}. Now let’s find all the Toyota cars that are 4x4 by making a request to http://dev-cars-api.pantheonsite.io/api/cars/toyota/4x4. There you got! Now we are not only filtering by Brand but also Type.

So now we have finally implemented 2 contextual filters and our little basic API can filter out content, isn’t great? On following episodes I will explain about validation criterias which can be really usefull in some cases.

If you have any questions shoot me a comment, a tweet or an email.

Build a Quick RESTful View in Drupal 8


Drupal 8 is the new version of Drupal that actually came out just a couple of months ago and which development phase started at 2011, so it brings a lot of new chages to the table including Symphony components, Twig as the template engine and many other cool stuff.

One of the new changes added to Drupal8 is that Views module is now part of the core, which is something that makes a lot of sense, since Views is part of pretty much all Drupal sites.

With RESTful Web Services also in Core, we now have all the tools we need to create highly customizable solutions out of the box in regards to RESTful services.

In this blog post, I will show you how to create a view that returns a list of cars (content-type) in JSON via the REST API. Let’s get started!

First you need a Drupal 8 installation, if you don’t have one, it’s very easy to get up and running using Drupal Console’s command $ drupal site:new or if you prefer a more visual way, you can download and use Acquia’s Dev Desktop and use the wizard to create a new site.

Activate required modules

For our little example, we will need to activate Drupal Core’s RESTful Web Services and Serialization modules. To do this go to Extend and find/activate the modules mentioned above. Also make sure that Views and Views UI are enabled (they usually are by default).

Create the content type

I want a service that returns a list of cars in sale in JSON format, so Drupal will take care of managing the content, and on a later post i’m currently working on, we’ll consume the API with Angular2.

Let’s create a new content type called Car and add some fields for Price, Photo, Brand, Model and Type. Go to Structure > Content Types > Add Content Type and fill the requested fields. For the Title field label it as Name. Here’s a picture of how my content type looks:

Now, we might want to create a few cars before we create the service so we have content to return. Also you can use the Devel to generate “Dummy” content for testing. If you are using Drupal Console just use $ drupal module:download devel and then $ drupal module:install devel. Then just go to Configuration > Development > Generate content, and create a bunch of cars.

Creating the view

Now let’s create our view. Go to Structure > Views > Add new view. Name it Cars and select Cars in the type selector. We do not need to create a page or block, so uncheck those options to keep things simple and check Provide a REST export and define the path you wich the API respond to, in my case api/cars/view.

After you hit Save and edit you will be prompted with a regular Drupal View UI, the only difference is that the output will be JSON. As any other View, you can control access by role, use contextual filters, sorting, etc. By default, you will see all the data for every car, including metadata. You might want to pick the fields you wish to send on the JSON response by switching to Show: Fields in the FORMAT section. Now you can select all the fields you want to display on the FIELDS section, in my case I selected Title, Brand, Price, Type, Photo, and Body(description).

You can view your results in the path we defined when we created the view, im my case is api/cars. I have a LIVE example in the following URL: http://dev-cars-api.pantheonsite.io/api/cars. Right now as i’m writing this post looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[{
  "name": "Toyota Prado",
  "brand": "Toyota",
  "price": "$30000.00",
  "type": "4X4",
  "photo": "http://dev-cars-api.pantheonsite.io/sites/default/files/styles/large/public/2016-03/download.jpeg?itok=3QRT2liF",
  "description": "New version, full extras. brand new"
}, {
  "name": "Toyota Vitz",
  "brand": "Toyota",
  "price": "$7500.00",
  "type": "Sedan",
  "photo": "http://dev-cars-api.pantheonsite.io/sites/default/files/styles/large/public/2016-03/Toyota_Yaris_front_20080104.jpg?itok=uJMZTbHm",
  "description": "Small and compact, cheap and fast"
}, {
  "name": "Land Rover Defender",
  "brand": "Land Rover",
  "price": "$15000.00",
  "type": "4X4",
  "photo": "http://dev-cars-api.pantheonsite.io/sites/default/files/styles/large/public/2016-03/L550_15ACC_EXT_LOC02_V1_04__293-111196_500x330.jpg?itok=w5Gud-8b",
  "description": "A great car in great conditions, it only has 4000miles and new whells"
}, {
  "name": "Mitsubishi Montero Sport",
  "brand": "Mitsubishi",
  "price": "$10000.00",
  "type": "4X4",
  "photo": "http://dev-cars-api.pantheonsite.io/sites/default/files/styles/large/public/2016-03/1342471999-2000_Mitsubishi_Montero_Sport_0.JPG?itok=91O63bRS",
  "description": "Beautiful 4x4u00a0Mitsubishi Montero Sport 99' model for 7 passengers"
}]

You might be wondering how I changed the labels of each field so it doesn’t display like field_photo for example? Well it’s quite simple, just click in the field settings located at the FORMAT section, and you will be able to define an alias for each field.

And that’s it! We have our endpoint returning the cars data as JSON and we can consume it wherever we want. If you have any questions shoot me a comment, a tweet or an email.