power-modules / framework
A powerful modular PHP framework with encapsulated modules, each having its own DI container and explicit import/export mechanisms
Requires
- php: ^8.4
- psr/container: ^2.0
- psr/simple-cache: ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.87
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^12.3
README
A general-purpose modular architecture framework for PHP. Build applications where each module has its own dependency injection container, with carefully controlled sharing through explicit import/export contracts.
๐ก Versatile: Works well for CLI tools, data pipelines, background processors, APIs, and complex PHP applications that benefit from clear module boundaries.
โจ Why Modular Framework?
- ๐ True Encapsulation: Each module has its own isolated DI container
- โก PowerModuleSetup: Extend module functionality without breaking encapsulation
- ๐ Microservice Ready: Isolated modules can easily become independent services
- ๐ Explicit Dependencies: Import/export contracts make relationships visible
- ๐งช Better Testing: Test modules in isolation with their own containers
- ๐ฅ Team Scalability: Different teams can own different modules
- ๐ Plugin-Ready: Third-party modules extend functionality safely
Quick Start
composer require power-modules/framework
use Modular\Framework\App\ModularAppBuilder; $app = new ModularAppBuilder(__DIR__) ->withModules( \MyApp\Auth\AuthModule::class, \MyApp\Orders\OrdersModule::class, ) ->build(); // Get any exported service $orderService = $app->get(\MyApp\Orders\OrderService::class);
โก PowerModuleSetup Extension System
A key feature of the framework is PowerModuleSetup - a mechanism that allows extending module functionality without breaking encapsulation. This is how the import/export system itself is built!
// Extend modules with powerful setups $app = new ModularAppBuilder(__DIR__) ->withModules(UserModule::class, OrderModule::class) ->addPowerModuleSetup(new RoutingSetup()) // Add HTTP routing capabilities to modules ->addPowerModuleSetup(new EventBusSetup()) // Add event publishing and handling ->build();
Real-world extensions:
- power-modules/router - HTTP routing with PSR-15 middleware
- power-modules/events Event-driven architecture (Coming soon!)
- Custom setups - Authentication, logging, validation, you name it!
Key benefits:
- Modules remain completely isolated and testable
- Extensions work across ALL modules automatically
- No coupling between core framework and extensions
- Enables building ecosystems of reusable functionality
๐ Microservice Evolution Path
Start with a modular monolith, evolve to microservices naturally:
// 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)]; } }
Later: Independent microservices
UserModule
โ User API serviceOrderModule
โ Order API service- Import/export contracts โ HTTP API contracts
- Minimal architectural changes needed
Your modules are designed with clear boundaries. When you're ready to scale, the module structure supports splitting them into separate services.
๐ Documentation
Guide | Description |
---|---|
Getting Started | Build your first module in 5 minutes |
Architecture | Deep dive into module system, containers, and lifecycle |
Use Cases | Examples for web apps, ETL pipelines, and more |
API Reference | Complete interface and class documentation |
Advanced Patterns | Plugin systems, composition patterns, performance tips |
Migration Guide | Convert existing applications to use the framework |
Real-World Examples
Simple Module
class OrdersModule implements PowerModule { public function register(ConfigurableContainerInterface $container): void { $container->set(OrderService::class, OrderService::class) ->addArguments([OrderRepository::class]); } }
Module with Exports
class AuthModule implements PowerModule, ExportsComponents { public static function exports(): array { return [UserService::class]; } public function register(ConfigurableContainerInterface $container): void { $container->set(UserService::class, UserService::class); // Internal services stay private by default $container->set(PasswordHasher::class, PasswordHasher::class); } }
Module with Imports
class OrdersModule implements PowerModule, ImportsComponents { public static function imports(): array { return [ImportItem::create(AuthModule::class, UserService::class)]; } public function register(ConfigurableContainerInterface $container): void { // UserService is now available for injection $container->set(OrderService::class, OrderService::class) ->addArguments([UserService::class]); } }
Contributing
See CONTRIBUTING.md for development setup and guidelines.
License
MIT License. See LICENSE for details.