Passing Named Parameters
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
Comment
1 cool 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 :-)
Comment
2 useful
With this approach, you can append additional attributes to any URL in your application and process them when you find them..
Thanks!
Comment
3 some suggestions
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.
Bug
4 Missing a dollar sign
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!
Question
5 Help Please
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
Comment
6 Cool
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.
Comment
7 Name Params in Cake 1.2
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...
Comment
8 Named Params
$this->params['named']['id'];I'm not sure how the contents of the 'named' array index varies form the 'pass' array though.
Question
9 Changing the Argument Separator