Tutorial

Writing custom Event Subscriber in Drupal 8 - Drupal Commerce

Drupal 8 is trying to get rid of usage of Hooks and is trying to replace them with Events. Is this change necessary? I do not think so, but we have to play with the same cards and adapt.

What are Event Subscribers?

Event subscriber, as the title says is a part of code executed when some event is met in the system. Whole Drupal Commerce bundle in Drupal 8 is actually built around Events and Event Subscribers are a huge part of Drupal itself.

Why are they good for you?

They are executed way faster than Hooks. While Hooks are easy way of altering the Render Array, they are as well run each and every time your Drupal site is being rendered, while Events are only run when certain conditions is met / Event is being executed. Drupal actually puts Event Subscribers to it's cache and runs them only when necessary. Thats why they are way faster.

Writing the custom Event Subscriber

If you want to write your custom Event Subscriber, just follow the code provided below. It is strongly advised that you have at least some background in programming and know how Drupal 8 works in general.

Event Subscriber we are about to write is for Drupal Commerce 2, Drupal 8 and listens to Order Complete event, so when user completes an order. But I am pretty sure even beginner can adapt the code for his own needs.

Pridal/a lubo dňa Ut, 07/21/2020 - 00:51
Create the custom module

This step is easy, just create your_module folder under /modules directory and place the following code inside the files:

- your_module.module (nothing much inside, only php opening, but the file needs to be present)

<?php

- your_module.info.yml

name: Your Module Name
description: My new custom Event Subscriber for Drupal Commerce
package: Grafeon

type: module
core: 8.x
Create custom services file

In your module folder, create the file with a name your_module.services.yml, place this code inside:

services:
  your_module.order_complete:
    class: Drupal\grafeon_kredity\EventSubscriber\OrderCompleteSubscriber
    arguments: ['@entity_type.manager']
    tags:
      - { name: event_subscriber }

What it does?

services:

- This is telling Drupal that we are about to work and inject our code into using services

your_module.order_complete:

- first part is the name of your module and second part is the event you are about to be listening to. In this case we are listening to Drupal Commerce Order Complete event. So when an user completes the order.

class: Drupal\grafeon_kredity\EventSubscriber\OrderCompleteSubscriber

- Tells where the code we are about to create sits in module directory. Folder structure is being set by default and Drupal is looking for EventSubscriber folders in a module's directories anyway.

arguments: ['@entity_type.manager']

- Arguments, that are being passed to an event

 tags:
 - { name: event_subscriber }

- Those two lines are super necessary and do not leave them out. Tags are telling drupal that we are actually writing an Event Subscriber.

Creating the Event Subscriber itself

Drupal is looing for a structure in your module. It has to be like follows:

- Create /src folder in your module root directory

- Create EventSubscriber folder in /src directory, so now you have /src/EventSubscriber folder available

- Create OrderCompleteSubscriber.php file inside in EventSubscriber folder, so now you have /src/EventSubscriber/OrderCompleteSubscriber.php file available

The code inside Event Subscriber itself

In this tutorial, we are creating an Event Subscriber for Drupal Commerce, listening to Order Complete event. Place this code inside in your newly created OrderCompleteSubscriber.php file.

<?php

namespace Drupal\your_module\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\state_machine\Event\WorkflowTransitionEvent;
use Drupal\Core\Entity\EntityTypeManager;

/**
 * Class OrderCompleteSubscriber.
 *
 * @package Drupal\your_module
 */
class OrderCompleteSubscriber implements EventSubscriberInterface {

  /**
   * Drupal\Core\Entity\EntityTypeManager definition.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  protected $entityTypeManager;

  /**
   * Constructor.
   */
  public function __construct(EntityTypeManager $entity_type_manager) {
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  static function getSubscribedEvents() {
    $events['commerce_order.place.post_transition'] = ['orderCompleteHandler'];

    return $events;
  }

  /**
   * This method is called whenever the commerce_order.place.post_transition event is
   * dispatched.
   *
   * @param WorkflowTransitionEvent $event
   */
  public function orderCompleteHandler(WorkflowTransitionEvent $event) {
    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $event->getEntity();
    // Order items in the cart.
    $items = $order->getItems();
    
    // do something with the items in cart here if you wish...

  }

}
Extend the code

Now it is up to you to work with the code. Of course you can listen to any event. Node add, node edit, user viewed and many more. Just like Rules does in Drupal 7, but with a lot more work. So hooray to coding!

Might interest you

Tutorial
In this tutorial we are going to override any Views Field in your View and populate it with a new data. You can do so by creating a module…
Tutorial
This one is quick and works the same with any other code provided by third party.

Recommended

Article
32 views
For the past few days I am trying to comprehend why / how this blockchain even gained it'…
Tutorial
95 views
This sketch is quite easy, I used Arduino Nano with OLED 0.96″ display 128×64 resolution…
Tutorial
157 views
While working on a fairly complex website with very complex views setup, including tens…
Tutorial
14 views
In this case we have two options, either we use hook_user_presave() or we can create new…
Tutorial
15 views
When using Swiftmailer under Drupal 8 / 9 it automatically sets the headers for sender to…
Tutorial
7 views
Yes, IOS / Safari is the new internet explorer. Amount of time I spend on debugging…
Tutorial
43 views
There is a very handy function in Drupal 8 / 9, allowing developers refresh view when…
Tutorial
22 views
Often, when doing SEO checkups, SEO specialist come up with adding Schema.org…
Tutorial
174 views
I needed to test my contracts against USDC contract, specifically I needed ERC-721 mint…
Tutorial
85 views
If you are a newbie like I am and struggling with setting the proper MYSQL my.cnf config…
Tutorial
25 views
I had trouble to set this up properly, because documentation is quite misleading or often…
Article
72 views
As the title says, DO NOT in any circumstances install ANY bitcoin price extension to ANY…
Tutorial
278 views
This is (or should be) a working example of sending some Ether between two addresses.…
Module
45 views
This list was fetched from Zapper, with their /v1/token-list endpoint. Which you can…
Tutorial
143 views
In the last months I am being pretty much bombarded by my clients with asking what…