首页 > 解决方案 > 使用 EntityType 显示选择时,无法从 Symfony 表单中保存实体

问题描述

我的 symfony 项目中有两个相关的实体——它们是使用 Doctrine 存储的。一个实体是“广告商”,它有一个 ID 和一个名称。另一个导致问题的实体是一个“报告”,它有一个自己的 id 以及一个名为“advertiser_id”的字段。

在为广告商添加报告时,在 Symfony 表单中,我使用 EntityType 作为advertisingr_id 字段,以便我可以显示选择的广告商。那部分工作得很好,但是当我尝试提交表单时,我收到一个错误,因为它正在将一个 Advertiser 对象而不是广告商的 id 传递给 adser_id 字段。

这是我在表单构建器中的内容:

$builder
    ->add('advertiser_id', EntityType::class, [
        'class'        => Advertiser::class,
        'query_builder' => $this->advertiserRepository->findAllNotDeletedUnpaginated(),
        'choice_label' => 'name',

    ])
    ->add('submit', SubmitType::class, [
        'label' => 'Submit',
    ])
;

当我提交表单时,我收到了这个错误:Expected argument of type "integer", "App\Entity\Advertiser" given。

关于如何强制 symfony 仅尝试保存所选广告商的 id 而不是传递整个广告商的任何想法?

更新:现在我已经对其进行了重构,以便广告商是要报告的相关实体,我正在尝试弄清楚如何使广告商成为隐藏字段并且无处可去。

我已经使用回调转换器尝试了之前提到的 iiirxs 的代码——将“advertiser_id”更改为“advertiser”——但我没有运气。我一直在阅读像Symfony hiddenType 这样的帖子,使用 data_class for entity 而不是transformer,但是我无法像在该示例中获取 $options['selected_course'] 那样获取 'advertiser' 的值。

当我尝试(出于测试目的)为广告客户硬编码值 1,然后将其放在表单上时,表单会显示,但在提交时出现错误:

    $advertiser=1;

    $builder
        ->add('advertiser', HiddenType::class,['data' => $advertiser, 'data_class' => null])

提交表单时出现的错误是:“App\Entity\Advertiser 或 null”类型的预期参数,给出了“字符串”。

我很抱歉在这件事上打了一匹死马。这似乎应该是一件很常见/容易做的事情,但我很难找到如何让它成为一个隐藏的领域。任何想法将不胜感激!

标签: symfonysymfony-forms

解决方案


问题是您没有在 Report 实体中正确定义与 Advertiser 实体的关联。您应该已经定义了这样的关联:

// inside Report.php class

/**
 * @ORM\ManyToOne(targetEntity="App\Entity\Advertiser")
 */
private $advertiser;

而不是定义一个包含外键的字段advertiser_id。Doctrine 足够聪明,可以advertiser_id自行将广告客户字段映射到数据库中的外键,因此最好使用关联映射。您可以在文档中找到更多信息。

但是,如果您出于自己的原因确实必须仅使用整数将 存储advertiser_id为整数,则应使用 Symfony 的 Data Transformer 将广告商实体转换为整数,如下所示:

$advertiserRepository = $this->advertiserRepository;
$builder->get('advertiser_id')
        ->addModelTransformer(new CallbackTransformer(
            function ($advertiserAsInteger) use ($advertiserRepository) {
                // transform the integer to an entity object
                return $advertiserRepository->find($advertiserAsInteger);
            },
            function ($advertiserAsEntity) {
                // transform the entity back to an integer
                return $advertiserAsEntity->getId();
            }
        ))
    ;

在上面的代码中,我使用 CallbackTransformer 来实现转换,但您也可以使用转换器类来实现。您还可以在数据转换器文档中找到更多相关信息。


推荐阅读