PHP 的依赖注入(DI)和服务提供者。灵感来源于 .NET DI。

v1.1.3 2024-04-21 13:42 UTC

This package is auto-updated.

Last update: 2024-09-21 14:48:52 UTC


README

依赖注入和服务提供者,用于 PHP。灵感来源于 .NET DI。

使用方法

composer require ivanvoitovych/dot-di

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

use DotDi\DependencyInjection\ServiceProvider;
use DotDi\DependencyInjection\ServiceProviderHelper;

$services = new ServiceProvider();
// register a singleton
$services->addSingleton(FooService::class);
// register a transient
$services->addTransient(BarService::class);
// register scoped using interface as a type
$services->addScoped(ITaxService::class, TaxService::class);
$services->addScoped(GenericService::class);
$services->addScoped(UserService::class);

// factory
$serviceProvider->addSingleton(
    IRedisConnector::class,
    function (Config $config) { // params are autoinjected
        return new RedisConnector($config->values['redisDbIndex']);
    }
);

// to auto register everything in the folder (as Scoped, for ex.: controllers)
ServiceProviderHelper::discover($services, ['path/to/your/files']);

使用泛型

class GenericService
{
    public function __construct(private string $type, private ?string $dbMap = null, ?int $dbIndex = null)
    {
    }
}
...
// injecting generic type using Inject attribute

class TestService
{
    /**
     * 
     * @param GenericService<UserEntity, UserEntityDbMap> $usersRepository 
     * @return void 
     */
    public function __construct(
        #[Inject([
            'type' => 'UserEntity',
            'dbMap' => 'UserEntityDbMap'
        ])]
        public GenericService $usersRepository
    ) {
    }
}

// extending generic class
#[Inject([
    'type' => 'UserEntity',
    'dbMap' => 'UserEntityDbMap'
])]
class UserService extends GenericService
{
}

使用作用域

// creating a scope
$scope = $services->createScope();
// getting a service
$scope->serviceProvider->get(FooService::class);
$scope->serviceProvider->get(ITaxService::class);
// setting up a service for current scope only
$requestScope->serviceProvider->set(HttpContext::class, new HttpContext());
// dispose at the end
$scope->dispose();

适用于 swoole 或 ReactPHP

dot-di 非常高效且节省内存 - 没有内存泄漏。

与 IDisposable 一起使用来自动释放资源

<?php

namespace Application\Swoole\Connectors;

use DotDi\Interfaces\IDisposable;
use Redis;
use Swoole\Database\RedisPool;

class SwooleRedisConnector implements IDisposable
{
    private Redis $redis;

    public function __construct(private RedisPool $pool)
    {
    }

    /**
     * 
     * @return Redis 
     */
    function get()
    {
        if (!isset($this->redis)) {
            $this->redis = $this->pool->get();
        }
        return $this->redis;
    }

    // this will be called automatically
    function dispose()
    {
        if (isset($this->redis)) {
            $this->pool->put($this->redis);
            unset($this->redis);
        }
    }
}
// swoole app example
...
    function handle(HttpContext $httpContext)
    {
        // create scope
        $scope = $this->serviceProvider->createScope();
        try {
            // create request and http context
            $scope->serviceProvider->set(HttpRequest::class, $httpContext->request);
            $scope->serviceProvider->set(HttpResponse::class, $httpContext->response);
            $scope->serviceProvider->set(HttpContext::class, $httpContext);
            $requestDelegate = new RequestDelegate($this, $scope);
            $scope->serviceProvider->set(RequestDelegate::class, $requestDelegate);
            // run middleware(s)
            $requestDelegate();
            // end response
            $httpContext->response->end();
        } finally {
            // dispose the scope
            $scope->dispose();
        }
    }

许可证

MIT 许可证

版权所有 (c) 2022 年至今 Ivan Voitovych

有关许可证文本,请参阅 LICENSE

法律

通过提交拉取请求,您放弃对 Viewi 项目的任何权利或索赔,并将这些更改的版权转让给 Ivan Voitovych。

如果您不能或不想转让这些权利(您的雇主的工作合同可能不允许这样做),则不应提交 PR。请提出一个问题,其他人可以完成这项工作。

这是说“如果您向我们提交 PR,那么代码就归我们所有”的法律方式。99.9% 的情况下,这就是您的意图;我们希望这不会让您害怕贡献。