Passing Named Parameters

by 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

    var $namedArgs = FALSE;
    var $argSeparator = ":";

Define the callback function

   /**
   * 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.

    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:

<?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:


var $argSeparator = "|";

Report

More on Tutorials

Advertising

Comments

  • bluesclues9 posted on 02/27/13 06:48:29 PM
    Hi, This is pretty neat solution for passing variables across different actions within a controller.
    However, I have a need to pass variables across different controller actions. How can this used?

    Any ideas?
  • bluesclues9 posted on 02/27/13 06:46:12 PM
    Hi, this is pretty neat.

    However, I have a need in which I need to pass certain variables across different controllers and I don't want to pass these using redirect just for the same reasons explained below plus, I need to hide those parameters from users.
  • samuelcorradi posted on 12/07/09 02:46:12 PM
    Using named parameters, to pass the parameters for action, it is the order or the name?

    If not matter the order, and ALSO does NOT matter the name, any name I give to the parameter will be valid.

    That means I can have more than one valid URL for a page?
  • mhuggins posted on 06/12/08 04:36:50 PM
    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.
  • mhuggins posted on 01/30/08 06:01:54 PM
    @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.
  • kushaura posted on 10/16/07 02:10:52 AM
    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...
  • tom_m posted on 09/09/07 10:52:59 PM
    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.
  • Byron posted on 11/26/06 08:49:50 PM
    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!
  • bisho posted on 11/03/06 11:02:57 AM
    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.
  • sbarre posted on 11/02/06 02:40:48 PM
    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!
  • Dieter_be posted on 11/01/06 02:55:00 PM
    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 :-)
  • Kat123 posted on 11/30/99 12:00:00 AM
    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
login to post a comment.