依赖注入主要有两种类型。在 Symfony 中,我们还有一个额外的方法。我在这里解释所有这些:
1-构造函数注入
这种方法要求客户端在服务的构造函数中提供参数,如果您在配置文件中定义服务参数,Symfony 将为您提供。
saman.search:
class: Saman\SearchBundle\Services\SearchService
arguments:
- @translator
- @doctrine.orm.default_entity_manager
- %search_service_parameters%
在您的服务类别中,您有:
<?php
namespace Library\Services;
use Doctrine\ORM\EntityManager;
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
class SearchService
{
/**
* Translator services
*
* @var TranslatorService $translatorService
*/
protected $translatorService;
/**
*
* @var EntityManager $em
*/
protected $em;
/**
* Client side parameters
*
* @var array
*/
protected $parameters;
public function __construct(
TranslatorService $translatorService,
EntityManager $em,
array $parameters = array()
)
{
$this->translatorService = $translatorService;
$this->em = $em;
$this->parameters = $parameters;
}
public function doSomething()
{
return $this->translatorService->trans('app.text.hello');
}
}
?>
2-二传手注入
此方法要求您的服务为每个依赖项提供一个 setter 方法。当您想使用该服务时,您可以动态设置依赖关系。这使您可以随时自由设置依赖项。
saman.search:
class: Saman\SearchBundle\Services\SearchService
arguments:
- @translator
- @doctrine.orm.default_entity_manager
- %search_service_parameters%
saman.a:
class: Saman\SearchBundle\Services\A
arguments: ~
在您的服务中,您拥有:
<?php
namespace Library\Services;
use Doctrine\ORM\EntityManager;
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
use Library\Services\A;
class SearchService
{
/**
* Translator services
*
* @var TranslatorService $translatorService
*/
protected $translatorService;
/**
*
* @var EntityManager $em
*/
protected $em;
/**
* Service A
* @var A $a
*/
protected $a;
/**
* Client side parameters
*
* @var array
*/
protected $parameters;
public function __construct(
TranslatorService $translatorService,
EntityManager $em,
array $parameters = array()
)
{
$this->translatorService = $translatorService;
$this->em = $em;
$this->parameters = $parameters;
}
public function setServiceA(A $a)
{
$this->a = $a;
return $this;
}
public function doSomethingNeedServiceA()
{
return $this->getServiceA()->doSomethingInA();
}
private function getServiceA()
{
if (null === $this->a) {
throw new \LogicException("You should set service A first");
}
return $this->a;
}
}
?>
这也可以通过使用接口来改进
<?php
namespace Library\Services;
use Doctrine\ORM\EntityManager;
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
use Library\Interfaces\A;
class SearchService
{
/**
* Translator services
*
* @var TranslatorService $translatorService
*/
protected $translatorService;
/**
*
* @var EntityManager $em
*/
protected $em;
/**
* Interfaces A
* @var A $a
*/
protected $a;
/**
* Client side parameters
*
* @var array
*/
protected $parameters;
public function __construct(
TranslatorService $translatorService,
EntityManager $em,
array $parameters = array()
)
{
$this->translatorService = $translatorService;
$this->em = $em;
$this->parameters = $parameters;
}
public function setServiceA(A $a)
{
$this->a = $a;
return $this;
}
public function doSomethingNeedServiceA()
{
return $this->getServiceA()->doSomethingInA();
}
private function getServiceA()
{
if (null === $this->a) {
throw new \LogicException("You should set a service that implement A interfaces");
}
return $this->a;
}
}
?>
还有你的界面
<?php
namespace Library\Interfaces;
interface A
{
public function doSomethingInA();
}
?>
然后,当您想使用此服务时,您应该这样做
$aService = $this->get('saman.a');
$searchService = $this->get('saman.search');
$searchService->setServiceA($aService)
->doSomethingNeedServiceA();
3- 标记服务
在 Symfony 中,有一种使用标签配置在另一个服务中注册服务的方法。请参阅使用标记服务
我过去实现过这种方法,它非常好,但它很大。如果有人需要实现,我很乐意把它放在这里。