Back to Main Site

Справочник по хукам и фильтрам: полное руководство для разработчиков

Last updated on Jun 23, 2026 09:18

Справочник по хукам и фильтрам

Аудитория: Разработчик — Требуются знания PHP/Laravel. Категория: Технический справочник — техническая документация для разработчиков интеграции.

Чему вы научитесь

  • Понять механизм действия и фильтра в PolyCMS.

  • Поиск имен крюков, параметров и мест отправки.

— Зарегистрируйте хуки из темы «functions.php» и модуля «ServiceProvider».

  • Используйте приоритет для контроля порядка выполнения

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

1. Введение в систему хуков

PolyCMS использует систему Hook/Filter, подобную WordPress, встроенную в Laravel:

  • Действие (Hook::doAction): выполняет побочные эффекты (ведение журнала, отправка электронной почты, синхронизация данных). Возвращаемое значение не требуется.

  • Filter (Hook::applyFilters): получает значение, изменяет его и должен вернуть измененное значение.

Базовый синтаксис

use App\Facades\Hook;

// Register an Action
Hook::addAction('order_completed', function ($order) {
    Mail::to($order->user)->send(new OrderCompletedMail($order));
}, priority: 10);

// Register a Filter
Hook::addFilter('post.default_image', function (?string $imageUrl, $post) {
    if ($post?->categories->contains('slug', 'news')) {
        return '/images/news-default.jpg';
    }
    return $imageUrl;
}, priority: 10);

2. Контент и публикации

Фильтры

Крюк Параметры Описание
post.default_image $imageUrl, $context Изображение по умолчанию, если в сообщении нет избранного изображения
post.frontend_url $url, $post Настройте общедоступный URL-адрес публикации
post.content.render $html, $post Фильтруйте HTML-содержимое публикации перед возвратом к API
post.query.builder $query, $request Измените запрос Eloquent для списка сообщений
category.frontend_url $url, $category Настройте общедоступный URL-адрес категории
content.render.blocks $blocks Фильтровать массив блоков перед рендерингом
content.render.html $html, $blocks Фильтрация конечного вывода HTML
content.render.block.{type} $html, $block Отображение или переопределение определенного типа блока

Действия

Крюк Параметры Описание
tag.saved $tag, $context Срабатывает после создания/обновления тега
tag.deleted $tag, $context Срабатывает после удаления тега
category.saved $category, $context Запускается после создания/обновления категории
category.deleted $category, $context Срабатывает после удаления категории

Практические примеры использования

UC1 — Миниатюра по умолчанию для конкретной категории: Сохраняйте специальную миниатюру по умолчанию для каждой категории, если в публикации нет избранного изображения:

Hook::addFilter('post.default_image', function (?string $url, $post) {
    if ($post?->categories->contains('slug', 'tech')) return '/images/defaults/tech.jpg';
    if ($post?->categories->contains('slug', 'lifestyle')) return '/images/defaults/lifestyle.jpg';
    return $url; // fallback to admin setting
});

UC2 — Структура URL-адреса вики: Понизьте или измените структуру URL-адреса публикации с /posts/slug на /docs/slug для макета в стиле вики:

Hook::addFilter('post.frontend_url', function ($url, $post) {
    return ($post->type === 'wiki') ? '/docs/' . $post->slug : $url;
});

UC3 — Автоматическое внедрение встроенной рекламы. Автоматически вставлять блоки рекламных баннеров после третьего абзаца сообщения:

Hook::addFilter('content.render.html', function (string $html) {
    $adBanner = '<div class="ad-inline">Advertisement</div>';
    $parts = explode('</p>', $html, 4);
    if (count($parts) > 3) {
        $parts[2] .= '</p>' . $adBanner;
        return implode('</p>', $parts);
    }
    return $html;
});

3. Медиатека

Фильтры

Крюк Параметры Описание
media.upload.file $file, $data Измените загруженный файл перед обработкой
media.upload.data $data, $file Изменить метаданные загрузки
media.create.data $mediaData, $file Изменить атрибуты медиа-записи перед сохранением в БД
media.delete.should $shouldDelete, $media Ворота безопасности: верните false, чтобы заблокировать удаление носителя
media.url $url, $media Переписать URL-адрес (например, для перенаправления на CDN)

Действия

Крюк Параметры Описание
media.uploaded $media, $file, $data Срабатывает после успешной загрузки
media.deleting $media Срабатывает перед удалением
media.deleted $media Срабатывает после удаления

Практические примеры использования

UC1 — перезапись URL-адресов CDN. Интеграция с Cloudflare R2 или Amazon S3, автоматическое преобразование путей локального хранилища в URL-адреса CDN:

Hook::addFilter('media.url', function (string $url, $media) {
    return str_replace('/storage/', 'https://cdn.mysite.com/', $url);
});

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

Hook::addFilter('media.delete.should', function (bool $allow, $media) {
    $logoUrl = get_option('site_logo', null, 'general');
    return ($media->url === $logoUrl) ? false : $allow;
});

UC3 — автоматическая оптимизация изображений при загрузке. Отправка фоновых очередей для создания облегченных изображений WebP на основе стандартных загрузок:

Hook::addAction('media.uploaded', function ($media, $file) {
    if (str_starts_with($media->mime_type, 'image/')) {
        dispatch(new ConvertToWebpJob($media));
    }
});

4. Электронная коммерция — заказы и возврат средств

Действия

Крюк Параметры Описание
order_status_updated $order, $oldStatus, $newStatus Срабатывает при изменении статуса заказа
order_completed $order Срабатывает при успешном выполнении заказа
order.refund.processing $order, $validated Срабатывает перед обработкой возврата
order.refund.completed $order, $result Срабатывает после успешного возврата
order.refund.succeeded $order, $result, $validated, $userId Возврат API выполнен успешно
order.refund.failed $order, $validated, $exception, $userId Возврат API не удался

Фильтры

Крюк Параметры Описание
order.refund.preview.result $preview, $order, $input Изменить данные предварительного просмотра возврата

Практические примеры использования

UC1 — Уведомление о новых заказах в Telegram:

Hook::addAction('order_status_updated', function ($order, $old, $new) {
    if ($old === 'pending' && $new === 'processing') {
        TelegramBot::send(" Order #{$order->code} has been confirmed!");
    }
});

UC2 — Бонусные баллы за лояльность при выполнении заказа:

Hook::addAction('order_completed', function ($order) {
    if ($order->user_id) {
        $points = (int) floor($order->total / 10); // 1 point per $10 spent
        LoyaltyService::addPoints($order->user_id, $points, "Order #{$order->code}");
    }
});

UC3 — Журнал аудита неудачных возвратов средств:

Hook::addAction('order.refund.failed', function ($order, $data, $exception, $userId) {
    AuditLog::create([
        'action' => 'refund_failed',
        'order_id' => $order->id,
        'user_id' => $userId,
        'reason' => $exception->getMessage(),
    ]);
});

5. Электронная коммерция — корзина, доставка, налоги, инвентарь.

Фильтры

Крюк Параметры Описание
cart.totals $totals, $cart Изменить сумму корзины
shipping.calculate_cost $cost, $method, $cart Переопределить стоимость доставки
shipping.available_methods $methods, $address, $cart Фильтрация способов доставки по адресу и содержимому корзины
tax.calculated $result, $subtotal, $address Переопределить результат расчета налога
inventory.is_stockable_product $default, $product, $context Проверьте, отслеживает ли продукт уровень запасов
review.can_submit $allowed, $user, $product Ворота безопасности: разрешить пользователю оставить отзыв?

Действия

Крюк Параметры Описание
cart.item.added $item, $cart Срабатывает после добавления товара в корзину
cart.item.updated $item, $oldQty, $newQty Срабатывает при изменении количества товара
cart.item.removed $item, $cart Срабатывает после удаления элемента
cart.cleared $cart Срабатывает после очистки корзины
cart.merged $userCart, $guestCart Срабатывает, когда гостевая корзина объединяется с корзиной аутентифицированного пользователя
review.submitted $review Активируется после отправки отзыва
review.approved $review Активируется после одобрения отзыва
review.rejected $review Срабатывает после отклонения отзыва

Практические примеры использования

UC1 — Бесплатная доставка для заказов на сумму более 100 долларов США:

Hook::addFilter('shipping.calculate_cost', function ($cost, $method, $cart) {
    $subtotal = collect($cart->items)->sum(fn($i) => $i->price * $i->quantity);
    return ($subtotal >= 100) ? 0 : $cost;
});

UC2 — Блокировка отзывов, если пользователь не купил продукт:

Hook::addFilter('review.can_submit', function (bool $allowed, $user, $product) {
    $hasPurchased = Order::where('user_id', $user->id)
        ->where('status', 'completed')
        ->whereHas('items', fn($q) => $q->where('product_id', $product->id))
        ->exists();
    return $hasPurchased;
});

UC3 — отслеживание пикселей Facebook для события AddToCart:

Hook::addAction('cart.item.added', function ($item, $cart) {
    session()->push('fb_pixel_events', [
        'event' => 'AddToCart',
        'product_id' => $item->product_id,
        'value' => $item->price,
    ]);
});

6. Электронная коммерция — платежные шлюзы

Фильтры

Крюк Параметры Описание
payment.gateway.config_schema $schema, $gateway Расширение полей конфигурации схемы для шлюза

Практический пример использования: добавьте настраиваемое поле в шлюз банковских переводов:

Hook::addFilter('payment.gateway.config_schema', function ($schema, $gateway) {
    if ($gateway->code === 'bank_transfer') {
        $schema['branch_code'] = [
            'type' => 'text', 'label' => 'Branch Code', 'required' => false,
        ];
    }
    return $schema;
});

7. Тема и внешний вид

Фильтры

Крюк Параметры Описание
theme.view.data $data, $viewName Внедрить/изменить переменные представления для любого шаблона Blade
theme.template.resolve $viewName, $templateTheme, $entityType, $entity Переопределить соответствующие виды лезвий
theme.template.registry $templates, $viewType Зарегистрируйте новые шаблоны страниц
theme.options.values $options Фильтровать значения параметров загруженной темы
theme.options.css_vars $cssVars, $themeOptionValues Изменение пользовательских свойств CSS
theme.breadcrumbs.post $breadcrumbs, $post Фильтровать хлебные крошки сообщений
theme.breadcrumbs.product $breadcrumbs, $product Фильтровать панировочные сухари
theme.show_page_header $show, $page Переключить видимость заголовка страницы
frontend.topbar.banners $banners Внедрить рекламные баннеры в верхнюю панель
themes.list $themes Фильтровать список доступных тем в администраторе

Действия

Крюк Параметры Описание
theme.activated $theme Срабатывает при активации темы
theme.main.changed $theme, $oldMainTheme Срабатывает при смене основных тем
theme.installing $file Срабатывает перед распаковкой ZIP темы
theme.activating $slug, $type, $mode Срабатывает перед активацией темы
theme.deactivating $slug Срабатывает перед деактивацией темы
theme.deleting $theme Срабатывает перед удалением темы
cms_head (нет) Перехватчик вывода внутри тега макета <head>

Практические примеры использования

UC1 — Вставка рекламного баннера из модуля:

Hook::addFilter('frontend.topbar.banners', function (array $banners) {
    $banners[] = [
        'text' => ' Flash Sale — 30% Off Today!',
        'url' => '/sale',
        'bg_color' => '#ff4444',
    ];
    return $banners;
});

UC2 – внедрение головы в Google Analytics:

Hook::addAction('cms_head', function () {
    $ga = get_option('google_analytics_id', null, 'seo');
    if ($ga) {
        echo "<script async src='https://www.googletagmanager.com/gtag/js?id={$ga}'></script>";
    }
});

UC3 — Загрузка переменной боковой панели популярных сообщений:

Hook::addFilter('theme.view.data', function ($data, $viewName) {
    if ($viewName === 'posts.index') {
        $data['popular_posts'] = Post::orderBy('views', 'desc')->limit(5)->get();
    }
    return $data;
});

8. Настройки и конфигурация

Фильтры

Крюк Параметры Описание
settings.defaults $defaults, $settingsService Расширить или переопределить определения базовых настроек
settings.media.drivers $drivers Зарегистрируйте новые драйверы накопителей
settings.permalinks.structure $structure, $settingsService Система фильтров постоянных ссылок

Действия

Крюк Параметры Описание
setting.updating $key, $value, $group, $type Срабатывает перед сохранением настройки
settings.saved $payload Срабатывает после сохранения настроек

Практические примеры использования

UC1 — Регистрация раздела пользовательских настроек через модуль:

Hook::addFilter('settings.defaults', function ($defaults) {
    $defaults['mymodule'] = [
        'mymodule_api_key' => [
            'key' => 'mymodule_api_key', 'value' => '', 'type' => 'text',
            'label' => 'API Key', 'description' => 'Enter your API key',
        ],
    ];
    return $defaults;
});

UC2 — Очистка кэша маршрутов при обновлении постоянных ссылок:

Hook::addAction('settings.saved', function ($payload) {
    if (($payload['group'] ?? '') === 'permalinks') {
        Artisan::call('route:clear');
        Cache::tags('routes')->flush();
    }
});

9. Пользователи, роли и аутентификация

Фильтры

Крюк Параметры Описание
user.resource.to_array $data, $user, $request Расширение вывода ресурсов пользовательского API
auth.login.pre_token $response, $user, $request Перехват жизненного цикла входа в систему (например, для многофакторной аутентификации)

Действия

Крюк Параметры Описание
user.creating / user.updating / user.deleting `$user $data`
role.creating / role.updating / role.deleting / role.cloning `$role $data`

Практические примеры использования

UC1 — перехватчик многофакторной аутентификации:

Hook::addFilter('auth.login.pre_token', function ($response, $user, $request) {
    if ($user->hasRole('admin') && !$request->filled('otp_code')) {
        return response()->json(['requires_2fa' => true, 'user_id' => $user->id], 403);
    }
    return $response; // null = continue token generation
});

UC2 — Приветственное письмо при регистрации пользователя:

Hook::addAction('user.creating', function ($data) {
    dispatch(new SendWelcomeEmail($data['email'], $data['name']));
});

10. SEO

Фильтры

Крюк Параметры Описание
seo.canonical_url $url Переопределить канонические URL-адреса
seo.site_favicon $iconUrl Переопределить пути к значкам

Практический пример использования — канонический URL-адрес для многоязычных настроек:

Hook::addFilter('seo.canonical_url', function (string $url) {
    $locale = app()->getLocale();
    if ($locale !== 'en') {
        return url("/{$locale}" . parse_url($url, PHP_URL_PATH));
    }
    return $url;
});

11. Виджеты

Фильтры

Крюк Параметры Описание
widget.render.instance $instance Измените настройки экземпляра виджета перед рендерингом
widget.render.{widget_type} $widget Изменить определенные данные виджета
widget.area.render.instances $instances, $area Фильтрация экземпляров виджетов, загруженных в пределах области
widget.render.output $html, $instance Фильтрация вывода HTML одного виджета
widget.area.render.output $html, $area Фильтровать вывод рендеринга области виджетов
widgets.types $widgets Фильтровать список зарегистрированных типов виджетов

Действия

Крюк Параметры Описание
widgets.register_types $widgetManager Зарегистрируйте новые типы виджетов
widgets.register_areas $widgetManager Зарегистрируйте новые области виджетов

Практический пример использования — зарегистрировать тип виджета «Карта магазина»:

Hook::addAction('widgets.register_types', function ($manager) {
    $manager->registerType('store_map', [
        'label' => 'Store Map',
        'description' => 'Google Maps showing store locations',
        'fields' => [
            'api_key' => ['type' => 'text', 'label' => 'Google Maps API Key'],
            'lat' => ['type' => 'text', 'label' => 'Latitude'],
            'lng' => ['type' => 'text', 'label' => 'Longitude'],
        ],
        'view' => 'widgets.store-map',
    ]);
});

12. Административная навигация и редактор

Фильтры

Крюк Параметры Описание
topbar.menu.items $items, $request, $user Добавить/удалить элементы из панели администратора
topbar.menu.should_show $show, $user Переключить видимость верхней панели администратора интерфейса
admin.editor.panels $panels, $type, $user Добавьте пользовательские панели на боковую панель редактора блоков

Действия

Крюк Параметры Описание
admin.menu.build (нет) Срабатывает при сборке навигационного меню боковой панели
topbar.menu.context $request, $user Запускается при инициализации панели администратора интерфейса

Практический пример использования — добавьте пункт пользовательского меню статуса SEO в верхнюю панель:

Hook::addFilter('topbar.menu.items', function (array $items, $request, $user) {
    $items[] = [
        'key' => 'seo_score',
        'label' => 'SEO Score',
        'icon' => 'chart-bar',
        'url' => '/admin/seo/score',
        'position' => 50,
    ];
    return $items;
});

13. Модули

Фильтры

Крюк Параметры Описание
module.resource.meta $meta, $moduleData Расширить детали метаданных модуля
modules.list $modulesArray Фильтровать перечисленные модули в администраторе
product.query.builder $query, $request Изменить продукт Запросы на список Eloquent

Действия

Крюк Параметры Описание
module.activating $moduleKey, $module Срабатывает перед активацией модуля
module.deactivating $moduleKey, $module Срабатывает перед деактивацией модуля
module.deleting $moduleKey, $module Срабатывает перед удалением модуля
module.installing $uploadedFile Срабатывает при загрузке ZIP-файлов нового модуля

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

Hook::addAction('module.activating', function ($moduleKey, $module) {
    Artisan::call('migrate', [
        '--path' => "modules/Polyx/{$moduleKey}/database/migrations",
        '--force' => true,
    ]);
});

14. Загрузка системы

Действия

Крюк Параметры Описание
roles.register_permissions $permissionRegistry Зарегистрируйте новые системные разрешения
register_email_templates $emailTemplateManager Зарегистрируйте основные шаблоны электронной почты
layout.register_assets $layoutAssetManager Зарегистрируйте пользовательские ресурсы макета администратора/интерфейса
routes.frontend.register (нет) Внедрить пользовательские маршруты интерфейса

Практический пример использования — модуль регистрирует пользовательские возможности/разрешения:

Hook::addAction('roles.register_permissions', function ($registry) {
    $registry->register('manage analytics', 'Analytics', 'View and manage analytics dashboard');
    $registry->register('export reports', 'Analytics', 'Export analytics reports to CSV');
});

Статьи по теме