Symfony4.3更新后EntityType首选选项排序失效求助
解决Symfony 4.3+中EntityType首选选项排序问题
针对你遇到的Symfony 4.3升级后preferred_choices丢失排序的问题,我有几个无需在表单构建器外单独创建事件数组的解决方案,推荐优先尝试以下SQL层面的排序方案:
方案一:通过Query Builder的CASE表达式控制全局排序
这个方法利用SQL的条件排序,先把未来事件放在列表最前面(按日期升序),再排列过去的事件(同样按日期升序)。因为preferred_choices会保留这些事件在原列表中的顺序,所以首选选项自然就是升序的:
->add('event', EntityType::class, [ 'class' => 'App:Event', 'choice_label' => 'name', 'expanded' => false, 'multiple' => false, 'required' => false, 'placeholder' => '-', 'query_builder' => function (EntityRepository $er) { $now = new \DateTime(); return $er->createQueryBuilder('e') // 添加隐藏字段区分未来/过去事件 ->addSelect('CASE WHEN e.date > :now THEN 0 ELSE 1 END AS HIDDEN isPast') ->setParameter('now', $now) // 先按是否为过去事件排序(未来事件在前),再按日期升序 ->orderBy('isPast', 'ASC') ->addOrderBy('e.date', 'ASC'); }, 'preferred_choices' => function ($event) { return $event->getDate() > new \DateTime(); } ])
这个方案只需要一次数据库查询,完全在Query Builder内处理排序逻辑,保持了代码的简洁性,同时解决了首选选项的排序问题。
方案二:在表单内拆分事件集合(单次查询)
如果不想修改SQL查询,也可以在表单构建器内获取所有事件,然后拆分并分别排序:
->add('event', EntityType::class, [ 'class' => 'App:Event', 'choice_label' => 'name', 'expanded' => false, 'multiple' => false, 'required' => false, 'placeholder' => '-', 'choices' => function (EntityRepository $er) { $now = new \DateTime(); // 获取所有事件并按日期升序排列 $allEvents = $er->createQueryBuilder('e') ->orderBy('e.date', 'ASC') ->getQuery() ->getResult(); // 拆分未来和过去事件 $futureEvents = []; $pastEvents = []; foreach ($allEvents as $event) { if ($event->getDate() > $now) { $futureEvents[] = $event; } else { $pastEvents[] = $event; } } // 合并后未来事件在前,且各自保持升序 return array_merge($futureEvents, $pastEvents); }, 'preferred_choices' => function ($event) { return $event->getDate() > new \DateTime(); } ])
这个方案只查询一次数据库,然后在内存中拆分集合,确保未来和过去事件都按日期升序排列,preferred_choices会沿用集合中的顺序展示首选选项。
这两个方案都不需要在表单构建器外维护额外的数组,完美贴合你的需求。
内容的提问来源于stack exchange,提问作者Flo
相关产品推荐
相关产品推荐

