2012-07-13 25 views
9

Estoy tratando de encontrar una forma de utilizar el Symfony 2 Dependency Injection component con el nuevo PHP 5.4 traits.Symfony 2: inyección de dependencia y rasgos

Para resumir una historia corta (no tan corta, en realidad), mi proyecto ha desacoplado clases de vista que tienen su propio constructor específico. Cada vista puede utilizar cero o más ayudantes de vista, que se definen como rasgos:

trait TranslatorHelper 
{ 
    /** 
    * @var Translator 
    */ 
    protected $translator; 

    /** 
    * @param Translator $translator 
    */ 
    protected function setTranslator(Translator $translator) 
    { 
     $this->translator = $translator; 
    } 

    /** 
    * @param string $text 
    * @return string 
    */ 
    public function translate($text) 
    { 
     return $this->translator->translate($text); 
    } 
} 

-

class UserEditView extends AbstractView 
{ 
    use TranslatorHelper; 

    public function __construct(User $user, UserEditForm $form) 
    { 
     // ... 
    } 
} 

Me gustaría tener un método en mi controlador, renderView(), que realiza colocador inyección en base a todos los rasgos utilizados por la clase View, antes de renderizar la vista:

class Controller 
{ 
    public function renderView(View $view) 
    { 
     // Check what traits are used by $view, and inject their dependencies 
     // {...} 


     // Then render the View 
     return $view->render(); 
    } 
} 

Cualquier idea sobre cómo hacer esto con el DependencyInjection componente?

El problema principal es, obviamente, que las vistas no serán creadas por el contenedor DI, sino que se pueden crear en cualquier lugar del flujo de la aplicación. Es solo antes de que se procesen que las dependencias deben ser inyectadas.

Una última nota: no estoy vinculado al componente de Symfony. También se apreciaría cualquier ventaja en otro contenedor DI.

+0

Puede intentar DI con AOP: https://github.com/schmittjoh/JMSAopBundle/blob/master/Resources/doc/index.rst para inyectar automáticamente servicios mediante anotación de propiedades y argumentos. – lisachenko

+0

El problema es que quería mantener los helpers de visualización (como 'TranslatorHelper') genéricos, por lo que idealmente no deberían contener el id. Específico del proyecto de las dependencias en el contenedor. – Benjamin

Respuesta

4

Creo que los rasgos no están destinados a ser utilizados para hacer DI de esta manera. Lo que haría en un escenario similar es usar inyección de constructor (o incluso setter estaría bien, incluso el constructor resistente es mejor cuando sea posible) en la clase de vista que implementa rasgos para inyectar directamente los servicios necesarios.

Si considera que los rasgos implementados por una clase están definidos estáticamente antes de que la aplicación se ejecute, no necesita inspeccionar los rasgos para realizar una inyección dinámica. Sabrá qué servicios necesita antes de ejecutar, solo piense en los rasgos como si fueran interfaces con algún método concreto.

+0

Entiendo su punto, sin embargo mi preocupación es que quiero mantener el constructor de Vista libre de cualquier dependencia específica de Helper (quiero que el controlador use explícitamente el constructor de Vista para pasar solo las variables que necesita la vista en sí, sin tener que preocuparse por los ayudantes). Además, probablemente tendré cientos de clases de Vista, todas usando los mismos ~ 3 asistentes de visualización. Por lo tanto, prefiero poder inyectar según el nombre de Trait. Por ejemplo, me gustaría definir en mi configuración que todas las clases que usan el rasgo 'TranslatorHelper' usarían el traductor señalado por la tecla del contenedor' traductor'. – Benjamin

+3

En ese caso, lo que podría hacer es usar el etiquetado DI: defina una etiqueta y un compilador que registre la dependencia del instalador correcto para cada rasgo de ayudante. Se ha publicado recientemente en la documentación de Symfony cierta documentación sobre el uso avanzado de DIC (como los pases y las etiquetas del distribuidor). No se inyecta automáticamente en función del rasgo (creo que la única manera de hacerlo sería utilizando la reflexión que es bastante lenta) pero es bastante ordenado y limpio. –

Cuestiones relacionadas