Symfony 2 注入类型

  • 发布时间 2015-02-02
  • 分类 php

Construct Injection(初始化注入)


namespace Kittencup\Di;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

include "vendor/autoload.php";

class Article
{

    protected $title;
    protected $content;
    protected $id;

    public function __construct($id,Db $db)
    {
        $data = $db->findArticle($id);
        $this->id = $id;
        $this->title = $data['title'];
        $this->content = $data['content'];
    }

}

class Db
{
    public function findArticle($id)
    {
        return [
            'title' => 'kittencup',
            'content' => 'kittencup.com'
        ];
    }
}

$container = new ContainerBuilder();
$container->register('db', 'Kittencup\Di\Db');

Article类在初始化的时候需要注入Db类,你需要在注册Article时告诉容器__construct所需要的参数


$container->register('article','Kittencup\Di\Article')->addArgument(100)->addArgument(new Reference('db'));

$article = $container->get('article');

通过register()注册后返回的是Symfony\Component\DependencyInjection\Definition对象,通过Definition对象里的addArgument()方法顺序的注册进__construct需要依赖的参数,$id需要的是数字直接传入,而$db则需要的是一个Kittencup\Di\Db实例,该类前面已经在Container里注册过了,所以通过实例一个Symfony\Component\DependencyInjection\Reference,来告诉Container这个参数需要使用Container中服务名为db的实例,当从Container中获取服务名为article的实例时,Container会根据你的设置,解决Article的依赖问题,用户不需要关心对象注入的过程

Setter Injection (通过方法注入)


namespace Kittencup\Di;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

include "vendor/autoload.php";
class Article
{

    protected $title;
    protected $content;
    protected $id;

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

    public function setDb(Db $db)
    {
        $data = $db->findArticle($this->id);
        $this->title = $data['title'];
        $this->content = $data['content'];
    }

}

class Db
{
    public function findArticle($id)
    {
        return [
            'title' => 'kittencup',
            'content' => 'kittencup.com'
        ];
    }
}

这时Db注入Article已经不是通过__construct注入了,通过改为setDb方法注入


$container = new ContainerBuilder();

$container->setParameter('id', 100);

$container->register('db', 'Kittencup\Di\Db');

$container->register('article', 'Kittencup\Di\Article')->addArgument('%id%')->addMethodCall('setDb', [new Reference('db')]);

$article = $container->get('article');

var_dump($article);

通过Definition对象里方法addMethodCall()来告诉容器,当调用article服务需要先通过什么方法注入什么内容,在这里通过setDb方法,注入Container里的db服务

Property Injection(属性注入)


namespace Kittencup\Di;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

include "vendor/autoload.php";

class Article
{

    protected $title;
    protected $content;
    protected $id;

    public $db;

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

}

class Db
{
    public function findArticle($id)
    {
        return [
            'title' => 'kittencup',
            'content' => 'kittencup.com'
        ];
    }
}

Db 是Article类中公开的属性


$container = new ContainerBuilder();

$container->setParameter('id', 100);

$container->register('db', 'Kittencup\Di\Db');

$container->register('article', 'Kittencup\Di\Article')
    ->addArgument('%id%')
    ->setProperty('setDb', [new Reference('db')]);

$article = $container->get('article');

var_dump($article);

通过setProperty方法注入,类似于方法注入