miladrahimi/phpcontainer
Composer 安装命令:
composer require miladrahimi/phpcontainer
包简介
Dependency injection (IoC) container for PHP projects
README 文档
README
PhpContainer
A dependency injection (Inversion of Control) container written in PHP programming language, compliant with PSR-11 standards.
Features:
- Singleton, transient, and closure bindings
- Explicit and implicit bindings
- Typed and named bindings
- Automatic injection
Overview
Dependency Inversion is a fundamental concept in Object-oriented design.
It leads to important ideas like Dependency Injection, Inversion of Control, and the creation of an IoC Container.
For PHP projects, there's the PhpContainer, a handy tool that provides a dependency injection container (IoC Container) conforming to PSR-11 standards.
Installation
To integrate PhpContainer into your project, use the following Composer command:
composer require miladrahimi/phpcontainer:5.*
Documentation
Explicit Binding
Explicit binding involves directly linking an abstraction to a concrete implementation.
This binding can be achieved by using the singleton(), transient(), and closure() methods.
use MiladRahimi\PhpContainer\Container; $container = new Container(); $container->singleton(DatabaseInterface::class, MySQL::class); $container->transient(MailerInterface::class, MailTrap::class); $container->closure('sum', function($a, $b) { return $a + $b; }); $database = $container->get(DatabaseInterface::class); // An instance of MySQL $mailer = $container->get(MailerInterface::class); // An instance of MailTrap $sum = $container->get('sum'); // A closure: $sum(6, 7) => 13
Binding Methods
- Singleton binding: The container creates the concrete only once and returns it whenever needed.
- Transient binding: The container clones or creates brand-new concrete each time you need it.
- Closure binding: Only for closures. It prevents the container from calling the closure (the default behavior).
The following example demonstrates the differences between singleton and transient binding.
use MiladRahimi\PhpContainer\Container; $container = new Container(); $container->transient(InterfaceA::class, ClassA::class); $container->singleton(InterfaceB::class, ClassB::class); $a1 = $container->get(InterfaceA::class); $a1->name = 'Something'; $a2 = $container->get(InterfaceA::class); echo $a2->name; // NULL $b1 = $container->get(InterfaceB::class); $b1->name = 'Something'; $b2 = $container->get(InterfaceB::class); echo $b2->name; // 'Something'
Implicit Binding
When the container needs a class without a specific binding, it tries to create an instance.
In the example below, it instantiates the MySQL class in the provided code.
But if it encounters an abstract class or an interface that can't be instantiated directly, an error occurs.
use MiladRahimi\PhpContainer\Container; $container = new Container(); // No (explicit) binding here! $database = $container->get(MySQL::class);
Binding to Objects
You can connect abstracts to specific objects. Using singleton binding gives you the original object when required, while transient binding offers a fresh copy of the object every time you ask for it.
use MiladRahimi\PhpContainer\Container; $user = new User(); $user->name = 'Milad'; $container = new Container(); $container->singleton('user', $user); // OR $container->transient('user', $user);
Constructor Auto-injection
Concrete classes might contain constructor parameters that either possess default values or can be resolved by the container.
use MiladRahimi\PhpContainer\Container; class Notifier implements NotifierInterface { public MailInterface $mail; public Vonage $vonage; public string $sender; public function __constructor(MailInterface $mail, Vonage $vonage, $sender = 'PhpContainer') { $this->mail = $mail; $this->vonage = $vonage; $this->sender = $sender; } } $container = new Container(); $container->transient(MailInterface::class, MailTrap::class); $container->transient(NotifierInterface::class, Notifier::class); $notifier = $container->get(NotifierInterface::class); print_r($notifier->mail); // $mail would be an instnace of MailTrap (explicit binding) print_r($notifier->vonage); // $vonage would be an instnace of Vonage (implicit binding) print_r($notifier->sender); // $sender would be "PhpContainer" (default value)
Binding Using Closure
The following example illustrates how to bind using Closure.
use MiladRahimi\PhpContainer\Container; $container = new Container(); $container->singleton(Config::class, function () { return new JsonConfig('/path/to/config.json'); }); // $config would be auto-injected $container->singleton(Database::class, function (Config $config) { return new MySQL( $config->get('database.host'), $config->get('database.port'), $config->get('database.name'), $config->get('database.username'), $config->get('database.password') ); });
In singleton binding, the container executes the Closure once and retrieves the result whenever needed.
Conversely, in transient binding, the container invokes the Closure each time it's required.
If you intend to bind an abstraction to a Closure without immediate invocation by the container, you can use the closure() method instead.
Resolving Using Closure
You have the option to use the call method, allowing the container to execute the provided function or closure and resolve its arguments.
use MiladRahimi\PhpContainer\Container; $container = new Container(); $container->singleton(MailInterface::class, MailTrap::class); // Direct Closure call $response = $container->call(function(MailerInterface $mailer) { return $mailer->send('info@example.com', 'Hello...'); }); // Direct function call function sendMail(MailerInterface $mailer) { return $mailer->send('info@example.com', 'Hello...'); } $response = $container->call('sendMail'); // Direct method call class UserManager { function sendMail(MailerInterface $mailer) { return $mailer->send('info@example.com', 'Hello...'); } } $response = $container->call([UserManager::class, 'sendMail']);
Type-based and name-based binding
PhpContainer supports typed-based and name-based bindings. The following example demonstrates these types of bindings.
use MiladRahimi\PhpContainer\Container; $container = new Container(); // Type-based binding $container->singleton(Database::class, MySQL::class); $container->call(function(Database $database) { $database->ping(); }); // Name-based binding $container->singleton('$number', 666); $container->call(function($number) { echo $number; // 666 });
Error handling
The ContainerException might be raised by the container for several reasons.
It can arise when a ReflectionException occurs, indicating a missing concrete implementation for a provided abstraction.
Additionally, this exception occures when the container cannot inject parameter values into concrete constructors or closures.
License
PhpContainer is created by Milad Rahimi and released under the MIT License.
miladrahimi/phpcontainer 适用场景与选型建议
miladrahimi/phpcontainer 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 24.03k 次下载、GitHub Stars 达 13, 最近一次更新时间为 2015 年 07 月 27 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「container」 「dependency」 「di」 「dic」 「injection」 「ioc」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 miladrahimi/phpcontainer 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 miladrahimi/phpcontainer 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 miladrahimi/phpcontainer 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A fast and intuitive dependency injection container.
PHP 8.1-8.5 compatible fork of rdlowrey/auryn — a dependency injector for bootstrapping object-oriented PHP applications.
Dependency injection container for the Monolith framework.
The PSR-11 container bridges
Http Microframework for Hack
A simple Dependency Injection Container, PSR-11 compliant.
统计信息
- 总下载量: 24.03k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 13
- 点击次数: 18
- 依赖项目数: 2
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2015-07-27