父类的beforeFilter中的Cakephp 3重定向
在我们的CakePHP 3应用程序中,我们发现了一种不同的行为。我们确信它在CakePHP2中工作得很好,所以我想在新版本中有些变化 当用户访问此url时:父类的beforeFilter中的Cakephp 3重定向,php,cakephp,redirect,url-redirection,cakephp-3.0,Php,Cakephp,Redirect,Url Redirection,Cakephp 3.0,在我们的CakePHP 3应用程序中,我们发现了一种不同的行为。我们确信它在CakePHP2中工作得很好,所以我想在新版本中有些变化 当用户访问此url时:/b2controller/myMethod,这些方法将运行: AppController::beforeFilter() BController::beforeFilter() B2Controller::beforeFilter() B2Controller::myMethod() B2Controller::myMeth
/b2controller/myMethod
,这些方法将运行:
AppController::beforeFilter()
BController::beforeFilter()
B2Controller::beforeFilter()
B2Controller::myMethod()
B2Controller::myMethod2()
然后用户被重定向到此url/ccontroller/myMethod10/
但我们需要:
当用户访问
/b2controller/myMethod
和$isOk
条件为true
,然后将用户重定向到/ccontroller/myMethod10/
,而不运行BController::beforeFilter()
,b2controller::beforeFilter()
,b2controller::myMethod()
和BController::MyMethod2()
我们的最小代码如下所示:
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()
后会被重定向
还请注意,还有其他控制器,如
CController
,使用beforeFilter重定向行为。以下是3种有效的方法:
方法1-在控制器中覆盖startupProcess
覆盖AppController
的startupProcess
方法:
// In your AppController
public function startupProcess() {
// Compute $isOk
if ($isOk) {
return $this->redirect('/c/myMethod10');
}
return parent::startupProcess();
}
public function beforeFilter(\Cake\Event\Event $event) {
// Compute $isOk
if ($isOk) {
$this->response = $this->redirect('/c/myMethod10');
$this->response->send();
die();
}
}
这是一个简短而干净的方法,所以如果可以的话,我会选择这个方法。如果这不符合您的需要,请参见下文
注意:如果使用此方法,在计算$isOk
时可能不会初始化组件,因为初始化是由parent::startupProcess
完成的
方法2-从AppController
发送响应:
一种简单但并非真正干净的方法可能是从AppController::beforeFilter
发送响应:
// In your AppController
public function startupProcess() {
// Compute $isOk
if ($isOk) {
return $this->redirect('/c/myMethod10');
}
return parent::startupProcess();
}
public function beforeFilter(\Cake\Event\Event $event) {
// Compute $isOk
if ($isOk) {
$this->response = $this->redirect('/c/myMethod10');
$this->response->send();
die();
}
}
方法3-使用
更“干净”的方法是使用:
在src/Routing/Filter/RedirectFilter.php中
<?php
namespace App\Routing\Filter;
use Cake\Event\Event;
use Cake\Routing\DispatcherFilter;
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(\Cake\Routing\Router::url('/c/myMethod10', true));
return $response;
}
}
}
DispatcherFactory::add('Redirect');
您可以在AppController
中删除重定向。如果您能够从DispatcherFilter
计算$isOk
,这可能是最干净的方法
请注意,如果您有beforeRedirect事件,则此方法不会触发这些事件
编辑:这是我以前的答案,如果您有多个类似
B
的控制器,则该答案不太适用
您需要返回由$this->redirect()
返回的响应
对象。实现这一目标的一种方法是执行以下操作:
class BController extends AppController {
public function beforeFilter(\Cake\Event\Event $event) {
$result = parent::beforeFilter($event);
if ($result instanceof \Cake\Network\Response) {
return $result;
}
// Your stuff
}
}
只有在没有重定向(parent::beforeFilter($event)
未返回响应
对象)时,才会执行if
下面的代码
注意:我不知道如何计算
isOk
,但如果调用$this->redirect()
时调用/ccontroller/mymethod10
请在BController
中尝试返回父对象::预过滤($event)
Controller::redirect
返回一个响应
对象,如果在beforeFilter
调用中未返回该对象,则表明要执行重定向。您的意思是这样的<代码>类BController扩展AppController{函数beforeFilter(Event$Event){返回父级::beforeFilter($Event);}}Yes。我一点也不确定,但看看startupProcess
的源代码,似乎您需要返回一些东西才能停止请求过程。我更新了代码。假设我更改了BController::beforeFilter()
,并在该函数中添加了return。在这种情况下,如果$isOk
为false,则BController::beforeFilter()
中的剩余代码将无法工作。我终于能够在一个工作的CakePHP安装上测试您的代码,请参阅我的答案。方法2是die()
很好,或者可以$this->response->stop()
用于相同的事情吗?@trante实际上$this->response->stop($status)
严格等同于退出($status)
(参见源代码),而退出
相当于死亡
,所以代码是等效的,我不确定这是一个非常干净的方法来做你想做的事情,非常感谢,让我开心