Symfony:CollectionType 中的 OrderBy

Posted

技术标签:

【中文标题】Symfony:CollectionType 中的 OrderBy【英文标题】:Symfony : OrderBy in CollectionType 【发布时间】:2021-08-06 12:42:21 【问题描述】:

我有两个具有 OneToMany 关联的表(Player 和 Historique)。在我的 PlayerType 表单中,我有一个 CollectionType,其中我的 HistoriqueType 有一个 entry_type。我的问题是关于 HistoriqueType 数据到达的顺序。目前,它以idASC 顺序出现。但我希望它出现在ASC 年份顺序(季节)中。

这是我的两个实体:

<?php

/**
 * @ORM\Entity(repositoryClass=PlayerRepository::class)
 */
class Player

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

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

    
    /**
     * @ORM\OneToMany(targetEntity=Historique::class, mappedBy="player", cascade="persist", orphanRemoval = true)
     */
    public $playerHistoriques;


public function __construct()

    $this->playerHistoriques = new ArrayCollection();

还有我的历史课:

<?php

/**
 * @ORM\Entity(repositoryClass=HistoriqueRepository::class)
 */
class Historique

/**
 * @ORM\Id
 * @ORM\GeneratedValue
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @ORM\ManyToOne(targetEntity=Club::class, inversedBy="historiques")
 * @ORM\JoinColumn(nullable=true)
 */
private $club;

/**
 * @ORM\ManyToOne(targetEntity=Season::class, inversedBy="historiques")
 * @ORM\JoinColumn(nullable=true)
 * @ORM\OrderBy("season" = "ASC")
 */
private $season;

/**
 * @ORM\ManyToOne(targetEntity=Player::class, inversedBy="playerHistoriques")
 * @ORM\JoinColumn(nullable=true)
 */
private $player;

/**
 * @ORM\ManyToOne(targetEntity=Position::class, inversedBy="historiques")
 */
private $position;

我的玩家类型:

<?php

class PlayerType extends AbstractType

public function buildForm(FormBuilderInterface $builder, array $options)

    $builder
        ->add('name')
        ->add('playerHistoriques', CollectionType::class, [
            'entry_type' => HistoriqueType::class,
            'entry_options' => [
                'label' => false
            ],
            'by_reference' => false,
            'allow_add' => true
        ])
    ;


public function configureOptions(OptionsResolver $resolver)

    $resolver->setDefaults([
        'data_class' => Player::class,
    ]);


还有我的 HistoriqueType:

<?php

class HistoriqueType extends AbstractType


public function buildForm(FormBuilderInterface $builder, array $options)


    $builder
        ->add('club', EntityType::class, [
            'class' => Club::class,
            'choice_label' => 'name',
            'label' => false,
            'required' => false,
            'placeholder' => '-',
            'query_builder' => function (EntityRepository $er) 
                return $er->createQueryBuilder('c')
                    ->orderBy('c.name', 'ASC');
            
        ])
        ->add('season', EntityType::class, [
            'class' => Season::class,
            'choice_label' => 'year',
            'label' => false,
            'placeholder' => '-',
            'query_builder' => function (EntityRepository $er) 
                return $er->createQueryBuilder('s')
                    ->orderBy('s.year', 'ASC');
            
        ])
        ->add('position', EntityType::class, [
            'class' => Position::class,
            'choice_label' => 'position',
            'label' => false,
            'placeholder' => '-',
            'required' => false
        ])
    ;
    



public function configureOptions(OptionsResolver $resolver)

    $resolver->setDefaults([
        'data_class' => Historique::class,
        'method' => 'get',
        'csrf_protection' => false
    ]);


public function getBlockPrefix() 
    return '';


在我的编辑表单中,我想按 'season' => 'ASC' 对我的 collectionType 进行排序,以便即使在我的编辑表单中也能按时间顺序排列年份。

我已经在我的 PlayerType 中尝试过这样的 query_builder :

'query_builder' => function (EntityRepository $er) 
                return $er->createQueryBuilder('h')
                          ->orderBy('h.season', 'ASC');
            

但它产生了一个错误,因为 collectionTypes 中不能有查询。

我尝试在我的 PlayerEntity @ORM\OrderBy("season" = "ASC") 中自动订购,但没有成功。

【问题讨论】:

【参考方案1】:

在您的 Historique 实体中将顺序更改为 year 而不是 season (我相信在您的其他形式中,您是按年份排序的所以希望这是您要排序的属性)。

/**
 * @ORM\ManyToOne(targetEntity=Season::class, inversedBy="historiques")
 * @ORM\JoinColumn(nullable=true)
 * @ORM\OrderBy("year" = "ASC")
 */
private $season;

您现在应该可以删除查询生成器了,除非您需要缩小选择范围。

【讨论】:

感谢您的回答,但不幸的是它不起作用...在我的编辑表单中,我的 collectionType 仍未按 ASC 年份顺序呈现,而是按 id 的 ASC 顺序呈现。 【参考方案2】:

OrderBy 必须在 OneToMany 关系中的 Palyer 实体中,而不是在 Historique 中

/**
 *@ORM\OneToMany(targetEntity=Historique::class, mappedBy="player", cascade="persist", orphanRemoval = true)
 *@ORM\OrderBy("season" = "ASC")
*/
public $playerHistoriques;

【讨论】:

非常感谢您的回答。是的,它有效。我把 Order By 放在了错误的地方。谢谢。

以上是关于Symfony:CollectionType 中的 OrderBy的主要内容,如果未能解决你的问题,请参考以下文章

Symfony CollectionType:合并新条目

Symfony5 handleRequest 更新原始 collectionType 对象

Symfony 4.4如何使用collectionType从0个字段开始

Symfony 4 表单 CollectionType:仅使新行需要 FileType 元素

Select2 与 collectionType - Symfony2

Symfony2.8 表单 CollectionType 字段 manyTo many