vection-framework/dependency-injection 问题修复 & 功能扩展

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

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

vection-framework/dependency-injection

Composer 安装命令:

composer require vection-framework/dependency-injection

包简介

The Vection Dependency Injection injects dependencies quickly and effectively.

README 文档

README

release QA PHPStan

PHP DI - Dependency Injection Container

⚠️ Vection Dependency Injection is currently in development stage, so atm only pre-releases are available. Breaking changes may be made until a stable release!

Dependency Injection Container for PHP

This vection component provides a powerful dependency injection container for PHP. It supports several ways of automatic injection like annotations, attributes and injection by interfaces. An optional configuration allows the mapping of interfaces and concrete implementation.

<?php

use Vection\Component\DependencyInjection\Traits\AnnotationInjection;

class MyApiController implements LoggerAwareInterface // Auto injection Logger via mapping in container config.
{
    use AnnotationInjection; 
    
    #[Inject] private IdentityQueryService $identityQueryService;
    
    public function __construct(CommandBusInterface $commandBus) 
    { 
        // Auto constructor parameter injection
    }
}

Supported injection types

  • Constructor injection
    Constructor params will automatically resolved and injected by container.

  • Attribute based injection
    Class property injection by using #[Inject] attribute.

  • Interface injection
    Mapping of interfaces and implementations that can be inject via construct, methods and property.

  • Interface aware injection
    Mapping of interfaces and implementations that will inject by setters defined in the interfaces.

  • Magic injection
    Injects the dependency via property definition by using __inject method.

  • Injection by class inheritance
    Subclasses get automatically injection by parents dependencies defined in parent classes.

Installation

Vection Components supports only installation via composer. So first ensure your composer is installed, configured and ready to use.

$ composer require vection-framework/dependency-injection

How to use

First we take a look how to use the DI container before start explaining the setup.

Constructor injection

This DI container supports the automatically injection of construct properties insofar as the properties are objects with type hints, means no primitive types! The following example would injection the object of type FooBar at creation.

public function __construct(FooBar $fooBar)

Annotation / Attribute injection

The annotation injection provides a powerful possibility to injection dependencies into protected object properties by using the #[Inject] attribute on properties. The usage of annotation injection requires the use of the AnnotationInjection trait. Annotations also requires the fully qualified class names (< PHP 7.4)

<?php

class Awesome
{
    use AnnotationInjection;

    #[Inject] protected FooBar $fooBar;
}

Important notice
Injected properties cannot be accessed from constructor. If you need to access an injected property from the constructor you can use the alternative construction method __init() in your class. This method will be called immediately after the object is created with its dependencies.

<?php

class Awesome
{
    use AnnotationInjection;
    
    #[Inject] protected FooBar $fooBar;

    public function __construct()   
    {
        // Cannot access $this->fooBar yet
    }
    
    // Alternative construction method, called immediately after the object is created with its dependencies
    public function __init(): void
    {
        // Here you can access
        $this->fooBar;
    }
}

Interface injection

The interface injection is a great way to decouple the concrete implementation with its interfaces. It provides the injection by using the interfaces instead of concrete implementations.

<?php

class Awesome
{
    use AnnotationInjection;
    
    public function __construct(FooBarInterface $fooBar)
    {...}
}

This kind of injection requires the following entry in the configuration file. (Detailed documentation of the configuration file you can read in the Setup -> Configuration section)

resolve(FooBarInterface::class)
   ->viaFactory(fn(Container $container) => $container->get(FooBar::class))
,

Interface aware injection

This injection type provides the injection of dependencies by its aware interfaces. This injection requires an configuration entry to map the interface with the concrete implementation.

<?php

class Awesome implements LoggerAwareInterface
{
    public function setLogger(LoggerInterface $logger)
    {...}
}

This kind of injection requires the following entries in the configuration file.

# First map the interface to the implementation
resolve(LoggerInterface::class)
    ->viaFactory(fn(Container $container) => new Logger())
,

# Now we can map the aware interface with the LoggerInterface by using the inject() method
resolve(LoggerAwareInterface::class)
    ->viaSetter('setLogger', LoggerInterface::class)
,

The second parameter (Logger) defined the name of the setter method.

Explicit injection

This kind of injection provides an alternative way of injection if the constructor of all other injection types does not fit any use case.

<?php

class Awesome
{
    public function __inject(FooBar $fooBar)
    {
        $this->fooBar = $fooBar;
    }
}

Injection by parent class inheritance

This feature allows subclasses to get automatically dependency injection by parent classes, if the parent class uses any injection type.

<?php

class AwesomeParent
{
    use AnnotationInjection;
                
    #[Inject] protected FooService $service;
    
    public function __construct(FooBarInterface $fooBar)
    {...}
}

class Awesome extends AwesomeParent
{
    public function getFooBar()
    {
        return $this->fooBar;
    }
}

Setup

The setup of the container is simple and takes only a few lines of code. Optional related of the use case and injection type you have to define a container configuration.

Create the container

The following snipped shows the fastest way of creating a working container.

<?php

$container = new Container();

// Create now your class where to start dependency injection
$myApplication = $container->get(MyApplication::class); 

If the class have some parameters which you have to pass manually, you can use the create method on the container. The second parameter is an array that will pass to the constructor of the class, the third parameter can be used to set this object as shared object or not. Shared objects will be reused by the container, non shared object will be create every time it is requested.

$myApplication = $container->create(MyApplication::class, [$optional, $params], $optionalSharedOrNot);

Configuration

The fasted way of setup does not fit the best way of usage, so lets take a look at some optional setup steps. The use of interface injection or some special object creations requires a configuration. This can be done by a configuration file (e.g. container.php). The benefit of a php config is the autocompletion and use of functions. The configuration file just returns an array with some definitions.

<?php use function Vection\Component\DependencyInjection\resolve;
return [
    // configuration here
];

To load this configuration file you have to add it to the container. You can also add multiple config files in the case of modular development.

$container = new Container();

$container->load('path/to/config/container.php');
$container->load('path/other/*/config/container.php');

The configuration use the set function defined by the DI. This method takes the class as injection subject and returns an definition object on which you can define the injection. In common way it would look like the following snipped:

// Not recommended writing type
$instruction = resolve(My\Awesome\MegaClass::class);
$instruction->viaFactory(....);

The right way would look like this:

<?php use function Vection\Component\DependencyInjection\resolve;
return [

    resolve(My\Awesome\MegaClass::class)
        ->viaFactory(fn(Container $container) => new My\Awesome\MegaClass('example'))
    ,

];

[MORE CONFIGURATION DOC COMMING SOON...]

Third party library injection

The DI container creates an internal tree of dependencies. This can end up in the resolving of third party library classes with unresolvable parameters (e.g. in case of primitive construct parameters of unknown library class) and exits with an error. To avoid this, it is recommended to restrict the di container to the own applications namespace.

$container->setAllowedNamespacePrefixes(['MyApplication', 'optionalOtherNamespaces']);

But if you want to use a third party library by injection, YOU CAN. In this case you should manually create the third party library object and just add this object to the container, now you this class can be used for injection.

$thirdPartyObject = new ThirdPartyObject(5, 'primitive');
$container->add($thirdPartyClass);

This will register the object by its class name and provide it as injectable object.

Caching

It is recommended to use the cache to avoid performance issues on large applications. The DI component uses the Cache contracts of the Vection Contracts. So you can use an own cache implementation by implementing the CacheInterface from Vection\Contracts\Cache or use one of the already existed Vection Cache provider (Redis, Memcache, APCu). You can also use the Symfony Bridge (Vection\Bridge\Symfony\Cache\SymfonyCacheProviderBridge).

    $cacheProvider = new Vection\Component\Cache\Provider\RedisCacheProvider(...);
    $cache = new Vection\Component\Cache\Cache($cacheProvider);

    $container = new Container();
    $container->setCache($cache);    

Support

Support Vection via Ko-fi:

Ko-fi

vection-framework/dependency-injection 适用场景与选型建议

vection-framework/dependency-injection 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 4, 最近一次更新时间为 2022 年 09 月 01 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「container」 「di」 「PHP Dependency Injection」 「php-di」 「Dependency-Container」 「php-dic」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

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

围绕 vection-framework/dependency-injection 我们能提供哪些服务?
定制开发 / 二次开发

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

BUG 修复 & 性能优化

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

项目外包 & 长期维护

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

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

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2022-09-01