2012-09-22 19 views
9

Sử dụng Symfony 2.1.3-dev và Doctrine 2.3Sử dụng loại lĩnh vực tổ chức theo hình thức symfony2.1

Tôi đang cố gắng để xây dựng một hình thức cung cấp nhiều tùy chọn cho người dùng để lọc một tập trở lại của dữ liệu (Entity\EngineCodes) . Biểu mẫu bao gồm 1 trường nhập văn bản (id) và 3 trường chọn (module, type, status). Tôi đang cố gắng sử dụng Symfony2 entity form_type để tạo giá trị cho 3 trường chọn từ thực thể EngineCodes.

Vì tôi muốn lọc bảng bằng cách kết hợp bất kỳ 3 trường nào trong số các trường được chọn. Dựa trên tài liệu 2.1, tôi quyết định tạo FormType (EngineCodesFilterType) và đặt ba trường biểu mẫu thành entity nhập với câu lệnh query_builder để trả về một tập hợp các giá trị duy nhất cho từng trường.

Thật không may, tôi nhận được lỗi theo dõi và tôi không chắc chắn lý do tại sao nó trả về mảng thay vì một đối tượng.

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. 

Nếu tôi đặt data_class để null, tôi nhận được lỗi này:

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. 

Kể từ khi tôi vẫn đang học các tính năng này Symfony2, mục tiêu của tôi là để phù hợp với 2.1 tài liệu về xây dựng và định dạng Càng nhiều càng tốt.

Dưới đây là chức năng trong Bộ điều khiển:

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(),)); 

Đây là loại hình thức:

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

Và đây là lớp 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(); 
    } 
} 

Trả lời

14

vấn đề đầu tiên của bạn là $entity không phải là một thực thể duy nhất, mà là một mảng của các đơn vị (đó là những gì được trả về bởi phương pháp findAll()). Khi bạn xác định loại biểu mẫu, bạn đã nói rằng bạn dự kiến ​​sẽ tạo biểu mẫu từ một thực thể (đó là tùy chọn data_class dành cho) và đó là lý do bạn nhận được lỗi đầu tiên.

Nếu bạn đặt data_class thành không, bạn đang nói rằng bạn không mong đợi biểu mẫu được tạo từ một thực thể, vì vậy nó sẽ chấp nhận mảng thực thể của bạn và không phàn nàn. Nhưng, tại sao bạn lại truyền một mảng các thực thể tới kiểu biểu mẫu? Đây chỉ là một hình thức lọc cho phép bạn chọn bốn giá trị có thể để lọc các thực thể của bạn. Điều này không cần một mảng các thực thể như là dữ liệu cơ bản của nó. Nếu bạn nghĩ rằng bạn cần nó để có được các giá trị cho các trường mã, loại và trạng thái, đây không phải là vì chúng đã được tìm nạp với trình tạo truy vấn của bạn. Vì vậy, mã điều khiển của bạn phải là:

public function displayAction() { 

// ... 

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

// ... 

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

// ... 

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

Sau đó, bạn gặp lỗi khác vì bạn đang thêm ba trường biểu mẫu và mỗi trường cho phép bạn chọn từ danh sách đối tượng. Nhưng, làm thế nào để bạn "hiển thị" thực thể này? Symfony không biết trường nào sẽ hiển thị cho bạn để biểu diễn thực thể, vì vậy nó sẽ ném lỗi này.Lỗi này có thể được sửa bằng cách thêm phương thức __toString() vào lớp EngineCodes, chỉ nói "hey, đây là cách tôi muốn hiển thị lớp này", nhưng mặc dù lỗi sẽ không được ném, nó sẽ không hoạt động như dự kiến ​​vì mỗi một trong ba trường muốn hiển thị một thuộc tính khác.

Một giải pháp khác là sử dụng tùy chọn property của trường biểu mẫu để cho biết thuộc tính nào của đối tượng bên dưới bạn muốn sử dụng để hiển thị dữ liệu.

Ví dụ:

$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 để tìm lỗi mảng. – gremo

+1

Ahhhh, có nghĩa là không áp dụng mảng thực thể của tôi cho biểu mẫu. Cảm ơn vì sự quan sát đó. –

+0

Và bây giờ nó xuất hiện câu lệnh query_builder của tôi không trả về mảng/đối tượng mà là các số nguyên và chuỗi. Gonna phải quay lại với đôi mắt tươi sáng vào buổi sáng. –

11

Bạn chỉ đơn giản là mất tích property option trong các loại thực thể "trạng thái", "loại" và "mô-đun":

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

Cảm ơn đã quan sát. Buồn cười như thế nào đi bộ trong một giờ và sau đó trở lại giúp thông báo lỗi rất rõ ràng có ý nghĩa hơn. –

Các vấn đề liên quan