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');
。
我正在与 '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');
。