php - Cómo dar contenedor como argumento a los servicios
symfony symfony-2.3 (4)
Añadir:
<argument type="service" id="service_container" />
Y en tu clase de oyentes:
use Symfony/Component/DependencyInjection/ContainerInterface;
//...
public function __construct(ContainerInterface $container, ...) {
en mi constructor de servicios
public function __construct(
EntityManager $entityManager,
SecurityContextInterface $securityContext)
{
$this->securityContext = $securityContext;
$this->entityManager = $entityManager;
Paso entityManager y securityContext como argumento. también mi services.xml está aquí
<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" />
pero ahora, quiero usar contenedores en servicios tales como
$this->container->get(''router'')->generate(''fos_user_profile_edit'')
¿Cómo puedo pasar el contenedor a los servicios?
Es fácil, si el servicio se extiende a ContainerAware
use /Symfony/Component/DependencyInjection/ContainerAware;
class YouService extends ContainerAware
{
public function someMethod()
{
$this->container->get(''router'')->generate(''fos_user_profile_edit'')
...
}
}
service.yml
your.service:
class: App/.../YouService
calls:
- [ setContainer,[ @service_container ] ]
Si todos sus servicios son ContainerAware
, sugiero crear una clase BaseService que contendrá todos los códigos comunes con sus otros servicios.
1) Crea la clase Base/BaseService.php
:
<?php
namespace Fuz/GenyBundle/Base;
use Symfony/Component/DependencyInjection/ContainerAware;
abstract class BaseService extends ContainerAware
{
}
2) Registre este servicio como resumen en sus services.yml
parameters:
// ...
geny.base.class: Fuz/GenyBundle/Base/BaseService
services:
// ...
geny.base:
class: %geny.base.class%
abstract: true
calls:
- [setContainer, [@service_container]]
3) Ahora, en sus otros servicios, amplía su clase BaseService
lugar de ContainerAware
:
<?php
namespace Fuz/GenyBundle/Services;
use Fuz/GenyBundle/Base/BaseService;
class Loader extends BaseService
{
// ...
}
4) Finalmente, puede usar la opción parent
en su declaración de servicios.
geny.loader:
class: %geny.loader.class%
parent: geny.base
Prefiero esta manera por varias razones:
- hay consistencia entre el código y la configuración
- esto evita duplicar demasiadas configuraciones para cada servicio
- tienes una clase base para cada servicio, muy útil para el código común
Es 2016 , puedes usar un rasgo que te ayudará a extender la misma clase con múltiples bibliotecas.
<?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);
}
}
Su objeto, que será el servicio.
namespace AppBundle/Utils;
use iBasit/ToolsBundle/Utils/Lib/Container;
class myObject
{
use Container;
}
Su configuración de servicio
myObject:
class: AppBundle/Utils/myObject
calls:
- [setContainer, ["@service_container"]]
Llame a su servicio en el controlador
$myObject = $this->get(''myObject'');