2013-07-29 39 views
8

Tôi có 3 đơn vị:Symfony2 Form Builder Chọn Across Tham Bảng với Metadata

[Member] ----OneToMany----> [MemberCategory] ---ManyToOne---> [Category] 

này hoạt động kết quả cũng như xa như quyến rũ từ cơ sở dữ liệu, nhưng tôi không thể nhận được Form Builder để xây dựng một hình thức chính xác điều khiển.

Tôi muốn danh sách tất cả các danh mục có hộp kiểm được chọn cho các danh mục được thành viên sử dụng. Cuối cùng tôi muốn thêm trường ưu tiên.

Member

class Member 
{ 
    protected $id; 

    @ORM\OneToMany(targetEntity="MemberCategory", mappedBy="member") 
    protected $categories; 
} 

Thể loại

class Category 
{ 
    protected $id; 

    @ORM\Column(name="category_name", type="string", length=50, nullable=false, unique=true) 
    private $categoryName; 
} 

MemberCategory

class MemberCategory 
{ 
    @ORM\Id 
    @ORM\ManyToOne(targetEntity="Member") 
    @ORM\JoinColumns({ 
    @ORM\JoinColumn(name="member_id", referencedColumnName="id", onDelete="CASCADE") 
    private $member; 

    @ORM\Id 
    @ORM\ManyToOne(targetEntity="Category") 
    @ORM\JoinColumns({ 
    @ORM\JoinColumn(name="category_id", referencedColumnName="id", onDelete="CASCADE") 
    private $category; 

    @ORM\Column(name="priority", type="integer", nullable=true) 
    protected $priority; 
} 

att hiển nhiên trao đổi với trình tạo biểu mẫu không hoạt động.

Nếu tôi sử dụng:

$builder->add('categories', 'entity', array(
    'class'  => 'SMWMemberBundle:Category', 
    'property'  => 'categoryName', 
    'multiple'  => true, 
    'expanded'  => true, 
    'required'  => false 
)); 

tôi nhận được một lựa chọn với tất cả các loại, nhưng không ai trong số những người được chọn trong MemberCategory cho thành viên này.

Nếu tôi sử dụng:

$builder->add('categories', 'entity', array(
    'class'  => 'SMWMemberBundle:MemberCategory', 
    'property'  => 'category.categoryName', 
    'multiple'  => true, 
    'expanded'  => true, 
    'required'  => false 
)); 

tôi nhận được tất cả các loại lựa chọn cho tất cả người dùng.

Có ai biết cách làm việc này không, đây là một mô hình phổ biến rõ ràng trong dữ liệu quan hệ và sẽ dễ dàng sử dụng SQL và PHP.

Có giải pháp chuyển tiếp thẳng trong Symfony 2.3 và Doctrine không?

Trả lời

1

Bạn sẽ cần phải sử dụng querybuilder bên trong hình thức của bạn

$builder->add('categories', 'entity', array(
     'class' => 'SMWMemberBundle:MemberCategory', 
     'property'  => 'category.categoryName', 
     'query_builder' => function(EntityRepository $er) use (?) { 
      return $er->createQueryBuilder(?) 

      // your query with a left join probably 

     } 
     'multiple'  => true, 
     'expanded'  => true, 
     'required' => false 
    )); 

Xem tài liệu hướng dẫn sử dụng thích hợp. xem symfony2 form querybuilder with parameters để biết số tiền

+0

Vui lòng điền của bạn câu trả lời, như phần chính được nhận xét trong câu trả lời của bạn – Trix

3

Đây là cách tôi giải quyết vấn đề này trong quá khứ (áp dụng cho ví dụ của bạn) nhưng đây là những gì tôi đã tìm ra để có thể không phù hợp với trường hợp của bạn.

Đầu tiên tạo ra một loại MemberCategory hình thức phù hợp với nhu cầu của bạn:

<?php  
namespace Company\YourBundle\Form\Type; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

class MemberCategoryType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('priority') 
      ->add('category', 'entity', 
        array('property' => 'name', 
         'class' => 'CompanyYourBundle:Category')) 
     ; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'Company\YourBundle\Entity\MemberCategory' 
     )); 
    } 

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

Sau đó thêm loại hình thức này bên trong hình thức Member kiểu của bạn:

<?php 

namespace Company\YourBundle\Form\Type; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

class MemberType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('name') 
      ->add('members', 'collection', array(
       'type' => new MemberCategoryType(), 
       'allow_add' => true, 
       'allow_delete' => true, 
       'by_reference' => false,)); 
     ; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'Company\YourBundle\Entity\Member' 
     )); 
    } 

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

Sau đó, bạn có thể làm theo the documentation để thêm bao nhiêu loại như bạn muốn các thành viên của bạn và chỉ định ưu tiên mỗi lần.

+0

Tài liệu làm cho nó xuất hiện rằng việc thêm và xóa các danh mục sẽ là một lượng lớn rắc rối, thậm chí liên quan đến mã phía máy khách. Đó có phải là trường hợp hoặc tôi đang hiểu sai tài liệu? –

+0

Bạn đọc nó ngay! Đó là cách tôi đã làm nó, không chắc chắn đó là cách tho tốt nhất. Tôi cũng sẽ xem xét các câu trả lời khác vì tôi đồng ý với bạn về điều này là một mẫu chung mà không có bất kỳ tài liệu rõ ràng nào trên trang web chính thức. – cheesemacfly

+1

Cảm ơn, tài liệu Doctrine mô tả cách xử lý vấn đề này từ phía thực thể trong http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html (xem trường hợp sử dụng 3). Nhưng họ không cung cấp gì về việc sử dụng nó với một biểu mẫu Symfony. –

0

Bài đăng cheesemacfly không quá tệ, nhưng nó được gọi là dạng nhúng và có thể phức tạp để quản lý. Trong thực tế, bạn jus cần phải tạo ra một "Custom Repositories" http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes

Nó sẽ thêm một phương pháp mới để "lấy" đối tượng ORM của bạn với Doctrine2 như find() hoặc findBy();

1) Tạo một kho lưu trữ mới trong một thư mục Repository của Bundle của bạn

<?php 
    namespace YourVendor\SMWMemberBundle\Repository; 
    use Doctrine\ORM\EntityRepository; 

    class CategoryRepository extends EntityRepository{ 

    public function UsedByMember($member){ 
    return $this 
     ->createQueryBuilder('c') 
     ->leftJoin('c.Member', 'mc') 
     ->where('mc.member = ?1') 
     ->setParameter(1, $member); 
} 

}

2) đính kèm kho Cutom của bạn để Entity bạn

namespace YourVendor\SMWMemberBundle\Entity; 
use Doctrine\ORM\Mapping as ORM; 

/** 
* @ORM\Entity(repositoryClass="YourVendor\SMWMemberBundle\Entity\ProductRepository") 
* @ORM\Table(name="Category") 
*/ 
class Category{ 

3) thêm một constructor vào lớp Biểu mẫu của bạn và vượt qua Trình quản lý đối tượng và biến cần thiết cho truy vấn của bạn:

class CategoryUserForm extends AbstractType 
{ 
    private $em; 
    private $member ; 


    public function __construct(EntityManager $em, $site, $seed) 
    { 
     $this->em = $em; 
     $this->member = $member; 

    } 

public function buildForm(FormBuilder $builder, array $options) 
{ 
    $qb = $this->em->getRepository('SMWMemberBundle:Category')->UsedByUsers($this->member); 
    $builder->add('categories', 'entity', array(
     'class' => 'SMWMemberBundle:MemberCategory', 
     'query_builder'  => $qb, 
     'multiple'  => true, 
     'expanded'  => true, 
     'required' => false 
    )); 
} 

4) Trong điều khiển của bạn, bạn tạo biểu mẫu như thế:

$editForm = $this->createForm(new CategoryUserForm($em, $member), $category); 

Hãy hỏi tôi câu hỏi này, tôi hy vọng đây là những gì bạn đang tìm kiếm;)