Component concept
A component in Concept Core is an isolated functional application module
(modular monolith): its own routes, templates, migrations, CLI commands, and optionally DI providers.
Core assembles active components through ComponentRegistry and
ComponentsServiceProvider.
See also: directory structure, component providers, creating a component (AuthAdmin).
Why components
- Package by feature — admin, cabinet, catalog code lives together, not spread across
App/Controllerslayers. - Enable/disable — a module is enabled with one line in
config/components.php. - Team boundaries — changes in
AuthAdmin/rarely touchUserCabinet/. - Shared core — HTTP, validation, Twig, DB remain in Concept Core and
App/.
Where to put what
src/
├── App/ # shared application code
│ ├── Controllers/ # global pages (home, about)
│ ├── Models/ # BaseModel, shared entities
│ └── Extensions/Twig/ # global Twig extensions
└── Components/
└── AuthAdmin/ # example module
├── AuthAdminComponent.php
├── routes.php # HTTP routes
├── Controllers/
├── Middlewares/
├── Requests/ Dto/ Models/
├── Services/
├── Views/ # module templates (@auth-admin/...)
├── Database/
│ ├── Migrations/
│ └── Seeders/
├── Commands/ # console commands
├── Extensions/ # Twig for module
└── Assets/ # JS/CSS → public via CLI
config/
└── components.php # which modules are active
resources/views/ # shared layouts (@dashboard, @frontend)
routes/web.php # global routes + middleware stack
| What | Component | Application (App/) |
|---|---|---|
| Feature routes | Component/routes.php | routes/web.php |
| Module templates | Component/Views/ | resources/views/ |
| Module migrations | Component/Database/Migrations/ | database/migrations/ |
| Base model, utilities | — | App/Models/ |
| Shared admin layout | extends @dashboard/... | resources/views/dashboard/ |
ComponentInterface contract
The component class implements Concept\Core\Services\Component\Contracts\ComponentInterface directly — metadata and registration data are returned from its methods:
| Method | Purpose |
|---|---|
name(), version(), description() | Metadata for component:list |
routes() | Absolute path to routes.php or null |
providers() | Additional module service providers |
viewPaths() | Twig namespace → path (auth-admin → /src/Components/.../Views) |
viewContexts() | URI prefix → context (/admin → dashboard) |
viewExtensions() | Twig\Extension\ExtensionInterface classes |
commands() | Symfony Console commands |
seeders() | Seeder classes |
migrationPaths() | Paths to migration directories |
assets() | Map of source → public for component:publish-assets |
Use PathManager in the constructor to build paths relative to the application root (see AuthAdminComponent).
Application registration
// config/components.php
return [
'components' => [
AuthAdminComponent::class => AuthAdminComponent::class,
UserCabinetComponent::class => UserCabinetComponent::class,
],
];
Key and value are the component class FQCN (container creates instance via DI).
In config/dev/components.php you can add dev-only modules (e.g. DebugBar).
The class list goes into ComponentRegistry when
ComponentsServiceProvider is registered (last in bootstrap/providers/app.php).
What happens on boot
ComponentsServiceProvider::boot() for each active component:
- Records telemetry
FRAMEWORK_COMPONENT_REGISTERED(Telemetry) - Registers console commands, migration paths, and seeders
- Registers nested service providers from
providers() requiresroutes.phpfiles ($routervariable available)- In HTTP (not CLI) — adds Twig paths, extensions, and view contexts
Order: core providers → ComponentsServiceProvider → module routes and views.
Moving existing code into a component
Typical refactor from a “flat” App/:
- Create
src/Components/MyFeature/with subdirectories following AuthAdmin. - Move controllers, models, FormRequest, views, middleware into the component directory; update namespace to
Concept\Components\MyFeature\.... - Extract feature routes from
routes/web.phpintoMyFeature/routes.php. - Add
MyFeatureComponent.phpimplementingComponentInterface. - Register the class in
config/components.php. - Leave only shared code in
App/: BaseModel, global layouts, utilities. - Run
php bin/console.php db:migrateandcomponent:publish-assetsas needed.
If a module uses a shared layout (@dashboard), templates in resources/views/dashboard/
are not moved — the component only extends them in Twig.
Reference components
The demo application ships several ready-made modules (code in src/Components/):
| Component | Purpose | Registration |
|---|---|---|
AuthAdmin |
Admin login, dashboard, user CRUD | config/components.php |
Acl |
Role-based access control, route interceptor, admin UI | config/components.php + routes.interceptors |
SettingsManager |
Typed application settings, admin CRUD, Twig helpers | config/components.php |
DebugBar |
PHP Debug Bar for HTML responses (dev only) | config/dev/components.php |
Acl also requires AclRouteAuthorization in config/routes.php and
HandleAccessDeniedMiddleware as the first global middleware — see
Route interceptors.
Component vs App code
Not everything must go into components. Keep in App/:
- landing, static pages, shared API gateway;
- base model classes, interfaces, cross-module services;
- global Twig namespaces (
frontend,dashboard) inconfig/view.php.
A separate component — when there is a clear boundary: “admin”, “user cabinet”, “project catalog”.
One component — one responsibility. If two modules import each other directly,
move shared code to App/ or a separate application “core” package.