如何仅在Form中加载OneToMany关联的子集? [英] How to load only a subset of a OneToMany association in a form?
问题描述
我有两个实体: A
和 B
。 A
通过 OneToMany
关联到 B
/ p>
class A
/ pre>
{
/ / ...
/ **
* @ ORM\OneToMany(targetEntity =.. \AcmeBundle\Entity\B,mappedBy =A,fetch =EXTRA_LAZY)
* /
private $ things;
public function __construct()
{
$ this-> things = new ArrayCollection();
}
// ...
// addThing(),removeThing()和getThings()被正确定义
我有一个Form类为
A
实体:class AThingsType extends AbstractType
{
public function buildForm(FormBuilderInterface $ builder,array $ options)
{
$ builder
- > add('things','collection',array(
'type'=> new BType()
))
- > add('send','submit')
;
}
public function setDefaultOptions(OptionsResolverInterface $ resolver)
{
$ resolver-> setDefaults(array(
'data_class'=> .. \AcmeBundle\Entity\A'
));
}
public function getName()
{
return'a_things';
}
}
BType
class包含字段来定义B的形式,没有什么特别的。
我使用这个表单从我的控制器:
$ a = $ em-> getRepository('AcmeBundle:A') - > getAWithSubsetOnly($ A_id) ;
$ form = $ this-> createForm(new AThingsType(),$ a / * A * /的实例)
然后窗体在Twig模板中呈现。
它将为
A->东西
中的每个元素添加一个BType
,但我想要仅显示A->字符串
值的子集,因为当前用户没有权限修改所有A->东西
,他只能更新一些这些B
实体。我不知道该怎么做,因为整个集合A->东西
被自动加载(即使一个- > ; innerJoin()
仅获取一部分东西),所以表单显示所有的BType
,而我只想显示其中的一些基于SQL查询)。
现在,通过调用
{%do form.contenu.setRendered%}
,但希望可能会有更好的解决方案。解决方案问题可能是您没有在getAWithSubsetOnly存储库方法中明确选择您在DQL / QueryBuilder调用中所需的实体。
例如,这将获得一个用户,如果我想以我的形式将所有日志显示为一个集合,将延迟加载所有日志,而不管我的条件如何:
$ userData = $ this-> getEntityManager()
- > createQueryBuilde r() - > select('u')// constraint ignored
- > from('SomeUserBundle:User','u')
- > join('u.logs' 'l')
- > where('l.id< 20880')
- > andWhere('u.id = 7')
- > getQuery() - > getSingleResult();
如果你明确地告诉学说在下面的连接中获取子实体,它不会懒惰收藏&您将获得过滤的集合子集:
$ userData = $ this-> getEntityManager()
- > createQueryBuilder() - > select('u,l')//约束被考虑为
//日志不懒加载
- > from('SomeUserBundle:User','u')
- > join('u.logs','l')
- > where('l.id< 20880')
- > andWhere('u.id = 7')
- > getQuery() - > getSingleResult();
您还可以使用此方法为您自己添加大量的惰性加载SQL查询。
I have two entities:
A
andB
.A
is associated toB
through aOneToMany
association:class A { // ... /** * @ORM\OneToMany(targetEntity="..\AcmeBundle\Entity\B", mappedBy="A", fetch="EXTRA_LAZY") */ private $things; public function __construct() { $this->things = new ArrayCollection(); } // ... // addThing(), removeThing() and getThings() are properly defined
I have a Form class for the
A
entity:class AThingsType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('things', 'collection', array( 'type' => new BType() )) ->add('send', 'submit') ; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => '..\AcmeBundle\Entity\A' )); } public function getName() { return 'a_things'; } }
The
BType
class contains fields to define the forms of B, there is nothing particular in it.And I use this form from my controller:
$a = $em->getRepository('AcmeBundle:A')->getAWithSubsetOnly($A_id); $form = $this->createForm(new AThingsType (), $a /* instance of A*/);
Then the form is rendered in the Twig template.
It will add one
BType
for each element inA->things
but I want to display only a subset of theA->strings
values, because the current user doesn't have the rights to modify all theA->things
, he can only update some of theseB
entities. I don't know how to do this, because the whole collection ofA->things
is loaded automatically (even if a do a->innerJoin()
to fetch only a subset of the things) so the form display all theBType
whereas I only want to display some of them (based on a SQL query).Now the fields are hidden by calling
{% do form.contenu.setRendered %}
in Twig but I hope there may be a better solution.解决方案The problem is likely you're not explicitly selecting the entities you want in your DQL/QueryBuilder call in your getAWithSubsetOnly repository method.
For example, this will get a user and if I wanted to display all its logs as a collection in my form, will lazy load all logs regardless of my criteria:
$userData = $this->getEntityManager() ->createQueryBuilder()->select('u') // constraint ignored ->from('SomeUserBundle:User', 'u') ->join('u.logs', 'l') ->where('l.id < 20880') ->andWhere('u.id = 7') ->getQuery()->getSingleResult();
If you explicity tell doctrine to fetch the sub entity at join like below, it won't lazy load the collection & you will get your filtered collection subset:
$userData = $this->getEntityManager() ->createQueryBuilder()->select('u, l') // constraint taken into account as // logs not lazy loaded ->from('SomeUserBundle:User', 'u') ->join('u.logs', 'l') ->where('l.id < 20880') ->andWhere('u.id = 7') ->getQuery()->getSingleResult();
You'll also save yourself a lot of lazy loading SQL queries with this approach.
这篇关于如何仅在Form中加载OneToMany关联的子集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!