Skip to content

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:

config.dir = "config/demo"

Changing this value switches the entire application:

  • config/demo → loads app/demo
  • config/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:

$app = require __DIR__.'/../'.$_ENV['config.dir'].'/bootstrap.php';

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

  1. Copy app/starterapp/myapp
  2. Copy config/starterconfig/myapp
  3. Copy tests/AppStartertests/AppMyapp
  4. Replace all AppStarter with AppMyapp in source files
  5. Add namespaces to composer.json
  6. Run composer dump-autoload
  7. Add Behat suites to behat.yml
  8. Add test tasks to taskfile.yaml
  9. 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