2013-04-05 12 views
6

Sto cercando di popolare una casella di scelta in symfony2 con i valori di una query personalizzata. Ho cercato di semplificare il più possibile.symfony2 - aggiunta di scelte dal database

controller

class PageController extends Controller 
{ 

    public function indexAction() 
    { 
     $fields = $this->get('fields'); 
     $countries = $fields->getCountries(); // returns a array of countries e.g. array('UK', 'France', 'etc') 
     $routeSetup = new RouteSetup(); // this is the entity 
     $routeSetup->setCountries($countries); // sets the array of countries 

     $chooseRouteForm = $this->createForm(new ChooseRouteForm(), $routeSetup); 


     return $this->render('ExampleBundle:Page:index.html.twig', array(
     'form' => $chooseRouteForm->createView() 
    )); 

    } 
} 

ChooseRouteForm

class ChooseRouteForm extends AbstractType 
{ 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 

    // errors... ideally I want this to fetch the items from the $routeSetup object 
    $builder->add('countries', 'choice', array(
     'choices' => $this->routeSetup->getCountries() 
    )); 

    } 

    public function getName() 
    { 
    return 'choose_route'; 
    } 
} 

risposta

18

È possibile passare le scelte per il vostro modulo utilizzando ..

$chooseRouteForm = $this->createForm(new ChooseRouteForm($routeSetup), $routeSetup); 

Poi nel modulo ..

private $countries; 

public function __construct(RouteSetup $routeSetup) 
{ 
    $this->countries = $routeSetup->getCountries(); 
} 

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder->add('countries', 'choice', array(
     'choices' => $this->countries, 
    )); 
} 

aggiornamento (e migliorato) per 2.8 o successiva

In primo luogo non si ha realmente bisogno di passare nei paesi come parte dell'oggetto percorso a meno che non stanno per essere memorizzati nel DB.

Se si memorizzano i paesi disponibili nel DB, è possibile utilizzare un listener di eventi. In caso contrario (o se non si desidera utilizzare un listener) è possibile aggiungere i Paesi nell'area delle opzioni.

Uso delle opzioni

Nel controllore ..

$chooseRouteForm = $this->createForm(
    ChooseRouteForm::class, 
    // Or the full class name if using < php 5.5 
    $routeSetup, 
    array('countries' => $fields->getCountries()) 
); 

E nel modulo ..

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder->add('countries', 'choice', array(
     'choices' => $options['countries'], 
    )); 
} 

public function configureOptions(OptionsResolver $resolver) 
{ 
    $resolver 
     ->setDefault('countries', null) 
     ->setRequired('countries') 
     ->setAllowedTypes('countries', array('array')) 
    ; 
} 

Uso di un listener (se i paesiarray è disponibile nel modello)

Nel controllore ..

$chooseRouteForm = $this->createForm(
    ChooseRouteForm::class, 
    // Or the full class name if using < php 5.5 
    $routeSetup 
); 

E nel modulo ..

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) { 
      $form = $event->getForm(); 
      /** @var RouteSetup $routeSetup */ 
      $routeSetup = $event->getData(); 

      if (null === $routeSetup) { 
       throw new \Exception('RouteSetup must be injected into form'); 
      } 

      $form 
       ->add('countries', 'choice', array(
        'choices' => $routeSetup->getCountries(), 
       )) 
      ; 
     }) 
    ; 
} 
+1

Quindi, a partire da Symfony 2.8, è deprecato passare in una classe di modulo istanziata. Ora è necessario passare il nome completo della classe. Che toglie di essere in grado di usare il costruttore ... Questo fa schifo, perché non voglio dover caricare le opzioni dal controller come nel mio caso, questo campo di scelta è usato da molti controller e avrebbe senso costruire le scelte nella classe del modulo, tuttavia, come si ottiene il doctrine manager nella classe form senza utilizzare le opzioni oi servizi ...? Hack Hack Hack, a meno che non manchi qualcosa, per favore dimmi così – Prof83

+1

A dire il vero questo non era il miglior approccio neanche allora. Aggiornerò – qooplmao

+0

Nessun problema, il tuo post è stato il 2013 e 2.8 è come pochi mesi fa. Grazie per l'aggiornamento ... Non riesco a giocarci adesso – Prof83

10

non posso commentare o downvote ancora, quindi mi limiterò a rispondi alla risposta di Qoop qui: Ciò che hai proposto funzionerà, a meno che tu non inizi a utilizzare la classe del tipo di modulo come servizio. In generale, si dovrebbe evitare di aggiungere dati all'oggetto del tipo di modulo tramite il costruttore.

Pensate tipo di modulo classe come un Classe - è una sorta di descrizione del modulo. Quando si crea un'istanza di (costruendola) si ottiene l'oggetto di modulo creato dalla descrizione nel tipo di modulo e quindi riempito con i dati.

Date un'occhiata a questo: http://www.youtube.com/watch?v=JAX13g5orwo - questa situazione è descritta attorno al 31 minuto della presentazione.

È necessario utilizzare form evento FormEvents :: PRE_SET_DATA e manipolare i campi quando il modulo viene iniettato con i dati. Vedi: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#customizing-your-form-based-on-the-underlying-data

+1

Qual è il vantaggio di questo? Perché non controllare solo se i Dati modulo '$ routesetup' sono impostati? E se no non aggiungi il campo/fai un bel errore? – user2019515

+0

Questo era l'approccio migliore, ho appena corretto il codice nella domanda per farlo funzionare piuttosto che "migliorarlo" a. Ho aggiornato la mia risposta ora con l'approccio PRE_SET_DATA menzionato e un altro (a causa di un nuovo commento, a differenza del fatto che sono un pazzo che rilegge la mia risposta di 2 anni fa). – qooplmao

Problemi correlati