2012-09-22 13 views
9

Utilizzando Symfony 2.1.3-dev e Dottrina 2.3Utilizzando entità tipo di campo in forma symfony2.1

Sto tentando di costruire una forma che forniscono diverse opzioni per un utente per filtrare una serie tornato dei dati (Entity\EngineCodes) . Il modulo è composto da 1 campo di immissione testo (id) e 3 campi di selezione (module, status). Sto tentando di utilizzare Symfony2 entity form_type per generare valori per i 3 campi di selezione dall'entità EngineCodes.

Poiché desidero filtrare la tabella utilizzando una combinazione di 3 dei campi selezionati. In base ai documenti 2.1, ho deciso di creare un FormType (EngineCodesFilterType) e impostare tre dei campi modulo su entity con le istruzioni query_builder per restituire un insieme di valori univoci per ciascuno dei campi.

Sfortunatamente, sto ricevendo l'errore di follow, e non sono esattamente sicuro del motivo per cui sta restituendo un array invece di un oggetto.

The form's view data is expected to be an instance of class 
    Vendor\IndexBundle\Entity\EngineCodes, but is a(n) array. 
    You can avoid this error by setting the "data_class" option 
    to null or by adding a view transformer that transforms a(n) 
    array to an instance of Vendor\IndexBundle\Entity\EngineCodes. 

Se ho impostato data_class a null, ricevo questo errore:

A "__toString()" method was not found on the objects of type 
    "Vendor\IndexBundle\Entity\EngineCodes" passed to the choice 
    field. To read a custom getter instead, set the option 
    "property" to the desired property path. 

Dal momento che sto ancora imparando queste caratteristiche Symfony2, il mio obiettivo era quello di abbinare i documenti 2.1 in termini di costruzione e il formato per quanto possibile.

Ecco la funzione all'interno della Controller:

public function displayAction() { 

    // ... 

    $entity = $this->getDoctrine()->getEntityManager() 
     ->getRepository('VendorIndexBundle:EngineCodes') 
     ->findAll(); 

    // ... 

    $form = $this->createForm(new EngineCodesFilterType(), $entity); 

    // ... 

    return $this->render(
     'VendorIndexBundle::layout.html.twig', 
     array(
      'entity' => $entity, 
      'form' => $form->createView(),)); 

Ecco il tipo di modulo:

class EngineCodesFilterType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add(
      'id', 
      'integer', 
      array(
       'label' => 'Code ID',)); 
     $builder->add(
      'status', 
      'entity', 
      array(
       'label' => 'Code Status', 
       'class' => 'VendorIndexBundle:EngineCodes', 
       'query_builder' => function(EntityRepository $er) 
        { 
         return $er->createQueryBuilder('u') 
          ->select('u.status') 
          ->add('groupBy', 'u.status'); 
        }, 
       'multiple' => true,)); 
     $builder->add(
      'type', 
      'entity', 
      array(
       'label' => 'Code Type', 
       'class' => 'VendorIndexBundle:EngineCodes', 
       'query_builder' => function(EntityRepository $er) 
        { 
         return $er->createQueryBuilder('u') 
          ->select('u.type') 
          ->add('groupBy' ,'u.type'); 
        }, 
       'multiple' => true,)); 
     $builder->add(
      'module', 
      'entity', 
      array(
       'label' => 'Code Module', 
       'class' => 'VendorIndexBundle:EngineCodes', 
       'query_builder' => function(EntityRepository $er) 
        { 
         return $er->createQueryBuilder('u') 
          ->select('u.module') 
          ->add('groupBy', 'u.module'); 
        }, 
       'multiple' => true,)); 
    } 

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

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(
      array(
       'data_class'  => 'Vendor\IndexBundle\Entity\EngineCodes', 
       /*'data_class'  => null,*/ 
       'validation_groups' => 'filter',)); 
    } 
} 

E qui è la classe Vendor\Entity\EngineCodes:

/** 
* Vendor\IndexBundle\Entity\EngineCodes 
* 
* @ORM\Table(name="engine_codes") 
* @ORM\Entity(repositoryClass="Vendor\IndexBundle\Entity\EngineCodesRepository") 
* @UniqueEntity(fields="id", message="ID already in use! Enter a unique ID for the code.") 
*/ 
class EngineCodes 
{ 
    /** 
    * @var integer $id 
    * 
    * @ORM\Column(name="id", type="integer", nullable=false, unique=true) 
    * @ORM\Id 
    * @Assert\NotBlank(message="ID cannot be blank!") 
    * @Assert\Regex(pattern="/^\d+$/", match=true, message="ID must be an integer!") 
    * @Assert\MinLength(limit=8, message="ID must be 8 numbers in length!") 
    * @Assert\MaxLength(limit=8, message="ID must be 8 numbers in length!") 
    */ 
    private $id; 

    /** 
    * @var string $token 
    * 
    * @ORM\Column(name="token", type="string", length=255, nullable=false, unique=true) 
    */ 
    private $token; 

    /** 
    * @var boolean $status 
    * 
    * @ORM\Column(name="status", type="integer", nullable=false) 
    * @Assert\NotBlank(message="Status cannot be blank!") 
    */ 
    private $status; 

    /** 
    * @var string $module 
    * 
    * @ORM\Column(name="module", type="string", length=255, nullable=false) 
    * @Assert\NotBlank(message="Module cannot be blank!") 
    */ 
    private $module; 

    /** 
    * @var string $submodule 
    * 
    * @ORM\Column(name="submodule", type="string", length=255, nullable=false) 
    * @Assert\NotBlank(message="Submodule cannot be blank!") 
    */ 
    private $submodule; 

    /** 
    * @var string $type 
    * 
    * @ORM\Column(name="type", type="string", length=255, nullable=false) 
    * @Assert\NotBlank(message="Type cannot be blank!") 
    */ 
    private $type; 

    /** 
    * @var string $description 
    * 
    * @ORM\Column(name="description", type="text", nullable=false) 
    * @Assert\NotBlank(message="Description cannot be blank!") 
    */ 
    private $description; 

    /** 
    * @var string $title 
    * 
    * @ORM\Column(name="title", type="string", length=255, nullable=false) 
    * @Assert\NotBlank(message="Title cannot be blank!") 
    */ 
    private $title; 

    /** 
    * @var string $definition 
    * 
    * @ORM\Column(name="definition", type="text", nullable=true) 
    */ 
    private $definition; 

    /** 
    * @var string $color 
    * 
    * @ORM\Column(name="color", type="string", length=10, nullable=true) 
    */ 
    private $color; 

    /** 
    * @var \DateTime $createTimestamp 
    * 
    * @ORM\Column(name="create_timestamp", type="datetime", nullable=false) 
    */ 
    private $createTimestamp; 

    /** 
    * @var Accounts 
    * 
    * @ORM\ManyToOne(targetEntity="Accounts") 
    * @ORM\JoinColumns({ 
    * @ORM\JoinColumn(name="create_account_fk", referencedColumnName="id") 
    * }) 
    */ 
    private $createAccountFk; 


    // getters and setters ... 

    /** 
    * Set createAccountFk 
    * 
    * @param Vendor\IndexBundle\Entity\Accounts $createAccountFk 
    * @return EngineCodes 
    */ 
    public function setCreateAccountFk(\Vendor\IndexBundle\Entity\Accounts $createAccountFk = null) 
    { 
     $this->createAccountFk = $createAccountFk; 

     return $this; 
    } 

    /** 
    * @ORM\PrePersist 
    */ 
    public function setCreateTimestampValue() 
    { 
     $this->createTimestamp = new \DateTime(); 
    } 
} 

risposta

14

tuo primo problema è che $entity non è una singola entità, ma piuttosto un array di entità (che è ciò che viene restituito dal metodo findAll()). Quando hai definito il tipo di modulo, hai detto che ti aspettavi di creare il modulo da un'entità (questo è l'opzione data_class) ed è per questo che ottieni il primo errore.

Se si imposta data_class su null, si sta dicendo che non ci si aspetta che il modulo venga creato da un'entità, quindi accetterà l'array di entità e non si lamenterà. Ma, perché stai passando una serie di entità al tipo di modulo? Questo è solo un modulo di filtro che ti permette di scegliere quattro possibili valori per filtrare le tue entità. Questo non ha bisogno di una serie di entità come i suoi dati sottostanti. Se pensi di averne bisogno per ottenere i valori per il codice, i campi di tipo e di stato, questo non è così come sono già stati recuperati con i tuoi creatori di query. Quindi, il codice di controllo dovrebbe essere solo:

public function displayAction() { 

// ... 

$entity = $this->getDoctrine()->getEntityManager() 
    ->getRepository('VendorIndexBundle:EngineCodes') 
    ->findAll(); 

// ... 

$form = $this->createForm(new EngineCodesFilterType()); 

// ... 

return $this->render(// ... 

poi si ottiene l'altro errore, perché si sta aggiungendo tre campi del modulo e ognuno consente di scegliere da un elenco di entità. Ma come "mostri" questa entità? Symfony non sa quale campo dovrebbe mostrare per rappresentare l'entità, quindi genera questo errore.

Questo errore può essere risolto aggiungendo un metodo __toString() alla classe EngineCodes, che dice semplicemente "hey, questo come voglio mostrare questa classe", ma anche se l'errore non verrà generato non funzionerà come previsto poiché ciascuno dei tre campi vuole mostrare una proprietà diversa.

Un'altra soluzione consiste nell'utilizzare l'opzione property del campo modulo per indicare quale proprietà dell'oggetto sottostante si desidera utilizzare per visualizzare i dati.

Ad esempio:

$builder->add(
     'status', 
     'entity', 
     array(
      'label' => 'Code Status', 
      'class' => 'VendorIndexBundle:EngineCodes', 
      'property' => 'status' 
      'query_builder' => function(EntityRepository $er) 
       { 
        return $er->createQueryBuilder('u') 
         ->select('u.status') 
         ->add('groupBy', 'u.status'); 
       }, 
      'multiple' => true,)); 
+1

+1 per trovare l'errore dell'array. – gremo

+1

Ahhhh, ha perfettamente senso non applicare la mia matrice di entità al modulo. Grazie per questa osservazione. –

+0

E ora sembra che le mie istruzioni query_builder non stiano restituendo matrici/oggetti ma piuttosto interi e stringhe. Devo rivedere con occhi nuovi al mattino. –

11

Siete semplicemente manca il property option nei tipi di entità "status", "type" e "module":

property

type: string

This is the property that should be used for displaying the entities as text in the HTML element. If left blank, the entity object will be cast into a string and so must have a __toString() method.

+2

Grazie per l'osservazione. È divertente come camminare per un'ora e poi tornare aiuta a chiarire il messaggio di errore. –

Problemi correlati