Кастомные хуки Directus для бизнес-логики

Отметим: когда данные в Directus требуют мгновенной реакции — проверка корректности заказа, отправка уведомления о новой заявке или синхронизация с внешней системой — стандартных средств CMS часто не хватает. Разработка кастомных хуков (Hook Extensions) позволяет встроить бизнес-логику прямо в ядро:

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

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

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Кастомные хуки Directus для бизнес-логики
Средний
~2-3 дня

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1414
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1285
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    982
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1241
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    982
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    994

Отметим: когда данные в Directus требуют мгновенной реакции — проверка корректности заказа, отправка уведомления о новой заявке или синхронизация с внешней системой — стандартных средств CMS часто не хватает. Разработка кастомных хуков (Hook Extensions) позволяет встроить бизнес-логику прямо в ядро: вы подписываетесь на события CRUD, аутентификации или загрузки файлов и выполняете произвольный код. Это снижает задержки на 30–50% по сравнению с внешними вызовами API, а также упрощает архитектуру — не нужно поднимать отдельный микросервис для обработки данных. Наша команда имеет 5-летний опыт и более 30 проектов на Directus, что обеспечивает надёжное и производительное решение. Свяжитесь с нами, чтобы обсудить вашу задачу — мы подготовим оценку за 1 день.

Проблемы, решаемые кастомными хуками

Кастомные хуки устраняют необходимость во внешних вызовах API для обработки изменений — они работают в том же контексте, что и CMS, что сокращает задержку на 30-50% по сравнению с внешней логикой. Типовые сложности:

  • Валидация сложных данных — проверка остатков на складе, корректности связей, уникальности полей. Например, при создании заказа хук проверяет, доступен ли товар в нужном количестве.
  • Побочные эффекты — отправка уведомлений в Slack/Telegram, запись аудит-логов, инвалидация кэша. Хуки обрабатывают события в 3–5 раз быстрее, чем внешние API-вызовы.
  • Интеграции — синхронизация с ERP, CRM (например, 1С), платёжными шлюзами.
  • Автоматизация — генерация slug, обновление остатков, формирование отчётов по расписанию с помощью cron.

Почему кастомные хуки лучше внешней логики?

Внешние сервисы добавляют задержки на сетевые вызовы и требуют отдельного деплоя. Хуки выполняются в том же процессе Directus, что снижает TTFB и упрощает мониторинг. Например, при обработке заказа хук проверяет остатки за 5 мс, тогда как внешний API-вызов занимает 50–100 мс. Это особенно важно для high-load проектов, где каждая миллисекунда на счету.

Как сделать первый хук валидации?

  1. Создайте файл extensions/hooks/custom/index.ts.
  2. Экспортируйте функцию, принимающую HookExtensionContext.
  3. Вызовите filter('items.create', async (payload, meta, context) => { ... }).
  4. Для отмены операции выбросьте ошибку через throw new Error('Сообщение').
  5. Перезапустите Directus — хук подхватится автоматически.

Пример валидации: проверка, что email уникален в коллекции users. Если занят — хук выбрасывает ошибку, и запись не создаётся.

Типы событий

Тип Описание Применение
action После выполнения операции Уведомления, кэш, интеграции
filter До выполнения операции (можно изменить данные) Валидация, модификация payload
init При старте сервера Загрузка конфигураций, инициализация подключений
schedule По расписанию cron Ежедневные отчёты, очистка данных

Сравнение action и filter хуков

Критерий Action-хуки Filter-хуки
Когда выполняется После записи в БД До записи в БД
Может изменить данные Нет Да
Блокирует ответ Нет (асинхронные) Да (синхронные)
Типичные сценарии Уведомления, кэш Валидация, присвоение значений

Полный пример Hook Extension

// extensions/hooks/business-logic/index.ts import type { HookExtensionContext } from '@directus/types' import type { EventContext } from '@directus/types' export default ({ action, filter, schedule }: HookExtensionContext) => { // ===== АВТОМАТИЧЕСКАЯ ГЕНЕРАЦИЯ SLUG ===== filter('items.create', (payload, meta) => { if (meta.collection === 'articles' && payload.title && !payload.slug) { payload.slug = generateSlug(payload.title as string) } if (meta.collection === 'products' && payload.name && !payload.slug) { payload.slug = generateSlug(payload.name as string) } return payload }) // ===== ВАЛИДАЦИЯ ===== filter('items.create', async (payload, meta, context) => { if (meta.collection !== 'orders') return payload const { database } = context as EventContext & { database: any } // Проверить наличие товара if (payload.items && Array.isArray(payload.items)) { for (const item of payload.items) { const product = await database('products') .where({ id: item.product_id }) .first() if (!product) { throw new Error(`Product ${item.product_id} not found`) } if (product.stock < item.quantity) { throw new Error(`Insufficient stock for "${product.name}"`) } } } return payload }) // ===== ИНВАЛИДАЦИЯ КЭША ===== action('items.update', async ({ collection, keys, payload }) => { const collectionsToRevalidate = ['articles', 'pages', 'products', 'settings'] if (!collectionsToRevalidate.includes(collection)) return try { await fetch(`${process.env.NEXTJS_URL}/api/revalidate`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-revalidate-secret': process.env.REVALIDATE_SECRET!, }, body: JSON.stringify({ collection, keys }), }) } catch (err) { console.error('Failed to revalidate cache:', err) } }) // ===== УВЕДОМЛЕНИЯ ===== action('items.create', async ({ collection, key, payload }, context) => { if (collection !== 'contact_submissions') return // Уведомить команду в Slack await fetch(process.env.SLACK_WEBHOOK!, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: `📬 Новая заявка от ${payload.name} <${payload.email}>\n${payload.message}`, }), }) }) // ===== АУДИТ ЛОГ ===== action('items.update', async ({ collection, keys, payload, accountability }) => { if (!accountability?.user) return // Логировать изменения в audit_logs коллекцию const { getSchema } = context as any const schema = await getSchema() // ... записать в audit_logs }) // ===== СИНХРОНИЗАЦИЯ ОСТАТКОВ ===== action('items.update', async ({ collection, keys, payload }, context) => { if (collection !== 'orders') return if (payload.status !== 'paid') return const { database } = context as EventContext & { database: any } const order = await database('orders') .where({ id: keys[0] }) .first() if (order?.items) { const items = JSON.parse(order.items) for (const item of items) { await database('products') .where({ id: item.product_id }) .decrement('stock', item.quantity) } } }) // ===== CRON — ежедневный отчёт ===== schedule('0 9 * * 1-5', async () => { const response = await fetch(`${process.env.API_URL}/custom/reports/sales`) const stats = await response.json() await fetch(process.env.SLACK_WEBHOOK!, { body: JSON.stringify({ text: `📊 Отчёт за вчера: заказов ${stats.count}, выручка ${stats.revenue.toLocaleString()} ₽`, }), }) }) } function generateSlug(text: string): string { const translitMap: Record<string, string> = { а: 'a', б: 'b', в: 'v', г: 'g', д: 'd', е: 'e', ё: 'yo', ж: 'zh', з: 'z', и: 'i', й: 'y', к: 'k', л: 'l', м: 'm', н: 'n', о: 'o', п: 'p', р: 'r', с: 's', т: 't', у: 'u', ф: 'f', х: 'h', ц: 'ts', ч: 'ch', ш: 'sh', щ: 'sch', ъ: '', ы: 'y', ь: '', э: 'e', ю: 'yu', я: 'ya', } return text .toLowerCase() .replace(/[а-яё]/g, char => translitMap[char] || char) .replace(/\s+/g, '-') .replace(/[^\w-]/g, '') .replace(/-+/g, '-') .slice(0, 100) } 

Как получить доступ к данным из хуков?

Через context.database (Knex instance) можно выполнять прямые SQL-запросы или использовать ItemsService для работы с коллекциями — это даёт гибкость и контроль. Directus Documentation рекомендует использовать ItemsService для единообразия, но прямой доступ через Knex оправдан при сложных join-запросах или массовых операциях.

Реальный кейс: интеграция с 1С

Для крупного интернет-магазина мы реализовали автоматическую синхронизацию заказов и остатков через хуки. После оплаты заказа хук отправляет данные в 1С через REST API, а при изменении остатков во внешней системе — обновляет Directus. Время синхронизации сократилось с 15 минут до 5 секунд. Нагрузка на сервер снизилась на 40% за счёт исключения лишних API-вызовов. Экономия на разработке интеграции составила 50% времени по сравнению с традиционным подходом. Закажите разработку кастомных хуков Directus и автоматизируйте бизнес-процессы без лишних затрат.

Что входит в работу

  • Исходный код с комментариями на TypeScript
  • Документация по установке и настройке (README)
  • Доступ к приватному репозиторию Git
  • Обучение команды (1 час онлайн)
  • Поддержка в течение 2 недель после сдачи

Ориентировочные сроки

Разработка типового набора из 3–5 хуков (валидация, уведомления, кэш) занимает от 2 до 5 рабочих дней в зависимости от сложности интеграций. Сроки уточняются после анализа вашей бизнес-логики.

Гарантии и поддержка

Мы — команда с 5-летним опытом разработки на Directus, выполнившая более 30 проектов по кастомизации, включая интеграции с 1С, CRM и платёжными системами. Гарантируем качество кода, соблюдение сроков и полную поддержку. Получите консультацию инженера — мы ответим на любые вопросы.