Cakephp 3 在父类的 beforeFilter 中重定向
在我们的 CakePHP 3 应用程序中,我们发现了不同的行为.我们确信它在 CakePHP 2 中运行良好,所以我想在新版本中发生了一些变化.
In our CakePHP 3 application we found a different behaviour. We're sure that it worked well in CakePHP 2, so I suppose something changed in new version.
当用户访问这个url:/b2controller/myMethod
,这些方法运行:
When user visits this url: /b2controller/myMethod
, these methods run:
AppController::beforeFilter()
BController::beforeFilter()
B2Controller::beforeFilter()
B2Controller::myMethod()
B2Controller::myMethod2()
然后用户被重定向到这个 url /ccontroller/myMethod10/
then user is redirected to this url /ccontroller/myMethod10/
但我们需要这个:
当用户访问时/b2controller/myMethod
和 $isOk
条件为 true
,然后将用户重定向到 /ccontroller/myMethod10/
,没有运行 BController::beforeFilter()
、B2Controller::beforeFilter()
、B2Controller::myMethod()
和 BController::MyMethod2()
.
When user visits
/b2controller/myMethod
and $isOk
condition is true
, then redirect user to /ccontroller/myMethod10/
, without running BController::beforeFilter()
, B2Controller::beforeFilter()
, B2Controller::myMethod()
and BController::MyMethod2()
.
我们的最小代码是这样的:
Our minimal code is like this:
class AppController {
function beforeFilter(Event $event) {
// set $isOk variable
if ($isOk == TRUE) {
return $this->redirect('/ccontroller/myMethod10/');
}
$aa=1;
$ab=2;
}
}
class BController extends AppController {
function beforeFilter(Event $event) {
parent::beforeFilter($event);
$a=1;
$b=2;
}
function myOtherMethod() {
myOtherMethod2();
}
function myOtherMethod2() {
...
...
}
}
class B2Controller extends BController {
function beforeFilter(Event $event) {
parent::beforeFilter($event);
$m1=1;
$m2=2;
}
function myMethod() {
myMethod2();
}
function myMethod2() {
...
...
}
}
class CController extends AppController {
function beforeFilter(Event $event) {
parent::beforeFilter($event);
}
function myMethod10() {
...
...
...
}
}
如何让用户从主类的 beforeFilter 重定向到另一个控制器操作?请注意,发生重定向.但是用户在调用 myMethod()
和 myMethod2()
后被重定向.
How can I make user to redirect to another controller action, from the beforeFilter of main class ? Note that redirect occurs. But user is redirected after calling myMethod()
and myMethod2()
.
另请注意,还有其他控制器,如 CController
使用 beforeFilter 重定向行为.
Also note that there is other controllers like CController
that uses beforeFilter redirect behaviour.
推荐答案
这里有 3 种有效的方法:
Here are 3 methods that works:
覆盖AppController
的startupProcess
方法:
// In your AppController
public function startupProcess() {
// Compute $isOk
if ($isOk) {
return $this->redirect('/c/myMethod10');
}
return parent::startupProcess();
}
这是一种简短且非常干净的方法,所以如果可以的话,我会选择这个方法.如果这不符合您的需求,请参见下文.
This is a short and quite clean method, so I would go for this one if you can. If this does not fit your needs, see below.
注意:如果你使用这个方法,你的组件在你计算$isOk
时可能不会被初始化,因为初始化是由parent::startupProcess<完成的/代码>.
Note: If you use this method, your components may not be initialized when you compute $isOk
since the initialization is done by parent::startupProcess
.
一种简单但不是很干净的方法可能是从 AppController::beforeFilter
发送响应:
One easy but not really clean way may be to send the response from AppController::beforeFilter
:
public function beforeFilter(CakeEventEvent $event) {
// Compute $isOk
if ($isOk) {
$this->response = $this->redirect('/c/myMethod10');
$this->response->send();
die();
}
}
方法 3 - 使用 Dispatcher Filters
更干净"的方法是使用 调度器过滤器
:
在src/Routing/Filter/RedirectFilter.php
:
In src/Routing/Filter/RedirectFilter.php
:
<?php
namespace AppRoutingFilter;
use CakeEventEvent;
use CakeRoutingDispatcherFilter;
class RedirectFilter extends DispatcherFilter {
public function beforeDispatch(Event $event) {
// Compute $isOk
if ($isOk) {
$response = $event->data['response'];
// The code bellow mainly comes from the source of Controller.php
$response->statusCode(302);
$response->location(CakeRoutingRouter::url('/c/myMethod10', true));
return $response;
}
}
}
在config/bootstrap.php
中:
In config/bootstrap.php
:
DispatcherFactory::add('Redirect');
并且您可以在 AppController
中删除重定向.如果您能够从 DispatcherFilter
计算 $isOk
,这可能是最干净的方法.
And you can remove the redirection in your AppController
. This may be the cleanest way if you are able to compute $isOk
from the DispatcherFilter
.
请注意,如果您有 beforeRedirect
事件,则不会使用此方法触发这些事件.
Note that if you have beforeRedirect
event, these will not be triggered with this method.
这是我之前的答案,如果您有多个类似 B
的控制器,则效果不佳.
This was my previous answer which does not work very well if you have multiple B
-like controllers.
你需要返回$this->redirect()
返回的Response
对象.实现此目的的一种方法是执行以下操作:
You need to return the Response
object returned by $this->redirect()
. One way of achieving this is by doing the following:
class BController extends AppController {
public function beforeFilter(CakeEventEvent $event) {
$result = parent::beforeFilter($event);
if ($result instanceof CakeNetworkResponse) {
return $result;
}
// Your stuff
}
}
if
后面的代码只有在没有重定向时才会执行(parent::beforeFilter($event)
没有返回 Response
> 对象).
The code bellow the if
is executed only if there was no redirection (parent::beforeFilter($event)
did not return a Response
object).
注意:我不知道你如何计算 isOk
,但是如果你调用 $this->redirect()<,请注意无限重定向循环/code> 调用
/ccontroller/mymethod10
时.
Note: I do not know how you compute isOk
, but be careful of infinite redirection loop if you call $this->redirect()
when calling /ccontroller/mymethod10
.
相关文章