Introduction
Shopware 6.7 introduces significant enhancements to its event system, providing developers with more powerful tools for extending and customizing the platform. The event system serves as the backbone of Shopware's extensibility model, allowing developers to hook into various points in the application lifecycle without modifying core code. This guide will explore the intricacies of Shopware 6.7's event system, focusing on event subscribers, their implementation, and practical use cases.
Understanding Shopware Events
In Shopware 6.7, events are objects that represent specific moments in the application execution flow. These events can be triggered during various operations such as product creation, order processing, user authentication, or template rendering. The event system follows a publish-subscribe pattern where events are dispatched and listeners (subscribers) react to them.
Events in Shopware 6.7 are typically named using PascalCase and follow the pattern VendorName.EventName. For example, product.written is triggered when products are written to the database, while checkout.order.placed fires when an order is successfully placed.
Event Subscriber Architecture
Basic Subscriber Implementation
Creating an event subscriber in Shopware 6.7 involves implementing the Symfony\Contracts\EventDispatcher\EventSubscriberInterface and defining a static method that returns the events to subscribe to:
<?php declare(strict_types=1);
namespace MyPlugin\Subscriber;
use Shopware\Core\Checkout\Order\Event\OrderPlacedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class OrderSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
OrderPlacedEvent::class => 'onOrderPlaced',
];
}
public function onOrderPlaced(OrderPlacedEvent $event): void
{
// Your custom logic here
$order = $event->getOrder();
$orderId = $order->getId();
// Process the order
$this->processOrder($orderId);
}
private function processOrder(string $orderId): void
{
// Custom processing logic
}
}
Advanced Event Subscriber Patterns
Shopware 6.7 supports multiple event types and provides enhanced subscriber capabilities. The framework now offers better type hinting, improved event object structures, and more granular control over event handling.
<?php declare(strict_types=1);
namespace MyPlugin\Subscriber;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class EntityWrittenSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
'product.written' => 'onProductWritten',
'category.written' => 'onCategoryWritten',
];
}
public function onProductWritten(EntityWrittenEvent $event): void
{
// Handle product written events with enhanced data access
$ids = $event->getIds();
$context = $event->getContext();
foreach ($ids as $id) {
// Process each written product
$this->handleProductUpdate($id, $context);
}
}
public function onCategoryWritten(EntityWrittenEvent $event): void
{
// Handle category written events
$ids = $event->getIds();
foreach ($ids as $id) {
$this->invalidateCategoryCache($id);
}
}
private function handleProductUpdate(string $productId, Context $context): void
{
// Custom product update logic
}
private function invalidateCategoryCache(string $categoryId): void
{
// Cache invalidation logic
}
}
Event Object Structure in Shopware 6.7
Shopware 6.7 has refined the structure of event objects, providing better access to entity data and context information. The enhanced event objects include:
- Entity Context: Detailed context information including user, sales channel, and permissions
- Entity Data Access: Improved methods for accessing written entities and their relations
- Event Metadata: Additional properties that provide more insight into the event trigger
<?php declare(strict_types=1);
namespace MyPlugin\Subscriber;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class EnhancedEventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
'product.written' => 'onProductWritten',
];
}
public function onProductWritten(EntityWrittenEvent $event): void
{
// Access to event metadata
$context = $event->getContext();
$versionId = $event->getVersionId();
// Get the actual written entities
$entities = $event->getEntities();
foreach ($entities as $entity) {
// Enhanced entity access
$entityData = $entity->getData();
$entityId = $entity->getId();
// Process with enhanced context information
$this->processEntity($entityData, $context);
}
}
private function processEntity(array $data, Context $context): void
{
// Enhanced processing logic with full context access
}
}
Practical Use Cases and Examples
Custom Order Processing
One of the most common use cases for event subscribers is custom order processing. In Shopware 6.7, you can intercept orders at various stages:
<?php declare(strict_types=1);
namespace MyPlugin\Subscriber;
use Shopware\Core\Checkout\Order\Event\OrderPlacedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class OrderProcessingSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
OrderPlacedEvent::class => 'onOrderPlaced',
];
}
public function onOrderPlaced(OrderPlacedEvent $event): void
{
$order = $event->getOrder();
$orderNumber = $order->getOrderNumber();
$customerId = $order->getCustomerId();
// Send custom notification
$this->sendCustomNotification($orderNumber, $customerId);
// Update external systems
$this->syncWithExternalSystem($order);
// Calculate custom metrics
$this->calculateCustomMetrics($order);
}
private function sendCustomNotification(string $orderNumber, ?string $customerId): void
{
// Custom notification logic
}
private function syncWithExternalSystem(Order $order): void
{
// External system synchronization
}
private function calculateCustomMetrics(Order $order): void
{
// Custom metrics calculation
}
}
Product Inventory Management
Event subscribers can also be used for inventory management and real-time updates:
<?php declare(strict_types=1);
namespace MyPlugin\Subscriber;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class InventorySubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
'product.written' => 'onProductWritten',
'stock.written' => 'onStockWritten',
];
}
public function onProductWritten(EntityWrittenEvent $event): void
{
// Handle product creation/update
$this->handleProductChange($event);
}
public function onStockWritten(EntityWrittenEvent $event): void
{
// Handle stock changes
$this->handleStockUpdate($event);
}
private function handleProductChange(EntityWrittenEvent $event): void
{
// Product change handling logic
}
private function handleStockUpdate(EntityWrittenEvent $event): void
{
// Stock update handling logic
$entities = $event->getEntities();
foreach ($entities as $entity) {
if ($entity->getEntityName() === 'stock') {
$this->updateInventoryTracking($entity);
}
}
}
private function updateInventoryTracking($entity): void
{
// Inventory tracking logic
}
}
Performance Considerations
When implementing event subscribers in Shopware 6.7, it's crucial to consider performance implications:
- Avoid Heavy Operations: Event handlers should be lightweight to prevent blocking the main execution flow.
- Use Asynchronous Processing: For time-consuming tasks, implement asynchronous processing using message queues.
- Optimize Database Access: Minimize database queries within event handlers.
<?php declare(strict_types=1);
namespace MyPlugin\Subscriber;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Messenger\MessageBusInterface;
class AsyncProcessingSubscriber implements EventSubscriberInterface
{
private MessageBusInterface $messageBus;
public function __construct(MessageBusInterface $messageBus)
{
$this->messageBus = $messageBus;
}
public static function getSubscribedEvents(): array
{
return [
'product.written' => 'onProductWritten',
];
}
public function onProductWritten(EntityWrittenEvent $event): void
{
// Dispatch to async processor instead of processing synchronously
$this->messageBus->dispatch(new ProductProcessingMessage($event->getIds()));
}
}
Best Practices for Event Subscribers
- Keep Subscribers Focused: Each subscriber should handle a specific concern.
- Handle Exceptions Gracefully: Implement proper error handling to prevent event chain failures.
- Use Proper Logging: Log events and processing information for debugging.
- Consider Event Priority: Use priority levels when multiple subscribers need to process the same event.
<?php declare(strict_types=1);
namespace MyPlugin\Subscriber;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class RobustSubscriber implements EventSubscriberInterface
{
private LoggerInterface $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public static function getSubscribedEvents(): array
{
return [
'product.written' => ['onProductWritten', 10],
];
}
public function onProductWritten(EntityWrittenEvent $event): void
{
try {
// Process the event
$this->processEvent($event);
} catch (\Exception $e) {
$this->logger->error('Error processing product written event: ' . $e->getMessage());
// Don't throw exception to prevent breaking the chain
}
}
private function processEvent(EntityWrittenEvent $event): void
{
// Processing logic
}
}
Conclusion
Shopware 6.7's event system provides developers with powerful capabilities for extending and customizing the platform. Understanding how to properly implement event subscribers, handle event objects, and optimize performance is crucial for building robust extensions. The enhanced event architecture in version 6.7 offers better type safety, improved data access, and more granular control over the extension points available.
By following best practices and implementing efficient subscriber patterns, developers can create maintainable, performant extensions that integrate seamlessly with Shopware's core functionality while providing valuable customizations to merchants and end-users. The event system remains one of the most important aspects of Shopware's extensibility model, and mastering it is essential for any serious Shopware developer working with version 6.7 and beyond.