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.
When user visits this url: /b2controller/myMethod
, these methods run:
AppController::beforeFilter()
BController::beforeFilter()
B2Controller::beforeFilter()
B2Controller::myMethod()
B2Controller::myMethod2()
then user is redirected to this url /ccontroller/myMethod10/
But we need this:
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() {
...
...
...
}
}
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()
.
Also note that there is other controllers like CController
that uses beforeFilter redirect behaviour.
Here are 3 methods that works:
startupProcess
in your controller(s)Override the startupProcess
method of AppController
:
// 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.
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
:One easy but not really clean way may be to send the response from AppController::beforeFilter
:
public function beforeFilter(\Cake\Event\Event $event) {
// Compute $isOk
if ($isOk) {
$this->response = $this->redirect('/c/myMethod10');
$this->response->send();
die();
}
}
Dispatcher Filters
A more "clean" way would be to use Dispatcher Filters
:
In 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;
}
}
}
In config/bootstrap.php
:
DispatcherFactory::add('Redirect');
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
.
Note that if you have beforeRedirect
event, these will not be triggered with this method.
Edit: This was my previous answer which does not work very well if you have multiple B
-like controllers.
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(\Cake\Event\Event $event) {
$result = parent::beforeFilter($event);
if ($result instanceof \Cake\Network\Response) {
return $result;
}
// Your stuff
}
}
The code bellow the if
is executed only if there was no redirection (parent::beforeFilter($event)
did not return a Response
object).
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With