Drupal 8's routing system came from Symfony's, and it can do everything that Symphony’s can, and more. It’s an overhaul from Drupal 7, as D7 used hook_menus while in D8 a module’s routes are defined in yml files and these trigger actions defined in module’s controller.

Watch the video to understand Drupal 8 routing system:

What is a Route?

A route is a way to reach from a starting point to some destination. In Drupal, a route is a way defined that would return some sort of content.

Example: /node the default front page is a route.
       /node/add that opens up a node add page is a route
       /node/{nid}/edit

Overview of Routing in Symfony

In Symfony we have 

#app/config/routing.yml

blog_show: 
    path:            /blog
    defaults:   {_controller: ControllerName:method} 


Routing in Drupal 7

In Drupal 7 routing is handled by hook_menu(). Apart from just routing it had many other responsibilities as well: 

  • Access Control
  • Visible Navigation

It’s too much for a single function to handle and made some sort of a tight coupling. It looks a much of alien concept to developers coming from other MVC frameworks.

Drupal 8 has said Goodbye hook_menu() adopting its routing from Symfony.

What happens when Drupal receives a request - HTTP Kernel

Drupal does this with the help of Symfony. To have a look in Drupal code where this Symfony Kernel lies, go to 
<drupal folder>/vendor/symfony/http-kernel/
 

Drupal receiving a request from HTTP Kernel
Symfony HTTP kernel

Drupal System uses this HTTP Kernel, which gets the request and asks other systems to produce o/p what are these other systems lets see 

Explanation: A request can come in from a mobile device or a laptop or any other device goes to the HTTP kernel which checks the access check and requirements on the accessing user and if the access is granted a 200 status code is returned else a 404 is returned.

Drupal System uses this HTTP Kernel which gets the request and asks other systems to produce output. These other systems are: 

YML File: <modulename>.routing.yml 

YML file tells Drupal how to behave when a particular path is encountered.

If you want to specify a default value, you put it into the defaults array. In the same yml array you specify the class and method connected with '::' to tell the system where to look up stuff.

Routing system

Controllers: ExampleController.php - Inside src/Controller/

Controller is a piece of code that is responsible to generate the response object.

The key concept is the controller which gets some parameters from the system and converts them to the response. 
So everything without an underscore is considered to be a parameter to the controller. Every other property has nothing to do with the controller parameters and so are considered to be internal and so have an underscore as prefix.

Drupal 8 Routing system

 

Precedence of same routes 

When two routes match the same URL, the first route that's loaded wins. 

So if we have two routes defined as
1. drupalcamp.blogshow:
  path: '/blog/{slug}'
  defaults:
    _controller: '\Drupal\drupalcamp\Controller\ExampleController::blogshow'
    _title: 'Shows blog'
  requirements:
    _access: 'TRUE'

And 
2. drupalcamp.eventshow:
  path: '/blog/{event}'
  defaults:
    _controller: '\Drupal\drupalcamp\Controller\ExampleController::eventshow'
    _title: 'Shows event'
  requirements:
    _access: 'TRUE'

Unfortunately, that means that /blog/test will match the blogshow and not eventshow. 

No good!

To fix this, add a requirement wherein you can define the inputs that should be matched for a particular route to load.

So with requirements the code would look like 
drupalcamp.blogshow:
  path: '/blog/{slug}'
  defaults:
    _controller: '\Drupal\drupalcamp\Controller\ExampleController::blogshow'
    _title: 'Shows blog'
  requirements:
    _access: 'TRUE'
    slug: '\d+'

Loading blogshow in case of integers.

drupalcamp.eventshow:
  path: '/blog/{event}'
  defaults:
    _controller: '\Drupal\drupalcamp\Controller\ExampleController::eventshow'
    _title: 'Shows event'
  requirements:
    _access: 'TRUE'
    event: en|fr

Loading eventshow in case of en OR fr being entered by accessing user.

You can also pass default values to a route by defining this value in defaults array.

Named params in route
 

Drupal routing system

If you want to get access to an entity type you can use named params in the url.$user is the name of an entity type.
If the userid does not exist drupal would give a 404.

Named parameters are not sanitized by default. This means that you really should sanitize all values prior to use. 
You can somewhat decrease a code injection security concern by specifying regex requirements. Inside the  controller you will have access to the complete user object

Upcasting

You don't want to take care about loading an entity, see /user/{user} as an example. For entities you basically just use the name of the entity type and it will execute an entity_load with the ID passed in the URL. Param converter manager


Some Useful Commands

While working with routing If you update a routes file in Drupal 8 how do you clear the cache?

So instead of clearing caches you can rebuild the router table.


If you use drush, drush ev '\Drupal::service("router.builder")->rebuild();' to rebuild the routing information without clearing all the caches.
If you use drupal console: drupal router:rebuild

You can checkout this code here.

Posts You May Like...