Welcome Guest, Not a member yet? Register   Sign In
setting a catchall controller
#1

[eluser]mohrt[/eluser]
I'd like a way to send all unknown controller URLs through a "catchall" controller without polluting the routing table with every valid controller definition. This way I can have:

http://mysite.com/[username]

remap to a profile controller, but when a valid controller name is present, do not remap to the profile controller.

Here is how I went about it, so tell me if I missed something better Smile

First I make a new entry in the routes.php file:

Code:
$route['catchall_controller'] = "profile/index";

Then, I need the CI_Router to respect this new setting. I create a MY_Router.php file in application/libraries/My_Router.php that looks like the following:

Code:
<?php
class MY_Router extends CI_Router {
  
    /**
     * Validates the supplied segments.  Attempts to determine the path to
     * the controller.
     *
     * @access    private
     * @param    array
     * @return    array
     */    
    function _validate_request($segments)
    {
        // Does the requested controller exist in the root folder?
        if (file_exists(APPPATH.'controllers/'.$segments[0].EXT))
        {
            return $segments;
        }

        // Is the controller in a sub-folder?
        if (is_dir(APPPATH.'controllers/'.$segments[0]))
        {        
            // Set the directory and remove it from the segment array
            $this->set_directory($segments[0]);
            $segments = array_slice($segments, 1);
            
            if (count($segments) > 0)
            {
                // Does the requested controller exist in the sub-folder?
                if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT))
                {
                    show_404($this->fetch_directory().$segments[0]);
                }
            }
            else
            {
                $this->set_class($this->default_controller);
                $this->set_method('index');
            
                // Does the default controller exist in the sub-folder?
                if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT))
                {
                    $this->directory = '';
                    return array();
                }
            
            }

            return $segments;
        }  

        // is a catchall controller set?
        if(isset($this->routes['catchall_controller'])) {
          $catchall_segments = explode('/',$this->routes['catchall_controller']);
          if(!empty($catchall_segments[1]))
            array_unshift($segments,$catchall_segments[1]);
          else
            array_unshift($segments,'index');
          if(!empty($catchall_segments[0]))
            array_unshift($segments,$catchall_segments[0]);
          return $segments;
        }

        // Can't find the requested controller...
        show_404($segments[0]);
    }
  
}

All I really did is add this snippet to the existing code just before the show_404() function:


Code:
// is a catchall controller set?
        if(isset($this->routes['catchall_controller'])) {
          $catchall_segments = explode('/',$this->routes['catchall_controller']);
          if(!empty($catchall_segments[1]))
            array_unshift($segments,$catchall_segments[1]);
          else
            array_unshift($segments,'index');
          if(!empty($catchall_segments[0]))
            array_unshift($segments,$catchall_segments[0]);
          return $segments;
        }

So now when a valid controller name is not found in the URL and not in the routing table, instead of throwing an error it reroutes to my defined catchall controller by prepending the controller/method to the $segments array.

Did I go about this the right way?
#2

[eluser]danmontgomery[/eluser]
You could have just added a line at the bottom of routes...

Code:
$route[':any'] = 'profile/index';
#3

[eluser]mohrt[/eluser]
But that won't work (?) I want existing controllers to still work (no remap) without defining them in the route map. Maybe it works differently than what I understood in the docs. Will that not redirect everything?
#4

[eluser]tonanbarbarian[/eluser]
why not use the error_404.php file
i assume that if the link they are going to is not correct you want to display a particular message, or even do some actions
well the error_404.php file is what will be displayed if the route does not exist.
you may not have full access to the CI instance but you can at least show a message or write some code to do whatever you want
#5

[eluser]WanWizard[/eluser]
Migrate to CI 2.0.

It has a reserved route '404_override':
Code:
// in case we run into a 404, load the catchall controller
$routes['404_override'] = 'catchall/index';
note that the method name is required, it doesn't load the index by default!
#6

[eluser]mohrt[/eluser]
[quote author="WanWizard" date="1287710437"]Migrate to CI 2.0.

It has a reserved route '404_override':
Code:
// in case we run into a 404, load the catchall controller
$routes['404_override'] = 'catchall/index';
note that the method name is required, it doesn't load the index by default![/quote]

Sounds promising, although 2.0 is not even into beta is it?
#7

[eluser]mohrt[/eluser]
[quote author="tonanbarbarian" date="1287710218"]why not use the error_404.php file
i assume that if the link they are going to is not correct you want to display a particular message, or even do some actions
well the error_404.php file is what will be displayed if the route does not exist.
you may not have full access to the CI instance but you can at least show a message or write some code to do whatever you want[/quote]

The error_404 file does not designate the correct controller.
#8

[eluser]WanWizard[/eluser]
[quote author="mohrt" date="1287710656"]Sounds promising, although 2.0 is not even into beta is it?[/quote]
Correct.

But it's more stable than 1.7.2 at the moment. That version is frozen, all bugs found are currently fixed in the 2.0dev branch on bitbucket. ExpressionEngine and Mojomotor, Ellislab's commercial products, run on 2.0, as do several large projects from members here. I've been using 2.0 for months now, and find it stable as a rock...




Theme © iAndrew 2016 - Forum software by © MyBB