События Joomla: механизм работы с index.php

Раздел: Joomla -> Joomla

События в Joomla: механизмы и применение

Основной способ работы с событиями в Joomla заключается в создании плагина, который подписывается на определённые события, возникающие при выполнении index.php. Парсер Joomla запускает серию событий: onAfterInitialise, onAfterRoute, onAfterDispatch и другие. Плагины регистрируются через расширение plg_system.

Пример создания плагина для события onAfterRoute:


// Файл: plugins/system/myroute/myroute.php
class PlgSystemMyroute extends JPlugin
{
    public function onAfterRoute()
    {
        $app = JFactory::getApplication();
        if ($app->isClient('site')) {
            $app->enqueueMessage('Маршрут обработан', 'success');
        }
    }
}
    

Php itemid (параметр itemid в joomla)

После установки и включения плагина при каждой загрузке страницы будет выводиться сообщение после обработки маршрута.

Проблема: Плагин не срабатывает.

Решение: Проверить, что тип плагина system, файл назван корректно (myroute.php), и в манифесте указано событие. Также убедиться, что плагин опубликован и порядок не заблокирован другими плагинами.

Как перехватить событие до загрузки приложения?

Событие onBeforeInitialise не существует в стандартном цикле. Для работы до инициализации используют конструктор плагина или системную перегрузку JApplicationCms.


class PlgSystemMyearly extends JPlugin
{
    public function __construct(&$subject, $config)
    {
        parent::__construct($subject, $config);
        // Код выполняется до onAfterInitialise
        file_put_contents(JPATH_ROOT . '/debug.log', 'Ранняя инициализация');
    }
}
    

Php option com content (компонент com_content в joomla)

Ошибка: Конструктор не видит объект приложения.

Исправление: Использовать JFactory::getApplication() только после того, как приложение создано. В конструкторе это может быть недоступно. Вместо этого использовать событие onAfterInitialise.

Как выполнить код после отправки ответа?

Событие onAfterRespond позволяет выполнить финальные действия, например, запись в лог или очистку кэша.


class PlgSystemMyafter extends JPlugin
{
    public function onAfterRespond()
    {
        $log = JPATH_ROOT . '/logs/response.log';
        JFile::write($log, date('Y-m-d H:i:s') . ' - Ответ отправлен\n', FILE_APPEND);
    }
}
    

Index php event (события в joomla)

Проблема: Файл не записывается.

Решение: Убедиться, что папка logs существует и доступна для записи. Использовать JFile::write с абсолютными путями.

Как изменить содержимое ответа перед отправкой?

Событие onBeforeRender позволяет модифицировать тело документа.


class PlgSystemMycontent extends JPlugin
{
    public function onBeforeRender()
    {
        $doc = JFactory::getDocument();
        $buffer = $doc->getBuffer('component');
        $buffer = str_replace('старый текст', 'новый текст', $buffer);
        $doc->setBuffer($buffer, 'component');
    }
}
    

Ошибка: Изменения не отображаются.

Коррекция: Событие onBeforeRender может срабатывать до заполнения буфера. Использовать onAfterRender и манипулировать выводом через JResponse.

Как отловить событие при ошибке 404?

Событие onErrorPage (или onException в Joomla 4+) позволяет обработать исключения.


class PlgSystemMyerror extends JPlugin
{
    public function onErrorPage()
    {
        $app = JFactory::getApplication();
        $app->redirect('index.php?option=com_content&view=article&id=1');
    }
}
    

Проблема: Редирект не срабатывает.

Объяснение: Событие вызывается после отправки заголовков, редирект невозможен. Использовать JError::raiseError или модифицировать шаблон ошибки через onAfterRoute.

Расширенные примеры работы с событиями

Ниже представлены более сложные сценарии, включая работу с диспетчером событий и создание собственных событий.

Пример 1: Динамическая подписка на события через EventDispatcher

Пример

use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Factory;
use Joomla\Event\DispatcherInterface;

class PlgSystemMyadvanced extends JPlugin
{
    public function onAfterInitialise()
    {
        $dispatcher = Factory::getContainer()->get(DispatcherInterface::class);
        $dispatcher->addListener('onCustomEvent', function ($event) {
            $data = $event->getArguments();
            file_put_contents(JPATH_ROOT . '/custom.log', json_encode($data) . "\n", FILE_APPEND);
        });
    }
}

Проблема: Событие не вызывается.

Уточнение: Собственное событие должно быть инициировано через $dispatcher->dispatch('onCustomEvent', new AbstractEvent(...)) в другом месте кода. Без вызова слушатель не выполнится.

Пример 2: Работа с параметрами плагина и условиями выполнения

Плагин, который выводит сообщение только для определённых компонентов:

Пример

class PlgSystemMyconditional extends JPlugin
{
    public function onAfterRoute()
    {
        $app = JFactory::getApplication();
        $option = $app->input->getCmd('option', '');
        $enabled = $this->params->get('enabled_components', array());
        
        if (in_array($option, $enabled)) {
            $app->enqueueMessage('Плагин активен для ' . $option, 'info');
        }
    }
}
Результат: при загрузке компонента com_content появляется сообщение, если 'com_content' добавлен в настройки плагина.

Пример 3: Использование событий для кэширования и оптимизации

Событие onAfterRender позволяет сжать HTML или добавить метки:

Пример

class PlgSystemMyoptimize extends JPlugin
{
    public function onAfterRender()
    {
        $body = JResponse::getBody();
        $body = preg_replace('/\s+/', ' ', $body); // минификация
        JResponse::setBody($body);
    }
}

Типичная ошибка: Изменение тела запроса после отправки заголовков.

Решение: Убедиться, что вывод не был уже отправлен. Использовать буферизацию вывода через ob_start().

Пример 4: Создание собственного события и его вызов

Сначала зарегистрируем событие в плагине (зависит от Joomla 4+):

Пример

use Joomla\CMS\Event\AbstractEvent;

class PlgSystemMycustom extends JPlugin
{
    public function onAfterRoute()
    {
        $dispatcher = $this->getDispatcher();
        $event = new AbstractEvent('onBeforeCustomAction', ['data' => 'test']);
        $dispatcher->dispatch('onBeforeCustomAction', $event);
    }
}
Результат: Будет вызван любой слушатель, подписанный на 'onBeforeCustomAction'.

Пример 5: Отладка последовательности событий

Плагин для логирования всех событий:

Пример

class PlgSystemLogger extends JPlugin
{
    public function onAfterInitialise() { $this->log('onAfterInitialise'); }
    public function onAfterRoute()      { $this->log('onAfterRoute'); }
    public function onAfterDispatch()   { $this->log('onAfterDispatch'); }
    public function onBeforeRender()    { $this->log('onBeforeRender'); }
    public function onAfterRender()     { $this->log('onAfterRender'); }
    public function onAfterRespond()    { $this->log('onAfterRespond'); }
    
    private function log($event)
    {
        file_put_contents(JPATH_ROOT . '/logs/events.log', 
            date('Y-m-d H:i:s') . ' - ' . $event . "\n", FILE_APPEND);
    }
}
Файл events.log после загрузки страницы:
2025-04-10 14:32:10 - onAfterInitialise
2025-04-10 14:32:10 - onAfterRoute
2025-04-10 14:32:10 - onAfterDispatch
2025-04-10 14:32:10 - onBeforeRender
2025-04-10 14:32:10 - onAfterRender
2025-04-10 14:32:10 - onAfterRespond

События в Joomla - comments

En
Index php event (php)