Configuration
Phexium uses PHP-based configuration files located in the config/ directory. All configuration is explicit and type-safe, avoiding YAML/XML parsing overhead.
Configuration Files
| File | Purpose |
|---|---|
bootstrap.php | Application bootstrap and middleware stack |
container.php | Dependency injection container (PHP-DI) |
routes.php | HTTP route definitions (Slim) |
events.php | Domain event subscriptions |
permissions.php | RBAC permission definitions |
Environment Variables (.env)
The .env file contains environment-specific configuration. Use env.sample as a template.
Key Settings
# Environment
slim.environment = "development"
config.dir = "config/demo"
# Database type: InMemory, Sqlite, Mysql, Postgresql
database.type = "Sqlite"
# Logger
logger.type = "file"
logger.level = "debug"
# Session
session.adapter = "php"
# Cache
cache.type = "redis"
For the complete list of environment variables, see the Environment Variables Reference.
Dependency Injection (container.php)
Phexium uses PHP-DI as its dependency injection container. PHP-DI implements PSR-11 (Psr\Container\ContainerInterface), ensuring interoperability with any PSR-11 compliant library.
The demo application (config/demo/container.php) demonstrates dependency registration:
// Repository switching based on database type
$repositoryDefinition = match ($_ENV['database.type'] ?? 'Sqlite') {
'InMemory' => DI\autowire('AppDemo\*\Infrastructure\InMemory*Repository'),
'Mysql' => DI\autowire('AppDemo\*\Infrastructure\Mysql*Repository'),
default => DI\autowire('AppDemo\*\Infrastructure\Sqlite*Repository'),
};
Advanced DI Patterns
Match Expression for Adapter Selection
Environment-based implementation switching using PHP 8 match expressions:
TransactionInterface::class => match ($_ENV['database.type'] ?? 'Sqlite') {
'InMemory' => DI\autowire(InMemoryTransaction::class),
'Mysql' => DI\autowire(MysqlTransaction::class),
'Postgresql' => DI\autowire(PostgresqlTransaction::class),
default => DI\autowire(SqliteTransaction::class),
},
Autowiring Wildcards for Repositories
PHP-DI wildcards automatically resolve repository implementations based on naming conventions:
// Maps BookRepository interface to SqliteBookRepository
'AppDemo\*\Domain\*Repository' => DI\autowire('AppDemo\*\Infrastructure\Sqlite*Repository'),
The * wildcard captures module names, allowing one definition to handle all repositories.
Closure Factories for Lazy Initialization
Complex objects with conditional construction logic use closure factories:
PDO::class => function (): PDO {
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
return match ($_ENV['database.type'] ?? 'Sqlite') {
'Mysql' => new PDO($mysqlDsn, $user, $password, $options),
'Postgresql' => new PDO($pgsqlDsn, $user, $password, $options),
default => new PDO('sqlite:'.$dbFile),
};
},
Event Subscription Registration
Event listeners are registered at bootstrap time by iterating over the events configuration:
// In bootstrap.php
$eventBus = $container->get(EventBusInterface::class);
$eventSubscriptions = require __DIR__.'/events.php';
foreach ($eventSubscriptions as $eventName => $listeners) {
foreach ($listeners as $listenerName) {
$listener = $container->get($listenerName);
$eventBus->subscribe($eventName, $listener);
}
}
This pattern separates event configuration (declarative) from registration logic (procedural).
HTTP Routing (routes.php)
The demo application (config/demo/routes.php) demonstrates route definitions:
$app->get('/', [HomeController::class, 'index']);
$app->post('/books', [CreateBookController::class, 'createBook'])
->add($rbac->forPermission('book.create'));
Event Subscriptions (events.php)
The demo application (config/demo/events.php) maps events to listeners:
return [
BookCreatedEvent::class => [BookEventHandler::class],
LoanCreatedEvent::class => [LoanCreatedEventHandler::class],
];
RBAC Permissions (permissions.php)
The demo application (config/demo/permissions.php) defines role permissions:
return [
'admin' => ['book.create', 'book.update', 'book.delete', 'loan.view_all'],
'user' => ['loan.view_own', 'loan.borrow'],
];
See Also
- RBAC Permissions - Permission checking and route protection
- Domain Events - Event subscription configuration
- Repository Implementations - Database switching patterns
- PSR-11 Container Interface - Interface specification