The Routing System is a core architectural component of Drupal that connects incoming HTTP requests to executable code. Every page request, form submission, REST endpoint, and AJAX callback in Drupal passes through the routing system.
Starting with Drupal 8, Drupal adopted Symfony’s Routing component. This was a major architectural shift from the menu based routing system used in Drupal 7. The modern routing system is declarative, object oriented, cache aware, and tightly integrated with access control, controllers, and dependency injection.
The goal here is to understand how Drupal routes requests internally, not just how to define a route.
Why Routing Belongs in Core Architecture
Routing is not a UI feature. It is a fundamental request handling mechanism.
Drupal’s routing system is responsible for:
- Mapping URLs to controllers or forms
- Enforcing access checks
- Resolving route parameters
- Integrating with the service container
- Supporting multilingual paths
- Enabling cacheability metadata
Without routing, Drupal cannot respond to a single HTTP request.
High Level Request Flow
Understanding routing starts with understanding the request lifecycle.
- Browser sends an HTTP request
- Symfony HttpKernel receives the request
- Router matches the URL to a route
- Access checks are executed
- Route parameters are resolved
- Controller or form is executed
- Response object is returned
Routing sits at the center of this flow.
What Is a Route in Drupal
A route is a definition that maps a URL path to executable code.
A route defines:
- The URL path
- The controller or form to execute
- Access requirements
- Parameter constraints
- Defaults and options
Routes are declared using YAML files.
Route Definition File
Routes are defined in a module’s routing file.
Example: my_module.routing.yml
my_module.example:
path: '/my-module/example'
defaults:
_controller: '\\Drupal\\my_module\\Controller\\ExampleController::content'
_title: 'Example Page'
requirements:
_permission: 'access content'
Key parts:
- Route name must be unique
- Path defines the URL
- Defaults define what executes
- Requirements control access
Controllers and Routing
Most routes point to controllers.
A controller is a PHP class method that returns a render array or a response object.
namespace Drupal\my_module\Controller;
use Drupal\Core\Controller\ControllerBase;
class ExampleController extends ControllerBase {
public function content() {
return [
'#markup' => 'Hello from routing system',
];
}
}
The routing system instantiates the controller using the service container.
Routing to Forms
Routes can directly point to forms.
my_module.example_form:
path: '/my-module/example-form'
defaults:
_form: '\\Drupal\\my_module\\Form\\ExampleForm'
_title: 'Example Form'
requirements:
_permission: 'access content'
Drupal automatically builds and processes the form when this route is matched.
Access Control in Routing
Access control is part of routing, not controller logic.
Common access keys:
- _permission
- _role
- _custom_access
Example using permission:
requirements:
_permission: 'administer site configuration'
Custom access uses an access check service.
requirements:
_custom_access: '\\Drupal\\my_module\\Access\\ExampleAccess::access'
Access checks run before the controller is executed.
Route Parameters
Routes can include dynamic parameters.
path: '/node/{node}'
Drupal automatically converts parameters using parameter converters.
Example controller:
public function content(NodeInterface $node) {
return ['#markup' => $node->label()];
}
This conversion is handled by the routing system and entity type manager.
Parameter Constraints
You can restrict parameter values.
requirements:
node: '\\d+'
This improves route matching performance and correctness.
Route Options
Options provide additional metadata.
Common options:
- _admin_route
- parameters
- no_cache
Example:
options:
_admin_route: TRUE
Admin routes receive admin theme and different caching behavior.
Route Caching
Routes are compiled and cached.
Drupal builds a route cache during cache rebuild.
Important points:
- Routing is not evaluated on every request
- YAML is compiled into PHP
- Route cache improves performance
Changing routing files requires a cache rebuild.
Multilingual Routing
Drupal supports translated paths.
Example:
- /about
- /es/sobre
Routing integrates with:
- Language negotiation
- Path aliases
- Content translation
The routing system resolves language specific paths automatically.
Drupal 10 and 11 Best Practices
- Keep routes declarative
- Move logic into controllers or services
- Use dependency injection in controllers
- Use access checks instead of if statements
- Avoid heavy logic during routing
Common Mistakes
- Performing access checks inside controllers
- Using hardcoded URLs
- Forgetting cache rebuild after route changes
- Overusing custom access checks
- Returning responses instead of render arrays unnecessarily
Routing Compared to Drupal 7
Drupal 7:
- hook_menu
- Procedural callbacks
- Mixed routing and access logic
Drupal 8+:
- YAML based routing
- Controllers and forms
- Clear separation of concerns
This shift is foundational to modern Drupal architecture.
How Routing Fits with Other Core Systems
Routing works closely with:
- Service container
- Event dispatcher
- Access API
- Entity system
- Cache system
Understanding routing makes these systems easier to understand.
Summary
The routing system is a core architectural layer that translates URLs into executable code. It is tightly integrated with dependency injection, access control, caching, and multilingual support. Mastering routing is essential for building clean, secure, and scalable Drupal 10 and 11 applications.
This article prepares you for deeper topics such as route subscribers, dynamic routes, event based routing, and REST routing.