定制 frogsystem/spawn 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

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

Latest Stable Version Total Downloads Latest Unstable Version License Build Status Codacy Badge Codacy Badge SensioLabsInsight

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 我们能提供哪些服务?
定制开发 / 二次开发

基于 frogsystem/spawn 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 56
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 24
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 3
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2015-05-24