Welcome Guest, Not a member yet? Register   Sign In
_remap() is my new best friend! Here's why
#1

[eluser]Colin Williams[/eluser]
Lately, I've been finding more and more uses for the _remap() method that, when used in Controllers, gets called regardless of what function was passed via the URL. When you're looking into routes and thinking, "How in the World am I gonna route this?" you probably want to look into employing _remap(). Typically, you will only want to use _remap() to add a layer above the typical Controller method loading convention.

Consider this use of _remap():

Code:
function _remap($method)
{
   if (is_numeric($method))
   {
      if (!$action = $this->uri->segment(3))
      {
         $action = 'view';
      }
      if (method_exists($this, $action))
      {
         if (!$this->object = $this->object_model->get($method))
         {
            show_404();
         }
         else
         {
            // Do something with $this->obj
         }
         $this->$action();
      }
      else
      {
         show_404();
      }
   }
   elseif (method_exists($this, $method))
   {
      $this->$method();
   }
   else
   {
      show_404();
   }
}

What's happening above is when a certain condition is met, in this case our second URI parameter is numeric, we alter the convention of routing to the method indicated by the 2nd param. If this condition is not met, the convention holds.

Additionally, when the condition is met, we can perform some operations that might normally happen in the constructor. In the example above, we take the numeric id and try to load an object with our object_model. If the object loads, we save it as a property of our Controller class and move on to the method defined in the third parameter of the URI (or a default one, in this case, 'view'). If the object fails to load or the method indicated in the 3rd URI param doesn't exist in our Controller, we appropriately call show_404().

What this affords us is not having to repeatedly call our object_model to fetch the object and catch the exceptions in EVERY method that deals with a single instance of the particular object (think of view, edit, delete methods that deal with a single blog post object, for example). All we need to do is check the existence of $this->object and act upon it accordingly.

So, when possible, save yourself the headaches of a complex routing scheme and make intelligent use of the Controller's _remap() method.
#2

[eluser]sophistry[/eluser]
nice. i agree that _remap() is a very flexible tool.

your solution to lessening routing headaches reminds me of this autoload view approach i came up with after seeing xwero's Router class hacking that allowed him to autoload views.

note the use of the second parameter in rsegment() method which you could use to tighten your code. see the URI class docs for detail, but basically it sets a default segment to return if there is no segment.
Code:
function _remap()
    {
        // use _remap() method to call up view files
        // via uri if they exist in a subdir of views dir
        // but only if there is no method in the controller
        // this allows "overriding" default view files
        // just by adding methods to this class
        $default_view = 'index';
        $view = $this->uri->rsegment(2,$default_view);
        
        if (method_exists($this,$view))
        {
            $this->$view($this->uri->ruri_string());
            exit();
        }
        else
        {
            $this->load->view($this->uri->rsegment(1).'/'.$view);
        }
    }

EDIT: there should probably be a thread on cool _remap usages!
#3

[eluser]Randy Casburn[/eluser]
Way cool you guys! Compliments!
#4

[eluser]sophistry[/eluser]
oh yeah, i just noticed that your default action is "view" which if used as an actual controller method name will cause PHP 4 to die (PHP 5 survives).

i would change the line

Code:
if (!$action = $this->uri->segment(3))
      {
         $action = 'view';
      }
to:
Code:
$action = $this->uri->segment(3, 'default_method'));
#5

[eluser]Colin Williams[/eluser]
Ahah.. forgot you could return a default from uri->segment(). Thanks for the reminder!

Quote:“view” which if used as an actual controller method name will cause PHP 4 to die

Man, I thought I was gonna prove you wrong, but I see that I'm running PHP 5 on my local machine when I thought I was using 4! Better check those statements I made about stuff I've contributed being PHP 4 compatible... :grrr:




Theme © iAndrew 2016 - Forum software by © MyBB