Symfony 针对特定异常注入闪存

Symfony 针对特定异常注入闪存,symfony,exception,controller,Symfony,Exception,Controller,我正在为所有已处理的应用程序错误扩展自定义异常 abstract class AbstractApplicationException extends \Exception { public function __construct(array $context = array()) { $this->context = $context; parent::__construct('exceptions.'.lcfirst(self::cla

我正在为所有已处理的应用程序错误扩展自定义异常

abstract class AbstractApplicationException extends \Exception
{
    public function __construct(array $context = array())
    {
        $this->context = $context;
        parent::__construct('exceptions.'.lcfirst(self::classname()));
    }
}
我使用messages.xx.yml向用户描述错误

exceptions:
    incompatibleSettings: Vos réglages ne sont pas compatibles
我想在AbstractApplicationException类异常上自动注入一个带有翻译消息的flash,这样我就不必在所有控制器上都这样做了

public myControllerAction()
    try {
        $someService->someFunction();
    } catch (AbstractApplicationException $e) {
        $flashBag->add('error',
            $this->get('translator')->trans(
                $e->getMessage(), $e->getContext()
            )
        );
    }
    $this->render('related_template.html.twig');
}
use ControllerTrait;

public myControllerAction()
    $this->tryFlash(function () (use $someParam) {
        $someService->someFunction($someParam);
    });
    $this->render('related_template.html.twig');
}

我知道如何使用侦听器重定向用户,但实际上我希望用户仅在注入闪存的情况下才能登录特定的操作响应。

您可以创建一个异常:

/**
 * Class ControllerTrait
 * @requirement The using class must be containerAware
 */
trait ControllerTrait {
    public function injectExceptionFlash(AbstractApplicationException $e) {
        if (!isset($this->container)) {
            throw new \Exception(sprintf('You must containerAware to use %s',
                __TRAIT__
            ));
        }
        $flashBag = $this->container->get('session')->getFlashBag();
        $flashBag->add('error',
            $this->container->get('translator')->trans(
                $e->getMessage(), $e->getContext()
            )
        );
    }

    public function tryFlash($lambda) {
        try {
            $lambda();
        } catch (AbstractApplicationException $e) {
            $this->injectExceptionFlash($e);
        }
    }
}
然后设置flash message并将用户重定向到所需的操作,该操作将呈现:

class AcmeExceptionListener
{
    /**
     * @var UrlGeneratorInterface
     */
    private $router;

    /**
     * @var SessionInterface
     */        
    private $session;

    public function __construct(UrlGeneratorInterface $router, SessionInterface $session)
    {
        $this->router  = $router;
        $this->session = $session;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();

        if ($exception instanceof YourExceptionType) {
            $this->session->getFlashBag()->add('error', $exception->getMessage());

            $event->setResponse(new RedirectResponse($this->router->generate('your_route')));    
        }
    }
}

但要小心:如果在异常处理过程中再次抛出ExceptionType,则最终会出现无限重定向循环。

您可以创建一个异常:

然后设置flash message并将用户重定向到所需的操作,该操作将呈现:

class AcmeExceptionListener
{
    /**
     * @var UrlGeneratorInterface
     */
    private $router;

    /**
     * @var SessionInterface
     */        
    private $session;

    public function __construct(UrlGeneratorInterface $router, SessionInterface $session)
    {
        $this->router  = $router;
        $this->session = $session;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();

        if ($exception instanceof YourExceptionType) {
            $this->session->getFlashBag()->add('error', $exception->getMessage());

            $event->setResponse(new RedirectResponse($this->router->generate('your_route')));    
        }
    }
}
但要小心:如果在异常处理过程中再次抛出ExceptionType,最终将导致无限重定向循环。

我最终使用了一个,以便能够在注入闪存的情况下继续执行控制器

/**
 * Class ControllerTrait
 * @requirement The using class must be containerAware
 */
trait ControllerTrait {
    public function injectExceptionFlash(AbstractApplicationException $e) {
        if (!isset($this->container)) {
            throw new \Exception(sprintf('You must containerAware to use %s',
                __TRAIT__
            ));
        }
        $flashBag = $this->container->get('session')->getFlashBag();
        $flashBag->add('error',
            $this->container->get('translator')->trans(
                $e->getMessage(), $e->getContext()
            )
        );
    }

    public function tryFlash($lambda) {
        try {
            $lambda();
        } catch (AbstractApplicationException $e) {
            $this->injectExceptionFlash($e);
        }
    }
}
下面是我如何从我的控制器使用它

public myControllerAction()
    try {
        $someService->someFunction();
    } catch (AbstractApplicationException $e) {
        $flashBag->add('error',
            $this->get('translator')->trans(
                $e->getMessage(), $e->getContext()
            )
        );
    }
    $this->render('related_template.html.twig');
}
use ControllerTrait;

public myControllerAction()
    $this->tryFlash(function () (use $someParam) {
        $someService->someFunction($someParam);
    });
    $this->render('related_template.html.twig');
}
tryFlash是一种快捷方式,使用来执行try/catch/flash作业

请毫不犹豫地告诉我某个地方是否存在不良做法

我最终使用了一个可以在注入闪存的情况下继续执行我的控制器

/**
 * Class ControllerTrait
 * @requirement The using class must be containerAware
 */
trait ControllerTrait {
    public function injectExceptionFlash(AbstractApplicationException $e) {
        if (!isset($this->container)) {
            throw new \Exception(sprintf('You must containerAware to use %s',
                __TRAIT__
            ));
        }
        $flashBag = $this->container->get('session')->getFlashBag();
        $flashBag->add('error',
            $this->container->get('translator')->trans(
                $e->getMessage(), $e->getContext()
            )
        );
    }

    public function tryFlash($lambda) {
        try {
            $lambda();
        } catch (AbstractApplicationException $e) {
            $this->injectExceptionFlash($e);
        }
    }
}
下面是我如何从我的控制器使用它

public myControllerAction()
    try {
        $someService->someFunction();
    } catch (AbstractApplicationException $e) {
        $flashBag->add('error',
            $this->get('translator')->trans(
                $e->getMessage(), $e->getContext()
            )
        );
    }
    $this->render('related_template.html.twig');
}
use ControllerTrait;

public myControllerAction()
    $this->tryFlash(function () (use $someParam) {
        $someService->someFunction($someParam);
    });
    $this->render('related_template.html.twig');
}
tryFlash是一种快捷方式,使用来执行try/catch/flash作业


如果某个地方有不好的做法,请毫不犹豫地告诉我

谢谢您的回答,此异常侦听器代码很有趣。最后,我使用了一个trait添加了一个try/catcher快捷方式,这样我就可以继续执行我的控制器,即返回相关的特定响应。我将在这里添加我的解决方案谢谢你的回答,这个异常侦听器代码很有趣。最后,我使用了一个trait添加了一个try/catcher快捷方式,这样我就可以继续执行我的控制器,即返回相关的特定响应。我将在这里添加我的解决方案