error-handling - 如何使用 ZF2 的自定义异常页面?

标签 error-handling zend-framework2 redirect

我需要从名为 Admin 的模块的 Module.php 中将用户重定向到错误页面 (view/error/403.phtml) 当不允许用户访问特定资源时。我一直在寻找解决方案,但到目前为止没有成功。我找到的最好的是 this question ,接受的答案对我不起作用(我目前无法向链接的问题添加评论,因为我没有所需的信誉级别) - 页面显示为好像根本没有重定向和用户被允许访问它。我尝试用一​​个简单的 die; 替换重定向代码来测试 isAllowed() 是否正常工作,并且它正确显示了一个空白页面,所以问题出在在重定向本身。

Module.php中的相关代码为:

public function onBootstrap(MvcEvent $e)
{
    $this->initAcl($e);
    $eventManager = $e->getApplication()->getEventManager();

    $eventManager->attach('route', array($this, 'checkAcl'));
    $moduleRouteListener = new ModuleRouteListener();
    $moduleRouteListener->attach($eventManager);
}

public function checkAcl(MvcEvent $e)
{
    // ...

    if (!$this->acl->isAllowed($userRole, $controller, $privilege))
    {
        $response = $e->getResponse();
        $response->setHeaders($response->getHeaders()->addHeaderLine('Location', $e->getRequest()->getBaseurl() . '/error/403'));
        $response->setStatusCode(403);
        $response->sendHeaders();
    }

    // ...
}

module.config.php

'view_manager' => array(
    'display_exceptions' => true,
    'exception_template' => 'error/403',
    'template_map' => array(
        'layout/layout'           => __DIR__ . '/../view/layout/admin_layout.phtml',
        'error/403'               => __DIR__ . '/../view/error/403.phtml',
        'error/404'               => __DIR__ . '/../view/error/404.phtml',
        'error/index'             => __DIR__ . '/../view/error/index.phtml',
    ),
    'template_path_stack' => array(
        'Admin' => __DIR__ . '/../view',
    ),
    'strategies' => array(
        'ViewJsonStrategy',
    ),
),

如果我添加行

throw new \Exception($translator->translate('Access denied'));

在重定向代码之后,我确实被重定向到 URL http://[servername]/error/403,但是页面的内容是,而不是我自定义的 403 .phtml,一个样式化(带布局)的 404 错误页面,指出“路由无法匹配请求的 URL。”

最佳答案

实现您想要的效果的更好方法是在您的 checkAcl 函数中触发一个 dispatch.error 事件,而不是尝试进行重定向。然后您可以处理此事件并显示 403 页面。

触发事件:

if (!$this->acl->isAllowed($userRole, $controller, $privilege))
{
    $app = $e->getTarget();
    $route = $e->getRouteMatch();

    $e->setError('ACL_ACCESS_DENIED') // Pick your own value, would be better to use a const
      ->setParam('route', $route->getMatchedRouteName());
    $app->getEventManager()->trigger('dispatch.error', $e);
}

然后在您的 onBootstrap 中为 dispatch.error 事件添加一个监听器:

use Zend\Mvc\MvcEvent;
...

$eventManager->attach(MvcEvent::EVENT_DISPATCH_ERROR, <any callable>, -999);

在您刚刚附加到的 dispatch.error 事件的回调中:

$error = $event->getError();

if (empty($error) || $error != "ACL_ACCESS_DENIED") {
    return;
}

$result = $event->getResult();

if ($result instanceof StdResponse) {
    return;
}

$baseModel = new ViewModel();
$baseModel->setTemplate('layout/layout');

$model = new ViewModel();
$model->setTemplate('error/403');

$baseModel->addChild($model);
$baseModel->setTerminal(true);

$event->setViewModel($baseModel);

$response = $event->getResponse();
$response->setStatusCode(403);

$event->setResponse($response);
$event->setResult($baseModel);

return false;

关于error-handling - 如何使用 ZF2 的自定义异常页面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20711562/

相关文章:

c++ - 用户输入整数 - 错误处理

php - ZF2 转发电子邮件 (Zend\Mail\Storage\Message)

php - ZF2 分页器不显示最后一页

zend-framework2 - Zend Framework-2 : Best way to protect all Controllers?(ZfcUser/HybridAuth)

ruby-on-rails-3 - 设计和存储位置_为 : how do you store the return location?

mysql - Node - 查询处理完成后无法重定向(或者在处理完成之前重定向......或者......啊)

spring - 如何使DispatcherServlet初始化错误从嵌入式Jetty冒出来?

rest - RESTful Web服务: Handle invalid uri - 404 Error

actionscript-3 - 错误1010 ActionScript 3

redirect -/news 和/news/是两个不同的页面吗?