Как проверить данные из поста в успокоительном API

Мне нужно проверить некоторые данные перед вставкой в ​​базу данных, для этого я создаю небольшой сервис, который возвращает недействительные поля от сущности. Это работает нормально при проверке отдельных объектов.

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 успокоительного, которая получает json с user_id и процентом в теле сообщения, она проверит сущность, чтобы увидеть, правильно ли она сопоставлена ​​с ограничителями валидатора 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);    
}

Кажется неправильным хранить подобную бизнес-логику в контроллере, но я не знаю, где ее разместить. Нужно ли создавать службу только для этого? тогда каждая конечная точка, которая имеет более сложную проверку, будет создавать новый сервис?

1 ответ

Решение
  1. Создайте модельное представление полезной нагрузки вашего запроса JSON. Модель с публичными свойствами и больше ничего. Например, скажем, модель называется Sale,
  2. Создайте пользовательское ограничение проверки, которое будет связано с Sale модель. В этом классе валидации вы бы перебрали Sale.percentage свойство и запустить вашу логику проверки.
  3. В вашем контроллере вы вызываете компонент сериализатора и компонент валидатора для проверки запроса.

Полные примеры для каждого пункта выше:

  1. Обе ссылки ниже имеют примеры моделей, но если вы хотите больше примеров, просто нажмите Ctrl+ F json на этой странице http://www.inanzzz.com/index.php/posts/symfony
  2. Пользовательское ограничение проверки уровня класса в Symfony
  3. Простой способ обработки запросов, ответов и исключений в Symfony API. Скопируйте и не трогайте AbstractController, Что делать UserController::create делает для вашего собственного контроллера. Он использует $this->data в демонстрационных целях на том же контроллере, но вы должны передать его службе и обработать там.

Для проверки 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
  }

Перейдите по этой ссылке для получения дополнительной информации

экспресс-валидатор

Другие вопросы по тегам