【问题标题】:Symfony form: filter collection with a parameterSymfony 形式:带参数的过滤器集合
【发布时间】:2018-11-19 19:13:01
【问题描述】:

我正在使用 Symfony 3.4。

我有一个表格可以编辑给定国家/地区的一些答案,我需要按类别编辑这些答案。

我在我的实体中设置了一个过滤器,但我不知道如何使用表单中的参数调用此 getter。

肮脏的替代方法是从我的控制器中的表单中删除不需要的元素,但这并不理想......

这是我的表格:

<?php

namespace cwt\psmdbBundle\Form;

use cwt\psmdbBundle\Entity\CcdbServicesAnswers;
use cwt\psmdbBundle\Entity\countries;

use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;

class countriesCCDBServicesAnswersType extends AbstractType
{

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('AnswersOfCategory', CollectionType::class, array(
                'entry_type' => CcdbServicesAnswersType::class,
                'entry_options' => array('label' => false,),
                'label' => false,
            ));    
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'cwt\psmdbBundle\Entity\countries',
            'categoryID' => 1,
        ));
    }

    /**
     * @return string
     */
    public function getBlockPrefix()
    {
        return 'cwt_psmdbbundle_countries';
    }
}

这是我的实体:

<?php

namespace cwt\psmdbBundle\Entity;

use APY\DataGridBundle\Grid\Mapping as GRID;
use Doctrine\ORM\Mapping as ORM;

/**
 * countries
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="cwt\psmdbBundle\Entity\Repository\countriesRepository")
 */
class countries
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="code", type="string", length=2)
     */
    private $code;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=100)
     */
    private $name;    

    /**
     * @ORM\OneToMany(targetEntity="cwt\psmdbBundle\Entity\CcdbServicesAnswers", mappedBy="country", cascade={"persist", "remove"})
     */
    private $ccdbServicesAnswers;


// Specific Functions

    /**
     * Get ccdbServicesAnswers.
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getAnswersOfCategory($categoryID)
    {

        return $this->getCcdbServicesAnswers()->filter(function(CcdbServicesAnswers $answer) use($categoryID) {
            return $answer->getQuestion()->getCategory()->getId() == $categoryID;
        });
    }

这是我在控制器中创建表单的功能:

private function createCountryEditForm(Countries $entity, $categoryID)
{
    $form = $this->createForm(countriesCCDBServicesAnswersType::class, $entity, array(
        'action' => $this->generateUrl('updateCountryCcdbServicesAnswers', array('countryID' => $entity->getId())),
        'method' => 'PUT',
        'categoryID' => $categoryID,
    ));

    $form->add('submit', submitType::class, array('label' => 'Update', 'attr' => array('class' => 'hidden')));

    return $form;
}

[2018 年 11 月 20 日更新]

这是我到目前为止所做的。这项工作,但我更喜欢一个更干净的解决方案,它在数据库级别使用 where 子句处理此过滤器,并且会更干燥。在控制器级别执行此操作意味着我必须在需要此过滤器的任何地方执行此操作。

private function createCountryEditForm(Countries $entity, $categoryID)
{
    $form = $this->createForm(countriesCCDBServicesAnswersType::class, $entity, array(
        'action' => $this->generateUrl('updateCountryCcdbServicesAnswers', array('countryID' => $entity->getId(), 'categoryID' => $categoryID)),
        'method' => 'PUT',
        'categoryID' => $categoryID,
    ));

    $answers = $form->get('ccdbServicesAnswers')->getData();


    foreach ($answers as $answer) {

        if($answer->getQuestion()->getCategory()->getId() != $categoryID) {
            $answers->removeElement($answer);
        }

    }

    $form->get('ccdbServicesAnswers')->setData($answers);

    $form->add('submit', submitType::class, array('label' => 'Update', 'attr' => array('class' => 'hidden')));

    return $form;
}

【问题讨论】:

    标签: symfony doctrine-orm symfony-forms


    【解决方案1】:

    您不应该在您的实体中使用过滤器。您应该使用 DQL 手动获取答案。 获取实体数组并使用 CollectionType 将其传递给您的表单。

    use cwt\psmdbBundle\Entity\CcdbServicesAnswers;
    use cwt\psmdbBundle\Form\countriesCCDBServicesAnswersType;
    
    // ....
    $queryBuilder = $this->createQueryBuilder()
        ->select('a')
        ->from(CcdbServicesAnswers::class, 'a')
        ->where('
            country = :country
            AND category = :category
        ')
        ->setParameters([
            'country' => $country,
            'category' => $category
        ]);
    
    $answers = $queryBuilder->getQuery()->getArrayResult();
    
    $this->createForm(countriesCCDBServicesAnswersType::class, [
        'AnswersOfCategory' => $answers
    ]);
    

    您可以将所需数据的获取封装到存储库: https://symfony.com/doc/current/doctrine.html#querying-for-objects-the-repository

    【讨论】:

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