承接 intraworlds/service-container 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

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

intraworlds/service-container

Composer 安装命令:

composer require intraworlds/service-container

包简介

Lightweight yet powerful implementation of dependancy injection container with autowiring

README 文档

README

Lightweight yet powerful implementation of dependency injection container with autowiring.

Installation

Use Composer to install the package:

composer require intraworlds/service-container

Config

The container is implementing standard PSR-11 interface. You can use it with autowiring out-of-the-box. However, sometimes you want to configure things which needs parameters (eg. DB connection).

// zero configuration required
$container = new ServiceContainer;
$container->get(ClassWithManyDependencies::class);

// bind factory of a value object
#[Bind(self::load(...))]
final class Config
{
  function __construct(private array $values)

  static function load(Filesystem $fs) : self
}

// by method
$container->bind(Config::class, Config::load(...));

// delay actual factory execution (eg. connection to DB) with lazy objects
// inline factories in attributes are possible since PHP 8.5
#[Lazy, Bind(fn(Config $config) => new Aws\S3\S3Client(['region' => $config->get('S3_REGION')]))]
final class S3
{
  public function __construct(private Aws\S3\S3Client $client)
}

// by methods
$container->bind(S3::class, fn(Config $config) => new Aws\S3\S3Client(['region' => $config->get('S3_REGION')]));
$container->lazy(S3::class);

// use alias to bind without factory
#[Alias(MemoryCache::class)]
interface Cache

// by method
$container->alias(Cache::class, MemoryCache::class);

Composite types

A parameter typed as a union or intersection (eg. Cache|NullCache, Countable&Traversable) is not autowired by trying each member. The container resolves it under the type's string key, so you must register it explicitly — otherwise a CannotAutowireCompositType is thrown.

// a constructor param typed `Cache|NullCache` must be bound under that exact string
$container->bind('Cache|NullCache', fn() => new NullCache);

Usage

It can be useful to manipulate with Service Container directly.

// get singleton using configured factories or auto-wiring
$container->get(S3::class) === $container->get(S3::class);

// make fresh instances
$container->make(Uri::class) !== $container->get(Uri::class);

// service is always available if it's possible to create it
$container->has(Config::class) === true;

// return service only if it was already initialized before, NULL otherwise
$container->instance(Transaction::class);

// same as `get()` but fails gracefully (to NULL)
$container->try('NonExisting') === null;

// register an already existing instance as a singleton
$container->set(Clock::class, new FrozenClock($now));

// remove a singleton and return it (NULL if it wasn't set)
$container->unset(Clock::class);

// obtain (and memoize) the resolved factory for an ID
$container->factory(S3::class); // instance of IW\ServiceContainer\ServiceFactory

Examples

Auto wiring arbitrary callable

Internal CallableFactory is useful for resolving any dependencies of a callable. Especially it's useful for init template method. See following example.

abstract class Parent {
  function __construct(private Dependency $dependency, ServiceContainer $container) {
    if (method_exists($this, 'init')) {
      (new CallableFactory($this->init(...)))($container);
    }
  }
}

class Child extends Parent {
  function init(AnotherDependency $another) {
    // ...
  }
}

Manual Wiring

Sometimes you want to configure container manually. Let's consider following example on Command Pattern

interface OrderCommand
{
  function execute();
}

class OrderInvoker
{
  function __construct(private OrderCommand ...$commands) {}

  function execute() : void {
    array_walk($this->commands, fn($command) => $command->execute());
  }
}

With IW\ServiceContainer you have several options how to resolve OrderInvoker's dependencies.

// an alias but that's no good for multiple commands
$container->alias('OrderInvoker', 'ReserveItems');

// external factory
$container->bind('OrderInvoker', function (IW\ServiceContainer $container) {
  return new OrderInvoker($container->get('ReserveItems'), $container->get('SendInvoice'));
});

// internal factory
$container->bind('OrderInvoker', OrderInvoker::create(...));

class OrderInvoker
{
  static function create(ReserveItems $reserveItems, SendInvoice $sendInvoice) : OrderInvoker {
    return new OrderInvoker($reserveItems, $sendInvoice);
  }
}

// wiring factory
$container->wire('OrderInvoker', 'ReserveItems', 'SendInvoice');

// ...same but with attribute
#[Wire('OrderInvoker', 'ReserveItems', 'SendInvoice')]
class OrderInvoker
{
}

Arguably all approaches have their advantages. internal factory approach is good for static analysis. wiring factory is useful for common application pattern and when dependencies may vary.

Errors

All exceptions extend IW\ServiceContainer\Exception, which implements PSR-11's ContainerExceptionInterface; ServiceNotFound additionally implements NotFoundExceptionInterface. When a failure is wrapped (eg. a broken dependency deep in a resolution chain), Exception::getOrigin() returns the first original exception raised outside the container, which is handy for pinpointing the root cause.

License

All contents of this package are licensed under the MIT license.

intraworlds/service-container 适用场景与选型建议

intraworlds/service-container 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 76.14k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2018 年 11 月 06 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 intraworlds/service-container 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 intraworlds/service-container 我们能提供哪些服务?
定制开发 / 二次开发

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

BUG 修复 & 性能优化

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

项目外包 & 长期维护

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

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

统计信息

  • 总下载量: 76.14k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 35
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2018-11-06