8

我有 3 个实体:

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

就从数据库中获取结果而言,这很有效,但我无法让表单生成器构建正确的表单控件。

我想要一个所有类别的列表,其中包含针对会员使用的类别进行检查的复选框。最终我想添加优先级字段。

成员

class Member
{
    protected $id;

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

类别

class Category
{
    protected $id;

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

会员类别

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;
}

使用表单生成器的明显尝试不起作用。

如果我使用:

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

我得到一个包含所有类别的选择,但没有在 MemberCategory 中为该成员选择的那些。

如果我使用:

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

我得到所有用户的所有选定类别。

有谁知道如何让它工作,这是关系数据中明显的常见模式,使用 SQL 和 PHP 很容易。

Symfony 2.3 和 Doctrine 中是否有直接的解决方案?

4

3 回答 3

4

这就是我过去解决这个问题的方法(适用于你的例子),但这是我想出来的,所以它可能不是 100% 适合你的情况。

首先创建一个MemberCategory符合您需求的表单类型:

<?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';
    }
}

然后在您的Member类型表单中添加此表单类型:

<?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';
    }
}

然后,您可以按照文档为您的成员添加任意数量的类别并每次分配优先级。

于 2013-07-29T16:48:05.797 回答
1

您将需要在表单中使用查询构建器

$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
    ));

请参阅文档以正确使用。请参阅带有参数的 symfony2 表单查询构建器作为示例

于 2013-07-29T16:46:07.840 回答
0

cheesemacfly 的帖子还不错,但它是调用嵌入形式,管理起来可能很复杂。实际上,您只需要创建一个“自定义存储库” http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes

它将添加一个新方法,用于使用 Doctrine2 (如 find() 或 findBy())“抓取”您的 ORM 对象;

1) 在您的 Bundle 的存储库文件夹中创建一个新存储库

<?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)将您的Cutom存储库附加到您的实体

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

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

3)向您的 Form 类添加一个构造函数并传递 de Entity Manager 和查询所需的变量:

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)在您的控制器中,您可以这样创建表单:

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

随时问我问题,我希望这就是你要找的;)

于 2013-07-29T17:35:13.000 回答