Route Parameters

Objectives
  • Learn about routes with parameters
  • Add two more routes to your my_route_demo module
Prerequisites
  • Basic knowledge of the routing mechanism
  • Created a module with a routing file and a controller

Parameters make routes flexible

So far we've only discussed static routes such as the /hello route you created earlier.

Here's that route again:

Code
my_route_demo.hello:
  path: '/hello'
  defaults:
    _controller: '\Drupal\my_route_demo\Controller\HelloController::hello'
    _title: 'Hello'
  requirements:
    _permission: 'access content'

It would be nice if we could make a route that's a bit more flexible - a route that has some variable parts.

In the following example we're going to define a parametrized route that lets you browse to /hi/eve and see "Hi, Eve", or browse to /hi/john/doe and see "Hi, John Doe".

Here's my_route_demo's updated routing file:

Code
my_route_demo.hello:
  path: '/hello'
  defaults:
    _controller: '\Drupal\my_route_demo\Controller\HelloController::hello'
    _title: 'Hello'
  requirements:
    _permission: 'access content'

my_route_demo.hello_name:
  path: '/hi/{first_name}/{last_name}'
  defaults:
    _controller: '\Drupal\my_route_demo\Controller\HelloController::helloName'
    _title: 'Hello name'
  requirements:
    _permission: 'access content'

Activity 1

  • Identify the differences between the first and the second route definition.
  • The new route has a different name: my_route_demo.hello_name
  • The new route has a different title: Hello name
  • The new route's path has two parameters: {first_name} and {last_name}
  • The new route points to a new Controller method: HelloController::helloName
Hide hints
show hints

A note on parameter names

You can name parameters however you like as long as they're all lowercase and don't contain spaces or special characters other than underscores (_).

In our example we've given the parameters useful names, {first_name} and {last_name}, but could've just as easily called them first and last or fname and lname.

Similar to naming classes, functions, and variables it's best to keep parameter names short and useful.

Activity 2

  • Add the new route definition to your my_route_demo's routing file.
Hide hints
show hints

After you've updated the routing file you're not done yet: the new route points to a new controller method which doesn't exist yet. Let's change that.

The controller needs parameters too

The routing mechanism is going to pass the route parameters on to the controller method. For this to be possible, the controller method needs to be ready to receive the parameters, so the new controller method (helloName()) is going to be a little different from the first one (hello()).

Let's have a look:

Code
[...]

  public function hello() {
    return [
      '#markup' => $this->t('Hello. It is a fine day indeed!'),
    ];
  }

  public function helloName($first_name, $last_name) {
    return [
      '#markup' => $this->t('Hello @first_name @last_name', [
        '@first_name' => $first_name,
        '@last_name' => $last_name,
      ]),
    ];
  }

Two important things are happening in the helloName() method:

First of all, we add two parameters to the method signature, ensuring we use the same names we used in the route definition:

Code
public function helloName($first_name, $last_name)
  • {first_name}$first_name
  • {last_name}$last_name

Secondly, the parameters $first_name and $last_name are passed to the t() function in such a way that the output remains translatable.

For more in-depth information on different ways of using the t() function, see https://api.drupal.org/api/drupal/core%21includes%21bootstrap.inc/function/t/10

We'll also come back to the t() function later on in the section on using services.

Giving route parameters default values

Sometimes it's interesting to provide default values for route parameters.

Let's say you're building a webshop that sells T-shirts.
You could have a route like /product/{name}/{size}/{colour}, but want people to be able to access /product/{name} and /product/{name}/{size} as well.

You could define three different routes and three different controllers, but there's an easier option: you can provide default values for your parameters right inside your route definition:

Code
my_module.product
  path: '/product/{name}/{size}/{colour}'
  defaults:
    _controller: '\Drupal\my_module\Controller\ProductController::showProduct'
    _title: 'Product'
    size: 'M'
    colour: 'white'
  requirements:
    _permission: 'access content'

When you try to navigate to this route but don't provide a value for {size} or {colour}, 'M' and 'white' will be assumed.

Activity 3

  • Add the new controller method to your my_route_demo's controller file.
  • Be sure to clear your caches every time you make code changes.

If all went well, you should now be able to browse to your new route and try it out:

  • /hi/vint/cerf should show "Hi, vint cerf"
  • /hi/neo should show Hi, neo
  • … and so on.
  • Ensure you respected the indentation in the routing file.
  • Ensure you've added the new controller method.
  • Ensure there are no typos.
  • Ensure you've cleared your caches.
  • Ensure you have set defaults with the same name as the parameters.
Hide hints
show hints

Activity 4

  • Add a route and controller method for the path '/goodbye':
  • The route should take one parameter called 'name'
  • The route should point to a new controller method called 'goodbye'
  • When you browse to "/goodbye/aisha", the page should show "Goodbye aisha."
Hide hints
show hints

Summary

  • You can make a route flexible by making it accept parameters.
  • You can make a route accept parameters by adding the parameter in curly braces to the route's path property.
  • The controller method a parametrized route points to must also accept those newly defined parameters.
  • The names of the parameters you use in the route definition and controller method must be identical.