Understanding the Observer/Event System in Magento
Understanding the Observer/Event System in Magento
~6 Min. Lesezeit Zuletzt aktualisiert am August 9, 2026
Block 3 created nothing but state: attributes, a backend model, a resolver service - but not a single line so far actually reacts to a real business event like "a customer just completed an order". PointsCalculator (chapter 5) has been waiting to be called since chapter 5. Block 4 closes exactly that gap - and this chapter lays the groundwork before chapter 30 writes this series' first real observer.
What is an event?
Magento has a central event manager (\Magento\Framework\Event\ManagerInterface) that gets called via dispatch() at countless points throughout the core - and in any custom module - whenever something noteworthy happened: an order was placed, a product was saved, a credit memo was created. The dispatching code knows none of its listeners - classic publish/subscribe, fully decoupled.
// Somewhere in Magento core, roughly:
$this->eventManager->dispatch(
'sales_order_place_after',
['order' => $order]
);Registering an observer: events.xml
A custom module "subscribes" to an event via etc/events.xml - either globally (etc/events.xml, applies in every area) or scoped to one area (etc/frontend/events.xml, etc/adminhtml/events.xml, etc/webapi_rest/events.xml, and so on - the same area principle as di.xml). The name attribute of the <observer> node is the merge key across modules, exactly like block and layout XML.
<!-- Schema sketch, not a real file from this module -->
<config>
<event name="event_name_here">
<observer name="unique_observer_name"
instance="Vendor\Module\Observer\MyObserver"/>
</event>
</config>ObserverInterface: the contract side
Every observer class implements \Magento\Framework\Event\ObserverInterface with exactly one method: execute(\Magento\Framework\Event\Observer $observer): void. The Observer passed in wraps the data given to dispatch() - accessed via getEvent()->getData('order') or, when Magento defines a matching magic getter, directly getEvent()->getOrder().
declare(strict_types=1);
namespace Vendor\Module\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
class MyObserver implements ObserverInterface
{
public function execute(Observer $observer): void
{
$order = $observer->getEvent()->getData('order');
// ...
}
}Observers run synchronously and block
Achtung: An events.xml observer runs synchronously, in the same PHP process as the code that triggered it - unlike a real message queue (Magento has its own, entirely separate publish/consumer system in Magento_MessageQueue/Magento_AsynchronousOperations, deliberately out of scope for this series). A slow observer, or one that throws an exception, on a checkout-critical event directly delays or breaks that exact request. Chapter 30 shows the concrete consequence for AwardPointsOnOrderPlaced.
Which events even exist?
- Naming convention:
<entity>_<action>_<timing>, usually_before/_after. - Every
AbstractModelentity with an$_eventPrefixset automatically fires<prefix>_save_before,<prefix>_save_after,<prefix>_load_after,<prefix>_delete_after, and more - with nodispatch()call needed in your own code at all. - What data a specific event carries lives exclusively in the actual
dispatch()call in the core source code - not reliably in documentation, which can go stale.
Tipp: Instead of memorizing event names and payloads: look them up directly in the vendor directory. bin/cli grep -rn "eventManager->dispatch" vendor/magento/module-sales/Model/Order.php shows exactly which events \Magento\Sales\Model\Order fires and with what data - more reliable than any third-party list.
With this groundwork in place, chapter 30 registers this series' first real observer - AwardPointsOnOrderPlaced - on sales_order_place_after, and for the first time actually wires together PointsCalculator (chapter 5), CategoryBonusResolver (chapter 27), and the loyalty_points_earned sales attribute (chapter 23).