Upgrade Your Drupal Skills

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

See Advanced Courses NAH, I know Enough

Making a Drupal 8 route dynamic

Parent Feed: 

In the last tutorial in this series, Understanding routes and controllers, we looked at the two fundamental steps to programmatically define a custom page in Drupal 8. Today we are going to take this one step further and add a parameter to the route, so that it is dynamic.

Go back to the route defined in the Understanding routes and controllers tutorial. This is what it looks like:


  1. hello.content:

  2. path: '/hello'

  3. defaults:

  4. _controller: 'Drupal\hello\Controller\HelloController::content'

  5. _title: 'Hello world'

  6. requirements:

  7. _permission: 'access content'

With the above code, when you go to /hello, you will get a ’hello world’ message from the controller.

We are about to change the code so we can replace world in hello world with a name that we pass in via the URL. If you hit /hello/bob, the message will become hello bob, hello/alice will become hello alice and so on.

You are going to change this so that you can pass in a person’s name as a parameter.

You can add the name to the line that has the path key:


  1. path: '/hello/{name}'

In the above snippet, {name} is known as the slug and acts as a placeholder. You can name a slug what ever you like, as long as you surround it with accolades ({}). The same name should then be used as an argument in the controller (you’ll see that in a moment). The value will be passed into the controller. In other words, if you hit /hello/alice, then alice is the value for name and alice will be passed to the $name variable in the controller.

The full route will become:


  1. hello.content:

  2. path: '/hello/{name}'

  3. defaults:

  4. _controller: 'Drupal\hello\Controller\HelloController::content'

  5. _title: 'Hello world'

  6. requirements:

  7. _permission: 'access content'

Default name

There needs to be a default name, just in case the name is not passed in the URL. This allows you to hit /hello without the name added. To do that, you can add the default name to the defaults part of the route Yaml file.

The default can be whatever you want. I’m going to go with “world”, so that if in the absence of a name, the page content will be “hello world”.

Add the following default name to the route Yaml file:


  1. name: 'world'

So the complete route Yaml file becomes:


  1. hello.content:

  2. path: '/hello/{name}'

  3. defaults:

  4. _controller: 'Drupal\hello\Controller\HelloController::content'

  5. _title: 'Hello world'

  6. name: 'world'

  7. requirements:

  8. _permission: 'access content'

Add the name to the controller

Now that the route can take the name parameter, you need to use it in the controller for it to take effect.

Take another look at the controller from the previous tutorial:


  1. <?php

  2. /**

  3.  * @file

  4.  * Contains \Drupal\hello\Controller\HelloController.

  5.  */

  6. namespace Drupal\hello\Controller;

  7. use Drupal\Core\Controller\ControllerBase;

  8. class HelloController extends ControllerBase {

  9. public function content() {

  10. '#type' => 'markup',

  11. '#markup' => t('Hello world'),

  12. );

  13. }

  14. }

The name is now available to the controller as a variable. The variable is called $name.


  1. public function content()

will become


  1. public function content($name)

To use the variable, you can pass it into the t(). The is the same as it is in Drupal 7.


  1. '#markup' => t('Hello world')

will become


  1. '#markup' => t('Hello @name', array('@name' => $name))

The full controller is now:


  1. <?php

  2. /**

  3.  * @file

  4.  * Contains \Drupal\hello\Controller\HelloController.

  5.  */

  6. namespace Drupal\hello\Controller;

  7. use Drupal\Core\Controller\ControllerBase;

  8. class HelloController extends ControllerBase {

  9. public function content($name) {

  10. '#type' => 'markup',

  11. '#markup' => t('Hello @name', array('@name' => $name)),
  12. );

  13. }

  14. }

And that is all there is to it. You can now add any name you like to the URL and that will appear as part of the hello message.


  1. /welcome/bob will display hello bob

  2. /welcome/alice will display hello alice

  3. /welcome/jane will display hello jane

  4. /welcome will display hello there (there is the default)

Complete code

Here is the full code for the hello module.

In hello.routing.yml:


  1. hello.content:

  2. path: '/hello/{name}'

  3. defaults:

  4. _controller: 'Drupal\hello\Controller\HelloController::content'

  5. _title: 'Hello world'

  6. name: 'world'

  7. requirements:

  8. _permission: 'access content'

In src/Controller/HelloController.php:


  1. <?php

  2. /**

  3.  * @file

  4.  * Contains \Drupal\hello\Controller\HelloController.

  5.  */

  6. namespace Drupal\hello\Controller;

  7. use Drupal\Core\Controller\ControllerBase;

  8. class HelloController extends ControllerBase {

  9. public function content($name) {

  10. '#type' => 'markup',

  11. '#markup' => $this->t('Hello @name', array('@name' => $name)),
  12. );

  13. }

  14. }

And if you haven’t followed along with the previous tutorial, you’ll need a .info file.

In hello.info.yml:


  1. name: Hello

  2. description: An experimental module to build our first Drupal 8 module

  3. package: Custom

  4. type: module

  5. version: 1.0

  6. core: 8.x

Author: 
Original Post: 

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