Перейти к основному содержимому

События и слушатели событий

Общие сведения

Pimcore предоставляет обширное количество событий, которые инициируются во время выполнения функций системы. Эти события можно использовать для перехвата стандартных процессов Pimcore, таких как сохранение объекта, ассета или документа, а также для изменения или расширения поведения системы по умолчанию.

Наиболее распространенный сценарий использования событий — разработка бандлов, но вы можете использовать их в любом месте вашего кода или в конфигурации внедрения зависимостей (config/services.yaml).

Pimcore реализует стандартный диспетчер Symfony Framework Event и добавляет к нему специфические события Pimcore. Это означает, что вы также можете подписываться на любые основные события Symfony или события, генерируемые сторонними бандлами.

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

Доступные события

Все события Pimcore определены и задокументированы в виде констант в классах, соответствующих компонентам:

Примеры

Перехват события pre-update для ассетов, документов и объектов

В следующем примере показано, как зарегистрировать слушателя события для ассетов, документов и объектов.

В вашем config/services.yaml:

services:  
App\EventListener\TestListener:
tags:
- { name: kernel.event_listener, event: pimcore.asset.preUpdate, method: onPreUpdate }
- { name: kernel.event_listener, event: pimcore.document.preUpdate, method: onPreUpdate }
- { name: kernel.event_listener, event: pimcore.dataobject.preUpdate, method: onPreUpdate }

В вашем классе слушателя src/EventListener/TestListener

<?php  

namespace App\EventListener;

use Pimcore\Event\Model\ElementEventInterface;
use Pimcore\Event\Model\DataObjectEvent;
use Pimcore\Event\Model\AssetEvent;
use Pimcore\Event\Model\DocumentEvent;

class TestListener
{
public function onPreUpdate(ElementEventInterface $e): void
{
if ($e instanceof AssetEvent) {
// Работаем с ассетом
$foo = $e->getAsset();
} else if ($e instanceof DocumentEvent) {
// Работаем с документом
$foo = $e->getDocument();
} else if ($e instanceof DataObjectEvent) {
// Работаем с объектом
$foo = $e->getObject();
$foo->setMyValue(microtime(true));
// Метод save() вызывать не нужно, так как это событие pre-update ;-)
}
}
}

Перехват листинга объектов в дереве, интерфейсе сетки и поиске

Есть несколько глобальных событий, которые влияют на несколько мест. Одно из них - pimcore.admin.object.list.beforeListLoad. Список объектов может быть изменен (например, изменено условие) перед загрузкой. Это глобальное событие будет применено к дереву, списку таблиц, панели поиска и ко всем листингам объектов в графическом интерфейсе Pimcore. This way, it is possible to create custom permission rules to decide if the object should or not be listed (for instance, the user must be the owner of the object, ...).

Это удобно для создания кастомных правил доступа (например, показывать пользователю только те объекты, владельцем которых он является). Для максимальной безопасности рекомендуется комбинировать это с переопределением метода isAllowed через DI (Dependency Injection), чтобы проверка прав работала и через REST-сервисы.

Перехват диалога открытия документа, ассета или объекта

По умолчанию Pimcore ищет элемент по его ID или пути. Вы можете изменить это поведение через событие AdminEvents::RESOLVE_ELEMENT.

    \Pimcore::getEventDispatcher()->addListener(AdminEvents::RESOLVE_ELEMENT, function(ResolveElementEvent $event) {  
$id = $event->getId();
if ($event->getType() == "object") {
if (is_numeric($event->getId())) {
return;
}

$listing = new News\Listing();
$listing->setLocale('en');
$listing->setLimit(1);
$listing->setCondition('title LIKE ' . $listing->quote('%' . $id . '%'));
$listing = $listing->load();
if ($listing) {
$id = ($listing[0])->getId();
$event->setId($id);
}
}

Путь загрузки ассета

Определенные типы данных (например, изображения, отношения и т.д.) позволяют вам указать выделенный путь загрузки, который по умолчанию равен /\_default\_upload\_bucket, если иное не указано в файле конфигурации yml или в определении класса.

Событие AssetEvents::RESOLVE_UPLOAD_TARGET позволяет динамически изменять целевую папку для загрузки файлов в зависимости от контекста (например, поля объекта, в которое перетаскивается файл). Дополнительная контекстуальная информация (например, имя поля, индексный номер коллекции полей и т.д.) может быть использована для принятия решения.

Предоставленная контекстуальная информация совпадает с описанной здесь:

Пример кода: Для демонстрационного экземпляра этот пример кода поместил бы изображение, которое перетаскивается в поле image_1 объекта 6 (in-enim-justo_2). в папку ресурсов /news/in-enim-justo_2/image_1.

        \Pimcore::getEventDispatcher()->addListener(AssetEvents::RESOLVE_UPLOAD_TARGET,  
function(\Pimcore\Event\Model\Asset\ResolveUploadTargetEvent $event) {
$context = $event->getContext();
if ($context["containerType"] == "object") {
$objectId = $context["objectId"];
$newsObject = News::getById($objectId);
if ($newsObject) {
$fieldname = $context["fieldname"];
$targetPath = $newsObject->getPath() . $newsObject->getKey() . "/" . $fieldname;
$parent = \Pimcore\Model\Asset\Service::createFolderByPath($targetPath);
if ($parent) {
$event->setParentId($parent->getId());
}
}

}
});


Вы можете предложить улучшение документации или задать вопрос в комментариях.
Если вам нужна полноценная консультация — вы можете заказать её на нашем сайте.