Skip to Content
Разработка модулейСтруктура модуля

Структура модуля

Модуль в Flute CMS — это самостоятельный пакет, который добавляет новую функциональность. Каждый модуль располагается в отдельной папке внутри app/Modules/ и имеет стандартную структуру.

Файловая структура

Типичный модуль выглядит так:

    • module.json
      • BlogProvider.php

Что за что отвечает

ДиректорияДля чего нужна
Providers/Точка входа модуля. Здесь регистрируются сервисы и загружаются ресурсы
Http/Controllers/Контроллеры, обрабатывающие HTTP-запросы. Маршруты задаются через атрибуты
database/Entities/Сущности для работы с базой данных через Cycle ORM
Resources/config/Настройки модуля. Доступны через config('имя_файла.ключ')
Resources/lang/Переводы на разные языки
Resources/views/Blade-шаблоны для отображения страниц
Components/Интерактивные Yoyo-компоненты (работают без перезагрузки страницы)
Widgets/Блоки, которые можно размещать на страницах через админку
Services/Бизнес-логика модуля (не обязательная папка)
Middleware/Фильтры запросов (проверка прав, валидация и т.д.)

Не все папки обязательны. Минимально нужны только module.json и Providers/.


Манифест модуля (module.json)

Каждый модуль должен иметь файл module.json в корне. Это “паспорт” модуля — без него система не узнает о модуле.

Минимальный пример

{ "name": "Blog", "version": "1.0.0", "description": "Модуль блога для публикации статей", "providers": [ "Flute\\Modules\\Blog\\Providers\\BlogProvider" ] }

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

Если ваш модуль требует определённую версию PHP, другие модули или composer-пакеты:

{ "name": "Shop", "version": "2.0.0", "description": "Интернет-магазин с корзиной и оплатой", "authors": ["Иван Петров"], "providers": [ "Flute\\Modules\\Shop\\Providers\\ShopProvider" ], "dependencies": { "php": ">=8.2", "flute": ">=1.0.0", "modules": { "Payments": ">=1.0.0" }, "extensions": ["curl", "gd"], "composer": { "guzzlehttp/guzzle": "^7.0" } } }

Что можно указать в dependencies

ТипОписаниеПример
phpМинимальная версия PHP">=8.2"
fluteМинимальная версия Flute CMS">=1.0.0"
modulesДругие модули, которые должны быть активны{"Payments": ">=1.0.0"}
extensionsPHP-расширения["curl", "gd"]
composerComposer-пакеты{"guzzlehttp/guzzle": "^7.0"}
themeТребуемая тема{"standard": ">=1.0.0"}

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


Провайдер модуля

Провайдер — это главный класс модуля. Он говорит системе, какие сервисы регистрировать и какие ресурсы загружать.

Базовый провайдер

<?php namespace Flute\Modules\Blog\Providers; use Flute\Core\Support\ModuleServiceProvider; class BlogProvider extends ModuleServiceProvider { /** * Имя модуля (должно совпадать с именем папки) */ protected ?string $moduleName = 'Blog'; /** * Регистрация сервисов. * Вызывается ВСЕГДА, даже если модуль отключён. * Здесь регистрируем классы в DI-контейнере. */ public function register(\DI\Container $container): void { // Регистрируем сервис для работы со статьями $container->set(ArticleService::class, \DI\autowire()); } /** * Инициализация модуля. * Вызывается ТОЛЬКО для активных модулей. * Здесь загружаем ресурсы и настраиваем модуль. */ public function boot(\DI\Container $container): void { // Загружаем все ресурсы одной командой $this->bootstrapModule(); } }

Что делает bootstrapModule()

Метод bootstrapModule() — это “магия”, которая автоматически находит и загружает все ресурсы модуля:

Сущности базы данных

Ищет классы в database/Entities/ и регистрирует их в Cycle ORM. После этого вы можете работать с базой через rep(Article::class)->findAll().

Конфигурацию

Файлы из Resources/config/ становятся доступны через config(). Например, файл blog.php доступен как config('blog.posts_per_page').

Переводы

Файлы из Resources/lang/ru/messages.php регистрируются для локализации. Используйте __('messages.welcome') в коде.

Контроллеры с маршрутами

Сканирует папки Http/Controllers/, Controllers/ и Submodules/*/Controllers/. Маршруты берутся из атрибутов #[Get], #[Post] и т.д.

Yoyo-компоненты

Классы из Components/ автоматически регистрируются. Компонент ArticleCard.php становится доступен как @yoyo('article-card').

Виджеты

Классы из Widgets/, реализующие WidgetInterface, можно использовать на страницах.

Если вам нужен файл routes.php для ручного определения маршрутов, добавьте в boot():

$this->loadRoutesFrom('routes.php');

Загрузка ресурсов вручную

Иногда нужен более точный контроль. Вместо bootstrapModule() можно загружать ресурсы по отдельности:

public function boot(\DI\Container $container): void { // Только сущности БД $this->loadEntities(); // Только конфигурацию $this->loadConfigs(); // Только переводы $this->loadTranslations(); // Шаблоны с кастомным namespace // Теперь можно использовать: view('myblog::pages.index') $this->loadViews('Resources/views', 'myblog'); // Маршруты из файла $this->loadRoutesFrom('routes.php'); // SCSS стили (компилируются автоматически) $this->loadScss('Resources/assets/scss/blog.scss'); // Компоненты и виджеты $this->loadComponents(); $this->loadWidgets(); }

Жизненный цикл модуля

Когда Flute запускается, модули проходят несколько этапов:

Поиск модулей

Система сканирует папку app/Modules/ и находит все module.json.

Проверка статуса

Каждый модуль сверяется с базой данных. Статусы:

  • active — модуль работает
  • disabled — модуль отключён администратором
  • notinstalled — модуль найден, но ещё не установлен

Проверка зависимостей

Для каждого активного модуля проверяются зависимости из module.json. Если что-то не так (нет нужного PHP-расширения, не установлен зависимый модуль), модуль автоматически отключается.

Регистрация (register)

Вызывается метод register() у ВСЕХ модулей. Здесь регистрируются сервисы в DI-контейнере.

Инициализация (boot)

Вызывается метод boot() только у АКТИВНЫХ модулей. Здесь загружаются ресурсы и выполняется настройка.


Кеширование

Для производительности Flute кеширует результаты сканирования файлов. По умолчанию кеш живёт 1 час.

Когда нужно сбросить кеш

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

Как сбросить кеш

// Сбросить кеш всех модулей (список модулей, статусы) app(\Flute\Core\ModulesManager\ModuleManager::class)->clearCache(); // Сбросить кеш конкретного модуля (файлы, переводы, компоненты) $provider->clearFileCache();

Изменить время кеширования

public function boot(\DI\Container $container): void { // Кешировать на 2 часа вместо 1 $this->setCacheDuration(7200); $this->bootstrapModule(); }

Расширения модуля

Если модуль большой, можно разбить его на расширения:

class ShopProvider extends ModuleServiceProvider { /** * Расширения загружаются автоматически */ public array $extensions = [ CartExtension::class, PaymentExtension::class, DeliveryExtension::class, ]; }

Каждое расширение — это класс, который реализует ModuleExtensionInterface:

<?php namespace Flute\Modules\Shop\Extensions; use Flute\Core\ModulesManager\Contracts\ModuleExtensionInterface; class CartExtension implements ModuleExtensionInterface { public function register(): void { // Регистрация сервисов корзины } public function boot(): void { // Инициализация корзины } }

У расширений вызывается только register(). Метод boot() НЕ вызывается автоматически.


Соглашения об именовании

Чтобы модули были совместимы и код был читаемым, следуйте этим правилам:

ЧтоКак называтьПример
Папка модуляStudlyCaseBlog, UserProfile, PaymentGateway
КлассыStudlyCaseArticleController, PaymentService
МетодыcamelCasegetArticles(), processPayment()
Файлы шаблоновkebab-casearticle-card.blade.php, user-profile.blade.php
КонстантыUPPER_CASEMAX_ARTICLES, DEFAULT_LIMIT
Таблицы БДsnake_case с префиксомblog_articles, shop_orders

Имя папки модуля должно совпадать с полем name в module.json и свойством $moduleName в провайдере.