如何在Restful API中验证来自发布的数据

时间:2018-09-01 19:02:03

标签: php symfony model-view-controller code-structure symfony-validator

在插入数据库之前,我需要验证一些数据,为此,我创建了一个小服务,该服务从实体返回无效字段。验证单个实体时可以正常工作。

class EntityValidator
{
    protected $validator;

    public function __construct(ValidatorInterface $validator)
    {
        $this->validator = $validator;
    }

    public function validate($entity)
    {
        $errors = $this->validator->validate($entity);
        $response = null;
        if ($errors->count()) {
            foreach ($errors as $error) {
                $response[$error->getPropertyPath()] = $error->getMessage();
            }
        }

        return $response;
    }
}

但是我一直在努力验证更复杂的问题,例如: 这是一个宁静的api端点,它在帖子的正文中接收到带有user_id和percent的json,它将验证实体以查看是否正确,如symfony验证程序约束所映射。

public function create(Request $request, EntityValidator $entityValidator)
{
    $data = json_decode($request->getContent(), true);
    $entityExample = new EntityExample();
    $entityExample
         ->setUserId($data['user_id'])
         ->setPercentage($data['percentage'])
    ;
    $errors = $entityValidator->validate($entityExample);
    // .. do other things ..
    return new JsonResponse($errors);    
}

但是可以说我接收到一个数据数组,并且一次要插入很多行,并且有一个业务逻辑说“用户的百分比总和必须为100”

public function create(Request $request, EntityValidator $entityValidator)
{
    $data = json_decode($request->getContent(), true);
    $totalPercentage = 0;
    foreach ($data as $element) {
         $entityExample = new EntityExample();
         $entityExample
             ->setUserId($element['user_id'])
             ->setPercentage($element['percentage'])
         ;
         $totalPercentage += $element['percentage'];
    }
    $errors = $entityValidator->validate($entityExample);
    if ($totalPecentage != 100) {
        $errors[] = 'Sum of percentage must be 100';
    }
    // .. do other things ..
    return new JsonResponse($errors);    
}

在控制器中保留这种业务逻辑似乎是错误的,但是我不知道放在哪里,我是否应该为此专门创建服务?那么每个具有更复杂验证的端点都将创建一个新服务?

2 个答案:

答案 0 :(得分:3)

  1. 创建JSON请求有效负载的模型表示。具有公共属性的模型。例如假设模型称为Sale
  2. 创建一个自定义Validation Constraint,它将与Sale模型关联。在此验证类中,您将遍历Sale.percentage属性并运行验证逻辑。
  3. 在控制器中,您调用序列化程序组件和验证程序组件以验证请求。

上面每个点的完整示例:

  1. 下面的两个链接都有模型示例,但如果您想要更多示例,请在此页面http://www.inanzzz.com/index.php/posts/symfony中执行ctrl + f json
  2. Class level custom assert validation constraint in symfony
  3. A simple way of handling request, response and exceptions in Symfony API。复制并且不要触摸AbstractController。做UserController::create对您自己的控制器的作用。他在同一控制器中使用$this->data进行演示,但是您应该将其传递给服务并在其中进行处理。

答案 1 :(得分:0)

对于API验证,我们可以使用express-validator

用于安装使用 npm isntall --save express-validator

并使用此导入

const {check} = require('express-validator');

这里check是一个函数,它返回为我们的验证配置的中间件。 检查需要验证示例标题的请求正文 然后使用 check('title') 现在我们要检查它是否为空,所以我们将使用 check('title').not().isEmpty()

现在我们可以将其安装到路由器,并且它将在控制器运行之前运行

router.post('/',check('title').not().isEmpty(),placesControllers.createPlace);

现在要进行更多验证,我们需要将其保存在这样的数组中

router.post(
    '/',
    [
      check('title').not().isEmpty(),
      check('description').isLength({min: 5})
    ],
    placesControllers.createPlace
);

仅此一项是行不通的,您还应该在控制器中加入一些东西,将其导入

const {validationResult} =require('express-validator');

并在控制器的第一行添加

errors = validationResult(req);

您还可以通过以下方式处理错误

if(!errors.isEmpty()){
    //your error handler
  }

请参阅此链接以获取更多信息

express-validator