【问题标题】:Can i use query in form builder to get filtered collection in symfony form我可以在表单生成器中使用查询来获取 symfony 表单中的过滤集合吗
【发布时间】:2012-08-01 06:48:04
【问题描述】:

在 AcmePizza BUndle 中运行良好

->add('pizza', 'entity', array(
                'class'         => 'Acme\PizzaBundle\Entity\Pizza',
                'query_builder' => function ($repository) { return $repository->createQueryBuilder('p')->orderBy('p.name', 'ASC'); },
            ))

我可以在收藏中做类似的事情

->add('userTasks','collection',array('type' => new UserTaskType(),
                    'class'         => 'acme\myBundle\Entity\UserTask',
                    'query_builder' => function ($repository) { return $repository->createQueryBuilder('p')->orderBy('p.name', 'ASC'); },
                ))

【问题讨论】:

  • 你想做什么?使用带有query_builder 的自定义类型?如果是的话,你能粘贴UserTaskType的代码吗?
  • UserTask 类型只有一个名为name 的字段。我正在表单上加载用户任务的集合。它工作正常。但我只想要一些过滤后的任务,比如all tasks where status = 1,而不是所有与用户相关的任务

标签: php forms symfony doctrine-orm


【解决方案1】:

是的。

在您的 UserTaskType 类中,添加以下方法。

public function getDefaultOptions(array $options)
{
    return array(
        'data_class' => 'acme\myBundle\Entity\UserTask',
        'query_builder' => function($repo) {
            return $repo->createQueryBuilder('p')->orderBy('p.name', 'ASC');
        }
    );
}

【讨论】:

  • 我试过没有发生任何事情。我是否需要为此开设回购课程。我什至在字段名称上有错误,但它仍然没有显示任何错误。看起来 queru builder 根本没有运行
  • 这里也一样。我真的很想让它工作,但不幸的是它没有出于某种原因:(
  • 它不起作用。首先,您使用的是不存在的方法(getDefaultOptions)。它应该是“setDefaultOptions”。无论如何,即使将 query_builder 选项放在“setDefaultOptions”方法中它也不起作用,只是因为它不是可用的选项。
【解决方案2】:

我指出你正确的方向(我希望):

http://www.craftitonline.com/2011/08/symfony2-ajax-form-republish/

本文处理字段依赖关系。例如,当您选择一个国家/地区时,列表中会显示属于该国家/地区的城镇。

【讨论】:

    【解决方案3】:

    假设您的 userTasks 是一个关系,您将找到您的案例here 的答案。这些只是如何排序,但如果您需要一些 WHERE 条件,它不是那么简单,但也不难。

    我不得不过滤掉一些实体,解决它的关键是在返回所需集合的实体类中创建set/get方法。

    就我而言,它看起来像这样

    /**
     * Set values
     *
     * @param ArrayCollection $values
     * @return Attribute
     */
    public function setCustomValues($values)
    {
        $result = $this->getNotCustomValues();
        foreach ($values as $value)
        {
            $value->setAttribute($this);
            $result->add($value);
        }
        $this->values = $result;
    
        return $this;
    }
    
    /**
     * Get values
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getCustomValues()
    {
        $result = new ArrayCollection();
        foreach ($this->values as $value) {
            if($value->getCustom()) {
                $result->add($value);
            }
        }
        return $result;
    }
    

    创建表单时,字段的名称是“customvalues”而不是“values” 所以我的集合只包含自定义字段为 true 的值。

    【讨论】:

      【解决方案4】:

      当你更新一个实体时,你经常想要过滤集合,而不是一个新的,对吧?

      这是一个可行的解决方案,这是来自控制器 (CRUD) 的示例:

      public function updateAction($id)
      {
          $service = $this->getServiceRepository()->loadOne('id', $id);
          $this->checkPermission($service);
      
          $this->filterInventoryByPrimaryLocation($service);
      
          if($this->getFormHandler()->process('service_repair_service', $service, array('type' => 'update')))
          {
              $this->getEntityManager()->process('persist', $service);
      
              return $this->render('ServiceRepairBundle:Service:form_message.html.twig', [
                  'message' => $this->trans('Service has been updated successfully.')
              ]);
          }
      
          return $this->render('ServiceRepairBundle:Service:form.html.twig', [
              'form' => $this->getFormHandler()->getForm()->createView(),
          ]);
      }
      
      private function filterInventoryByPrimaryLocation(Service $service)
      {
          $inventory = $service->getInventory();
      
          $criteria = Criteria::create()
              ->where(Criteria::expr()->eq('location', $this->getUser()->getPrimaryLocation()))
              ->orderBy(array('timeInsert' => Criteria::ASC));
      
          $service->setInventory($inventory->matching($criteria));
      }
      

      $service = 实体, $inventory = ArrayCollection ($service->getInventory())

      这里的关键是使用 Doctrine's Criteria,更多信息在这里:

      http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-associations.html#filtering-collections

      还可以考虑将 Criteria 移动到实体本身,在那里创建一个公共方法。当您从数据库加载它时,您可以使用学说的 postLoad 生命周期回调触发该方法。如果您不需要任何服务或类似的东西,当然将其放入实体中会起作用。

      另一个解决方案可能是,如果您只需要在表单内部进行过滤,则将 Criteria 移动到 Form 类中的 Form Event 中。

      如果您需要在整个项目中透明地完成集合过滤,请编写一个学说监听器并将代码放在 postLoad() 方法中。你也可以在学说监听器中注入依赖,但我建议注入容器本身,因为延迟加载其他服务,所以你不会得到循环服务引用。

      祝你好运!

      【讨论】:

        【解决方案5】:

        在 Symfony 2.7 中,我通过在 UserTaskType 中执行以下操作解决了这个问题:

        <?php
        
        namespace AppBundle\Form;
        
        use Symfony\Component\Form\AbstractType;
        use Symfony\Component\Form\FormBuilderInterface;
        use Symfony\Component\OptionsResolver\OptionsResolver;
        use Doctrine\ORM\EntityRepository;
        
        class UserTaskType extends AbstractType
        {
        
            /**
             * @param FormBuilderInterface $builder
             * @param array $options
             */
            public function buildForm(FormBuilderInterface $builder, array $options)
            {
        
                $builder
                    ->add('the_name', 'entity', array(
                        'class' => 'acme\myBundle\Entity\UserTask',
                        'query_builder' => function (EntityRepository $er) {
                            return $er->createQueryBuilder('u')
                                ->where('u.id > :id')
                                ->setParameter('id', '1')
                                ->orderBy('u.username', 'ASC');
                        },
                    ));
            }
        
            /**
             * @param OptionsResolver $resolver
             */
            public function configureOptions(OptionsResolver $resolver)
            {
                $resolver->setDefaults(array(
                    'data_class' => 'acme\myBundle\Entity\UserTask',
                ));
            }
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多