php symfony symfony-2.3

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'');