Zend Framework 3 错误处理
Zend Framework 3 error handling
我正在尝试处理 ZF3 中 CheckAccess 插件的错误。
插件在模块的 onBootstrap 方法中是这样附加的
class Module {
public function onBootstrap()
{
...
$em->attach(MvcEvent::EVENT_DISPATCH, new Plugin\CheckAccess($sm), 2);
...
}
}
当我需要将未登录的用户从某个页面重定向到登录页面时,我正是在插件的 __invoke() 中做的:
if ($user->isGuest()) {
$rh = new RouteHelper($e->getRouter(), $e->getRouteMatch());
$url = $rh->frontend('auth', 'login') . '?request=' . urlencode($request->getRequestUri());
throw new HttpRedirectException(HttpRedirectException::SEE_OTHER_303, $url);
} else {
throw new HttpClientException(HttpClientException::FORBIDDEN_403);
}
}
问题是那些异常导致应用程序崩溃。我的意思是框架中没有对此类异常的任何处理。而且我没有在文档中找到任何帮助。我该如何解决?我想应该有一些关于 "correct" zf 中访问检查和访问异常处理的最佳实践。
我从未见过有人为此抛出异常,尤其是 HttpRedirectException 和 HttpClientException,所以不幸的是我现在没有答案。
您可以通过更简洁、更轻松的方式实现您想要的效果,而无需抛出异常。你可以这样做:
$sharedEventManager->attach(AbstractActionController::class,
MvcEvent::EVENT_DISPATCH, [$this, 'onDispatch'], 100);
然后检查用户是否登录,并基于此使用此重定向方法:
/**
* Event listener method for the 'Dispatch' event. We listen to the Dispatch
* event to call the access filter. The access filter allows to determine if
* the current visitor is allowed to see the page or not. If he/she
* is not authorized and is not allowed to see the page, we redirect the user
* to the login page.
*/
public function onDispatch(MvcEvent $event)
{
// Get controller and action to which the HTTP request was dispatched.
$controller = $event->getTarget();
$controllerName = $event->getRouteMatch()->getParam('controller', null);
$actionName = $event->getRouteMatch()->getParam('action', null);
// Convert dash-style action name to camel-case.
$actionName = str_replace('-', '', lcfirst(ucwords($actionName, '-')));
// Get the instance of AuthManager service.
$authManager = $event->getApplication()->getServiceManager()->get(AuthManager::class);
// Execute the access filter on every controller except AuthController
// (to avoid infinite redirect).
if ($controllerName!=AuthController::class)
{
$result = $authManager->filterAccess($controllerName, $actionName);
if ($result==AuthManager::AUTH_REQUIRED) {
// Remember the URL of the page the user tried to access. We will
// redirect the user to that URL after successful login.
$uri = $event->getApplication()->getRequest()->getUri();
// Make the URL relative (remove scheme, user info, host name and port)
// to avoid redirecting to other domain by a malicious user.
$uri->setScheme(null)
->setHost(null)
->setPort(null)
->setUserInfo(null);
$redirectUrl = $uri->toString();
// Redirect the user to the "Login" page.
return $controller->redirect()->toRoute('login', [],
['query'=>['redirectUrl'=>$redirectUrl]]);
}
else if ($result==AuthManager::ACCESS_DENIED) {
// Redirect the user to the "Not Authorized" page.
return $controller->redirect()->toRoute('not-authorized');
}
}
}
如您所见,这只是一个示例,但非常简单明了,您也检查了 ACL,无需抛出异常...
然而,为了拦截所有异常,我会做(并且我会做)的是附加以下内容:
// The "init" method is called on application start-up and
// allows to register an event listener.
public function init(ModuleManager $manager)
{
// Get event manager.
$eventManager = $manager->getEventManager();
$sharedEventManager = $eventManager->getSharedManager();
// Register the event listener method.
$sharedEventManager->attach(__NAMESPACE__, MvcEvent::EVENT_DISPATCH_ERROR,
[$this, 'onError'], 100);
$sharedEventManager->attach(__NAMESPACE__, MvcEvent::EVENT_RENDER_ERROR,
[$this, 'onError'], 100);
}
// Event listener method.
public function onError(MvcEvent $event)
{
// Get the exception information.
$exception = $event->getParam('exception');
if ($exception!=null) {
$exceptionName = $exception->getMessage();
$file = $exception->getFile();
$line = $exception->getLine();
$stackTrace = $exception->getTraceAsString();
}
$errorMessage = $event->getError();
$controllerName = $event->getController();
// Prepare email message.
$to = 'admin@yourdomain.com';
$subject = 'Your Website Exception';
$body = '';
if(isset($_SERVER['REQUEST_URI'])) {
$body .= "Request URI: " . $_SERVER['REQUEST_URI'] . "\n\n";
}
$body .= "Controller: $controllerName\n";
$body .= "Error message: $errorMessage\n";
if ($exception!=null) {
$body .= "Exception: $exceptionName\n";
$body .= "File: $file\n";
$body .= "Line: $line\n";
$body .= "Stack trace:\n\n" . $stackTrace;
}
$body = str_replace("\n", "<br>", $body);
// Send an email about the error.
mail($to, $subject, $body);
}
这会捕获所有错误,甚至会向您发送电子邮件!哈哈
我希望这些片段能帮助您了解如何更好地使用 ZF3 进行开发。
这些片段的来源是 olegkrivtsov。
我正在尝试处理 ZF3 中 CheckAccess 插件的错误。
插件在模块的 onBootstrap 方法中是这样附加的
class Module {
public function onBootstrap()
{
...
$em->attach(MvcEvent::EVENT_DISPATCH, new Plugin\CheckAccess($sm), 2);
...
}
}
当我需要将未登录的用户从某个页面重定向到登录页面时,我正是在插件的 __invoke() 中做的:
if ($user->isGuest()) {
$rh = new RouteHelper($e->getRouter(), $e->getRouteMatch());
$url = $rh->frontend('auth', 'login') . '?request=' . urlencode($request->getRequestUri());
throw new HttpRedirectException(HttpRedirectException::SEE_OTHER_303, $url);
} else {
throw new HttpClientException(HttpClientException::FORBIDDEN_403);
}
}
问题是那些异常导致应用程序崩溃。我的意思是框架中没有对此类异常的任何处理。而且我没有在文档中找到任何帮助。我该如何解决?我想应该有一些关于 "correct" zf 中访问检查和访问异常处理的最佳实践。
我从未见过有人为此抛出异常,尤其是 HttpRedirectException 和 HttpClientException,所以不幸的是我现在没有答案。
您可以通过更简洁、更轻松的方式实现您想要的效果,而无需抛出异常。你可以这样做:
$sharedEventManager->attach(AbstractActionController::class,
MvcEvent::EVENT_DISPATCH, [$this, 'onDispatch'], 100);
然后检查用户是否登录,并基于此使用此重定向方法:
/**
* Event listener method for the 'Dispatch' event. We listen to the Dispatch
* event to call the access filter. The access filter allows to determine if
* the current visitor is allowed to see the page or not. If he/she
* is not authorized and is not allowed to see the page, we redirect the user
* to the login page.
*/
public function onDispatch(MvcEvent $event)
{
// Get controller and action to which the HTTP request was dispatched.
$controller = $event->getTarget();
$controllerName = $event->getRouteMatch()->getParam('controller', null);
$actionName = $event->getRouteMatch()->getParam('action', null);
// Convert dash-style action name to camel-case.
$actionName = str_replace('-', '', lcfirst(ucwords($actionName, '-')));
// Get the instance of AuthManager service.
$authManager = $event->getApplication()->getServiceManager()->get(AuthManager::class);
// Execute the access filter on every controller except AuthController
// (to avoid infinite redirect).
if ($controllerName!=AuthController::class)
{
$result = $authManager->filterAccess($controllerName, $actionName);
if ($result==AuthManager::AUTH_REQUIRED) {
// Remember the URL of the page the user tried to access. We will
// redirect the user to that URL after successful login.
$uri = $event->getApplication()->getRequest()->getUri();
// Make the URL relative (remove scheme, user info, host name and port)
// to avoid redirecting to other domain by a malicious user.
$uri->setScheme(null)
->setHost(null)
->setPort(null)
->setUserInfo(null);
$redirectUrl = $uri->toString();
// Redirect the user to the "Login" page.
return $controller->redirect()->toRoute('login', [],
['query'=>['redirectUrl'=>$redirectUrl]]);
}
else if ($result==AuthManager::ACCESS_DENIED) {
// Redirect the user to the "Not Authorized" page.
return $controller->redirect()->toRoute('not-authorized');
}
}
}
如您所见,这只是一个示例,但非常简单明了,您也检查了 ACL,无需抛出异常...
然而,为了拦截所有异常,我会做(并且我会做)的是附加以下内容:
// The "init" method is called on application start-up and
// allows to register an event listener.
public function init(ModuleManager $manager)
{
// Get event manager.
$eventManager = $manager->getEventManager();
$sharedEventManager = $eventManager->getSharedManager();
// Register the event listener method.
$sharedEventManager->attach(__NAMESPACE__, MvcEvent::EVENT_DISPATCH_ERROR,
[$this, 'onError'], 100);
$sharedEventManager->attach(__NAMESPACE__, MvcEvent::EVENT_RENDER_ERROR,
[$this, 'onError'], 100);
}
// Event listener method.
public function onError(MvcEvent $event)
{
// Get the exception information.
$exception = $event->getParam('exception');
if ($exception!=null) {
$exceptionName = $exception->getMessage();
$file = $exception->getFile();
$line = $exception->getLine();
$stackTrace = $exception->getTraceAsString();
}
$errorMessage = $event->getError();
$controllerName = $event->getController();
// Prepare email message.
$to = 'admin@yourdomain.com';
$subject = 'Your Website Exception';
$body = '';
if(isset($_SERVER['REQUEST_URI'])) {
$body .= "Request URI: " . $_SERVER['REQUEST_URI'] . "\n\n";
}
$body .= "Controller: $controllerName\n";
$body .= "Error message: $errorMessage\n";
if ($exception!=null) {
$body .= "Exception: $exceptionName\n";
$body .= "File: $file\n";
$body .= "Line: $line\n";
$body .= "Stack trace:\n\n" . $stackTrace;
}
$body = str_replace("\n", "<br>", $body);
// Send an email about the error.
mail($to, $subject, $body);
}
这会捕获所有错误,甚至会向您发送电子邮件!哈哈
我希望这些片段能帮助您了解如何更好地使用 ZF3 进行开发。
这些片段的来源是 olegkrivtsov。