Как вызвать другую внутреннюю конечную точку из приложения Zend Expressive REST API?

Я пытаюсь вызвать конечную точку API REST (внутреннюю) из другого метода в приложении Zend Expressive (PSR-7). В настоящее время я отправляю еще один http-запрос, подобный этому (docs):

$request = (new Zend\Diactoros\Request())
    ->withUri(new Zend\Diactoros\Uri('http://example.com'))
    ->withMethod('PATCH')
    ->withAddedHeader('Authorization', 'Bearer ' . $token)
    ->withAddedHeader('Content-Type', 'application/json');

$request->getBody()->write(json_encode($data));
$response = $client->send($request);

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

URL-адрес конечной точки и тип запроса извлекаются из базы данных. Я могу вызвать метод напрямую, но переадресация конечной точки уменьшит работу, необходимую для условной проверки каждого модуля.

Ценю, если бы вы могли указать мне в правильном направлении.

Обновление:

Позвольте мне объяснить вариант использования. У нас есть база данных планировщика, которая содержит конечные точки и параметры для отправки. Запрос cURL отправляется в API планировщика каждые 5 минут (CRON). Планировщик проверяет интервал, указанный в базе данных, и запускает соответствующие конечные точки в этот интервал.


person Sanju    schedule 18.12.2019    source источник


Ответы (2)


Итак, если я правильно понимаю, ваш API получает набор команд и набор параметров для каждой команды. Я бы создал отдельный класс для каждой команды, и класс, содержащий сопоставление, вы могли бы рассматривать его как фабрику.

API:

public function handle(ServerRequestInterface $request): ResponseInterface
{
    $parameters = $request->getAttribute('parameters');
    foreach($request->getAttribute('commands') as $commandName){
        $commandClass = CommandsMappingClass::getClassForCommand($commandName);

        //you can save the response if you need to
        (new $commandClass())->__invoke($parameters[$commandName]);
    }


}

CommandsMappingClass:

    private const MAPPING = [
        'command1' => Command1::class,
    ];

    public static function getClassForCommand(string $commandName): ?string
    {
       //you can return a default command if you need to 
        return self::MAPPING[$commandName] ?? null;
    }

Это элементарное решение. Отображение можно рассматривать как динамический реестр, и каждый модуль вашего приложения может добавить в него команду задания cron (разумеется, команды не будут храниться в константе). См. https://docs.zendframework.com/zend-servicemanager/delegators/.

person Razvan Ionascu    schedule 03.01.2020

Первый метод, который приходит мне на ум, — преобразовать текущий класс (вероятно, реализацию RequestHandleInterface) в промежуточное ПО (MiddlewareInterface) и изменить определение маршрута. Вместо RequestHandler::class у вас будет [Middleware::class, RequestHandler::class] (например, [EditEntityMiddleware::class, GetEntityHandler::class]). Если вам нужно передать информацию из промежуточного программного обеспечения в обработчик, вы просто добавляете его в запрос:

return $handler->handle($request->withAttribute('newInfo' => $newInfo));

Чтобы получить доступ к информации в обработчике запроса:

$newInfo = $request->getAttribute('newInfo');

Этот API должен реагировать намного быстрее, но если у вас много конечных точек, может быть сложно добавлять/редактировать множество маршрутов.

Если вы дадите нам более убедительный пример, мы могли бы дать лучшие ответы. Я столкнулся с той же ситуацией при редактировании объекта, поскольку мне нужно было внести изменения в базу данных и вернуть новый объект. Для EditHandler я только что расширил GetEntityHandler (метод "handle"). Сначала я обновил объект базы данных, а затем просто вызвал return parent::handle($request), который возвращает новый объект базы данных.

person Razvan Ionascu    schedule 31.12.2019