手动触发404错误
我一直在努力从另一个控制器监听器中手动触发dispatch.error
。手动触发404错误
目标是提出一个404错误,其中路由参数无效,并使其被标准Zend\Mvc\View\Http\RouteNotFoundStrategy
“抓住”,以便呈现404页面。
public function FooController extends AbstractActionController
{
protected $foo;
public function getEventManager()
{
$em = parent::getEventManager();
// Attach with higher priority than dispatched indexAction
$em->attach('dispatch', array($this, 'getFooFromRouteParam'), 10);
}
public function indexAction()
{
$foo = $this->getFoo(); // Error 500 (not 400)
}
public function getFooFromRouteParam(EventInterface $event)
{
$id = $this->params('id', false);
if (! empty($id)) {
$foo = $this->aDatabaseService->loadFromTheDatabase($id);
if ($foo instanceof Foo) {
$this->setFoo($foo);
return;
}
}
$response = $event->getResponse();
$response->setStatusCode(404);
$event->setError(\Zend\Mvc\Application::ERROR_ROUTER_NO_MATCH);
$event->getApplication()
->getEventManager()
->trigger('dispatch.error', $event);
//return $response;
}
public function getObjectFoo()
{
if (null == $this->foo) {
throw new \RuntimeException('foo not set');
}
return $this->foo;
}
public fucntion setObjectFoo(Foo $object)
{
$this->foo = $object;
}
}
事件被正确触发,调试他们给了我:
CALLED
Zend\Mvc\View\Http\RouteNotFoundStrategy::detectNotFoundError
(错误是:error-controller-not-found
)CALLED
Zend\Mvc\View\Http\RouteNotFoundStrategy::prepareNotFoundViewModel
CALLEDZend\Mvc\View\Http\RouteNotFoundStrategy::injectNotFoundReason
但是,返回后的回应给我一个404
没有身体。
return $response; // ends execution with 404 but no body, just white screen.
如果我不回调度继续响应,我得到一个500
错误
RuntimeException的“富不设置”
我如何可以手动触发一个404错误,正确渲染404模板?
终于成功地找出问题。
Zend\Mvc\Controller\AbstractController
方法预计将返回一个Response
它将停止执行控制器的事件。
这是dispatch
方法的相关部分。
$result = $this->getEventManager()->trigger(MvcEvent::EVENT_DISPATCH, $e,
function ($test) {
return ($test instanceof Response);
}
);
if ($result->stopped()) {
return $result->last();
}
return $e->getResult();
我需要什么做的是回到我的结果(这是错误的视图模型)和手动停止事件传播(以确保剩余的控制器操作未执行)
// Set the event's 'error' vars
$event->setError(Application::ERROR_EXCEPTION);
$event->setParam('exception', new \Exception('A custom error message here'));
// Trigger the dispatch.error event
$event->getApplication()
->getEventManager()
->trigger(MvcEvent::EVENT_DISPATCH_ERROR, $event);
// The missing piece! Required to ensure the remaining dispatch
// listeners are not triggered
$event->stopPropagation(true);
// Contains the view model that was set via the ExceptionStrategy
return $event->getResult();
我不认为你可以,也不应该。当你在控制器中时,路由器已经完成了它的工作,所以回到Zend\Mvc\View\Http\RouteNotFoundStrategy
将不起作用。
你应该做的是使路由中所需的参数,所以路由器会为你做检查。
如果您已经考虑过这个,但是仍然要使用请求处理错误404响应,看看实际DispatchListener如何处理这个吧:
$event->setError($application::ERROR_EXCEPTION)
->setController($controllerName)
->setParam('exception', $exception);
$events = $application->getEventManager();
$results = $events->trigger(MvcEvent::EVENT_DISPATCH_ERROR, $event);
$return = $results->last();
if (! $return) {
$return = $event->getResult();
}
对于Zend框架3
TRIGER 404 manuely在控制器并把它在错误监听:
public function articleAction()
{
// For eg. if we can not found article fetched by url_slug
if(!$article){
$this->getResponse()->setStatusCode(404);
$this->getEvent()->setName(MvcEvent::EVENT_DISPATCH_ERROR);
$this->getEvent()->getApplication()->getEventManager()->triggerEvent($this->getEvent());
return false;
}
return ['article' => $article];
}
感谢您的意见。路由参数实际上已经是必需的参数;如果没有提供,它将会404。问题是我需要使用它加载一个对象,如果该对象无效,那么404。 – AlexP 2014-08-29 10:10:49
这不是404,因为请求匹配一个动作,并且处理请求时出现问题。 404是专门为无法匹配的请求而设计的。 在这种情况下,我会重定向一个错误消息(即:flash消息) – NDM 2014-08-29 10:17:38
HTTP响应需要为'404'。不过,我认为你可能是正确的实施细节。而不是处理'RouteNotFoundStrategy'内的错误,我应该在'ExceptionStrategy'内执行。这将允许我捕获自定义错误,以不同方式解释并仍返回404 HTTP响应。我会回报。 – AlexP 2014-08-29 10:43:09