| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [View Raw Code] [Original HTTPS Page] |
This document provides guidance for AI coding agents to effectively contribute to the Modular Framework codebase.
The Modular Framework is a general-purpose modular architecture framework for PHP that builds applications where each module is a self-contained unit with its own Dependency Injection (DI) container, promoting true encapsulation and clear boundaries. It's designed for any PHP system: CLI tools, data pipelines, background processors, web APIs, and complex applications that benefit from modular design.
Simple Module (no dependencies):
class SimpleModule implements PowerModule
{
public function register(ConfigurableContainerInterface $container): void
{
$container->set(MyService::class, MyService::class);
}
}Exporting Module:
class ExportingModule implements PowerModule, ExportsComponents
{
public static function exports(): array
{
return [PublicService::class];
}
public function register(ConfigurableContainerInterface $container): void
{
$container->set(PrivateService::class, PrivateService::class);
$container->set(PublicService::class, PublicService::class)
->addArguments([PrivateService::class]);
}
}Importing Module:
class ImportingModule implements PowerModule, ImportsComponents
{
public static function imports(): array
{
return [ImportItem::create(ExportingModule::class, PublicService::class)];
}
public function register(ConfigurableContainerInterface $container): void
{
// PublicService is automatically available for injection
$container->set(ConsumerService::class, ConsumerService::class)
->addArguments([PublicService::class]);
}
}Application Builder Pattern with PowerModuleSetup:
$app = new ModularAppBuilder(__DIR__)
->withConfig(Config::forAppRoot(__DIR__)->set(Setting::CachePath, '/path/to/cache'))
->withPowerSetup(...RoutingSetup::withDefaults()) // Adds HTTP routing with the default router composition
->withModules(
RoutingModule::class,
RouterModule::class,
ExportingModule::class,
ImportingModule::class,
)
->withPowerSetup(new EventBusSetup()) // Pulls module events into a central event bus
->build();
// Access exported services through the app container
$service = $app->get(PublicService::class);When the router extension is used, the default router-owned 404 and 405 responses and the default generic 500 response are RFC 7807 problem-details responses.
PowerModuleSetup Extension Pattern:
// PowerModuleSetup allows extending module functionality without breaking encapsulation
class CustomSetup implements PowerModuleSetup
{
public function setup(PowerModuleSetupDto $powerModuleSetupDto): void
{
// Add capabilities to ALL modules automatically
// This pattern is used by extensions like power-modules/router
}
}When working with the framework, keep these key architectural benefits in mind:
The framework is designed with a clear evolution path from modular monolith to microservices:
Today (Modular Monolith):
class UserModule implements PowerModule, ExportsComponents {
public static function exports(): array {
return [UserService::class];
}
}
class OrderModule implements PowerModule, ImportsComponents {
public static function imports(): array {
return [ImportItem::create(UserModule::class, UserService::class)];
}
}Tomorrow (Microservices):
The framework supports a rich ecosystem of extensions through PowerModuleSetup:
Extensions work across ALL modules automatically while maintaining module isolation and testability.
The project uses a Makefile to streamline common development tasks:
make test # Run PHPUnit tests (no coverage)
make codestyle # Check PHP CS Fixer compliance
make phpstan # Run static analysis with PHPStan level 8
make devcontainer # Build development containerThe ServiceDefinition class supports method chaining for configuration:
$container->set(ServiceClass::class, ServiceClass::class)
->addArguments([DependencyClass::class])
->addMethod('setLogger', [LoggerInterface::class]);Method injection: Use addMethod() for setter injection after constructor injection. Arguments resolution: Arguments are automatically resolved from the container using class names.
When adding new features or fixing bugs, ensure that new modules follow the encapsulation principles and that dependencies between modules are explicitly defined through the import/export mechanism.
| Back | FazBrowse Home | New Git URL |