如何使用 Symfony Forms 为 API 设置默认值?
How to set default values for an API using Symfony Forms?
我有一个很简单的API。您可以 POST 一个价格(价值和货币)到 API。默认货币为 EUR,因此可以省略货币。 API returns 全价对象:
$ curl -d '{"value":12.1}' http://localhost:8000/prices.json
{
"value": 12.1,
"currency": "EUR"
}
所以我想使用 Symfony Forms 来实现它。我已经建立了一个带有一些基本验证规则的小型数据模型:
namespace AppBundle\Model;
use Symfony\Component\Validator\Constraints as Assert;
class Price
{
/**
* @Assert\NotBlank()
* @Assert\GreaterThanOrEqual(0)
*/
public $value;
/**
* @Assert\NotBlank()
* @Assert\Length(min=3, max=3)
*/
public $currency = 'EUR';
}
以及具有以下形式的控制器:
namespace AppBundle\Controller;
use AppBundle\Model\Price;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class PriceController extends Controller
{
/**
* @Route("/prices.json")
*/
public function apiAction(Request $request)
{
$product = new Price();
$form = $this->createFormBuilder($product, [
'csrf_protection' => false,
])
->add('value', 'number')
->add('currency')
->getForm();
$form->submit(json_decode($request->getContent(), true));
if ($form->isValid()) {
return new JsonResponse($product);
}
return new JsonResponse($form->getErrorsAsString());
}
}
这仅在我传递请求正文中的所有字段时有效。我不能省略货币。设置 data
或 empty_data
也无济于事。
我尝试在 submit()
方法上切换 $clearMissing
,但这会禁用模型验证:
$form->submit(json_decode($request->getContent(), true), false);
到目前为止我想到的最好的想法是合并数据的事件侦听器:
$form = $this->createFormBuilder($product, [
'csrf_protection' => false,
])
->add('value', 'number')
->add('currency')
->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $e) {
$e->setData(array_merge((array) $e->getForm()->getData(), $e->getData()));
})
->getForm();
这适用于我的简单示例。但这是最好的方法吗?或者有其他/更好的选择吗?
我觉得你的解决方案不错!我认为像您一样添加事件侦听器是最好的方法。
我建议使用 array_replace()
而不是 array_merge()
,因为它专用于关联数组。
我有一个很简单的API。您可以 POST 一个价格(价值和货币)到 API。默认货币为 EUR,因此可以省略货币。 API returns 全价对象:
$ curl -d '{"value":12.1}' http://localhost:8000/prices.json
{
"value": 12.1,
"currency": "EUR"
}
所以我想使用 Symfony Forms 来实现它。我已经建立了一个带有一些基本验证规则的小型数据模型:
namespace AppBundle\Model;
use Symfony\Component\Validator\Constraints as Assert;
class Price
{
/**
* @Assert\NotBlank()
* @Assert\GreaterThanOrEqual(0)
*/
public $value;
/**
* @Assert\NotBlank()
* @Assert\Length(min=3, max=3)
*/
public $currency = 'EUR';
}
以及具有以下形式的控制器:
namespace AppBundle\Controller;
use AppBundle\Model\Price;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class PriceController extends Controller
{
/**
* @Route("/prices.json")
*/
public function apiAction(Request $request)
{
$product = new Price();
$form = $this->createFormBuilder($product, [
'csrf_protection' => false,
])
->add('value', 'number')
->add('currency')
->getForm();
$form->submit(json_decode($request->getContent(), true));
if ($form->isValid()) {
return new JsonResponse($product);
}
return new JsonResponse($form->getErrorsAsString());
}
}
这仅在我传递请求正文中的所有字段时有效。我不能省略货币。设置 data
或 empty_data
也无济于事。
我尝试在 submit()
方法上切换 $clearMissing
,但这会禁用模型验证:
$form->submit(json_decode($request->getContent(), true), false);
到目前为止我想到的最好的想法是合并数据的事件侦听器:
$form = $this->createFormBuilder($product, [
'csrf_protection' => false,
])
->add('value', 'number')
->add('currency')
->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $e) {
$e->setData(array_merge((array) $e->getForm()->getData(), $e->getData()));
})
->getForm();
这适用于我的简单示例。但这是最好的方法吗?或者有其他/更好的选择吗?
我觉得你的解决方案不错!我认为像您一样添加事件侦听器是最好的方法。
我建议使用 array_replace()
而不是 array_merge()
,因为它专用于关联数组。