Welcome Guest, Not a member yet? Register   Sign In
Bug in Router

This bug exhibits itself when you have the default route specified in routes but that default route does not exist, and you are trying to access a controller in a subdirectory based on the default route. I've only discovered it because I've not yet set up the main page and I'm developing a sub-page first. An example will explain this better.

$route['default_route'] = 'main';

controllers/main.php does not exist, but controllers/admin/main.php does. The index method exists in admin/main.php.

Visiting index.php/admin will present a 404 error. If controllers/main.php is created, index.php/admin will now work.

This is happening because the following process occurs in Router:

in _set_routing()
$this->_parse_routes() (line 120)
$this->_set_request($this->uri->segments) (line 332)
$segments = $this->_validate_request($segments) (line 177)

Route is correctly detected on lines 254 and 255. Routing is now complete, but the process continues. The return array is empty as the /admin has been sliced out.

returns to _set_request()
$this->_set_default_controller() (line 181)
$this->_set_request(array($this->default_controller, 'index')) (line 153)
$segments = $this->_validate_request($segments) (line 177)

Route cannot be validated now. 404 occurs.

This cyclic behaviour is not ideal. Is _validate_request supposed to validate the request or determine the routing?! It's not clear, but in this case it does determine the routing and gets it right, but that means that the array it returns has been modified so its done more than just validation, so the remaining process fails.

This all seems a bit messy. I think I'll have to re-write some of this class as I need this working. I would also like to be able to set a different default controller for each sub directory. I will post results if I do this. Otherwise, has this bug been recognised already? Should I post this as a bug report?

This is wrong!
$route['default_route'] = 'main';

$route['default_controller'] = 'main';

$route['login'] = "admin/admin/login";
$route['logout'] = "admin/admin/logout";
$route['register'] = "admin/admin/register";
$route['admin/dashboard'] = "admin/admin/index";


Ok so I typed default_route instead of default_controller. That's not what I've got in routes.php, the bug still exists.

What I would like to be able to do is something like:
$route['admin/default_controller'] = 'admin_main'

this would redirect index.php/admin but not index.php/admin/page2

Try this instead:
$route['admin/default_controller(.*)'] = 'admin_main'; // changed to 'any URI that starts with...

I've re-written the class and will post the code after I've tested it further.

The main problem is not the inability to specify the default controller of a subdirectory, it is the bug in the Router class which seems to be caused by the ambiguity of what the methods should do. If I had controllers/main.php and controllers/admin/main.php while the route would be correctly determined this bug would still be an issue as the cyclic nature of the code would mean it would go through some of the process twice, unnecessarily, which wastes time.

It is imho not a bug, because it was never a feature.

There is only one default controller, which is used when you don't specify any URI segments. In all other cases, you need routes or a generic 404 controller to capture URI requests.

If you need a default controller for admin, all you need is
$route['admin'] = 'admin_main'
which will load the admin_main controller if someone requests http://my.site/admin.

What you want is not possible in the default setup, and something that imho you shouldn't fix like this. You basically want a per-URI-segment 404 capture (i.e. if it starts with /admin/, and the second URI segment can't be found, load this specific controller).

My 2ct: rethink your design, you're making it very difficult on yourself.

p.s. don't talk about subdirectory (which is a term related to filesystems) when you mean URI segment. Very confusing.

Forget the default controller for each subdirectory.

The bug exists just by specifying only the $route['default_controller']. When visiting the uri which relates to a subdir in controllers, it first determines the route in _validate_request(), and then the route gets set again (unneccessarily) by _set_default_controller(). This functionality is supported, see the documentation:
Quote:Each of your sub-folders may contain a default controller which will be called if the URL contains only the sub-folder

IMO, and in the re-implementation I've done, _validate_controller (I renamed it) does just that - it is passed an array of the segments to be validated and checks if that controller exists. All the actual routing is done in _parse_routes. _set_request sets the internal variables when given an array of segments, and updates uri's rsegments. _set_default_controller is optionally passed a directory and then determines and validates a default route based on the value of $this->default_controller. $segments is always array(directory, controller, method) which avoids confusion. In this implementation there is no feedback between methods.

I have added the ability to set the default controller for each subdirectory, but it could easily be removed. It's all at the bottom of _parse_routes.

Maybe I'm missing things, but this seems like a much simpler way of achieving the same end result.

See the wiki Page

[eluser]Damien K.[/eluser]
I am going to call this "lack of feature" a bug too, and is aligned with my interpretation of the documentation, where the default controller specified in config/routers.php should also work with sub-directories.

My recollection, although vague, tells me that it worked in CI 2.0 and I am not getting the same results in a separate CI 2.0.2 implementation. Mind you, I did override the default behaviour and now I am going back to add more to my "patch"/extension. I hate to fight frameworks, hence why I chose CI, which is lightweight relatively speaking. Unfortunately, I need multi-level sub-directories and it is part of the same patch for me. My solution is not as elegant as I want it to be as it overrides core/Routes.php's _validate_request(), but it will have to do for now.

I also thought it was good to reference this issue as a sub-directory controller issue. We are talking implementation details here, and how sub-directories are handled here need to be communicated. That's my opinion though.

Theme © iAndrew 2016 - Forum software by © MyBB