Listen to order changes

Overview

This guide will teach you how to react to order changes, e.g. changes to the ordered line items, or changes to one of the order states.

Prerequisites

This guide is built upon our plugin base guide and uses the same namespaces as the said plugin. Also, since we're trying to listen to an event in this guide, you need to know about subscribers.

Listening to the event

First of all you need to know about the several possible order events in order to find your right order. You can find them in the OrderEvents class.
Let's assume you want to react to general changes to the order itself, then the event ORDER_WRITTEN_EVENT is the one to choose.
<plugin root>/src/Service/ListenToOrderChanges.php
1
<?php declare(strict_types=1);
2
3
namespace Swag\BasicExample\Service;
4
5
use Shopware\Core\Checkout\Order\OrderEvents;
6
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
7
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
8
9
class ListenToOrderChanges implements EventSubscriberInterface
10
{
11
public static function getSubscribedEvents(): array
12
{
13
return [
14
OrderEvents::ORDER_WRITTEN_EVENT => 'onOrderWritten',
15
];
16
}
17
18
public function onOrderWritten(EntityWrittenEvent $event): void
19
{
20
// Do stuff
21
}
22
}
Copied!

Reading changeset

Due to performance reasons, a changeset of the write operation is not automatically added to the event parameter. In order to force Shopware to generate a changeset, we need to listen to another event.
For this we're going to use the PreWriteValidationEvent, which is triggered before the write result set is generated.
<plugin root>/src/Service/ListenToOrderChanges.php
1
<?php declare(strict_types=1);
2
3
namespace Swag\BasicExample\Service;
4
5
use Shopware\Core\Checkout\Order\OrderDefinition;
6
use Shopware\Core\Checkout\Order\OrderEvents;
7
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
8
use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\ChangeSetAware;
9
use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\InsertCommand;
10
use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\UpdateCommand;
11
use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\PreWriteValidationEvent;
12
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
13
14
class ListenToOrderChanges implements EventSubscriberInterface
15
{
16
public static function getSubscribedEvents(): array
17
{
18
return [
19
PreWriteValidationEvent::class => 'triggerChangeSet',
20
OrderEvents::ORDER_WRITTEN_EVENT => 'onOrderWritten',
21
];
22
}
23
24
public function triggerChangeSet(PreWriteValidationEvent $event): void
25
{
26
foreach ($event->getCommands() as $command) {
27
if (!$command instanceof ChangeSetAware) {
28
continue;
29
}
30
31
/** @var ChangeSetAware|InsertCommand|UpdateCommand $command */
32
if ($command->getDefinition()->getEntityName() !== OrderDefinition::ENTITY_NAME) {
33
continue;
34
}
35
36
$command->requestChangeSet();
37
}
38
39
}
40
41
public function onOrderWritten(EntityWrittenEvent $event): void
42
{
43
foreach ($event->getWriteResults() as $result) {
44
$changeSet = $result->getChangeSet();
45
46
// Do stuff
47
}
48
}
49
}
Copied!
So the PreWriteValidationEvent is triggered before the write set is generated. In its respective listener triggerChangeSet, we're first checking if the current command is even able to generate a changeset. E.g. an "insert" command cannot generate a changeset, because nothing has changed - a whole new entity is generated.
Afterwards we're checking which entity is currently being processed. Since this has an impact on the performance, we only want to generate a changeset for our given scenario. Make sure to narrow it down as much as possible.
Afterwards we execute the method requestChangeSet on the command.
Note the changes made to the onOrderWritten method, which is now reading the newly generated change set.