You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony中如何保留被软删除实体在EntityType中的选中值?

解决方案

核心思路是让自定义的EntityField在编辑已有实体时,自动将当前关联的已软删除实体加入选项列表,新建实体时仅显示未删除的选项,完全基于Symfony表单原生机制实现。

调整EntityField的query_builder配置

修改configureOptions方法中的默认query_builder闭包,使其根据表单绑定的数据动态调整查询条件:

namespace App\Form\Fields;

use App\Entity\File;
use App\Entity\FileType;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;

class EntityField extends AbstractType
{
    public function configureOptions(OptionsResolver $resolver): void
    {
        parent::configureOptions($resolver);

        // some additional configuration

        $resolver->setDefaults([
            'query_builder' => function (EntityRepository $er, $options): QueryBuilder {
                $qb = $er->createQueryBuilder('entity')
                    ->andWhere('entity.deletedAt IS NULL');

                // 编辑已有File实体时,保留当前关联的FileType(即使已软删除)
                if (isset($options['data']) && $options['data'] instanceof File) {
                    $fileType = $options['data']->getFileType();
                    if ($fileType instanceof FileType) {
                        $qb->orWhere('entity.id = :fileTypeId')
                            ->setParameter('fileTypeId', $fileType->getId());
                    }
                }

                return $qb;
            },
        ]);
    }

    public function getParent(): string
    {
        return EntityType::class;
    }
}

原理说明

  • 新建File时,$options['data']为新实例或null,query_builder仅返回未软删除的FileType,满足“不可选择已删除类型”的需求;
  • 编辑已有File时,若该File关联了已软删除的FileType,会通过OR条件将该FileType加入查询结果,确保选项列表中存在对应值,表单即可正确显示选中状态;
  • 该方案完全遵循Symfony表单规范,无需手动修改视图属性,避免了非标准实现的维护成本。

通用型扩展(可选)

如果你的EntityField是通用组件(并非仅用于File关联FileType),可以通过新增自定义选项适配更多场景:

  1. 在configureOptions中新增可选参数:
$resolver->setOptional(['include_current_entity']);
$resolver->setAllowedTypes('include_current_entity', ['callable']);
  1. 在query_builder中调用该回调:
if (isset($options['include_current_entity']) && is_callable($options['include_current_entity'])) {
    $currentEntity = $options['include_current_entity']($options['data']);
    if ($currentEntity) {
        $qb->orWhere('entity.id = :currentId')
            ->setParameter('currentId', $currentEntity->getId());
    }
}
  1. 使用EntityField时传入回调:
$builder->add('fileType', EntityField::class, [
    'include_current_entity' => function (File $file) {
        return $file->getFileType();
    },
]);

内容的提问来源于stack exchange,提问作者Andrey Yanduganov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 17:26:03