Skip to content

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