2012-09-22 5 views
9

Mit Symfony 2.1.3-dev und Lehre 2.3Verwendung Entität Feldtyp in Form symfony2.1

Ich versuche, eine Form zu bauen, die für einen Benutzer mehr Optionen bietet einen zurück Satz von Daten zu filtern (Entity\EngineCodes) . Das Formular besteht aus 1 Texteingabefeld (id) und 3 Auswahlfeldern (module, type, status). Ich versuche, den Symfony2 entity form_type zu verwenden, um Werte für die 3 Auswahlfelder von der EngineCodes Einheit zu generieren.

Da ich die Tabelle mit einer Kombination von 3 der Auswahlfelder filtern möchten. Basierend auf den 2.1-Dokumenten entschied ich mich, einen FormType (EngineCodesFilterType) zu erstellen und drei der Formularfelder auf entity Typ mit query_builder-Anweisungen festzulegen, um eine Reihe von eindeutigen Werten für jedes der Felder zurückzugeben.

Leider erhalte ich den folgenden Fehler, und ich bin nicht genau sicher, warum es ein Array anstelle eines Objekts zurückgibt.

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. 

Wenn ich gesetzt data_class zu null, erhalte ich diesen Fehler:

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. 

Da ich noch diese Symfony2 Funktionen zu lernen, ist mein Ziel, die 2.1-Dokumentation in Bezug auf die Konstruktion und das Format anzupassen war so viel wie möglich. Hier

ist die Funktion im 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(),)); 

Hier ist die Form, Typ:

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

Und hier ist die Vendor\Entity\EngineCodes Klasse:

/** 
* 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(); 
    } 
} 

Antwort

14

Ihr erstes Problem ist, dass $entity nicht eine einzige Einheit ist, sondern eine Reihe von Unternehmen (das ist, was durch die findAll() Methode zurückgegeben wird). Als Sie den Formulartyp definierten, sagten Sie, dass Sie das Formular von einer Entität erstellen wollten (das ist die Option data_class) und deshalb erhalten Sie den ersten Fehler.

Wenn Sie auf null setzen, sagen Sie, dass Sie nicht erwarten, dass das Formular von einer Entität erstellt wird, so dass es Ihr Array von Entitäten akzeptiert und sich nicht beschwert. Warum übergeben Sie ein Array von Entitäten an den Formulartyp? Dies ist nur ein Filterformular, mit dem Sie vier mögliche Werte auswählen können, um Ihre Entitäten zu filtern. Dies benötigt kein Array von Entitäten als zugrundeliegende Daten. Wenn Sie meinen, dass Sie die Werte für die Code-, Typ- und Statusfelder benötigen, ist dies nicht so, wie sie bereits mit Ihren Abfrage-Buildern abgerufen wurden. So sollte Ihr Controller-Code einfach sein:

public function displayAction() { 

// ... 

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

// ... 

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

// ... 

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

Dann Sie die anderen Fehler, weil Sie drei Formularfelder hinzufügen, und jeder können Sie von einer Entität Liste auswählen. Aber wie "zeig" du diese Entität? Symfony weiß nicht, in welchem ​​Feld die Entität angezeigt werden soll. Daher wird dieser Fehler ausgegeben.

Dieser Fehler könnte durch Hinzufügen einer __toString() -Methode zu der EngineCodes-Klasse behoben werden, die nur sagt "hey, so wie ich diese Klasse zeigen möchte", aber obwohl der Fehler nicht geworfen wird, wird es nicht funktionieren erwartet, da jedes der drei Felder eine andere Eigenschaft anzeigen möchte.

Eine andere Lösung besteht darin, mit der property-Option des Formularfelds anzugeben, welche Eigenschaft des zugrunde liegenden Objekts zur Anzeige der Daten verwendet werden soll.

Zum Beispiel:

$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 zum Finden des Array-Fehlers. – gremo

+1

Ahhhh, es macht absolut Sinn, mein Array von Entitäten nicht auf das Formular anzuwenden. Danke für diese Beobachtung. –

+0

Und jetzt scheint es, dass meine query_builder-Anweisungen keine Arrays/Objekte zurückgeben, sondern Ganzzahlen und Strings. Ich werde morgen mit frischen Augen wiederkommen müssen. –

11

Sie einfach fehlen die property option in den Entity-Typen "status", "type" und "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

Danke für die Beobachtung. Lustig, wie man für eine Stunde weggeht und dann zurückkommt, hilft die sehr klare Fehlermeldung sinnvoller. –