如何仅在Form中加载OneToMany关联的子集? [英] How to load only a subset of a OneToMany association in a form?

查看:103
本文介绍了如何仅在Form中加载OneToMany关联的子集?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个实体: A B A 通过 OneToMany 关联到 B / p>



  class A 
{
/ / ...
/ **
* @ ORM\OneToMany(targetEntity =.. \AcmeBundle\Entity\B,mappedBy =A,fetch =EXTRA_LAZY)
* /
private $ things;

public function __construct()
{
$ this-> things = new ArrayCollection();
}

// ...
// addThing(),removeThing()和getThings()被正确定义
/ pre>

我有一个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 and B. A is associated to B through a OneToMany 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 in A->things but I want to display only a subset of the A->strings values, because the current user doesn't have the rights to modify all the A->things, he can only update some of these B entities. I don't know how to do this, because the whole collection of A->things is loaded automatically (even if a do a ->innerJoin() to fetch only a subset of the things) so the form display all the BType 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆