Passing Named Parameters

By Tom OReilly (TommyO)
This simple tutorial will add the ability to pass named parameters to your actions.

Named Parameters are beneficial because they:
* Make for much prettier URLs
* Allow passing of a variable number of parameters easier
* Allow passing of parameters in any order
* Remove the need to pass placeholders in URLs

A URL containing named parameters may look like:
http://example.com/controller/action/param1:value1/param2:value2/

Note: This is a feature planned for CakePHP 1.2. Because of this, I have tried to stick to the planned conventions as much as possible. The latest version presented here is in fact based on research done on the proposed functionality for CakePHP 1.2. I have included only a portion of the future functionality set, but enough to start using named params immediately.

This is 100% my code - not taken from the official source. Therefore I cannot guarantee that it will match exactly the functionality of the final release. I will say that if the final release matches what the proposal presents, then your code will migrate flawlessly simply by removing my code from the app_controller.

You are of course welcome to modify this code, but I ask that you stick as closely as possible to the planned conventions. Making it even more compliant is better still.


The Code

Modify your app_controller.php in the following way:

Set up the necessary members and their default values
Download code
    var $namedArgs = FALSE;
    var $argSeparator = ":";

Define the callback function
Download code
   /**
   * A callback function to populate the namedArgs array if activated
   * This should be triggered in the beforeFilter
   * @return TRUE always
   *
   **/
    function getNamedArgs() {
        if ($this->namedArgs)
        {
            $this->namedArgs = array();
            if (!empty($this->params['pass']))
            {
                foreach ($this->params['pass'] as $param)
                {
                    if (strpos($param, $this->argSeparator))
                    {
                        list($name, $val) = split( this->argSeparator,
                                                   $param );
                        $this->namedArgs[$name] = $val;
                    }
                }
            }
        }
        return TRUE;
    }

Make sure the callback is called before every controller/action. This can be place in the AppController or your individual controllers, as needed.
Download code
    function beforeFilter() {
        $this->getNamedArgs();
    }


Using named params in your controller

Now it is as simple as activating it in your controller. Once activated, named parameters will be available through $namedArgs array. An example:

Controller Class:

Download code <?php 
class MyExamplesController extends AppController
{
    var 
$namedArgs TRUE;
 
    function 
myAction()
    {
        if (isset(
$this->namedArgs['param1']))
        {
            
$myParam1 $this->namedArgs['param1'];
        }
    }
}
?>

In this example, $myParam1 will have a value of 'value' on the following request:
http://example.com/myexamples/myAction/param1:value/

There you have it. Simple and clean. Input welcome.


Options

There is one parameter, $argSeparator, that can be set to whatever you would like as a separator. The default is ":". Redefine in your controller like:

Download code
var $argSeparator = "|";

 

Comments 129

CakePHP Team Comments Author Comments
 

Comment

1 cool trick

Neat little trick.
I always loved how "in the old days", we could basically treat the url as a stack, where we could dump name/value-pairs without even thinking about the order.
(eg index.php?var4=value4&var1=value1&var3=value3&var2=value2)

I really missed this kind of behaviour in cake, where you _have to_ pass variables as actionname/var1/var2/var3/var4, or you would have to write some really complicated code just go retrieve the variables you need.

Seems like with current development, issues like this one will very soon be referred to in the past tense :-)
Posted Nov 1, 2006 by Dieter Plaetinck
 

Comment

2 useful

This is a very useful little add-on. I wasn't aware of the way the params array held the "pass" block with that info.

With this approach, you can append additional attributes to any URL in your application and process them when you find them..

Thanks!
Posted Nov 2, 2006 by Seb Barre
 

Comment

3 some suggestions

Nice add-on!

Just some suggestions:

Instead of using split I would use explode, that is faster (split expects a regexp). And the limit on the explode should be set to 1, to be able to use var_name:value:with:semicolons.

list($name, $val) = explode( $this->argSeparator,
$param, 1);

Also I'm putting this directly on the beforeFilter function, instead of the $beforeFilter var. That var is usually modified on the controllers, and you must remember adding the getNamedArgs to all controllers with a custom $beforeFilter.
Posted Nov 3, 2006 by Guillermo
 

Bug

4 Missing a dollar sign

Howdy Tom,

There's a missing $ sign on this line:

list($name, $val) = split( this->argSeparator, $param );

Needs to be:

list($name, $val) = split( $this->argSeparator, $param );


Thanks!
Posted Nov 26, 2006 by Byron
 

Question

5 Help Please

Hey guys.

I have a custom events calendar that I didn't write, that uses a custom PHP script. It requires the form to call itself and based on the values it GETS, it retrieves various event info.

I have been trying to make this solution work, but can not figure it out.

A few questions:
1 - Does the app_controller.php remain in its original place or does it get moved to the controllers/ folder?

2- Where exactly does this line go:
var $beforeFilter = array('getNamedArgs');
in the controller class as the first line or in the page that uses the controller?

Would appreciate the help, as its been very frustrating to use anothers' PHP.

Thanks,
K
Posted Dec 31, 1969 by Kat
 

Comment

6 Cool

Works great! Thanks. The typo threw me for a loop until I caught it...then read the comments and realized that would've been faster if I read them first.

Anyway. I was wondering if it's possible to use a "/" as a separator? I'm assuming it's in conflict w/ the rewriting that already exists... anyway to get around that?

Thanks.
Posted Sep 9, 2007 by Tom Maiaroto
 

Comment

7 Name Params in Cake 1.2

In case anyone wants to know, the current method of passing named params in 1.2 is done using the params variable in your controllers.

An example:
to get the named parameter "id", as in the case of www.mydomain.com/id:1


echo $this->params['pass']['id'];

I know the author mentioned above that his technique isn't the exact same as 1.2, but since documentation is so sparse for 1.2, this could potentially help someone...
Posted Oct 16, 2007 by John Tylwalk
 

Comment

8 Named Params

@7 - I actually use:

$this->params['named']['id'];
I'm not sure how the contents of the 'named' array index varies form the 'pass' array though.
Posted Jan 30, 2008 by Matt Huggins
 

Question

9 Changing the Argument Separator

Does anyone know how to change the argument separator for named parameters in CakePHP 1.2? I keep finding posts where people say to set the value of $argSeperator (or $argSeparator) in app_controller.php, but this doesn't change anything for me.
Posted Jun 12, 2008 by Matt Huggins