Check if an action was called from within a Controller
Posted by Felix Geisendörfer, on Jul 06, 2006 - in PHP & CakePHP » Controllers, Components & Shells
Gopher just asked me weather it was possible in CakePHP to see if an action was invoked by the dispatcher or called by $this->action();. So since I think this is one of these things that could be useful for others as well, here is my solution:
All you need to do is to check whether $this->action and the name of the function that is currently beeing executed match. This can be done like this:
-
if ($this->action == __FUNCTION__)
So for example you could use it like this:
-
class PostsController extends AppController
-
{
-
function index()
-
{
-
$post3 = $this->view(3);
-
}
-
-
function view($id)
-
{
-
-
if ($this->action != __FUNCTION__)
-
return $post;
-
else
-
$this->render();
-
}
-
}
Ok, this is a pretty useless example I have to admit, but I'm sure there are more interesting ways to utilize this ; ).
--Felix Geisendörfer aka the_undefined
6 Comments
whoops, should be :
function beforeFilter(){
/**
* array holding the names of functions that can be access by non-authenticated users
*/
$authByPass = array('view');
/* function is not in authByPass array and isnt being called by another function */
if(array_search($this->action,$authByPass) === FALSE AND $this->action != __FUNCTION__){
$this->checkSession();
}
}
Hi Drayen,
thanks for this example, I'm glad this is useful to somebody ; ). Anyway, why do you use array_search instead of in_array in your beforeFilter? I think in_array() is very intuitive and easy to understand when reading foreign code ; ).
No good reason really.
I am now trying to find a way to get this to work with requestAction() or something similar, so i can make calls from other classes. Any ideas?
Worked something out, but not sure how secure it would be - very interested to hear what you think :
/**
* Run before any of the functions to insure data is clean and users are valid
*/
function beforeFilter(){
/**
* array holding the names of functions that can be accessed by non-authenticated users
*/
$authBypass = array('');
$possibleUrls = array($this->here,$this->here.'/'.implode('/',array_slice($this->params['url'],1)));
/**
* UGLY, but should work, it checks :
* that it's not in authorise to bypass the check
* that it's not a local function
* that it's not being called by another controller** It does this by creating an array of possible URLs for direct access (one with params the Cake way /'ed, and one querystring style, as in ?param=1) and checks that against the calling URL
*/
if(in_array($this->action,$authBypass) === FALSE
AND ($this->action != __FUNCTION__)
AND in_array("/".implode('/',$this->params['url']), $possibleUrls) )
{
$this->checkSession();
}
}
This is great information, much better than what I've been doing - which is passing in an additional parameter to actions which told them to "return" or "render" or "redirect"...
thanks!



Here is a non trival use :
class AppController extends Controller
{
/**
* Checks that the user is logged in.
*/
function checkSession()
{
// If the session info hasn't been set...
if (!$this->Session->check('User'))
{
// Force the user to login
$this->redirect('/users/login');
}
}
class MyController extends AppController
{
/**
* Run before any of the functions to insure data is clean and users are valid
*/
function beforeFilter(){
/**
* array holding the names of functions that can be access by non-authenticated users
*/
$authByPass = array('view');
if(array_search($this->action,$authByPass) === FALSE OR $this->action == __FUNCTION__){
$this->checkSession();
}
}
}
This means you can bypass auth and still call funcitons from other controlers which would otherwise require auth - bloody handy!