Multi-Application Architecture
Phexium implements a multi-application architecture allowing multiple distinct applications to coexist within the same monorepo project, while sharing the common framework (src/).
Objectives
The multi-application architecture allows:
- Sharing a common framework (
src/) between applications - Complete isolation of each application (code, configuration, tests)
- Easy switching between applications via a single environment variable
- Independent testing of each application
Visual Architecture
phexium/
├── src/ # Phexium framework (shared)
├── app/
│ ├── demo/ # Application 1 (AppDemo\)
│ └── starter/ # Application 2 (AppStarter\)
├── config/
│ ├── demo/ # App 1 configuration
│ └── starter/ # App 2 configuration
└── tests/
├── AppDemo/ # App 1 tests
└── AppStarter/ # App 2 tests
Switching Mechanism
The .env file contains a single variable to control the active application:
Changing this value switches the entire application:
config/demo→ loads app/democonfig/starter→ loads app/starter
No server restart required - the value is reloaded on each request.
Entry Point
The web entry point (public/index.php) dynamically loads the bootstrap:
Naming Conventions
| Type | Pattern | Example |
|---|---|---|
| App directory | app/{name} | app/demo |
| Config directory | config/{name} | config/demo |
| App namespace | App{Name}\ | AppDemo\ |
| Tests directory | tests/App{Name} | tests/AppDemo |
Configuration Files
Each application has 6 configuration files in config/{name}/:
| File | Purpose |
|---|---|
bootstrap.php | Application entry point |
container.php | DI container definitions |
routes.php | HTTP routes |
events.php | Event subscriptions |
permissions.php | RBAC permissions |
container_test.php | Test overrides |
Creating a New Application
- Copy
app/starter→app/myapp - Copy
config/starter→config/myapp - Copy
tests/AppStarter→tests/AppMyapp - Replace all
AppStarterwithAppMyappin source files - Add namespaces to
composer.json - Run
composer dump-autoload - Add Behat suites to
behat.yml - Add test tasks to
taskfile.yaml - Update
php-cs-fixer.php,rector.php,sonar-project.properties
Test Isolation
Each application loads its own container in tests:
// GetContainerTrait loads config/{name}/container.php
$container = $this->getContainer();
$useCase = $container->get(HomeUseCase::class);
Running Tests
task tests:acceptance:starter # Starter app tests
task tests:acceptance:demoInMemory # Demo app with InMemory
task tests:acceptance # All applications
Benefits
- Complete isolation between applications
- Ultra-simple switching via single environment variable
- Framework sharing with centralized bug fixes
- Isolated tests with merged coverage reports
Limitations
- Configuration files must be maintained per application
- New applications require manual addition to build tools
- Strict naming conventions must be respected
See Also
- Project Structure - Directory organization
- Acceptance Testing (Behat) - Per-application test suites