| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
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.
This framework is more than just another library — it introduces a new architectural paradigm to the PHP ecosystem, built on runtime-enforced encapsulation and true modularity, inspired by mature systems like OSGi.
To understand the core innovations and how this framework differs from established solutions like Symfony and Laravel, please read our Architectural Vision Document.
composer require power-modules/frameworkuse Modular\Framework\App\ModularAppBuilder;
class OrdersModule implements PowerModule, ExportsComponents {
public static function exports(): array {
return [
OrderService::class,
];
}
public function register(ConfigurableContainerInterface $container): void
{
$container->set(OrderRepository::class, OrderRepository::class)
->addArguments([DatabaseConnection::class]);
$container->set(OrderService::class, OrderService::class)
->addArguments([OrderRepository::class]);
}
}
$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);
// Fully initialized, with all dependencies resolved within the module's own containerThe framework's most powerful feature - PowerModuleSetup allows extending module functionality without breaking encapsulation:
$app = new ModularAppBuilder(__DIR__)
->withPowerSetup(...RoutingSetup::withDefaults())
->withModules(
RoutingModule::class,
RouterModule::class,
UserModule::class,
OrderModule::class,
)
->withPowerSetup(new EventBusSetup()) // Pulls module events and handlers into a central event bus
->build();Available extensions:
Coming soon:
Start with a modular monolith, evolve to microservices naturally:
Today: Modular monolith
class UserModule implements PowerModule, ExportsComponents {
public static function exports(): array {
return [
// Expose the service directly for in-process use
UserRepositoryInterface::class,
];
}
public function register(ConfigurableContainerInterface $container): void
{
$container->set(UserRepositoryInterface::class, UserService::class);
}
}
class OrderModule implements PowerModule, ImportsComponents {
public static function imports(): array {
return [
// Import the interface from UserModule for in-process communication
ImportItem::create(UserModule::class, UserRepositoryInterface::class),
];
}
public function register(ConfigurableContainerInterface $container): void
{
$container->set(OrderService::class, OrderService::class)
->addArguments([UserRepositoryInterface::class]);
}
}Later: Independent microservices
class UserModule implements PowerModule, ExportsComponents, HasRoutes {
public static function exports(): array {
return [
// Still export the same interface — now resolved to an HTTP client rather than an in-process service
UserRepositoryInterface::class,
];
}
public function getRoutes(): array
{
return [
// Define HTTP routes for the User API
Route::get('/', UserController::class),
];
}
public function register(ConfigurableContainerInterface $container): void
{
// Implementation details remain private; OrderModule doesn't need to know anything changed
$container->set(UserApiService::class, UserApiService::class)
->addArguments([Psr\Http\ClientInterface::class]);
// Bind the interface to the API service instead of the in-process service
$container->set(UserRepositoryInterface::class, UserApiService::class);
$container->set(UserService::class, UserService::class);
$container->set(UserController::class, UserController::class)
->addArguments([UserService::class]);
}
}
class OrderModule implements PowerModule, ImportsComponents {
public static function imports(): array {
return [
// The same import as before — now backed by an HTTP client instead of an in-process service.
// You can also drop this import and implement your own HTTP client directly in OrderModule.
ImportItem::create(UserModule::class, UserRepositoryInterface::class),
];
}
public function register(ConfigurableContainerInterface $container): void
{
$container->set(OrderService::class, OrderService::class)
->addArguments([UserRepositoryInterface::class]);
}
}ℹ️ Note: This example is a simplified illustration of the evolution path. In a real application, UserModule might continue to support in-process communication alongside the HTTP client, and the actual microservice implementation would likely live in its own repository.
Because modules are designed with clear boundaries from the start, splitting them into independent services is a natural next step when you're ready to scale.
📖 Complete Documentation Hub - Comprehensive guides, examples, and API reference
Quick Links:
See CONTRIBUTING.md for development setup and guidelines.
MIT License. See LICENSE for details.
| Back | FazBrowse Home | New Git URL |