a deep dive into drupal 8 routing
TRANSCRIPT
![Page 1: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/1.jpg)
A Deep Dive into Drupal 8 Routing
DrupalCamp MumbaiApril 1, 2017Naveen Valecha
![Page 2: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/2.jpg)
About me
● Drupal: naveenvalecha● Git Administer on Drupal.org● Site Maintainer of groups.drupal.org● Twitter: @_naveenvalecha_● Web: https://www.valechatech.net● Drupal 5,6,7,8
![Page 3: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/3.jpg)
Agenda
● What are Routes. Why we need them?● Routes and Controllers● Access checking on routes● Custom Access Checkers● CSRF Prevention on routes● Altering routes● Dynamic Routes● Parameter Upcasting
![Page 4: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/4.jpg)
Routing System
● hook_menu to Symfony2 routing● Replace paths with route names for rendering
links● Converting all page callbacks to controllers● New breadcrumb system, new menu link system,
conversion of local tasks and actions to plugins
![Page 5: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/5.jpg)
Routing System - Cont.
● menu links, local tasks, local actions, contextual links
● Split all the pieces from hook_menu into YAML files finally
● module.routing.yml module.links.menu.yml● module.links.task.yml module.links.action.yml● module.contextual.yml
![Page 6: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/6.jpg)
hook_menu to Symfony Routing
● PHP array to multiple yaml files● Performance improvements● Developer Experience(DX)● Clean Code● Procedural to Object Oriented(OO)
![Page 7: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/7.jpg)
D7 hook_menu
$items['admin/appearance/settings'] = array(
'title' => 'Settings',
'description' => 'Configure default and theme specific settings.',
'page callback' => 'drupal_get_form',
'page arguments' => array('system_theme_settings'),
'access arguments' => array('administer themes'),
'type' => MENU_LOCAL_TASK,
'file' => 'system.admin.inc',
'weight' => 20,
);
![Page 8: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/8.jpg)
D8 system.routing.yml
system.theme_settings: path: '/admin/appearance/settings' defaults: _form: '\Drupal\system\Form\ThemeSettingsForm' _title: 'Appearance settings' requirements: _permission: 'administer themes'
![Page 9: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/9.jpg)
D8 system.links.task.yml
system.theme_settings: route_name: system.theme_settings
title: 'Settings' base_route: system.themes_page
weight: 100
![Page 10: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/10.jpg)
Route
● A route is a path which is defined for Drupal to return some sort of content on. For example, the default front page, '/node' is a route.
● Use mm.routing.yml for defining routes
![Page 11: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/11.jpg)
Routes and Controllers
● The routing system is responsible for matching paths to controllers, and you define those relations in routes. You can pass on additional information to your controllers in the route. Access checking is integrated as well.
![Page 12: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/12.jpg)
Route - Slugentity.node.preview:
path: '/node/preview/{node_preview}/{view_mode_id}'
defaults:
_controller: '\Drupal\node\Controller\NodePreviewController::view'
_title_callback: '\Drupal\node\Controller\NodePreviewController::title'
requirements:
_node_preview_access: '{node_preview}'
options:
parameters:
node_preview:
type: 'node_preview'
![Page 13: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/13.jpg)
/*** Defines a controller to render a single node in preview.*/class NodePreviewController extends EntityViewController {
/** * {@inheritdoc} */ public function view(EntityInterface $node_preview, $view_mode_id = 'full', $langcode = NULL) { $node_preview->preview_view_mode = $view_mode_id; $build = parent::view($node_preview, $view_mode_id);
return $build; }}
![Page 14: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/14.jpg)
example.content: path: '/example' defaults: _controller: '\Drupal\example\Controller\ExampleController::content' custom_arg: 12 requirements: _permission: 'access content'
// ...public function content(Request $request, $custom_arg) { // Now can use $custom_arg (which will get 12 here) and $request.}
![Page 15: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/15.jpg)
Routes Structure
● Path(*): /node/preview/{node_preview}/{view_mode_id}
● defaults(*)○ _controller:
\Drupal\node\Controller\NodePreviewController::view
○ _form: \Drupal\Core\Form\FormInterface
○ _entity_view, _entity_form:○ _title(optional), _title_context(optional),
_title_callback(optional)
![Page 16: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/16.jpg)
Routes Structure
● methods(optional)● Requirements
○ _permission, _role, _access, _entity_access, _custom_access, _format, _content_type_format
○ _module_dependencies○ _csrf_token
![Page 17: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/17.jpg)
Access checking
Permissionrequirements:
_permission: 'administer content types'
Role
requirements: _role: 'administrator'
![Page 18: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/18.jpg)
Access checking - Custom
class NodeRevisionAccessCheck implements AccessInterface {
public function access(Route $route, AccountInterface $account, $node_revision = NULL, NodeInterface $node = NULL) {
if ($node_revision) {
$node = $this->nodeStorage->loadRevision($node_revision);
}
$operation = $route->getRequirement('_access_node_revision');
return AccessResult::allowedIf($node && $this->checkAccess($node, $account, $operation))->cachePerPermissions()->addCacheableDependency($node);
}
}
![Page 19: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/19.jpg)
Route - CSRF Protection
aggregator.feed_refresh:
path: '/admin/config/services/aggregator/update/{aggregator_feed}'
defaults:
_controller: '\Drupal\aggregator\Controller\AggregatorController::feedRefresh'
_title: 'Update items'
requirements:
_permission: 'administer news feeds'
_csrf_token: 'TRUE'
![Page 20: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/20.jpg)
Routes - Altering
class NodeAdminRouteSubscriber extends RouteSubscriberBase {
protected function alterRoutes(RouteCollection $collection) {
if ($this->configFactory->get('node.settings')->get('use_admin_theme')) {
foreach ($collection->all() as $route) {
if ($route->hasOption('_node_operation_route')) {
$route->setOption('_admin_route', TRUE);
}
}
}
}
}
![Page 21: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/21.jpg)
Dynamic Routes
Image.routing.yml
route_callbacks: - '\Drupal\image\Routing\ImageStyleRoutes::routes'
![Page 22: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/22.jpg)
Dynamic Routes - Cont.
class ImageStyleRoutes implements ContainerInjectionInterface { public function routes() { $routes = []; $directory_path = $this->streamWrapperManager->getViaScheme('public')->getDirectoryPath(); $routes['image.style_public'] = new Route( '/' . $directory_path . '/styles/{image_style}/{scheme}', [ '_controller' => 'Drupal\image\Controller\ImageStyleDownloadController::deliver', ], [ '_access' => 'TRUE', ] ); return $routes; }}
![Page 23: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/23.jpg)
Route-Parameter Upcasting
entity.node.preview:
path: '/node/preview/{node_preview}/{view_mode_id}'
defaults:
_controller: '\Drupal\node\Controller\NodePreviewController::view'
_title_callback: '\Drupal\node\Controller\NodePreviewController::title'
requirements:
_node_preview_access: '{node_preview}'
options:
parameters:
node_preview:
type: 'node_preview'
![Page 24: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/24.jpg)
Route-Parameter Upcasting Cont.
node.services.ymlnode_preview:
class: Drupal\node\ParamConverter\NodePreviewConverter
arguments: ['@user.private_tempstore']
tags:
- { name: paramconverter }
lazy: true
![Page 25: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/25.jpg)
Route-Parameter Upcasting Cont.
class NodePreviewConverter implements ParamConverterInterface {
public function convert($value, $definition, $name, array $defaults) {
$store = $this->tempStoreFactory->get('node_preview');
if ($form_state = $store->get($value)) {
return $form_state->getFormObject()->getEntity();
}
}
public function applies($definition, $name, Route $route) {
if (!empty($definition['type']) && $definition['type'] == 'node_preview') {
return TRUE;
}
return FALSE;
}
![Page 26: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/26.jpg)
What’s for Drupal 9?
● Consider having a single class for Match Dumper, Route Provider and Route Builder
● Automatically unserialize request data and serialize outgoing data
![Page 27: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/27.jpg)
References
● http://symfony.com/doc/current/components/
routing.html● https://www.drupal.org/docs/8/api/routing-syste
m
![Page 28: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/28.jpg)
Questions?
![Page 29: A deep dive into Drupal 8 routing](https://reader034.vdocuments.net/reader034/viewer/2022042506/58e509611a28ab2c1c8b4ef9/html5/thumbnails/29.jpg)
THANK YOU!