我的问题涉及json负载验证的各种过程。 我已经接受: - 对模型进行反序列化,调用验证器服务并验证水合对象。 - 使用FormType(即使没有窗体...只是json提要),并在注入$ datas后验证表单构建器。Symfony Api Rest验证器进程
你更喜欢哪一个? 你有更好的解决方案吗?比如,也许一个中间件(唯一捆绑OU应用程序,与所有输入/输出,来有效载荷交易 - 请求/响应)
谢谢
我的问题涉及json负载验证的各种过程。 我已经接受: - 对模型进行反序列化,调用验证器服务并验证水合对象。 - 使用FormType(即使没有窗体...只是json提要),并在注入$ datas后验证表单构建器。Symfony Api Rest验证器进程
你更喜欢哪一个? 你有更好的解决方案吗?比如,也许一个中间件(唯一捆绑OU应用程序,与所有输入/输出,来有效载荷交易 - 请求/响应)
谢谢
我验证/与本地听众/工具FOSRestBundle
提供反序列化。
利用这个bundle,你可以拥有本地的form-validation ...或者自动反序列化和验证的模型,以及作为控制器参数注入的验证错误列表。
# app/config/config.yml
# You need SensioFrameworkExtraBundle for body converters to work
sensio_framework_extra:
request: { converters: true }
fos_rest:
zone:
- path: '^/api/(.*)+$'
# [..]
body_listener:
enabled: true
default_format: json
decoders:
json: fos_rest.decoder.jsontoform
# automatically injects query parameters into controller Actions
# see @FOSRest\QueryParam in the example below
param_fetcher_listener: force
# https://symfony.com/doc/master/bundles/FOSRestBundle/request_body_converter_listener.html
body_converter:
enabled: true
validate: true
validation_errors_argument: validationErrors
主体变换器可以反序列化和为您自动验证模型(不使用任何形式或手动步骤)。例如:
/**
* @ParamConverter(
* "post",
* converter = "fos_rest.request_body",
* options = {
* "validator" = {
* "groups" = {
* "validation-group-one",
* "validation-group-two",
* }
* },
* "deserializationContext" = {
* "groups" = {
* "serializer-group-one",
* "serializer-group-two"
* },
* "version"="1.0"
* }
* }
*)
*/
public function putPostAction(Post $post, ConstraintViolationListInterface $validationErrors)
{
if (!empty($validationErrors)) {
// return some 4xx reponse
}
// Do something with your deserialized and valid Post model
捆绑包可以将表单(和表单错误)序列化为JSON。
即具有无效字段的表单将呈现为:
{
"code": 400,
"message": "Validation Failed",
"errors": {
"errors": [
"This is a global form error."
],
"children": {
"oldPassword": {
"errors": [
"The old password is not correct."
]
},
"newPassword": [],
"submit": []
}
}
}
FOSRestBundle
提供请求体听者自动解码Content-Type: application/json
到Content: application/x-www-form-urlencoded
的Request
对象内,从而可以绑定请求到窗体具有如同你使用普通的HTML表单一样。您可以使用查询参数(在以下示例中为?validate=true
)发送请求,并返回HTTP 200(OK)/ 202(接受)的早期响应)在执行任何业务逻辑之前。
下面的例子表明,接受形式的请求端点:
{
"oldPassword": "xxxxxxx",
"newPassword": "yyyyyyy"
}
相应的控制器动作:
/**
* @FOSRest\Route(
* "/profile/change-password",
* name="api_put_password",
* methods={
* Request::METHOD_PUT
* }
*)
*
* @FOSRest\QueryParam(
* name="validate",
* allowBlank=false,
* default="false",
* strict=true,
* nullable=true,
* requirements="^(true|false)$"
*)
*/
public function putPasswordAction(Request $request, string $validate = 'false')
{
$validate = filter_var($validate, FILTER_VALIDATE_BOOLEAN);
$form = $this->formFactory->createNamed(null, ChangePasswordType::class, null, [
'action' => $this->router->generateUrl('api_put_password'),
'method' => $request->getMethod(),
]);
$form->handleRequest($request);
if (!$form->isValid()) {
$view = new View();
$view->setStatusCode(Response::HTTP_BAD_REQUEST);
$view->setData($form);
return $view;
}
if ($validate) {
$view = new View();
$responseCode = Response::HTTP_ACCEPTED;
$view->setStatusCode($responseCode);
$view->setData([
'code' => $responseCode,
'message' => 'Data is valid.',
'data' => null
]);
return $view;
}
$user = $this->securityContext->getToken()->getUser();
/** @var PasswordChangeRequest $passwordChangeRequest */
$passwordChangeRequest = $form->getData();
$user->setPassword($this->passwordEncoder->encodePassword($user, $passwordChangeRequest->getNewPassword()));
$this->userManager->persist($user);
$view = new View();
$view->setStatusCode(Response::HTTP_OK);
$view->setData([
'code' => Response::HTTP_OK,
'message' => 'Password changed successfully.',
'data' => $user
]);
$context = new Context();
$context->setGroups([
'profile'
]);
$view->setContext($context);
return $view;
}
我正在寻找这种解决方案nifr,它是完美的!谢谢。 – iKonenn
我有一个paramconverter @nifr的小问题,params添加到控制器动作中,改变url格式,比如“Post $ post”现在包含在url中。你知道我只能对待http_row_post_data和post方法吗?就是说,只处理$ request-> getContent()我的json有效载荷在哪里 – iKonenn
这些似乎是两个不同的问题,对吧?您可以通过明确提供@Route或添加@NoRoute并将该路由的配置直接放入'routing.yml'中来防止控制器参数显示在url中。动作参数通常只添加到带有隐式路由/ URL命名的URL中。你用那个吗?我没有得到第二部分。你想访问控制器动作中的原始JSON负载? – nifr
对我来说,最好的选择是通过形式 实体水化所以,你必须动态验证过程调用您的水合实体。 错误处理已经存在等 – Mcsky