Porting hook_init() to Drupal8

PIYUESH KUMAR   |  13th October, 2014

D8 beta is launched and its time to port modules from Drupal 7 to Drupal 8. One of the very widely used hooks hook_init() has been removed from Drupal 8. This has been replaced in favor of Symfony Kernel and events. Hook_init() was was a system level hook defined at core module system/system.api.php. 

What hook_init() does?
This hook is run at the beginning of the page request. It is typically used to set up global parameters that are needed later in the request. When this hook is called, the theme and all modules are already loaded in memory.

How does it work in Drupal 8 now?
Drupal 8 has adopted symfony as a part of its core. It uses Symfony kernel and events to do the same now. List of kernel events available in Drupal 8 are as follows:

Drupal 8 provides a way to subscribe to all these events and attach callbacks to be executed when these events occur. If our module needs to perform changes on the request/response object very early to the request an event subscriber should be used listening to the KernelEvents::REQUEST event. Same goes for the other events as well. 

How to create an Event Subscriber?
The example below shows a Drupal 7 hook_init() implementation which appends Access-Control-Allow-Origin to the response headers to allow CORS(Cross Origin Resource Sharing).

mymodule.module
/**
 * Implements hook_init()
 */
function mymodule_init() {
  drupal_add_http_header('Access-Control-Allow-Origin', '*', TRUE);
}
Steps to convert hook_init into an event subscriber in Drupal 8
  • Create a new Service for Event Subscriber
  • Attach a callback to the KernelEvents::RESPONSE event in Event Subscriber Class.
  • Port the above code inside the attached callback function.

Creating a new service
Create a yml file named <module_name>.services.yml as follows:

mymodule.services.yml
services:
  cors.allow_access_origin:
    class: Drupal\mymodule\EventSubscriber\mymoduleSubscriber
    tags:
      - {name: event_subscriber}
 

class: defines the class implementing EventSubscriberInterface.
tags: Parsing these services is an expensive task for Drupal. It parses all the services.yml files and stores the service definitions in a cached PHP file. These tags help categorize the services.

Attach a callback to the KernelEvents::RESPONSE event
EventSubscriberInterface provides a static function which can be used to attach callable functions to the above mentioned kernel events as shown in the below example.

mymoduleSubscriber.inc
namespace Drupal\mymodule\EventSubscriber;
 
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\Component\Utility\Unicode;
 
class mymoduleSubscriber implements EventSubscriberInterface {
  /**
  * {@inheritdoc}
  */
  static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = array('addAccessAllowOriginHeaders');
    return $events;
  }
}
 

Porting the logic inside hook_init to the callback function attached to KernelEvents::RESPONSE

mymoduleSubscriber.inc
namespace Drupal\mymodule\EventSubscriber;
 
+ use ...
 
class mymoduleSubscriber implements EventSubscriberInterface {
  public function addAccessAllowOriginHeaders(FilterResponseEvent $event) {
    $response= $event->getResponse();
    $response->headers->set('Access-Control-Allow-Origin', '*');
  }
 
  /**
  * {@inheritdoc}
  */
  static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = array('addAccessAllowOriginHeaders');
    return $events;
  }
}
 

Conclusion
In this post, we learned how to replace hook_init() with event subscriber & how symfony kernel events play with event subscribers. We have a better understanding on how Kernel events & callbacks work in Drupal8.

Next article, we’ll have a look at how to port routing access Callbacks to Drupal 8.

Looking for a Drupal partner ?

We are drupal 8 ready