How to alter the Route based on its parameters
The client recently asked me:
“I want to change how the Taxonomy Vocabulary page works. It should have a custom filter and more columns, but you should keep the default functionality like sorting, hierarchy, etc. Also, I want this change to apply only to a few vocabularies, not all of them.”
Most of us are familiar with Route Subscribers, which can be used to alter route defaults. However, they’re executed before the actual request, so we don’t have access to the real values of the route parameters — meaning we can’t make decisions based on them.
That’s where the Route Enhancer comes into play.
The vocabulary page is a form Drupal\taxonomy\Form\OverviewTerms with a bulky buildForm() method that I would have to extend in my own class and customize. And I don't want my customized form to be used for all of the Vocabularies. So I'm going to create the Route Enhancer service:
services:
my_module.route_enhancer:
class: Drupal\my_module\Routing\TaxonomyRouteEnhancer
tags:
- { name: route_enhancer }And the service itself:
namespace Drupal\my_module\Routing;
use Drupal\Core\Routing\EnhancerInterface;
use Drupal\Core\Routing\RouteObjectInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* A taxonomy vocabulary route enhancer.
*/
class TaxonomyRouteEnhancer implements EnhancerInterface {
/**
* {@inheritdoc}
*/
public function enhance(array $defaults, Request $request) {
if ($defaults['_route'] !== 'entity.taxonomy_vocabulary.overview_form') {
return $defaults;
}
if (
!empty($defaults['taxonomy_vocabulary']) &&
in_array($defaults['taxonomy_vocabulary']->id(), [
'voc_1',
'voc_2',
])
) {
$defaults['_form'] = 'Drupal\my_module\Form\FilterableOverviewTerms';
$route = $defaults[RouteObjectInterface::ROUTE_OBJECT];
$route->setDefault('_form', 'Drupal\my_module\Form\FilterableOverviewTerms');
}
return $defaults;
}
}After FilterableOverviewTerms is implemented, you're done!