reinfi/zf-dependency-injection

一个Laminas框架模块,用于通过注解或配置条目加载依赖。

6.2.0 2024-08-04 19:52 UTC

README

使用注解、yaml或自动装配在Laminas或Mezzio中配置依赖注入。

深受以下启发:https://github.com/mikemix/mxdiModule

=======

  1. 安装
  2. 自动装配
  3. 属性
  4. 注解
  5. YAML
  6. 缓存
  7. PHPStan扩展
  8. 控制台命令

安装

  1. 使用Composer安装: composer require reinfi/zf-dependency-injection
  2. 通过配置文件中的application.config.php下的modules键启用模块
    return [
        'modules' => [
            'Reinfi\DependencyInjection',
            // other modules
        ],
    ];

自动装配

要为您的服务使用自动装配,您需要在服务管理器配置中指定'AutoWiringFactory'。

'service_manager' => [
    'factories' => [
        YourService::class => \Reinfi\DependencyInjection\Factory\AutoWiringFactory::class,
    ],
]

回退自动装配

如果您正在将现有项目迁移到使用zend服务管理器,并且不想手动注册所有自动装配的服务,您可以注册抽象的FallbackAutoWiringFactory工厂。

请确保您不会对一切使用回退机制。您应该尝试编写并注册您服务的显式工厂。

'service_manager' => [
    'abstract_factories' => [
        \Reinfi\DependencyInjection\AbstractFactory\FallbackAutoWiringFactory::class,
    ],
]
什么可以被自动装配?

服务管理器中注册的每个服务都可以被自动装配。插件管理器中的插件也可以被自动装配。如果您需要注册另一个映射,您可以简单地添加以下内容

PluginManagerResolver::addMapping('MyInterfaceClass', 'MyPluginManager');

如果您的服务需要容器作为依赖项,这也支持自动装配。

添加另一个解析器

如果您想添加另一个解析器,您可以通过配置简单地添加一个。

'reinfi.dependencyInjection' => [
    'autowire_resolver' => [
        AnotherResolver::class,
    ],
]

它需要实现ResolverInterface。

属性

如果使用的是8.0或更高版本的PHP,则属性会被激活。要使用属性为您的依赖项指定'InjectionFactory',您需要在服务管理器配置中指定。

'service_manager' => [
    'factories' => [
        YourService::class => \Reinfi\DependencyInjection\Factory\InjectionFactory::class,
    ],
]

以下属性被支持

  • Inject(直接从服务定位器注入服务)
  • InjectParent(如果从插件管理器注入服务,则必须使用)
  • InjectConfig(点分隔的配置值路径,例如service_manager.factories)
  • InjectContainer(直接注入容器接口)

此外,还有几个注解可以用于从插件管理器注入。

  • InjectViewHelper
  • InjectFilter
  • InjectInputFilter
  • InjectValidator
  • InjectHydrator
  • InjectFormElement

您可以直接传递所需的服务名称,或者如果您需要选项,您可以按照以下方式传递

#[InjectFormElement(name="Service", options={"field": "value"}]

如果您需要一个Doctrine存储库,也存在一个属性。

  • InjectDoctrineRepository

仅支持构造函数注入,如果需要从setter中使用di,则需要使用代理工厂。

您可以在属性或__construct方法中添加属性。

#[Inject("Namespace\MyService")] 
private MyService $service;

public function __construct(MyService $service) 
{
    $this->service = $service;
}

private MyService $service;

#[Inject("Namespace\MyService")] 
public function __construct(MyService $service) 
{
    $this->service = $service;
}

顺序很重要,您应该在构造函数或属性注解之间做出选择。

注解

要使用注解为您的依赖项指定'InjectionFactory',您需要在服务管理器配置中指定。

'service_manager' => [
    'factories' => [
        YourService::class => \Reinfi\DependencyInjection\Factory\InjectionFactory::class,
    ],
]

以下注解被支持

  • Inject(直接从服务定位器注入服务)
  • InjectParent(如果从插件管理器注入服务,则必须使用)
  • InjectConfig(点分隔的配置值路径,例如service_manager.factories)
  • InjectContainer(直接注入容器接口)

此外,还有几个注解可以用于从插件管理器注入。

  • InjectViewHelper
  • InjectFilter
  • InjectInputFilter
  • InjectValidator
  • InjectHydrator
  • InjectFormElement

您可以直接传递所需的服务名称,或者如果您需要选项,您可以按照以下方式传递

@InjectFormElement(name="Service", options={"field": "value"})

如果您需要一个Doctrine存储库,也存在一个注解。

  • InjectDoctrineRepository

仅支持构造函数注入,如果需要从setter中使用di,则需要使用代理工厂。

您可以在属性或__construct方法中添加注解。

use Reinfi\DependencyInjection\Annotation\Inject;

/**
 * @Inject("Namespace\MyService")
 */
private MyService $service;

/**
 * @param MyService $service
 */
public function __construct(
    MyService $service,
) {
    $this->service = $service;
}

use Reinfi\DependencyInjection\Annotation\Inject;

/**
 * @Inject("Namespace\MyService")
 */
public function __construct(MyService $service) 
{
    $this->service = $service;
}

顺序很重要,您应该在构造函数或属性注解之间做出选择。

添加自己的注解

如果您想使用自己的注解,您只需要实现AnnotationInterface。

YAML

您可以在yaml文件中指定您的依赖项。

YourService:
  - {type: Inject, value: AnotherService}

要启用YAML使用,您需要指定以下配置

'reinfi.dependencyInjection' => [
    'extractor' => YamlExtractor::class,
    'extractor_options => [
        'file' => 'path_to_your_yaml_file.yml',
    ],
]

缓存

解析映射源非常耗时。您应该在生产服务器上启用缓存。您可以使用任何自定义或现有的PSR-16缓存适配器轻松设置缓存。

您可以为容器提供一个字符串,该字符串将被解析。工厂必须返回一个PSR-16缓存适配器。

'reinfi.dependencyInjection' => [
    'cache' => \Laminas\Cache\Storage\Adapter\Memory::class,
]

或者您提供一个缓存适配器的工厂。

'reinfi.dependencyInjection' => [
    'cache' => function() {
       return new \Laminas\Cache\Psr\SimpleCache\SimpleCacheDecorator(
           new \Laminas\Cache\Storage\Adapter\Memory()
       );
    },
]

PHPStan扩展

由于“自动连接”总是有点像魔法,因此这个库附带了一个PHPStan扩展来解决该问题。

如果您还安装了phpstan/extension-installer,那么您就设置好了!

手动安装

如果您不想使用phpstan/extension-installer,请在项目的PHPStan配置中包含phpstan-extension.neon

includes:
    - vendor/reinfi/zf-dependency-injection/phpstan-extension.neon

此扩展需要了解您的服务管理器以查找您为自动连接配置的所有类。

如果您不提供它,PHPStan扩展将什么也不做。

parameters:
    reinfiLaminasDependencyInjection:
       serviceManagerLoader: tests/service-manager.php

例如,tests/service-manager.php看起来可能如下所示

$app = \Laminas\Mvc\Application::init($config);
return $app->getServiceManager();

控制台命令

  • Laminas的预热脚本:php bin/zf-dependency-injection-cache-warmup 使用类所需的所有注入填充缓存。这可以通过AutoWiringFactory或InjectionFactory实现。

常见问题解答

请随时提出任何问题或打开自己的拉取请求。