frogsystem/spawn
Composer 安装命令:
composer require frogsystem/spawn
包简介
Spawn is a simple and lightweight implementation of an IoC application container and fully compatible with container-interop.
README 文档
README
Spawn
Spawn is a simple and lightweight implementation of an IoC application container and fully compatible with the container-interop standard.
Installation
You can install this package through Composer:
composer require frogsystem/spawn
The packages follows the Semantic Versioning specification, and there will be full backward compatibility between minor versions.
Documentation
Boot your container by creating a new instance:
$app = new Container();
Spawn will take care of itself; you will always get the same instance as long as you use Dependency Injection and the provided factory methods.
Get an entry
Retrieve an entry from the container with the standardized get method; use array access for your convenience:
print $app->get('MyEntry'); // will print whatever value 'MyEntry' has print $app['MyEntry']; // will do the same
However, if the entry is set to a callable, the callable will be invoked and its result returned instead. You will find use of this behavior to achieve different goals.
$app->set('MyEntry', function() { return 'Called!' }); print $app->get('MyEntry'); // will print 'Called!'
Set an entry
To register an entry with the container, use the provided set method or array access:
$app->set('MyEntry', $value); $app['MyEntry'] = $value;
Factory (Implementation)
By design, the purpose of the container is to provide you with implementations for abstracts. To do so, you'll have to bind the abstract to a factory closure:
$app['ACME\MyContract'] = function() use ($app) { return $app->make('MyImplementation'); };
There is a shorthand for this and other common use cases:
$app['ACME\MyContract'] = $app->factory('MyImplementation'); // shorthand for the statement above (roughly)
Assignment (Instance)
Binding a specific instance to an abstract can be done by normal assignment:
$app['ACME\MyContract'] = new MyImplementation();
Once (deferred execution)
If you want to defer execution of the callable to the time when it is actually requested (e.g. because its expensive but not always used), use once:
$app['ACME\MyContract'] = $app->once(function() { return very_expensive_call(); // will be executed once when 'ACME\MyContract' is requested; returns its result afterwards });
It will store the result and any further request on ACME\MyContract will return the stored result instead of invoking the callable.
One (Singleton)
This allows us to register implementations that behave more or less like singletons:
$app['ACME\MyContract'] = $app->one('ACME\MyClass'); // instantiated on first request; returns the same object every time
Protect a Callable
In case you want to store a closure or an other callable in the container, you can protect them from being invoked while retrieving:
$app['MyCallable'] = $app->protect(function() { print 'Called!'; }); $printer = $app->get('MyCallable'); // will do nothing $printer(); // will print 'Called!'
FactoryFactory
Putting all this together, you might easily create a so called FactoryFactory - a factory that provides you with a specific factory whenever you need one:
$app['UserFactory'] = $this->protect(function($username) use ($app) { $user = $app->one('User')->getByName($username); return $user; }); $userFactory = $app->get('UserFactory'); print $userFactory('Alice')->getName(); // will print 'Alice' print $userFactory('Bob')->getName(); // will print 'Bob'
Check for an entry
Use the has method to check whether an entry exists or not:
$app->has('MyEntry'); // true or false
Internals
You must only use the container to define your abstracts. They are meant to be shared with other containers and an implementation may be replaced by a different one during runtime. However, you will have cases where your code depends on a specific instance. Those internals are hold separately from the rest of the container and therefore have to be set as properties:
$app->config = $app->make('MyConfig');
Using the magic setter will provide you with the same API as set out above. You may also define an internal explicit as class property, but a callable will not be invoked on retrieval if set this way.
Get your internals through properties as well:
print $app->version;
To set a value for both, an internal and a normal container entry, simply chain the assignments:
$app->config = $app['ConfigContract'] = $this->factory('MyConfig');
Dependency Injection
Spawn provides you with two methods for using Dependency Injection and the Inversion of Control pattern. Use make to create new instances of abstracts; and use invoke to execute callables with filled-in dependencies. Both methods will using Dependency Injection to resolve their arguments. This means, if the invoked callable or class constructor has any parameters, those methods will use the container to find a suitable implementation and inject it in the argument list.
Additional any value retrieved from the container via get or ArrayAccess which is a callable, will be invoked using the very same invoke method. Thus they will also have their dependencies injected.
Use make to create an object from a concrete class:
class MyClass { __construct(OtherClass $other); } $app->make('MyClass');
When calling invoke with a callable as argument, Spawn will try resolve any arguments:
class MyObject { function print() { print 'Found!!' } } $callable = function(MyObject $object) { $object->print(); } $app->invoke($callable); // will print 'Found!'
Additional arguments
You may also pass additional arguments in an array to these methods. It allows you to override dependency lookup on a per case basis. During the argument selection, entries will first be looked up in the array, matching the parameters class and name against array keys.
class MyClass { __construct(OtherClass $other, $id); function do($name) { print $name; } } $object = $app->make('MyClass', ['id' => 42]); // $id will be 42, $other will be resolved through the container $app->invoke([$object, 'do'], ['name' => 'Spawn']); // will print 'Spawn'
As mentioned above, get will also invoke a callable before returning it. Thus you may pass additional arguments to this method, as well.
Delegate lookup
Delegate lookup is a featured introduced by the Container Interoperability standard. A request to the container is performed within the container. But if the fetched entry has dependencies, instead of performing the dependency lookup in the container, the lookup is performed on the delegate container. In other words: Whenever dependency injection happens, dependencies will be resolved through the delegate container.
Dependency lookup in Spawn is always delegated. By default the container delegates the lookup to itself.
Set a different delegate container via constructor argument or use the use the delegate method:
$app = new Container($delegateContainer); $app->delegate($delegateContainer);
Delegate lookup enables sharing of entries across containers and allows to build up a delegation queue. See Design principles to learn how to utilize this feature properly.
Design principles
- Implements container-interop
- Implements delegate lookup
- Separates storage of 'public' abstracts and internals
- Adding entries always via the same single method; all other features are implemented using closures
- Enforce users to use the delegate lookup feature and the delegation queue
frogsystem/spawn 适用场景与选型建议
frogsystem/spawn 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 56 次下载、GitHub Stars 达 0, 最近一次更新时间为 2015 年 05 月 24 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「container」 「dic」 「ioc」 「container-interop」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 frogsystem/spawn 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 frogsystem/spawn 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 frogsystem/spawn 相关的其它包
同方向 / 同关键字的高下载量 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.
Common IoC Api Interface
Dependency injection container for the Monolith framework.
Molajo Inversion of Control package offers a full-featured, simple-to-use dependency injection and object construction solution for PHP applications.
The PSR-11 container bridges
统计信息
- 总下载量: 56
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 24
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2015-05-24