On this page
Structure of routes
This documentation needs review. See "Help improve this page" in the sidebar.
The simplest way to define routes is to create a my_module_name.routing.yml file (see the introductory example). Each route is defined as a machine name in the form of my_module_name.route_name (for example book.render
) with the following properties:
- path (required): The URL to the route, with a leading forward slash (for example
path: '/book'
). You can use dynamic properties by including them in curly braces. (for examplepath: '/node/{node}/outline'
). These will be passed along as arguments via parameter converters to the controller/form. Note that the first item of the path cannot be an argument, and must be a string. You can also define optional parameters at the end of your path (See 'Optional Parameters' on Using parameters in routes). - defaults (required): Defines the default properties of a route. Provide one of the following to specify how the output is generated:
- _controller: A Callable. Allows you to map to a callable function in one of the following ways:
- Class::method:
\Drupal\[my_module_name]\Controller\[ClassName]::[method]
example:
_controller: '\Drupal\acme\Controller\AcmeController::build'
This will execute the
build()
method in theAcmeController
class, whose namespace isDrupal\acme\Controller
.Note that this value is not a path on the file system, but rather a PSR-4 namespace. Also note that module names are in snake_case, while class names are in PascalCase. See also An introductory example to Drupal 8 routes and controllers.
- Service:
controller.test:[method]
, where "controller.test" is a Drupal 8 service, defined in a *.services.yml file.example:
_controller: 'acme.controller:build'
This will execute the
build()
method in the class defined in the acme.services.yml for the acme.controller service.
- Class::method:
- _form: A class name implementing
Drupal\Core\Form\FormInterface
. See form API in Drupal 8 for an example. - _entity_view: The value is
entity_type.view_mode
. It will find an entity in the path and render it in the given view mode. For example,_entity_view: node.teaser
will return the render array of the {node} in teaser mode. See entity view pages provided by the entity view controller. - _entity_list: The value is
entity_type
. It provides a list of entities using theEntityListController
of the respective entity. For example,_entity_list: entity_type
returns the render array of entities list. - _entity_form: It is similar to _form, but it will provide an edit form for an entity. Entity form handlers are defined in the entity metadata (annotation). For example,
_entity_form: node.default
will display the default node form. "node" innode.default
refers to the entity ID, and "default" refers to the form handler key.
- _controller: A Callable. Allows you to map to a callable function in one of the following ways:
- defaults (optional): Additionally, you may provide optional defaults to specify how the output is generated:
- _title: The page title for the route. It may differ from the menu link title.
- _title_arguments: Additional arguments for the title text passed along to
t()
. - _title_context: Additional context information for the title text passed along to
t()
. - _title_callback: A PHP callable (typically
classname::method
) returning the translated page title for the route. The method should return an instance of\Drupal\Core\StringTranslation\TranslatableMarkup
.
- methods (optional): In addition to the URL, you can also match on the method of the incoming request (i.e. GET, HEAD, POST, PUT, DELETE). Enclosed in brackets, separated by commas, for example
[GET, HEAD]
. - requirements (required): Determines what conditions must be met to grant access to the route. All conditions must be met to gain access. It is an array of one or more of the following:
- _permission: A permission string (for example
_permission: 'access content'
). You can specify multiple permissions by separating them with ',' (comma) (_permission: 'access content,access user profiles'
) for AND logic or '+' (plus) for OR logic (_permission: 'access content+access user profiles'
means a visitor needs either theaccess content
permission or theaccess user profiles
permission to view the page.) Module-specific permission strings can be defined in my_module_name.permissions.yml. See hook_permission() replaced with permissions defined in a my_module_name.permissions.yml file for details. - _role: The machine name of one or more roles. Multiple roles can be separated by either a comma (
,
) or a plus (+
). Multiple roles separated with a comma (,
) will require all of the roles to gain access to the route. Multiple roles separated by a plus (+
) will allow access to the route when the user has any of the roles. Example:_role: organizer,participant,controller,site_admin
: Only users with all of these roles will be granted access to the route._role: organizer+participant+controller+site_admin
: Any users with at least one of these roles will be granted access to the route.
Note that, since the roles available may differ between sites, it's recommended to use permission-based access restriction when possible.
- _access: Set this to
'TRUE'
(with the single quotes and in uppercase) to have access granted to this route in all circumstances. - _entity_access: In the case where an entity is part of a route, can check a certain access level before granting access (
_entity_access: 'node.view'
). The format is[slug].[operation]
. Typically, the slug is an entity type ID, but it can be any slug defined in the route. The route match parameter corresponding to the slug is checked to see if it is entity-like and implementsEntityInterface
. You can also specify how the entity should be validated (node: \d+
). This is useful if the used routes are /foo/{node} and /foo/bar, where {node} is a node ID. /foo/bar won't match /foo/{node} because bar isn't a numeric value. (See book.routing.yml for an example.) - _entity_bundles: Deprecated. Use bundle for route parameters instead.
In the case where an entity is part of a route, restrict to certain bundles. The format is[entity_type]:[bundle]
(node:article
). You can also specify multiple bundles, separating them with|
(node:article|page
). - _entity_create_access: Check access with create operation. See the related change record for example.
- _custom_access: TODO. See Custom route access checking for details.
- _format: Use this to check the type of the request. For example, you can have
_format: json
and only match requests where the '_format' query parameter is 'json'. - _content_type_format: Use this to check the content type of the request. For example, you can have
_content_type_format: json
and only match requests where the Content-type header is json. See API doc for ContentTypeHeaderMatcher.php to get an idea how it works. - _module_dependencies: Optionally use this key to specify one or more modules that are required to serve this path. You can combine module names with a + (plus) for an AND relationship or , (comma) for an OR relationship. For example,
_module_dependencies: 'node + search'
means both node and search are needed,_module_dependencies: 'node, search'
means either node or search are needed. If your module already depends on other modules for its behavior (via .info.yml dependencies), there is no need for specifying the dependency here as well. However, for optional dependencies, where routes are provided only if those optional dependent modules are also enabled, this is a useful option. - _csrf_token: should be used and set to 'TRUE' for any URLs that perform actions or operations that do not use a form callback. See Access checking on routes for details.
- _csrf_request_header_token: set to
'TRUE'
to require X-CSRF-Token as an HTTP header. See CSRF token route protection moved out of the REST module to be available to other core systems and contrib to get more info. - _method: (OBSOLETE as of Symfony 3, read change record. Use '
methods: [POST]
') Optionally use this key to restrict the route to specific HTTP methods. Defaults to GET and POST. Expects a string. To restrict to more than one method concatenate with '|'. Example:'GET|POST'
. - _access_user_register: Set this to
'TRUE'
(with the single quotes) to have access granted to the route if the user is anonymous AND user registration is not set to "Administrators only" on the site. - _user_is_logged_in: Boolean. Use to require authentication, or require unauthenticated access to a route.
- _permission: A permission string (for example
- options (optional): Additional options on how the route should interact. Note that, unlike requirements, boolean values should not be quoted. Common options are:
- _access_mode: (ANY / ALL (default) For security reasons, this option has been removed. #2431281: Drop support for _access_mode routes and always assume ALL
- _admin_route: Indicate whether this is an admin route or not, so the admin theme is used. Defaults to
TRUE
for routes starting with '/admin', otherwise toFALSE
, so is only required to override this behavior. - _auth: The default authentication manager (Ex:
_auth: ['basic_auth', 'cookie']
) that enables developers to limit the set of allowed authentication mechanisms to the route. Check Authentication API for more details. - _maintenance_access: Set this to
TRUE
to bypass the offline message and show the page normally while in maintenance mode. - _theme: TODO
- no_cache: Set this to
TRUE
to mark route response as uncacheable. - parameters: See Using parameters in routes
Here's a more complex annotated example:
book.routing.yml
# Each route is defined by a machine name, in the form of my_module_name.route_name.
#
book.render:
# The path always starts with a leading forward-slash.
path: '/book'
# Defines the default properties of a route.
defaults:
# For page callbacks that return a render array use _controller.
_controller: '\Drupal\book\Controller\BookController::bookRender'
# Require a permission to access this route.
requirements:
_permission: 'access content'
book.export:
# This path takes dynamic arguments, which are enclosed in { }.
path: '/book/export/{type}/{node}'
defaults:
# This route returns a Response object so also uses _controller
_controller: '\Drupal\book\Controller\BookController::bookExport'
requirements:
_permission: 'access printer-friendly version'
# Ensure user has access to view the node passed in.
_entity_access: 'node.view'
options:
# Enable the admin theme for this route.
_admin_route: TRUE
Passing arguments to controllers
All keys under the defaults
section which do not start with an underscore will be passed in as arguments to the controller. Name your arguments appropriately for the arguments of the controller. For example a my_module_name.routing.yml file with the following:
example.content:
path: '/example'
defaults:
_controller: '\Drupal\example\Controller\ExampleController::content'
custom_arg: 12
requirements:
_permission: 'access content'
Will pass on $custom_arg
to the controller, so your content method can take $custom_arg
:
// ...
public function content($custom_arg) {
// Now you can use $custom_arg (which will get 12 here).
}
Routing for Form:
module_name.route_machine_name:
path: '/{module_name}/personal-info'
defaults:
_form: 'Drupal\{module_name}\Form\InfoForm'
_title: 'Personal information'
requirements:
_permission : 'custom_module_permission'
Where
module_name: is machine name of your module.
custom_module_permission: name of the permission implemented in module_name.permission.yml file
Combine this with dynamic routes to get true flexibility.
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion