By dawehner on
Change record status:
Published (View all published change records)
Project:
Introduced in branch:
8.x
Issue links:
Description:
In Drupal 7, the active theme could be changed either with a 'theme callback' entry in hook_menu(), or with hook_custom_theme(). In Drupal 8, both methods have been replaced with theme negotiators.
Drupal 7
/**
* Implements hook_menu()
*/
function example_menu() {
$items['path'] = array(
'page callback' => 'foo_bar',
'theme callback' => 'example_theme_callback',
);
return $items;
}
/**
* Always use stark on that menu route.
*/
function example_theme_callback() {
return 'stark';
}
Drupal 8
For active themes by route you first have to define a service in your example.services.yml file:
services:
theme.negotiator.example:
class: Drupal\example\Theme\ThemeNegotiator
tags:
- { name: theme_negotiator, priority: 0 }
and then in "example/src/Theme/ThemeNegotiator.php" use that new defined service class:
namespace Drupal\example\Theme;
use Drupal\Core\Theme\ThemeNegotiatorInterface;
use Drupal\Core\Routing\RouteMatchInterface;
class ThemeNegotiator implements ThemeNegotiatorInterface {
/**
* {@inheritdoc}
*/
public function applies(RouteMatchInterface $route_match) {
// Use this theme on a certain route.
// return $route_match->getRouteName() == 'example_route_name';
// Or use this for more than one route:
$possible_routes = array(
'entity.taxonomy_term.add_form',
'entity.taxonomy_term.edit_form'
);
return (in_array($route_match->getRouteName(), $possible_routes));
}
/**
* {@inheritdoc}
*/
public function determineActiveTheme(RouteMatchInterface $route_match) {
// Here you return the actual theme name.
return 'stark';
}
}
For hook_custom_theme() you can use the same mechanism. If you want to take over all existing routes you have to choose a high priority.
In case you want to just change the default theme dynamically but let route specific theme negotiators still apply, use a priority < 0.
Impacts:
Module developers
Themers
Comments
Parameter $route_match missing from applies()
Shouldn't
applies()be written asapplies($route_match)in the above example?I've fixed that :)
I've fixed that :)
In my case I had to add
In my case I had to add "services:" string to the first line of service file, otherwise I get a parsing error (D8.2.4):
I only succeeded in getting
I only succeeded in getting this to work by also providing a __construct() method inside my ThemeNegotiator class.
Otherwhise core (8.3.7) wouldn't recognize both applies() as determineActiveTheme() methods.
Since they are called from within core/lib/Drupal/Core/Theme/ThemeNegotiator.php based on the available (sorted) list of Negotiators, the custom developed needed to be constructed first via createService() method in core/lib/Drupal/Component/DependencyInjection/Container.php
This createService() method relies on the services.yml files, as the one provided in the above example.
Mine looks like :
with an additional argument @request_stack that will be received in the __construct() method of your Negotiator class.
Thank you! This helped me.
Thank you! This helped me.