2012-03-03 7 views
5

questo è più di un 'best practice' questione di un problema reale:Symfony2 dati che passano tra fasci e controller

Sto lavorando su un progetto in Symfony 2 e ho costruito un pacchetto per gestire tutte i miei servizi web Fondamentalmente un controllore prende alcuni dati JSON, li invia a un altro controllore per verificare che corrisponda a un formato descritto, quindi off a un altro controller per gestire le chiamate al database e infine tornare al controller iniziale per restituire una risposta JSON.

che sto invio di dati tra i controllori facendo qualcosa di simile a questo:

$controller = new \Acme\myBundle\Controller\DefaultController; 
$response = $controller->function(); 

Questo funziona correttamente, ma io continuo a tutto un problema. Nel controller passano i dati a Ho bisogno di istanziare AppKernel e chiamare la funzione di avvio per far funzionare qualsiasi funzione di Symfony. Questo per me sembra un po 'sciocco che mi porta a credere che stia sbagliando tutto questo.

Qualsiasi suggerimento o suggerimento apprezzato!

MODIFICA/AGGIORNAMENTO Grazie a tutti per i commenti. Ho configurato i miei controller come servizi, i servizi funzionano ma ho ancora bisogno di avviare/istanziare manualmente il kernel quando chiamo un servizio da un servizio.

#config.yml 
# API Services 
services: 
service.handler: 
    class: Acme\APIBundle\Controller\ServicesController 
    arguments: 
     container: "@service_container" 

service.definitions: 
    class: Acme\APIBundle\Controller\DefinitionController 
    arguments: 
     container: "@service_container" 

Da un altro controller fasci posso quindi chiamare una funzione da uno di questi servizi senza problemi:

$test = $this->get("service.handler")->testFunction(); 
$test2 = $this->get("service.definitions")->anotherTestFunction(); 

Dove ho un problema è se io chiamo una funzione all'interno di un servizio, allora provare a chiamare un altro servizio da dentro quel servizio ricevo il seguente errore PHP

Fatal error: Call to a member function get() on a non-object in /vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php on line 188 

posso evitare tale errore utilizzando questa funzione e chiamandolo piuttosto che utilizzare questo $

public function bootKernel(){ 
//boot kernel 
    $controller = new \Acme\myBundle\Controller\DefaultController; 
    $kernel = new \AppKernel('dev', true);$kernel->loadClassCache(); 
    $kernel->boot(); 
    $controller->setContainer($kernel->getContainer()); 
    return($controller);  
} 

Suppongo che la mia soluzione "funzioni", ma certamente non sembra un modo efficace per fare le cose.

EDIT 2: Se mi attengo questo al vertice della classe quindi modificare il servizio di chiamata sembra funzionare ... Ancora non so se questo è il modo migliore di fare le cose.

protected $container; 

public function __construct($container) { 
    $this->container= $container; 
} 
+1

Penso che [l'inoltro] (http://symfony.com/doc/current/book/controller.html#forwarding) possa essere un'opzione qui. –

+3

C'è un motivo per cui non stai utilizzando [servizi] (http://symfony.com/doc/current/cookbook/controller/service.html) per gestire i tuoi diversi metodi? – richsage

risposta

10

Vorrei andare lungo il percorso controller-as-a-service con quanto sopra. Supponi di dover chiamare 3 metodi come parte del tuo processo. Chiamiamoli foo(), bar() e something(). Ciascuno di questi metodi sono in controller separati:

namespace Acme\DemoBundle\Controller; 

class FooController 
{ 
    public function __construct($container, ...) 
    { 
     $this->container = $container; 
     // ... deal with any more arguments etc here 
    } 

    public function foo($params) 
    { 
     // ... 
     return $x; 
    } 

    protected function get($service) 
    { 
     return $this->container->get($service); 
    } 
} 

Idem per i metodi bar() e something(), ciascuno nel proprio controllore. Quindi, aggiungili alla tua applicazione come servizio.Ad esempio, nei tuoi config.yml (altri metodi disponibili):

services: 
    my.foo.service: 
     class: Acme\FooBundle\Controller\FooController 
     arguments: 
      container: "@service_container" 

Vedere la documentazione Symfony per more details su come è possibile costruire questa voce, tra cui l'iniezione di tutte le dipendenze come ad esempio un gestore di entità o simili. Ora, è possibile ottenere un'istanza di questo dal contenitore:

public function yourMainAction() 
{ 
    // ... 

    $newData = $this->get("my.foo.service")->fooAction($someData); 

    // ... 

    return new Response(json_encode($newData), ...); 
} 

Allo stesso modo nuovo per BarController e SomethingController. Il vantaggio ora è che questo servizio può essere reso disponibile in qualsiasi punto dell'applicazione (sia tramite il contenitore come sopra, sia come servizio inserito), attraverso i bundle, senza la necessità di istanziare manualmente la classe e fornire eventuali dipendenze.

Per ulteriori informazioni sul contenitore ecc., I documenti Symfony hanno un good section su di esso (a cui si fa riferimento nel link sopra).

Modifica: modificato l'esempio di codice per includere dettagli sul passaggio degli argomenti nel servizio. Aggiunto anche un comodo metodo get() per recuperare i servizi dal contenitore.

+0

Grazie per la risposta, Rich. In realtà ho tentato di utilizzare i controller come servizi ma ho incontrato lo stesso identico problema. Se chiamo un controller come servizio, allora da dentro quel controller chiamo un altro controller come servizio, devo comunque riavviare il kernel ogni volta. Ho letto i documenti e non sono del tutto sicuro di quali "dipendenze" devo impostare per evitare di eseguire la mia funzione di avvio ogni volta. – greg

+0

Senza istanziare il kernel ottengo questo errore: Errore irreversibile: chiamata a una funzione membro get() su un oggetto non in/Users/greg/Repos/Acme/vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php sulla linea 188 – greg

+0

I tuoi pacchetti sono stati aggiunti correttamente al tuo kernel? All'interno di 'AppKernel.php'? Dovrebbero essere avviati automaticamente se li hai aggiunti qui. – richsage

1

Suggerisco di utilizzare il controller come service.

Problemi correlati