سیستم هوک (hook) و رویداد (event) در دروپال

تاریخ انتشار: 1404/08/11 - 19:11
سیستم هوک (hook) و رویداد (event) در دروپال

یکی از ویژگی‌های متمایز دروپال، انعطاف‌پذیری آن در گسترش و تغییر رفتار هسته است. این ویژگی از طریق سیستم هوک (Hook System) و رویداد (Event System) ممکن می‌شود. هوک‌ها از ابتدا بخش جدایی‌ناپذیر دروپال بوده‌اند و به توسعه‌دهندگان اجازه می‌دهند در نقاط مشخصی از چرخه‌ی اجرای سیستم، رفتار پیش‌فرض را تغییر دهند. با ورود معماری شیءگرا از دروپال ۸ به بعد و استفاده از چارچوب Symfony، سیستم رویدادها نیز معرفی شد و جایگزین یا مکمل هوک‌ها گردید.


بخش اول: هوک‌ها در دروپال

تعریف هوک

هوک در دروپال تابعی است که ماژول‌ها برای مداخله در فرآیندهای داخلی هسته یا دیگر ماژول‌ها به‌کار می‌برند. هر هوک با الگوی مشخصی از نام‌گذاری دنبال می‌شود، مثلاً اگر دروپال هوکی به‌نام hook_node_insert() تعریف کرده باشد، ماژولی به‌نام my_module می‌تواند تابعی با نام my_module_node_insert() بنویسد تا هنگام ایجاد نود (Node) اجرا شود.

نحوه‌ی کارکرد

در هنگام وقوع یک رخداد خاص (مثلاً درج نود جدید)، دروپال همه‌ی ماژول‌های فعال را بررسی می‌کند تا ببیند آیا آن‌ها تابعی مطابق نام هوک دارند یا نه. در صورت وجود، آن تابع اجرا می‌شود. ترتیب اجرای هوک‌ها براساس وزن ماژول‌ها (Module Weight) تعیین می‌شود.

مزایا

  • پیاده‌سازی ساده و سریع
  • بدون نیاز به ساختار شیءگرا
  • مناسب برای تغییرات کوچک و موقتی

محدودیت‌ها

  • در پروژه‌های بزرگ، کنترل ترتیب اجرا دشوار می‌شود.
  • ساختار تابعی آن انعطاف‌پذیری محدودی نسبت به معماری سرویس‌محور دارد.
  • نگهداری و تست خودکار آن دشوارتر از روش‌های مدرن است.

نمونه‌ی ساده

در ماژول my_module.module می‌توان نوشت:

function my_module_node_insert(\Drupal\node\Entity\Node $node) {
  \Drupal::logger('my_module')->notice('Node created with ID: @id', ['@id' => $node->id()]);
}

در این مثال، هوک hook_node_insert هنگام ایجاد نود اجرا می‌شود و پیام لاگ ثبت می‌کند.


بخش دوم: رویدادها در دروپال

تعریف رویداد

رویداد (Event) در دروپال مفهومی برگرفته از الگوی معماری Event Dispatcher در Symfony است. این سیستم امکان می‌دهد بخش‌های مختلف برنامه بدون وابستگی مستقیم با یکدیگر تعامل کنند. در این الگو، رویدادی منتشر می‌شود و هر جزء که به آن رویداد مشترک است (Subscriber)، می‌تواند واکنش نشان دهد.

اجزای اصلی

  1. رویداد (Event): شیئی که اطلاعات مربوط به رخداد را نگه می‌دارد.
  2. پخش‌کننده (Dispatcher): سرویسی که مسئول ارسال رویدادها به مشترکین است.
  3. مشترک رویداد (Subscriber): کلاسی که مشخص می‌کند در پاسخ به کدام رویدادها چه متدی اجرا شود.

نمونه‌ی پیاده‌سازی

فرض کنید می‌خواهیم هنگام ایجاد نود، پیام خاصی ثبت شود:

۱. تعریف رویداد:

namespace Drupal\custom_logger\Event;

use Symfony\Contracts\EventDispatcher\Event;
use Drupal\node\Entity\Node;

class NodeCreatedEvent extends Event {
  public const EVENT_NAME = 'custom_logger.node_created';
  protected Node $node;

  public function __construct(Node $node) {
    $this->node = $node;
  }

  public function getNode(): Node {
    return $this->node;
  }
}

۲. پخش رویداد:

function custom_logger_node_insert(Node $node) {
  $event = new \Drupal\custom_logger\Event\NodeCreatedEvent($node);
  \Drupal::service('event_dispatcher')->dispatch($event, NodeCreatedEvent::EVENT_NAME);
}

۳. تعریف مشترک رویداد:

services:
  custom_logger.node_created_subscriber:
    class: Drupal\custom_logger\EventSubscriber\NodeCreatedSubscriber
    tags:
      - { name: event_subscriber }
namespace Drupal\custom_logger\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\custom_logger\Event\NodeCreatedEvent;

class NodeCreatedSubscriber implements EventSubscriberInterface {
  public static function getSubscribedEvents(): array {
    return [NodeCreatedEvent::EVENT_NAME => 'onNodeCreated'];
  }

  public function onNodeCreated(NodeCreatedEvent $event): void {
    $node = $event->getNode();
    \Drupal::logger('custom_logger')->notice('Node created via event: @id', ['@id' => $node->id()]);
  }
}

بخش سوم: مقایسه‌ی هوک و رویداد

ویژگیهوک (Hook)رویداد (Event)
نوع ساختارتابعی (Procedural)شیءگرا (OOP)
ترتیب اجراوابسته به وزن ماژولقابل‌تعریف با اولویت
سطح وابستگیبالاپایین
مناسب برایتغییرات سریع و سادهپروژه‌های مدرن و ماژولار
ابزار توسعهفایل .moduleکلاس و سرویس با Event Dispatcher

بخش چهارم: ترکیب هوک و رویداد

در بسیاری از پروژه‌ها، هر دو سیستم در کنار هم استفاده می‌شوند. به‌عنوان مثال، هوک برای شناسایی نقطه‌ی ورود (مثل ایجاد نود) استفاده می‌شود و در درون آن رویدادی منتشر می‌شود تا سایر ماژول‌ها بتوانند به آن گوش دهند. این ترکیب باعث می‌شود سیستم در عین حفظ سازگاری با هسته، از انعطاف بالای معماری رویدادها نیز بهره ببرد.


بخش پنجم: روند آینده

از دروپال ۸ به بعد، تمرکز اصلی روی سرویس‌ها، رویدادها و معماری شیءگرا است. بسیاری از ماژول‌های جدید، به‌جای تکیه بر هوک‌ها، از Event Subscriber استفاده می‌کنند. همچنین ماژولی به نام Hook Event Dispatcher توسعه داده شده که هوک‌های سنتی را به رویداد تبدیل می‌کند و مسیر مهاجرت تدریجی را برای پروژه‌های قدیمی فراهم می‌سازد.


نتیجه‌گیری

سیستم هوک و سیستم رویداد دو ستون اصلی توسعه در دروپال هستند. هوک‌ها برای تغییرات سریع و مستقیم در رفتار هسته مناسب‌اند، در حالی‌که رویدادها با معماری مدرن و شیءگرا، گزینه‌ی مطلوب‌تری برای توسعه‌های گسترده و ماژولار محسوب می‌شوند. در پروژه‌های حرفه‌ای معمولاً ترکیبی از هر دو استفاده می‌شود تا هم سادگی حفظ شود و هم انعطاف‌پذیری و قابلیت گسترش افزایش یابد.

Submitted by boof_admin_meytad on