Event Bus ونمط Observer في PHP
في تطوير تطبيقات الويب الحديثة باستخدام PHP، غالبًا ما تنشأ الحاجة إلى الاستجابة بمرونة للأحداث المختلفة: إرسال البريد الإلكتروني بعد التسجيل، تسجيل إجراءات المستخدم، تحديث ذاكرة التخزين المؤقت عند تغيير البيانات. لهذه الأغراض، يعتبر نمط Observer وتوسعته - Event Bus (ناقل الأحداث) مثاليين.
نمط Observer: الأساسيات
نمط Observer (المراقب) - هو نمط تصميم سلوكي ينشئ آلية اشتراك تسمح للكائنات بمراقبة الأحداث التي تحدث في كائنات أخرى والتفاعل معها. المكونات الأساسية:
- Subject (الموضوع) - الكائن الذي يولد الأحداث
- Observer (المراقب) - الكائن الذي يستجيب للأحداث
- Event (الحدث) - معلومات حول الإجراء الذي حدث
Event Bus: تطور Observer
Event Bus - هو ناقل مركزي يدير جميع الأحداث في التطبيق. على عكس Observer التقليدي حيث يكون الاشتراك مرتبطًا بشكل صارم بالموضوع، يوفر Event Bus:
- ربط ضعيف بين المرسلين والمستقبلين
- إمكانية إضافة/إزالة المعالجات أثناء التنفيذ
- وصول عالمي إلى الناقل من أي جزء من التطبيق
- اختبار وتصحيح أسهل
مثال على تنفيذ Event Bus في PHP
لنقم بإنشاء تنفيذ بسيط ولكنه وظيفي لـ Event Bus، متوافق مع PSR-14 (Event Dispatcher).
<?php// واجهة الحدثinterface EventInterface{ public function getName(): string;}
// حدث أساسيclass UserRegisteredEvent implements EventInterface{ public function __construct( private string $email, private string $username ) {}
public function getName(): string { return 'user.registered'; }
public function getEmail(): string { return $this->email; }
public function getUsername(): string { return $this->username; }}
// واجهة المعالجinterface EventHandlerInterface{ public function handle(EventInterface $event): void;}
// Event Busclass EventBus{ private array $listeners = [];
public function addListener(string $eventName, EventHandlerInterface $handler): void { $this->listeners[$eventName][] = $handler; }
public function removeListener(string $eventName, EventHandlerInterface $handler): void { if (!isset($this->listeners[$eventName])) { return; }
$this->listeners[$eventName] = array_filter( $this->listeners[$eventName], fn($h) => $h !== $handler ); }
public function dispatch(EventInterface $event): void { $eventName = $event->getName();
if (!isset($this->listeners[$eventName])) { return; }
foreach ($this->listeners[$eventName] as $handler) { $handler->handle($event); } }}?>الاستخدام العملي
الآن لنقم بإنشاء معالجات ونوضح عمل الناقل:
<?php// معالج إرسال البريد الإلكترونيclass SendWelcomeEmailHandler implements EventHandlerInterface{ public function handle(EventInterface $event): void { if (!$event instanceof UserRegisteredEvent) { return; }
echo "إرسال بريد ترحيبي إلى {$event->getEmail()}"; // mail($event->getEmail(), 'مرحبًا بك!', '...'); }}
// معالج التسجيلclass LogUserRegistrationHandler implements EventHandlerInterface{ public function handle(EventInterface $event): void { if (!$event instanceof UserRegisteredEvent) { return; }