Symfony 5.4 表单:EntityType 自定义 query_builder orderBy('rand') 和 setMaxResult 问题

Symfony 5.4 Form: Issue with EntityType custom query_builder orderBy('rand') and setMaxResult

我正在与 'strange' 行为作斗争。 当我在 query_builder 上使用 setMaxResult() + Rand() 时。我随机收到消息说我的值无效。

Symfony\Component\Validator\ConstraintViolation{#1320▼ -消息:“Cette valeur n'est pas valide。” -messageTemplate:“此值无效。” -参数:[▶] -复数:空 -root: Symfony\Component\Form\Form {#911 ▶} -propertyPath: "children[press]" -无效值:“8” -约束:Symfony\Component\Form\Extension\Validator\Constraints\Form {#987 …} -代码:“1dafa156-89e1-4736-b832-419c2e501fca” -原因:Symfony\Component\Form\Exception\TransformationFailedException {#916 …} }

如果我删除 setMaxResult(10) 它工作正常,如果我删除 Rand() 它也工作但不是两个

你能帮帮我吗...我不明白,我不知道我能做什么

这是我的代码:

网格类型:


namespace App\Form;

use App\Entity\Press;
use App\Model\GridModel;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class GridType extends AbstractType
{
    /**
     * @var EntityManagerInterface
     */
    private $entityManager;

    public function __construct(
        EntityManagerInterface $entityManager
    )
    {
        $this->entityManager = $entityManager;
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('press', EntityType::class, [
                'class' => Press::class,
                'query_builder' => $this->entityManager->getRepository(Press::class)->getIncluded($options['grid']),
                'choice_label' => 'number',
                'placeholder' => 'Sélectionner une presse',
            ]);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'grid' => null,
            'data_class' => GridModel::class,
            'csrf_protection' => false,
        ]);
    }
}

新闻资料库:

<?php

namespace App\Repository;

use App\Constant\GlobalConstant;
use App\Entity\Grid;
use App\Entity\Press;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;

/**
 * @method Press|null find($id, $lockMode = null, $lockVersion = null)
 * @method Press|null findOneBy(array $criteria, array $orderBy = null)
 * @method Press[]    findAll()
 * @method Press[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class PressRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Press::class);
    }

    /**
     * @param Grid|null $grid
     * @return QueryBuilder|null
     */
    public function getIncluded(Grid $grid = null): ?QueryBuilder
    {
        $result = $this->createQueryBuilder('i')
            ->andWhere('i.status = :status')
            ->andWhere('i.include = :include')
            ->setParameters([
                'status' => GlobalConstant::STATUS_VALID,
                'include' => true,
            ]);

        if ($grid) {
            $result->andWhere('i NOT IN (:grid)')
                ->setParameter(
                    'grid', $grid->getPress()
                );
        }

        return $result->orderBy('i.number', 'ASC')
            ->setMaxResults(5)
            ->orderBy('RAND()');
    }

表单的工作方式,每次实例化类型时都会执行查询,这意味着加载空表单时的初始查询结果与提交时的结果不同(因为随机排序) .由于提交的值不再在有效 'choices' 中,您会看到 TransformationFailedException.

解决此问题的一种方法是使用 ChoiceType 而不是 EntityType,并将查询结果保存在会话中,例如。

public function __construct(
    PressRepository $repository,
    // This is deprecated in 5.3
    // see https://symfony.com/blog/new-in-symfony-5-3-session-service-deprecation
    SessionInterface $session
)
{
    $this->repository = $repository;
    $this->session = $session;
}

public function buildForm(FormBuilderInterface $builder, array $options): void
{
    if (!$session->has('press_form_choices')) {
        $session->set(
            'press_form_choices',
            $this->repository->getIncluded($options['grid'])
        );
    }
    $choices = $session->get('press_form_choices');
    $builder
    ->add('press', ChoiceType::class, [
        'choices' => $choices,
        'choice_label' => 'number',
        'choice_value' => 'id',
        'placeholder' => 'Sélectionner une presse',
    ]);
}   

提交成功后,清理控制器中的会话:$session->remove('press_form_choices');