默认情况下,如果响应状态代码设置为404,ZF2将呈现404页面。
给出以下代码:
/** @var \Zend\Http\Response $response */
$response = $this->getResponse();
$response->setStatusCode( 404 );
$posts = null;
/**
* If we have a slug, try to load posts by the author.
*/
if( $this->params( 'slug' ) )
{
$posts = $this->postService->findMoreByAuthorSlug( $slug, 5 );
}
$vm = new ViewModel( compact( 'posts' ) );
$vm->setTemplate( 'posts/notfound' );
return $vm;
Zf2的RouteNotFoundStrategy将拦截ViewModel
并将其替换为可自定义的404。
有没有办法阻止这种情况?
我们试过像这样分开它:
$sm = $this->getServiceLocator();
/** @var \Zend\EventManager\EventManager $eventManager */
$eventManager = $sm->get('Application')->getEventManager();
/** @var \Zend\Mvc\View\Http\ViewManager $viewManager */
$viewManager = $sm->get('HttpViewManager');
$viewManager->getRouteNotFoundStrategy()->detach( $eventManager );
$eventManager->detach( $viewManager->getRouteNotFoundStrategy() );
由\ Zend \ Mvc \ View \ Http \ ViewManager:
注册 $routeNotFoundStrategy = $this->getRouteNotFoundStrategy();
$exceptionStrategy = $this->getExceptionStrategy();
$mvcRenderingStrategy = $this->getMvcRenderingStrategy();
$createViewModelListener = new CreateViewModelListener();
$injectTemplateListener = new InjectTemplateListener();
$injectViewModelListener = new InjectViewModelListener();
$this->registerMvcRenderingStrategies($events);
$this->registerViewStrategies();
$events->attach($routeNotFoundStrategy);
$events->attach($exceptionStrategy);
$events->attach(MvcEvent::EVENT_DISPATCH_ERROR, array($injectViewModelListener, 'injectViewModel'), -100);
$events->attach(MvcEvent::EVENT_RENDER_ERROR, array($injectViewModelListener, 'injectViewModel'), -100);
$events->attach($mvcRenderingStrategy);
$sharedEvents->attach('Zend\Stdlib\DispatchableInterface', MvcEvent::EVENT_DISPATCH, array($createViewModelListener, 'createViewModelFromArray'), -80);
$sharedEvents->attach('Zend\Stdlib\DispatchableInterface', MvcEvent::EVENT_DISPATCH, array($routeNotFoundStrategy, 'prepareNotFoundViewModel'), -90);
修改
策略检查控制器是否返回响应或视图模型。以下内容可行,但我不想在控制器中呈现html。
$vm = new ViewModel();
$vm->setVariables( compact( 'posts' ) );
$vm->setTemplate( 'posts/notfound' );
$viewRender = $this->getServiceLocator()->get( 'ViewRenderer' );
$layout = new ViewModel();
$layout->setTemplate( "layout/main" );
$layout->setVariable( "content", $viewRender->render( $vm ) );
$response->setContent( $viewRender->render( $layout ) );
return $response;
答案 0 :(得分:1)
好的,看起来共享事件的回调处理程序由于某种原因未存储在聚合侦听器(RouteNotFoundStrategy
)中。所以,你仍然可以删除策略,但它有点hacky:
<?php
namespace App;
use Zend\Mvc\MvcEvent;
use Zend\Stdlib\CallbackHandler;
class Module
{
public function onBootstrap(MvcEvent $event)
{
if (PHP_SAPI == 'cli')
{
return;
}
$app = $event->getApplication();
$services = $app->getServiceManager();
$events = $app->getEventManager();
$sharedEvents = $events->getSharedManager();
$listener = $services->get('Zend\Mvc\View\RouteNotFoundStrategy');
$events->detach($listener);
/** @var CallbackHandler[] $handlers */
$handlers = $sharedEvents->getListeners('Zend\Stdlib\DispatchableInterface', MvcEvent::EVENT_DISPATCH);
foreach ($handlers as $handler)
{
$callback = $handler->getCallback();
if (is_array($callback) && $callback[0] === $listener)
{
$sharedEvents->detach('Zend\Stdlib\DispatchableInterface', $handler);
}
}
}
}