Yii2 события

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Maksat1991
Сообщения: 57
Зарегистрирован: 2016.10.16, 00:15

Yii2 события

Сообщение Maksat1991 »

Есть три метода, при срабатывании которых я хочу записывать данные в лог-таблицу.
Я могу генерировать событие в этих трех методах.

Вопрос в том, где нужно поставить обработчик события, чтобы она автоматически срабатывал, как только наступит это событие?
Если это делать в контроллере, то кажется это глупо, зачем тогда вообще события.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Yii2 события

Сообщение ElisDN »

Если есть событие:

Код: Выделить всё

class OrderCreated extends Event
{
    public $order;

    public function __construct(Order $order)
    {
        $this->order = $order;
    }
}
То можно навешиваться глобально:

Код: Выделить всё

class SetUp implements BootstrapInterface
{
    public function bootstrap($app)
    {
        Event::on(OrderController::class, OrderController::EVENT_ORDER_CREATED, function (OrderCreated $event) {
            Yii::info('Order #' . $event->order->id . ' is created', 'app');
        });
        Event::on(OrderController::class, OrderController::EVENT_ORDER_PAYD, [OrderPaydListener::class, 'onOrderPayd']);
    }
}
и в контроллере вызывать:

Код: Выделить всё

$this->trigger(self::EVENT_ORDER_CREATED, new OrderCreated($order);
Или как шину событий использовать Yii::$app:

Код: Выделить всё

class SetUp implements BootstrapInterface
{
    public function bootstrap($app)
    {
        $app->on(OrderCreated::class, function (OrderCreated $event) {
            Yii::info('Order #' . $event->order->id . ' is created', 'app');
        });
        $app->on(OrderPayd::class, [OrderPaydListener::class, 'onOrderPayd']);
    }
}
и потом вызывать в любом месте:

Код: Выделить всё

Yii::$app->trigger(OrderCreated::class, new OrderCreated($order));
Если же пишете unit-тесты, то глобальные обработчики будут постоянно вызываться и в тестах. Поэтому сделайте отдельный EventDispatcher, который в тестах можно будет мОкнуть при необходимости:

Код: Выделить всё

class EventDispatcher extends Component
{
    public function dispatch($event)
    {
        $this->trigger(get_class($event), $event);
    }
}
и зарегистрируйте в DIC:

Код: Выделить всё

class SetUp implements BootstrapInterface
{
    public function bootstrap($app)
    {
        $container = Yii::$container;
        
        $container->setSingleton(EventDispatcher::class, function () {
            $dispatcher = new EventDispatcher();
            $dispatcher->on(OrderCreated::class, function (OrderCreated $event) {
                Yii::info('Order #' . $event->order->id . ' is created', 'app');
            };
            $dispatcher->on(OrderPayd::class, [OrderPaydListener::class, 'onOrderPayd']);
            return $dispatcher;
        });
    }
}
чтобы прокидывать его во все места через DIC:

Код: Выделить всё

class OrderService
{
    private $dispatcher;

    public function __construct(EventDispatcher $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }
    
    public function create(OrderForm $form)
    {
        $order = Order::create(...);
        ...
        $this->dispatcher->dispatch(new OrderCreated($order));
    }
}
Или зарегистрируйте как компонент:

Код: Выделить всё

class SetUp implements BootstrapInterface
{
    public function bootstrap($app)
    {
        $app->set('eventDispatcher', function () {
            $dispatcher = new EventDispatcher();
            $dispatcher->on(OrderCreated::class, function (OrderCreated $event) {
                Yii::info('Order #' . $event->order->id . ' is created', 'app');
            };
            $dispatcher->on(OrderPayd::class, [OrderPaydListener::class, 'onOrderPayd']);
            return $dispatcher;
        });
    }
}
чтобы он стал доступен через Yii::$app:

Код: Выделить всё

Yii::$app->eventDispatcher->dispatch(new OrderCreated($order));
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Yii2 события

Сообщение Nex-Otaku »

С диспетчером самый красивый код )
Ответить