Note
Note there are two approaches for alternate delivery in Drupal 8, a route subscriber and a route enhancer. This change notice covers route enhancers. For detail on route subscribers (kernel events) see Page "delivery" system removed. The preferred approach is to use route enhancers (as described below).
Detail
The first cut of the new routing system used a long set of logic in Drupal\Core\EventSubscriber\RouteProcessorSubscriber to determine which controller to route requests to based on the accept header and the current $defaults. This logic reacted to the KernelEvents::REQUEST event, examined the incoming request and where appropriate routed it to one of the following controllers
\Drupal\Core\HtmlFormController\Drupal\Core\HtmlPageController\Drupal\Core\AjaxController
With plans to introduce the HtmlEntityFormController, DialogController and ModalController to this mix, the logic surrounding the controller selection threatened to become unwieldy. As a result the logic was moved from a RouteProcessorSubscriber to RouteEnhancers.
If you wish to perform route enhancement/controller derivation you need to implement Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface and register a service tagged as route_enhancer.
Example from FormEnhancer
FormEnhancer (Drupal\Core\Routing\Enhancer\FormEnhancer) is used to send FormInterface routes (those with _form in their defaults) to the HtmlFormController.
/**
* @file
* Contains \Drupal\Core\Routing\Enhancer\FormEnhancer.
*/
namespace Drupal\Core\Routing\Enhancer;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface;
use Drupal\Core\ContentNegotiation;
/**
* Enhances a form route with the appropriate controller.
*/
class FormEnhancer implements RouteEnhancerInterface {
/**
* Content negotiation library.
*
* @var \Drupal\CoreContentNegotiation
*/
protected $negotiation;
/**
* Constructs a new \Drupal\Core\Routing\Enhancer\FormEnhancer object.
*
* @param \Drupal\Core\ContentNegotiation $negotiation
* The Content Negotiation service.
*/
public function __construct(ContentNegotiation $negotiation) {
$this->negotiation = $negotiation;
}
/**
* {@inhertdoc}
*/
public function enhance(array $defaults, Request $request) {
//
// Here we examine the incoming route defaults to check for _form
// If we find it we set the controller callable to be \Drupal\Core\HtmlFormController::content
//
if (empty($defaults['_controller']) && !empty($defaults['_form']) && $this->negotiation->getContentType($request) === 'html') {
$defaults['_controller'] = '\Drupal\Core\HtmlFormController::content';
}
return $defaults;
}
}