Reputation: 7704
My default_controller in the routes configuration is set as "home.php".
I have a sub directory for my controllers, lets call it "folder". So if I visit http://mysite.com/folder/, the default controller "folder/home.php" should be called right?
However for some reason this doesn't work, I get a 404. Visiting http://mysite.com/folder/home or http://mysite.com/folder/home/index works as expected. In addition to this, the default controller works in the root directory (http://mysite.com loads home.php).
Any ideas, has anyone else experienced this? I can't get my head around it - it would appear to be a CI issue but I can't find anybody else having the same problem.
The documentation, from the way I understand it at least, suggests that this should work fine: http://codeigniter.com/user_guide/general/controllers.html#subfolders
Setting the default controller to "folder/home.php" means that http://mysite.com/folder/ works fine as expected. Except for I want the default controller to just be "home.php" - whether in the root or in a sub directory, home.php within that directory should be loaded, as the documentation suggests.
Cheers
Upvotes: 12
Views: 58338
Reputation: 12037
Even though the question has many (and an accepted answer) I, still, would like to post mine.
I figured out that subfolders works for regular routes. For example, I can do:
$route['frontend/test'] = "frontend/Welcome/test";
and if I visit site/frontend/test
, it works as expected. The problem is getting "default_controller"
to work with subfolders. For example, the following doesn't work:
$route['default_controller'] = "frontend/Welcome/test";
If we examine the URI Routing > Reserved Routes section, it says:
You can NOT use a directory as a part of this setting!
So we need to hack our way in. I've used Girish's approach. I've examined the system/core/Router.php
and created application/core/MY_Router.php
.
At first, I thought Girish made a static change to the _set_default_controller
method, that it allows only subfolders. I thought it should be dynamic and subfolder should be optional. Later, I realized that he made a case for that too, but his code has duplicate logic and I was already done with mine. So I'm posting it anyway.
<?php
class MY_Router extends CI_Router {
/**
* The default controller expects a string in the following format: "controller/method".
* The method at the end is optional. If the method is omitted, the default method is "index".
*
* Examples:
* * $route['default_controller'] = "Welcome";
* * $route['default_controller'] = "Welcome/index";
*
* Both end up being routed to "Welcome/index".
*
* The default controller does NOT expect a subfolder in the "controllers" folder. So the following won't work:
* * $route['default_controller'] = "frontend/Welcome/index"
*
* To make subfolders work, _set_default_controller() needs to be modified, and that's what this MY_Router is for.
*
* The modification is kept to a minimum and is marked.
*/
protected function _set_default_controller()
{
if (empty($this->default_controller))
{
show_error('Unable to determine what should be displayed. A default route has not been specified in the routing file.');
}
/* START MODIFICATION */
/*
Removing this block, as it only allows/look for "controller/method".
// Is the method being specified?
if (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2)
{
$method = 'index';
}
*/
/*
Instead of just checking for "controller/method", we need to also look for a subfolder.
Because the latter operations depend on the first segment.
So, the first thing to do is to figure out if the first segment is a folder or a class/file.
Possible inputs:
"Welcome" -> class -> autocomplete
"Welcome/index" -> class/method
"frontend" -> folder
"frontend/Welcome" -> folder/class -> autocomplete
"frontend/Welcome/index" -> folder/class/method
*/
$segments = explode("/", $this->default_controller);
$segments = array_filter($segments); // ignore leading and trailing slashes
if (count($segments) > 3) {
show_error('Invalid controller. Default controller supports only one subfolder.');
}
$method = null;
// If the first segment is a folder, the second needs to be a class/file.
if (is_dir(APPPATH.'controllers/'.$segments[0])) {
$this->set_directory($segments[0]);
if (!isset($segments[1])) {
show_error('Invalid controller. A subfolder is provided, but the controller class/file is missing.');
}
$class = $segments[1];
if (isset($segments[2])) {
$method = $segments[2];
}
}
// If the first segment is NOT a folder, then it's a class/file.
else {
$class = $segments[0];
if (isset($segments[1])) {
$method = $segments[1];
}
}
// If the method isn't specified, assume that it's "index".
if (!$method) {
$method = "index";
}
/* END MODIFICATION */
if ( ! file_exists(APPPATH.'controllers/'.$this->directory.ucfirst($class).'.php'))
{
// This will trigger 404 later
return;
}
$this->set_class($class);
$this->set_method($method);
// Assign routed segments, index starting from 1
$this->uri->rsegments = array(
1 => $class,
2 => $method
);
log_message('debug', 'No URI present. Default controller set.');
}
}
Upvotes: 0
Reputation: 11
If i use the following code
$this->set_directory( "user" );
$route['default_controller'] = 'home/index';
then another route in another sub directory does not work.
Suppose i am using sub-directory user in controller directory for default controller. but if i like to use FrontEnd sub-directory for another route,
$this->set_directory( "FrontEnd" );
$route['product/(:any)'] = 'product/$1';
then it is not working.
Upvotes: 0
Reputation: 11
In application/config/routes.php just add this
$this->set_directory( "user" );
$route['default_controller'] = 'home/index';
Here, user is my folder name. Then in default controller you can call any controller that is in user folder following by function name
Upvotes: 0
Reputation: 154
Add this line in application/config/routes.php
$this->set_directory( "yourfoldername" );
$route['default_controller'] = 'controller name';
Upvotes: 4
Reputation: 137
MY FOLDER STRUCTURE
--controllers
--backend
--frontend
--home.php
--products.php
--productDetail.php
--homeIndex.php
In config/routes.php
$route['default_controller'] = 'homeIndex';
$route['frontend'] = 'frontend/home';
$route['backend'] = 'backend/home';
In controllers/homeIndex.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
require_once(APPPATH.'controllers/frontend/Home.php');
class homeIndex extends home {
public function index() {
$this->action();
}
}
by default homeIndex will be loaded and from homeIndex i call to frontend/home/action function.
Upvotes: 0
Reputation: 12127
You can extend system router as per requirements,
application/core/
directory
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */
/**
* Description of My_Router
*
* @author girish
*/
class My_Router extends CI_Router {
//put your code here
public function __construct($routing = NULL) {
parent::__construct($routing);
}
protected function _set_default_controller() {
if (empty($this->default_controller)) {
show_error('Unable to determine what should be displayed. A default route has not been specified in the routing file.');
}
// Is the method being specified?
if (sscanf($this->default_controller, '%[^/]/%[^/]/%s', $directory, $class, $method) !== 3) {
$method = 'index';
}
if (is_dir(APPPATH . 'controllers' . DIRECTORY_SEPARATOR . $directory) === true) {
if (!file_exists(APPPATH . 'controllers' . DIRECTORY_SEPARATOR . $directory . DIRECTORY_SEPARATOR . ucfirst($class) . '.php')) {
// This will trigger 404 later
return;
}
$this->set_directory($directory);
$this->set_class($class);
$this->set_method($method);
} else {
if (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2) {
$method = 'index';
}
if (!file_exists(APPPATH . 'controllers' . DIRECTORY_SEPARATOR . ucfirst($class) . '.php')) {
// This will trigger 404 later
return;
}
$this->set_class($class);
$this->set_method($method);
}
// Assign routed segments, index starting from 1
$this->uri->rsegments = array(
1 => $class,
2 => $method
);
log_message('debug', 'No URI present. Default controller set.');
}
}
and overwrite _set_default_controller()
from custom method, it will work from sub-directory controller as well root directory controller.
And in application/config/routes.php
if you need sub-directory default controller, then
$route['default_controller'] = "admin/admins/login";
if you need root-directory default controller, then
$route['default_controller'] = "welcome/index";
not sure it will work in all versions, but tested in CI3.0.6
Upvotes: 16
Reputation: 666
If you want to stay flexible you need to pass on everything after the starting folder (in application/config/config.php
):
$route['home'] = "home/whatever";
$route['home/(:any)'] = "home/whatever/$1";
Upvotes: 4
Reputation: 1957
For each sub-folder in your controllers folder you must specify a default controller in routes.php
. The built in $route['default_controller']
will not work for sub-folders.
e.g: For setting the default controller for you folder
sub-folder to home
add the following to your /application/config/routes.php
file:
$route['folder'] = "folder/home";
which means http://mysite.com/folder/
is the same as http://mysite.com/folder/home
as URL.
Upvotes: 26
Reputation: 11500
Default route is used to tell CI , which controller class should be loaded if the URI contains no data.
$route['default_controller'] = "unicorn/best";
So, when I load
http://example.com/index.php/unicorn/
the best controller will be loaded.
also when I load
http://example.com/
or
http://example.com/index.php/horse/
the best controller will be loaded.
Upvotes: 1