Створення компонента

Покроковий приклад на базі AuthAdmin: вхід адміністратора, dashboard, CRUD користувачів, міграції, сидер і CLI-команда.

Передумови: концепція компонентів, глобальний middleware у routes/web.php.

1. Каталог і клас компонента

Клас компонента напряму реалізує ComponentInterface — метадані, маршрути, міграції, views і assets оголошуються в методах (окремого config.php немає). Інжектуйте PathManager, щоб будувати шляхи відносно кореня застосунку.

// src/Components/AuthAdmin/AuthAdminComponent.php
namespace Concept\Components\AuthAdmin;

use Concept\Components\AuthAdmin\Commands\UserListCommand;
use Concept\Components\AuthAdmin\Database\Seeders\UserSeeder;
use Concept\Components\AuthAdmin\Extensions\TwigExtension;
use Concept\Core\Foundation\PathManager;
use Concept\Core\Foundation\PathName;
use Concept\Core\Services\Component\Contracts\ComponentInterface;

class AuthAdminComponent implements ComponentInterface
{
    private const string NAME = 'AuthAdmin';
    private const string VERSION = '1.0.0';
    private const string DESCRIPTION = 'Admin authentication, dashboard and user management.';
    private const string VIEW_NAMESPACE = 'auth-admin';

    protected string $componentDir = __DIR__;

    public function __construct(private readonly PathManager $pathManager) {}

    public function name(): string { return self::NAME; }
    public function version(): string { return self::VERSION; }
    public function description(): string { return self::DESCRIPTION; }

    public function routes(): ?string
    {
        return $this->componentDir . '/routes.php';
    }

    public function providers(): array { return []; }

    public function seeders(): array { return [UserSeeder::class]; }

    public function migrationPaths(): array
    {
        return [
            $this->pathManager->toRelative($this->componentDir . '/Database/Migrations'),
        ];
    }

    public function commands(): array { return [UserListCommand::class]; }

    public function viewExtensions(): array { return [TwigExtension::class]; }

    public function viewPaths(): array
    {
        return [
            self::VIEW_NAMESPACE => $this->pathManager->toRelative($this->componentDir . '/Views'),
        ];
    }

    public function viewContexts(): array
    {
        return ['/admin' => 'dashboard'];
    }

    public function assets(): array
    {
        return [
            $this->pathManager->toRelative($this->componentDir . '/Assets/admin-tokens.js') =>
                $this->pathManager->getRelative(PathName::PUBLIC, 'components/auth-admin/js/admin-tokens.js'),
        ];
    }
}
  • viewPaths() — шаблон @auth-admin/loginViews/login.twig
  • viewContexts() — URL під /admin отримують route_namespace = dashboard (див. Views)
  • providers() — опційні DI-провайдери (див. AclComponent, DebugBarComponent)

2. Реєстрація в застосунку

// config/components.php
use Concept\Components\AuthAdmin\AuthAdminComponent;

return [
    'components' => [
        AuthAdminComponent::class => AuthAdminComponent::class,
    ],
];

3. Маршрути

// src/Components/AuthAdmin/routes.php
/** @var Router $router */

$router->get('/admin/login', [AdminController::class, 'showLogin'])->setName('admin.login');
$router->post('/admin/login', [AdminController::class, 'login'])->setName('admin.login.submit');

$router->group('/admin', function (RouteGroup $route) {
    $route->get('/dashboard', [AdminController::class, 'index'])->setName('admin.dashboard');
    $route->get('/logout', [AdminController::class, 'logout'])->setName('admin.logout');
})->lazyMiddleware(AuthMiddleware::class);

$router->group('/admin/users', function (RouteGroup $route) {
    $route->get('/', [UserController::class, 'index'])->setName('admin.users');
    $route->post('/store', [UserController::class, 'store'])->setName('admin.user.store');
    // ...
})->lazyMiddleware(AuthMiddleware::class);

Публічний login — без AuthMiddleware; захищені групи — з middleware модуля. Імена маршрутів (admin.*) використовуються в redirectByName() і Twig uri().

4. Middleware авторизації

// Middlewares/AuthMiddleware.php — перевірка сесії, роль admin, статус ACTIVE
public function process(...): ResponseInterface
{
    if (!$this->auth->check()) {
        return new RedirectResponse('/admin/login', HttpStatusCode::FOUND);
    }
    // ...
    return $handler->handle($request);
}

Клас реєструється в DI автоматично; League Route створює екземпляр через контейнер.

5. Контролер і FormRequest

// Controllers/AdminController.php
public function login(LoginRequest $request): ResponseInterface
{
    $loginDto = $request->toDto();
    if ($loginDto && $this->auth->attempt($loginDto->email, $loginDto->password, $loginDto->remember)) {
        return $this->response->redirectByName('admin.dashboard');
    }
    return $this->response->redirectByName('admin.login');
}

public function showLogin(): ResponseInterface
{
    return $this->viewResponse->create('@auth-admin/login');
}

LoginRequest — правила валідації + DTO; CSRF і глобальний HandleValidationExceptionMiddleware працюють як для будь-якого контролера.

6. Views

{# Views/login.twig — namespace auth-admin, layout з App #}
{% extends '@dashboard/layouts/auth.twig' %}

<form method="post" action="{{ uri('admin.login.submit') }}">
    <input type="hidden" name="_csrf_token" value="{{ csrf_token }}">
    ...
</form>

Модульні шаблони — @auth-admin/...; спільний chrome адмінки — @dashboard/... з resources/views/dashboard/.

7. База даних

Міграція в Database/Migrations/V2026_03_24_120000_CreateUsersTable.php, модель UserModel, сидер UserSeeder.

php bin/console.php db:migrate
php bin/console.php db:seed -c "Concept\Components\AuthAdmin\Database\Seeders\UserSeeder"

Для одного сідера вкажіть повний FQCN класу в лапках (опція -c або --class). Коротке ім’я на кшталт UserSeeder не працює. Без опції db:seed запускає всі зареєстровані сидери.

Шляхи з migrationPaths() і класи з seeders() потрапляють у реєстри ядра при boot компонента.

8. Assets і CLI

php bin/console.php component:publish-assets
php bin/console.php component:list

Детальніше — CLI та assets.

Чеклист нового компонента

  1. {Name}Component.php, що реалізує ComponentInterface
  2. Запис у config/components.php
  3. routes.php (за потреби)
  4. Controllers, Services, Models, Requests/Dto
  5. Views + viewPaths() / viewContexts()
  6. Migrations / seeders / commands / assets — через методи інтерфейсу
  7. db:migrate, component:publish-assets, route:list

Інші еталонні компоненти в demo-застосунку: Acl (route interceptor + admin UI), SettingsManager (типізовані налаштування + Twig helpers), DebugBar (middleware і assets лише для dev).