Observer to jeden z najczęściej stosowanych wzorców w programowaniu obiektowym, a w ekosystemie Magento 2 jest wbudowany w sam rdzeń platformy. Jeśli kiedykolwiek pisałeś obserwatora zdarzenia w Magento, używałeś tego wzorca – często nie zdając sobie z tego sprawy.
Idea wzorca Observer
Observer definiuje relację jeden-do-wielu między obiektami: gdy jeden obiekt zmienia stan (Subject/Publisher), wszystkie zależne od niego obiekty (Observers/Subscribers) są automatycznie powiadamiane i mogą zareagować. Subject nie wie nic o konkretnych obserwatorach – zna tylko ich wspólny interfejs.
Klasyczna implementacja w PHP
<?php
// Interfejs obserwatora
interface ObserverInterface
{
public function update(string $event, mixed $data): void;
}
// Interfejs obiektu obserwowanego
interface SubjectInterface
{
public function attach(string $event, ObserverInterface $observer): void;
public function detach(string $event, ObserverInterface $observer): void;
public function notify(string $event, mixed $data = null): void;
}
// Implementacja Subject
class EventDispatcher implements SubjectInterface
{
private array $observers = [];
public function attach(string $event, ObserverInterface $observer): void
{
$this->observers[$event][] = $observer;
}
public function detach(string $event, ObserverInterface $observer): void
{
$this->observers[$event] = array_filter(
$this->observers[$event] ?? [],
fn($o) => $o !== $observer
);
}
public function notify(string $event, mixed $data = null): void
{
foreach ($this->observers[$event] ?? [] as $observer) {
$observer->update($event, $data);
}
}
}
Przykładowe obserwatory:
<?php
class EmailNotificationObserver implements ObserverInterface
{
public function update(string $event, mixed $data): void
{
echo "Wysyłam email dla zdarzenia: {$event}" . PHP_EOL;
// logika wysyłki emaila
}
}
class AuditLogObserver implements ObserverInterface
{
public function update(string $event, mixed $data): void
{
echo "Zapisuję do logu: {$event}" . PHP_EOL;
// logika zapisu do audit logu
}
}
// Użycie
$dispatcher = new EventDispatcher();
$dispatcher->attach('order.placed', new EmailNotificationObserver());
$dispatcher->attach('order.placed', new AuditLogObserver());
// Gdy zamówienie jest złożone – obaj obserwatorzy reagują automatycznie
$dispatcher->notify('order.placed', ['order_id' => 12345]);
Observer w Magento 2 – system zdarzeń
Magento 2 implementuje Observer przez własny Event Manager. Zamiast ręcznie rejestrować obserwatorów w kodzie, robisz to przez konfigurację XML, a Magento buduje graf zależności przez DI.
Rejestracja obserwatora w events.xml:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="sales_order_place_after">
<observer name="vendor_module_order_placed"
instance="Vendor\Module\Observer\OrderPlacedObserver"/>
</event>
</config>
Implementacja obserwatora Magento:
<?php
namespace Vendor\Module\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Sales\Api\Data\OrderInterface;
class OrderPlacedObserver implements ObserverInterface
{
public function __construct(
private \Psr\Log\LoggerInterface $logger
) {}
public function execute(Observer $observer): void
{
/** @var OrderInterface $order */
$order = $observer->getData('order');
$this->logger->info('Nowe zamówienie', [
'order_id' => $order->getId(),
'customer_email' => $order->getCustomerEmail(),
'grand_total' => $order->getGrandTotal(),
]);
}
}
Observer vs Plugin – kiedy co wybrać?
| Kryterium | Observer (Event) | Plugin |
|---|---|---|
| Punkt integracji | Zdarzenie zdefiniowane przez Magento | Dowolna publiczna metoda |
| Modyfikacja danych | Ograniczona (dane z eventu) | Pełna (argumenty i wynik) |
| Możliwość zatrzymania | Tak (stopPropagation) | Tak (around bez proceed) |
| Sprzężenie z kodem | Luźne | Silniejsze |
| Typowe zastosowanie | Reakcja na akcje biznesowe | Modyfikacja zachowania metody |
Zasada praktyczna: jeśli Magento emituje zdarzenie dla Twojego przypadku użycia – użyj Observera. Jeśli nie – sięgnij po Plugin. Unikaj sytuacji, gdy tworzysz Plugin tylko po to, żeby wewnątrz niego emitować własne zdarzenie – to niepotrzebna warstwa pośrednia.
Podsumowanie
Observer to wzorzec, który promuje luźne powiązanie między komponentami – Subject nie musi wiedzieć, co robią jego obserwatorzy. W Magento 2 ten wzorzec jest fundamentem rozszerzalności platformy. Znajomość klasycznej implementacji GoF pomaga lepiej rozumieć, co dzieje się „pod spodem” gdy rejestrujesz obserwatora zdarzeń w XML.
