我有3个实体:
[Member] ----OneToMany----> [MemberCategory] ---ManyToOne---> [Category]
就从数据库中获取结果而言,这很有效,但我无法让Form Builder构建正确的表单控件。
我想要一个包含复选框的所有类别的列表,这些复选框会针对成员使用的类别进行检查。最后我想添加优先级字段。
会员
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;
}
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;
}
表单构建器的明显尝试无效。
如果我使用:
$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中有直接的解决方案吗?
答案 0 :(得分:3)
这就是我过去解决这个问题的方法(适用于你的例子),但这是我想出来的,所以它可能不是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';
}
}
然后,您可以按照the documentation为您的成员添加任意数量的类别,并每次都分配优先级。
答案 1 :(得分: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 form querybuilder with parameters了解示例
答案 2 :(得分:0)
cheesemacfly的帖子并不是那么糟糕,但是它是嵌入式的形式,并且管理起来很复杂。 事实上,你需要创建一个“自定义存储库” http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes
它将添加一个新的方法来“抓取”你的ORM对象与Doctrine2,如find()或findBy();
1)在Bundle的Repository Folder中创建一个新的存储库
<?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);
随意问我问题,我希望这是你要找的;)