CodeIgniter Forums

Full Version: remapping controllers' function calls: what about arguments?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

El Forum

[eluser]Michael Ekoka[/eluser]
I'm experimenting with the controller's _remap() method that overrides a call to specific methods. In the user guide it states that
Quote:The overridden function call (typically the second segment of the URI) will be passed as a parameter the _remap() function
(User Guide : Controllers).

Code:
function _remap($method)
{
    if ($method == 'some_method')
    {
        $this->$method();
    }
    else
    {
        $this->default_method();
    }
}

Now, i would like to be able to call the original method with the arguments that were intended for it, but the guide doesn't mention anything about them.

Has anyone ever played with this?

El Forum

[eluser]zdknudsen[/eluser]
I played around with it once, ran into the same problem as you then decided to do it another way. Would be nice to know how to do this, though.

Now that I think about it, one way of doing it would be to pass an array of all the arguments to the methods and then use the php functions func_get_arg() / func_get_args() and func_num_args().

El Forum

[eluser]Michael Wales[/eluser]
When you use _remap you can not pass arguments to the function, instead you use the URI class:

[code]function _remap($method) {
if ($method == 'index') {
$this->index();
} else {
$this->somethingelse();
}
}

function index() {
$param1 = $this->uri->segment(2);
$param2 = $this->uri->segment(3);
}

El Forum

[eluser]Michael Ekoka[/eluser]
ok, I think I found a solution. The URI::$rsegments property contains the rerouted request (the one that the framework uses to call your controller/method/params). It's safer to use for this purpose than the URI::$segments which rather contains the original pre-routed url, because unlike the $segments array the $rsegments always has a controller, a method and no subdirectory.

This is what I have:
Code:
function _remap($method){
    // first lets get rid of the controller and method
    $args = array_slice($this->uri->rsegments,2);
    if(method_exists($this,$method)){    
        return call_user_func_array(array(&$this,$method),$args);            
    }
}
I let your imagination wander as to all the possibilities this little functionality offers.

El Forum

[eluser]kewisch[/eluser]
I think this should be part of the next release, since it adds some consistency. I created a patch to take care of this in a code-igniter way.

Code:
--- system/codeigniter/CodeIgniter.php  2007-07-12 12:53:28.000000000 +0000
+++ system/codeigniter/CodeIgniter.php  2007-11-04 11:59:21.000000000 +0000
@@ -198,12 +198,14 @@ else
         * ------------------------------------------------------
         */
        $EXT->_call_hook('post_controller_constructor');

+       $params = array_slice($RTR->rsegments, (($RTR->fetch_directory() == '') ? 2 : 3));
+
        // Is there a "remap" function?
        if (method_exists($CI, '_remap'))
        {
-               $CI->_remap($method);
+               call_user_func_array(array(&$CI, "_remap"), array($method, $params));
        }
        else
        {
                if ( ! method_exists($CI, $method))
@@ -212,9 +214,9 @@ else
                }

                // Call the requested method.
                // Any URI segments present (besides the class/function) will be passed to the method for convenience
-               call_user_func_array(array(&$CI, $method), array_slice($RTR->rsegments, (($RTR->fetch_directory() == '') ? 2 : 3)));
+               call_user_func_array(array(&$CI, $method), $params);
        }
}

// Mark a benchmark end point

El Forum

[eluser]Michael Ekoka[/eluser]
Quote:$params = array_slice($RTR->rsegments, (($RTR->fetch_directory() == '') ? 2 : 3));

This piece of code will create a bug as is, when your controller is in a subdirectory (e.g. /controllers/admin/users.php). You don't need to check for a sub-folder when using $rsegments, it only has information about the controller, the method and the parameters, never the subdir. You will need to modify your code :

Code:
$params = array_slice($RTR->rsegments, 2);

El Forum

[eluser]kewisch[/eluser]
Interesting, I just took this code from the existing. Is there a bug also in the existing code then?

El Forum

[eluser]Michael Ekoka[/eluser]
Quote:Interesting, I just took this code from the existing. Is there a bug also in the existing code then?

I reported it and proposed a fix here. Note that I'm currently using CI v1.5.4 from svn which is slightly different from the official stable distro. Both versions have this bug. For a fix to the normal distro, follow this link .