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:

php
  1. if ($this->action == __FUNCTION__)

So for example you could use it like this:

php
  1. class PostsController extends AppController
  2. {
  3.     function index()
  4.     {
  5.         $post3 = $this->view(3);
  6.     }
  7.  
  8.     function view($id)
  9.     {
  10.         $post = $this->Post->find(array('id' => $id));
  11.        
  12.         if ($this->action != __FUNCTION__)
  13.             return $post;
  14.         else
  15.             $this->render();
  16.     }
  17. }

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

Print this Post | Digg This | Stumble It | Delicious

6 Comments

Drayen on Jul 18, 2006:

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!

Drayen on Jul 18, 2006:

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();
}
}

Felix Geisendörfer on Jul 18, 2006:

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 ; ).

Drayen on Jul 18, 2006:

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?

Drayen on Jul 18, 2006:

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();
}
}

Alan Blount on Aug 21, 2008:

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!

Add a comment