php 如何将容器作为服务的参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17126277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to give container as argument to services
提问by whitebear
in my services constructor
在我的服务构造函数中
public function __construct(
EntityManager $entityManager,
SecurityContextInterface $securityContext)
{
$this->securityContext = $securityContext;
$this->entityManager = $entityManager;
I pass entityManager and securityContext as argument. also my services.xml is here
我将 entityManager 和 securityContext 作为参数传递。我的 services.xml 也在这里
<service id="acme.memberbundle.calendar_listener" class="Acme\MemberBundle\EventListener\CalendarEventListener">
<argument type="service" id="doctrine.orm.entity_manager" />
<argument type="service" id="security.context" />
but now,I want to use container in services such as
但是现在,我想在服务中使用容器,例如
$this->container->get('router')->generate('fos_user_profile_edit')
how can I pass the container to services?
如何将容器传递给服务?
回答by bigmax
It's easy, if service extends ContainerAware
很简单,如果服务扩展了 ContainerAware
use \Symfony\Component\DependencyInjection\ContainerAware;
class YouService extends ContainerAware
{
public function someMethod()
{
$this->container->get('router')->generate('fos_user_profile_edit')
...
}
}
service.yml
服务.yml
your.service:
class: App\...\YouService
calls:
- [ setContainer,[ @service_container ] ]
回答by Sybio
Add:
添加:
<argument type="service" id="service_container" />
And in your listener class:
在你的听众课上:
use Symfony\Component\DependencyInjection\ContainerInterface;
//...
public function __construct(ContainerInterface $container, ...) {
回答by Basit
It's 2016, you can use traitwhich will help you extend same class with multiple libraries.
现在是 2016 年,您可以使用trait来帮助您使用多个库扩展同一个类。
<?php
namespace iBasit\ToolsBundle\Utils\Lib;
use Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Component\DependencyInjection\ContainerInterface;
trait Container
{
private $container;
public function setContainer (ContainerInterface $container)
{
$this->container = $container;
}
/**
* Shortcut to return the Doctrine Registry service.
*
* @return Registry
*
* @throws \LogicException If DoctrineBundle is not available
*/
protected function getDoctrine()
{
if (!$this->container->has('doctrine')) {
throw new \LogicException('The DoctrineBundle is not registered in your application.');
}
return $this->container->get('doctrine');
}
/**
* Get a user from the Security Token Storage.
*
* @return mixed
*
* @throws \LogicException If SecurityBundle is not available
*
* @see TokenInterface::getUser()
*/
protected function getUser()
{
if (!$this->container->has('security.token_storage')) {
throw new \LogicException('The SecurityBundle is not registered in your application.');
}
if (null === $token = $this->container->get('security.token_storage')->getToken()) {
return;
}
if (!is_object($user = $token->getUser())) {
// e.g. anonymous authentication
return;
}
return $user;
}
/**
* Returns true if the service id is defined.
*
* @param string $id The service id
*
* @return bool true if the service id is defined, false otherwise
*/
protected function has ($id)
{
return $this->container->has($id);
}
/**
* Gets a container service by its id.
*
* @param string $id The service id
*
* @return object The service
*/
protected function get ($id)
{
if ('request' === $id)
{
@trigger_error('The "request" service is deprecated and will be removed in 3.0. Add a typehint for Symfony\Component\HttpFoundation\Request to your controller parameters to retrieve the request instead.', E_USER_DEPRECATED);
}
return $this->container->get($id);
}
/**
* Gets a container configuration parameter by its name.
*
* @param string $name The parameter name
*
* @return mixed
*/
protected function getParameter ($name)
{
return $this->container->getParameter($name);
}
}
Your object, which will be service.
你的对象,这将是服务。
namespace AppBundle\Utils;
use iBasit\ToolsBundle\Utils\Lib\Container;
class myObject
{
use Container;
}
Your service settings
您的服务设置
myObject:
class: AppBundle\Utils\myObject
calls:
- [setContainer, ["@service_container"]]
Call your service in controller
在控制器中调用您的服务
$myObject = $this->get('myObject');
回答by Alain Tiemblo
If all your services are ContainerAware
, I suggest to create a BaseService class that will contain all common code with your other services.
如果您的所有服务都是ContainerAware
,我建议创建一个 BaseService 类,该类将包含您的其他服务的所有通用代码。
1) Create the Base\BaseService.php
class:
1)创建Base\BaseService.php
类:
<?php
namespace Fuz\GenyBundle\Base;
use Symfony\Component\DependencyInjection\ContainerAware;
abstract class BaseService extends ContainerAware
{
}
2) Register this service as abstract in your services.yml
2) 将此服务注册为摘要 services.yml
parameters:
// ...
geny.base.class: Fuz\GenyBundle\Base\BaseService
services:
// ...
geny.base:
class: %geny.base.class%
abstract: true
calls:
- [setContainer, [@service_container]]
3) Now, in your other services, extends your BaseService
class instead of ContainerAware
:
3)现在,在您的其他服务中,扩展您的BaseService
类而不是 ContainerAware
:
<?php
namespace Fuz\GenyBundle\Services;
use Fuz\GenyBundle\Base\BaseService;
class Loader extends BaseService
{
// ...
}
4) Finally, you can use the parent
option in your services declaration.
4) 最后,您可以parent
在服务声明中使用该选项。
geny.loader:
class: %geny.loader.class%
parent: geny.base
I prefer this way for several reasons:
我更喜欢这种方式有几个原因:
- there is consistency between the code and the config
- this avoids duplicating too much config for each service
- you have a base class for each services, very helpful for common code
- 代码和配置之间有一致性
- 这避免了为每个服务重复太多配置
- 每个服务都有一个基类,对通用代码非常有帮助