them/container 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

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

them/container

Composer 安装命令:

composer require them/container

包简介

Autowiring DI Container based on and a drop in replacement for pimple/pimple

README 文档

README

them/container on packagist GPLv3

them/container

them/container is a dependency injection container for PHP >= 8.1.

Basically it's Pimple with autowiring capabilities and the psr/container interface on top.

Installation

Before using them/container in your project, add it to your composer.json file:

composer require them/container

Usage

If you don't already use Pimple, please read https://github.com/silexphp/Pimple#readme first.

them/container is a drop-in replacement for Pimple. When creating your container use the class \Them\Container\Container instead of Pimple\Container.

If you use service provider (https://github.com/silexphp/Pimple#extending-a-container) you may make them implement \Them\Container\ServiceProviderInterface instead of \Pimple\ServiceProviderInterface. The method register will then receive not a \Pimple\Container but a \Them\Container\Container instance.

Changes to Pimple

PSR-11

In contrast to Pimple, them/container is PSR-11 compliant by default. So no need to do things like

$container = new \Pimple\Container();
$psr11 = new \Pimple\PsrContainer($container);

Registering services

Besides the Pimple ways to register a service, \Them\Container\Container provides the method

set(string $id, mixed $value): self

Pre-registered services

Upon initialization, the container instance already has one service registered which is available under the following two ids, \Them\Container\Container::class and \Psr\Container\ContainerInterface::class where both point to the container instance itself.

Service aliases

Sometimes you need to register a service with more than one key. Think of a logger, that needs to be available under \Psr\Log\LoggerInterface but also under \Monolog\Logger:


declare(strict_types=1);

use Psr\Log\LoggerInterface;
use Monolog\Logger;
use Them\Container\Container;

$container = new Container();

$container[Logger::class] = fn() => new Logger('logger');

$container->aka(Logger::class, LoggerInterface::class);

Autwiring

When trying to get a service by id from them/container which is not already known to the container, it tries to instantiate it.

This, of course can only work if

  1. the provided id is a name of an existing class
  2. the class can be instantiated (i. e. not abstract, not an interface)
  3. the constructor can be invoked (i. e. not private/protected)
  4. every constructor parameter has a type assigned (not __construct($value))
  5. every parameter type can be resolved by the container using its name.

Constructor injection

Given a class

<?php

declare(strict_types=1);

use Psr\Log\LoggerInterface;

final readonly class SomeService
{
    public function __construct(
        private LoggerInterface $logger,
    ) {}
}

If you call $container->get(SomeService::class), the container will search for the id \Psr\LoggerInterface to resolve the value for the parameter $logger - and miserably fail if there is no such key registered and due to the fact that an interface cannot be instantiated.

To tell the container which key to use instead, just add the Attribute \Them\Container\Attribute\Constructor to the service class:

<?php

declare(strict_types=1);

use Monolog\Logger;
use Psr\Log\LoggerInterface;
use Them\Container\Attribute\Constructor;

#[Constructor(['logger' => Logger::class])]
final readonly class SomeService
{
    public function __construct(
        private LoggerInterface $logger,
    ) {}
}

In this case the container will use the key \Monolog\Monolog for resolving the parameter $logger.

Setter injection

Sometimes you need to inject a service by a setter method, for example a logger when working with the \Psr\Log\LoggerAwareInterface.

For this to achieve you add one or more Them\Container\Attribute\Method Attributes to the service class, telling the container to call a method with parameter values resolved by parameter types. If you need to override this, use the attribute's 2nd parameter to assign a key to a parameter:

<?php

declare(strict_types=1);

use Monolog\Logger;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
use Scn\Container\Attribute\Method;

#[Method('setLogger', ['logger' => Logger::class])]
final class SomeService implements LoggerAwareInterface
{
    protected ?LoggerInterface $logger = null;

    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }
}

Resolving dependencies to interfaces (or other non instantiatable classes)

If you are coding against interfaces, you will always have to tell the container which implementation to use when you ask for a service by an interface name. This can be done with aliases (see above) but also directly at the interface by adding the attribute \Them\Container\Attribute\Specific with the "real" class as parameter to the interface:

<?php

declare(strict_types=1);

use Them\Container\Attribute\Specific;
use Them\Container\Container;

require_once __DIR__ . '/../vendor/autoload.php';

#[Specific(Service::class)]
interface ServiceInterface {}

final class Service implements ServiceInterface {}

$c = new Container();
var_dump($c->get(ServiceInterface::class));

If you now ask the container for the service by the id ServiceInterface it will instantiate Service and return that instance instead.

Autowiring service providers

When registering a service provider to the container, you can not only provide a \Pimple\ServiceProviderInterface or a \Them\Container\ServiceProviderInterface instance, but also just the class name of one of the above. The container will try to autowire and register them.

them/container 适用场景与选型建议

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

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

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

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

BUG 修复 & 性能优化

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

项目外包 & 长期维护

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

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

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: GPL-3.0-or-later
  • 更新时间: 2022-07-29