通常,您希望通过返回响应来短路调度过程。在route 或dispatch 期间,您可以返回响应以停止通常的代码流停止并直接完成结果。如果是 ACL 检查,您很可能希望尽早返回该响应并重定向到用户的登录页面。
您要么在控制器中构造响应,要么检查插件的返回值并在响应时重定向。注意第二种方法类似于how the PRG plugin works。
第一种方法的例子:
use Zend\Mvc\Controller\AbstractActionController;
class MyController extends AbstractActionController
{
public function fooAction()
{
if (!$this->aclAllowsAccess()) {
// Use redirect plugin to redirect
return $this->redirect('user/login');
}
// normal code flow
}
}
类似 PRG 插件的例子:
use Zend\Mvc\Controller\AbstractActionController;
use Zend\Http\Response;
class MyController extends AbstractActionController
{
public function fooAction()
{
$result = $this->aclCheck();
if ($result instanceof Response) {
// Use return value to short-circuit
return $result
}
// normal code flow
}
}
插件可能看起来像这样(在第二种情况下):
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
class AclCheck extends AbstractPlugin
{
public function __invoke()
{
// Check the ACL
if (false === $result) {
$controller = $this->getController();
$redirector = $controller->getPluginManager()->get('Redirect');
$response = $redirector->toRoute('user/login');
return $response;
}
}
}
在你的问题中你说:
[...] 它不起作用,因为插件似乎需要控制器。
当您想在插件中执行$this->getController() 时,这可能是控制器插件内部的问题。您必须扩展 Zend\Mvc\Controller\Plugin\AbstractPlugin 或实现 Zend\Mvc\Controller\Plugin\PluginInterface 以确保您的 ACL 插件被控制器注入。
如果您不希望这样,可以选择直接返回您自己创建的响应。它有点不太灵活,你在已经有一个响应对象的时候创建一个响应对象(导致两个响应可能发生冲突),但是插件代码会改变如下:
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
use Zend\Http\PhpEnvironment\Response;
class AclCheck extends AbstractPlugin
{
public function __invoke()
{
// Check the ACL
if (false === $result) {
$response = new Response;
$response->setStatusCode(302);
$response->getHeaders()
->addHeaderLine('Location', '/user/login');
return $response;
}
}
}