Symfony 5.3 如何 return 来自前过滤器(EventSubscriberInterface)的 JSON 响应并设置变量以在控制器中访问?
Symfony 5.3 How to return a JSON response from a Before Filter (EventSubscriberInterface) and set Variable to access in Controller?
我正在创建一个 API 并想对每个端点进行一些检查,因此我决定将它放在中心位置以不重复任何代码。我创建了一个事件订阅者。现在的问题是,当 try catch 失败时,我如何 return 对 API 的 JSON 响应绕过控制器,其次,我如何将变量 $confirm 传递给控制器它成功了吗?这可以实现吗?
更新
它现在正在工作,我自己想出了另一点。我已经用更改更新了源代码,以防其他人需要它(检查更新评论)。我希望这也是正确的 Symfony 方法,即使它有效。再次感谢 Rova Ram!
<?php
namespace App\EventSubscriber;
use App\Controller\ApiCheckController;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\HttpFoundation\JsonResponse;
use Doctrine\ORM\EntityManagerInterface;
class ApiSubscriber implements EventSubscriberInterface
{
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public function onKernelController(ControllerEvent $event)
{
$controller = $event->getController();
// UPDATE add below line
$request = $event->getRequest();
// when a controller class defines multiple action methods, the controller
// is returned as [$controllerInstance, 'methodName']
if (is_array($controller)) {
$controller = $controller[0];
}
if ($controller instanceof \App\Controller\ApiCheckController) {
try {
$confirm = $this->confirmRequest($someData);
// UPDATE add below this way confirm will be available
// in the Controller via $confirm= $request->get('confirm');
$request->attributes->set('confirm', $confirm );
}
catch(\Exception $e) {
$payload = array(
"status" => "error",
"message" => $e->getMessage(),
);
// UPDATE replace below
// return new JsonResponse($payload, JsonResponse::HTTP_BAD_REQUEST);
// instead use
return $event->setController( function () use($payload) {
return new JsonResponse($payload, JsonResponse::HTTP_BAD_REQUEST);
} );
}
public static function getSubscribedEvents()
{
return [
KernelEvents::CONTROLLER => 'onKernelController'
];
}
}
尝试像这样返回您的 JSON 回复
$event->setController( function () use () {
return new JsonResponse();
} );
我正在创建一个 API 并想对每个端点进行一些检查,因此我决定将它放在中心位置以不重复任何代码。我创建了一个事件订阅者。现在的问题是,当 try catch 失败时,我如何 return 对 API 的 JSON 响应绕过控制器,其次,我如何将变量 $confirm 传递给控制器它成功了吗?这可以实现吗?
更新 它现在正在工作,我自己想出了另一点。我已经用更改更新了源代码,以防其他人需要它(检查更新评论)。我希望这也是正确的 Symfony 方法,即使它有效。再次感谢 Rova Ram!
<?php
namespace App\EventSubscriber;
use App\Controller\ApiCheckController;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\HttpFoundation\JsonResponse;
use Doctrine\ORM\EntityManagerInterface;
class ApiSubscriber implements EventSubscriberInterface
{
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public function onKernelController(ControllerEvent $event)
{
$controller = $event->getController();
// UPDATE add below line
$request = $event->getRequest();
// when a controller class defines multiple action methods, the controller
// is returned as [$controllerInstance, 'methodName']
if (is_array($controller)) {
$controller = $controller[0];
}
if ($controller instanceof \App\Controller\ApiCheckController) {
try {
$confirm = $this->confirmRequest($someData);
// UPDATE add below this way confirm will be available
// in the Controller via $confirm= $request->get('confirm');
$request->attributes->set('confirm', $confirm );
}
catch(\Exception $e) {
$payload = array(
"status" => "error",
"message" => $e->getMessage(),
);
// UPDATE replace below
// return new JsonResponse($payload, JsonResponse::HTTP_BAD_REQUEST);
// instead use
return $event->setController( function () use($payload) {
return new JsonResponse($payload, JsonResponse::HTTP_BAD_REQUEST);
} );
}
public static function getSubscribedEvents()
{
return [
KernelEvents::CONTROLLER => 'onKernelController'
];
}
}
尝试像这样返回您的 JSON 回复
$event->setController( function () use () {
return new JsonResponse();
} );