【问题标题】:Symfony form 2 different value types in one fieldSymfony 在一个字段中形成 2 种不同的值类型
【发布时间】:2016-02-26 12:11:48
【问题描述】:

我实际上正在构建一个非常简单的 REST Api,但我遇到了这个重要功能的问题。我试图在 Symfony 文档中找到一些有用的东西来解决这个问题,但我没有找到任何与此相关的东西。

我想收到这样的请求正文,例如:

{
    "amount": "200",
    "account": {
        "name": "XXX XXXX", 
        "value": "asdasdasdasdasdsadsad"
    }
}

该请求将创建一个新的帐户实体并将其持久化(没有问题)。

有时我也想收到这种请求

{
    "amount": "200",
    "account": "e76ad9ea-dbc1-11e5-a764-109add42947b"
}

我的应用程序的想法是将新实体与提供的帐户 ID (UUID) 关联起来。

EntityType.php

class EntityType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('amount')
            ->add('account', AccountType::class);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(['data_class' => Entity::class, 'csrf_protection' => false]);
    }
}

实体很简单:

class Entity
{
    /**
     * @ORM\Column(type="guid")
     * @ORM\Id
     *
     * @var string
     */
    protected $id;

    /**
     * UUIDableEntity constructor.
     */
    public function __construct()
    {
        $this->id = Uuid::uuid1()->toString();
    }

    /**
     * @return string
     */
    public function getId(): string
    {
        return $this->id;
    }

    /**
     * @var float
     *
     * @ORM\Column(type="float")
     */
    protected $amount;

    /**
     * @var Account
     *
     * @ORM\ManyToOne(targetEntity="Account", cascade={"persist"})
     * @ORM\JoinColumn(referencedColumnName="id", nullable=false)
     * @Assert\Valid()
     */
    protected $account;

    /**
     * @return float
     */
    public function getAmount()
    {
        return $this->amount;
    }

    /**
     * @param float $amount
     */
    public function setAmount(float $amount)
    {
        $this->amount = $amount;
    }

    /**
     * @return Account
     */
    public function getAccount()
    {
        return $this->account;
    }

    /**
     * @param Account $account
     */
    public function setAccount(Account $account)
    {
        $this->account = $account;
    }
}

我知道一种解决方案可以检测帐户值的类型并使用我需要的类型(因此我需要两种不同的表单类型)。但是这个解决方案在我看来有点脏。 关于处理它的 AccountType 实现的任何想法?

AccountType 每次创建新实体的实现非常简单,但不知道如何处理 2 种不同类型的请求值。

【问题讨论】:

    标签: php symfony-forms symfony


    【解决方案1】:

    在这些情况下,您最好自己处理映射,而不是依赖 SF 表单的默认行为。我认为您可以通过使用empty_data 来实现类似的目标:

    $resolver->setDefaults([
        'data_class' => 'Account::class',
        'empty_data' => function (FormInterface $form) {
            //on create
            $account = new Account(
                $form->get('name')->getData(),
                $form->get('value')->getData()
            );
    
            //on update you'll need to inject the repo
            $account = $this->accountRepository->findOne(
                           $form->getData()
                       );
    
            return $account;
        },
    ]);
    

    根据 buildForm,您可能需要动态生成表单字段。您可以通过在预先设置数据时添加 eventListener 来做到这一点。

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
            $data = $event->getData();
            // check what data is coming in the request and add form fields accordingly
            $form = $event->getForm();
            $form->add(...);
        });
    
    }
    

    【讨论】:

    • buildForm 呢?
    • 那行不通...因为我需要在构建表单函数中添加名称和值以从 empty_data 检索该数据,而我将无法处理另一个值(没有对象,只有 ID)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    • 2021-08-05
    • 1970-01-01
    相关资源
    最近更新 更多