В посте Заменяем устаревший метод CMSApplicationInterface::triggerEvent в Joomla 5.1.4 я вскольз упоминал собственные классы событий. Теперь я хочу рассказать о них подробнее.

Создание класса начинается с пространства имён, имени класса и родителя

Имя и пространство имён класса зависит от контекста. Например, я пишу компонент импорта для JoomShopping:

Пространство имён

Event\Model\Price - Событие относится к модели, но в компоненте есть и другие модели, у которых тоже есть метод importExcel . Поэтому включим имя модели Price в namespace.

Имя класса

А класс назовём BeforeImportExcelEvent аналогично другим классам из ядра Joomla. В компоненте могут классы событий с такие же именем, но другим namespase.

Родительский класс

Очевидный родитель для нашего класса — Joomla\CMS\Event\AbstractEvent, который является родителем и для Joomla\CMS\Event\GenericEvent используемого по-умолчанию.

И так, наш класс готов к использованию, но у него нет никаких преимуществ.

Недостатки стандартного класса события

Объект события в первую очередь предназначен для передачи данных в обработчик события и получения из него результатов. В классе \Joomla\CMS\Event\GenericEvent вам доступны методы getArgument и setArgument с помощью которых вы можете работать с аргументами по имени.

<?php
public function onJSImportPriceBeforeImportExcel(Event $event): void
{
  $data = $event->getArgument('data');
}

Недостаток такого подхода в том, что метод getArgument возвращает mixed то есть там может быть что угодно, ваша IDE не знает что в переменной, и не ожидаемый тип данных может вызвать ошибку.

Можно дописать @var-комментарий и проверку типа для каждого аргумента:

<?php
public function onJSImportPriceBeforeImportExcel(Event $event): void
{
  /** @var array $data */
  $data = $event->getArgument('data');

  if (!is_array($data))
  {
    throw new Exception('Data must be array');
  }
}

Но вам придётся делать это в каждом событии каждого плагина, что делает код более громоздким.

Преимущества собственного класса

Геттеры и сетеры для аргументов

В своём классе вы можете определить сеттеры и геттеры для аргументов и методы setArgument и getArgument родительского класса Joomla\CMS\Event\AbstractEvent будут их использовать.

on + Set/Get + Имя аргумента с большой буквы .

В моём случае onSetData($value) и onGetData($value).

setArgument передаст значение сеттеру и установит полученный от него результат .

getArgument передаст значение геттеру и вернёт полученный от него результат.

Собственные методы

Так же для удобства написания плагинов вы можете добавить в класс события собственный метод для получения данных: getData(): array указав ему тип возвращаемого значения. Таким образом, код для получения валидных данных в плагине сократится до одной строки, и IDE будет видеть тип данных.

<?php
public function onJSImportPriceBeforeImportExcel(BeforeImportExcelEvent $event): void
{
  $data = $event->getData();
}

А вот код нашего класса:

<?php
namespace Joomla\Component\Jsimport\Event\Model\Price;

use Joomla\CMS\Event\AbstractEvent;
use function defined;

// phpcs:disable PSR1.Files.SideEffects
defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects

/**
 * @since 1.0.0
 */
class BeforeImportExcelEvent extends AbstractEvent
{
	/**
	 * Setter for the data argument.
	 *
	 * @param   array  $value  The value to set
	 *
	 * @return  array
	 *
	 * @since  1.0.0
	 */
	protected function onSetData(array $value): array
	{
        if (!count($value))
        {
            throw new Exception('Data must be not empty array');
        }

        return $value;
	}

	/**
	 * Getter for the data.
	 *
	 * @return  array
	 *
	 * @since  1.0.0
	 */
	public function onGetData(array $value): array
	{
	 	return $value;
	}

  	/**
	 * @return  array
	 *
	 * @since  1.0.0
	 */
	public function getData(): array
	{
	 	return $this->getArgument('data');
	}
}

В Joomla 5.2.0 для событий есть и другие родительские классы, интерфейсы и трейты, о них напишу в следующей статье.

Комментарии (1)


  1. sergeytolkachyov
    25.10.2024 05:40

    Спасибо большое за статью :) Пригодится