Вынос кода в Middleware

Использование посредников middleware для выноса повторяющегося инфраструктурного кода из контроллеров. Очистка ввода и централизованная обработка доменных исключений.

Скрытый контент
Комментарии (10)
Arunas
2020-03-26 17:29

Спасибо.

Ответить
Denis
2020-03-27 06:19

Добрый день.

А как быть с middleware, если мне надо для какого - то опредленного контроллера добавить что - то специфическое? Какую - то дополнительную обработку.

И еще вопрос - Вот получили мы запрос в коноллере и ручками теперь собираем все в команду. А можно как - то автоматизировать данный процесс? Допустим, есть такие вещи, как JmsSerializer или подобный пакет от Симфони, можно данные вещи использовать для заполнения команды? Оно там даже должно немного ругать на неверно заполненные поля. Ведь бывают ситуации, когда с фронта приходит не 2 поля а 10 -15 , а то и 35 (если есть большая бизнес логика).

Ответить
Дмитрий Елисеев
2020-03-28 07:29

Если для определённого, то привязывем через add() напрямую к маршруту или группе:

$app->get('/cabinet', CabinetAction::class)->add(AuthMiddleware::class);
Ответить
Дмитрий Елисеев
2020-03-28 07:30

Да, можно автоматизировать заполнение через symfony/serializer.

Ответить
Степанов алексей
2020-03-27 19:32

Здравствуйте Дмитрий, спасибо как всегда и вопрос, а в Симфони такое можно сделать только через EventSubscriberInterface и отлавливать kernel request я правильно понимаю?

или есть возможность упростить там? Спасибо!

Ответить
Дмитрий Елисеев
2020-03-28 07:35

Да, там нет middleware. Только через подписку на события kernel.controller и kernel.exception.

Ответить
uhamurad
2020-04-28 09:48

Допустим, у нас возникла острая необходимость все-таки оставить значение одного из параметров запроса неизменным и не применять к нему мидлвар ClearEmptyInput (например, вводимый пользователь пароль может содержать пробел в любом месте). Как лучше всего поступить в данном случае, чтобы не вычеркивать мидлвар ClearEmptyInput из общего списка обработчиков в /api/config/middleware.php?

Мой вариант:

1) Создать объект, например, ClearEmptyInputRules, который содержит правила исключения параметров запроса из обработки: метод except будет добавлять исключение, а метод check проверять запрос на то, можно ли к нему применить фильтрацию

class ClearEmptyInputRules
{
	private array $exceptRules = [];

	public function except($method, $uri, $paramName) 
	{
	    $this->exceptRules[] = [$method, $uri, $paramName];
	}

	public function check(ServerRequestInterface $request, String $paramName) 
	{
		foreach ($this->exceptRules as $rule])
		{
			if (
				$request->getMenthod() == $rule[0]
				&& $request->getUri() == $rule[1]
				&& $paramName == $rule[2]
			)
			{
				return false;
			}
		}
		return true;
	}
}

2) В конфигах контейнера зависимостей вписать необходимые нам правила (например, в файл /api/config/common/inputFilters.php)

return [
	ClearEmptyInputRules::class => static function (ContainerInterface $container) {

	    $rules = new ClearEmptyInputRules();

	    $rules->except('POST', 'v1/api/auth/login', 'password');

	    return $rules;
	},
];

3) Добавить в класс ClearEmptyInput зависимость от ClearEmptyInputRules

class ClearEmptyInput implements MiddlewareInterface
{    
	
	//+++++++++
	private ClearEmptyInputRules $rules;

	//+++++++++
	public function __constructor(ClearEmptyInputRules $rules) 
	{
	    $this->rules = $rules;
	}

	public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
	{

		//+++++++++
		if ($this->rules->check($request)){

			$request = $request
				->withParsedBody(self::filterStrings($request->getParsedBody()))
				->withUploadedFiles(self::filterFiles($request->getUploadedFiles()));

		}

		return $handler->handle($request);
	}   
	
}

(Код писал не самым оптимальным образом - скорее, чтоб он был наглядным)

Я в правильном направлении думаю?

Ответить
Дмитрий Елисеев
2020-05-01 10:37

Да, можно по-разному:

  • Убрать из общего списка и применять к каждому нужному маршруту вручную.
  • Добавить поле $except (как сделано в Laravel) или $rules как у вас прямо в middleware.
  • Сделать обёртку Except или RulesMiddleware и оборачивать им любой оригинальный middleware.
Ответить
Dmitriy
2020-05-10 16:07

Я заметил, что вы много где используете приватные статичные методы и потом обращаетесь к ним через self. Не могу понять в чем тут выигрыш перед обычными приватными методами и this. Подскажите пожалуйста.

Ответить
Дмитрий Елисеев
2020-05-13 11:23

Обычный динамический метод привязан к каждому экземпляру объекта $this.

Статический же - это по сути просто функция, записанная в классе.

Так что если нам нужна функция, которой не нужен сам текущий объект $this, то нет особого смысла её делать динамическим методом.

Ответить
Зарегистрируйтесь или войдите чтобы оставить комментарий