此包已被废弃且不再维护。未建议替代包。

Selene 依赖注入组件

dev-development 2014-08-19 03:25 UTC

This package is not auto-updated.

Last update: 2016-02-07 09:58:41 UTC


README

Build Status Latest Stable Version Latest Unstable Version License HHVM Status

Coverage Status

<?php

use Selene\Components\DI;

$container = new Container;

使用

参数

<?php

$container->setParameter('my.param', 'param value');
$container->setParameter('my.options', [1, 2, 3]);

$container->getParameter('my.param');   // 'param value'
$container->getParameter('my.options'); // [1, 2, 3]

定义服务

<?php
$container->define('my.service', 'ServiceClass', ['service args']);

将类实例注入为服务

在某些情况下,可能无法或不需要容器创建服务。因此,您可以将类实例作为服务注入。

<?php

$container
    ->define('service_id', 'InjectedClass')
    ->setInjected(true);

    // ...

$container->inject('service_id', $instance);
同步注入服务上的依赖

如果您的服务依赖于另一个被注入的服务,您不能依赖该依赖在服务构造函数上声明。相反,您应该使用以下描述的setter注入。依赖于注入服务的setter仅在所有依赖都解决后才会调用。

注入

构造函数注入
<?php

$container->setParameter('my.param', 'param value');

// passing a parameter to the constructor of a service:
$container->define('my_service', 'Acme\FooService', ['%my.param%']);
// or
$container->define('my_service', 'Acme\FooService')
    ->addArgument('%my.param%');

// passing a service reference to the constructor of a service:

$container->define('other_service', 'Acme\OtherService');

$container->define('my_service', 'Acme\ServiceNeedsOtherService', ['$other_service']);
// or
$container->define('my_service', 'Acme\ServiceNeedsOtherService')
    ->addArgument('$other_service');

注意服务ID前面的 $ 符号。 $ 将表示您正在引用一个服务。您也可以创建一个引用对象而不是使用美元符号。

<?php

use \Selene\Components\DI\Reference;

$container->define('my_service', 'Acme\ServiceNeedsOtherService')
    ->addArgument(new Reference('other_service'));
setter注入
<?php

$container->setParameter('my.options', [1, 2, 3]);

// passing a parameter to a setter method of a service
$container->define('my_service', 'Acme\FooService')
    ->addSetter('setOptions', ['%my.options%'])

// passing a service reference to a setter method of a service

$container->define('other_service', 'Acme\OtherService');

$container->define('my_service', 'Acme\ServiceNeedsOtherService')
    ->addSetter('setOtherService', ['%other_service%']);
工厂

有时您可能发现使用工厂启动服务更容易。对于DIC来说,工厂是一个接收某些(或没有)参数的类方法,并返回您的服务实例。

工厂方法可以是静态的或非静态的。在服务定义上声明的所有参数都将注入到工厂方法中。

<?php

namespace Acme\Foo;

class ServiceFactory
{
    public function makeFooService($fooargs = null)
    {
        return new FooService($fooargs);
    }
}
<?php

$container->setParameter('foo.options', ['opt1', 'opt2']);
$container->setParameter('foo.factory.class', 'Acme\Foo\ServiceFactory');

$container
    ->setService('foo_service')
    ->setFactory('%foo.factory.class%', 'makeFooService')
    ->addArgument('%foo.options%');

作用域

目前有两种不同的作用域,即 containerprototype。服务默认为 container 创建。您可以通过设置相应的范围来覆盖此设置。

请注意,您不能将注入服务的范围更改为 prototype

<?php

$container->define('my_service', 'Acme\FooService')
    ->setScope(ContainerInterface::SCOPE_PROTOTYPE);
服务和容器作用域

使用 container 范围定义的服务将在每次调用服务时返回相同的实例。

服务和原型作用域

与容器范围不同,将服务的范围设置为 prototype 将在每次调用时创建该服务的新实例。

解析服务

所有服务都是懒加载的。服务是在第一次调用时解析的。

<?php
$service = $container->get('my_service');

别名

服务也可以通过别名进行别名化和解析。

<?php
$container->alias('my_service', 'my_alias');

服务继承

您可以从父服务继承依赖项。父服务可以是具体的或抽象的。

请注意,子服务将继承从其父服务继承的构造函数和setter注入依赖项。

<?php

$container->setParameter('Acme\AbstractServiceClass', ['$foo_service']);
$container
    ->define('parent_service', 'Acme\ConcreteServiceClass')
    ->setAbstract()
    ->addArgument('foo');

$container
    ->define('concrete_service', 'Acme\ConcreteServiceClass')
    ->setParent(new Reference('parent_service'));

构建容器

动态依赖注入会带来一定的开销。然而,从动态容器中构建静态容器是可行的。在将 DIC 应用于生产环境时,这非常有用。

<?php

use Selene\Components\DI\Builder;

$builder = new Builder($container);
$builder->build();

配置

可以使用文件加载器配置 DIC

使用 XML 进行配置

示例 XML

<?xml version="1.0" encoding="UTF-8"?>

<container>
    <parameters>
        <parameter id="service.class">Acme\Foo</parameter>
    </parameters>

    <services>
        <service id="service" class="%service.class%"/>
    </services>
</container>
<?php

use Selene\Components\DI\Builder;
use Selene\Components\DI\Loader\XmlLoader;
use Selene\Components\Config\Resource\Locator;

$loader = new XmlLoader($builder = new Builder($container), new Locator($paths));

$loader->load('services.xml');