default controller inside subfolder codeigniter 3 not working - php

In codeigniter 3 application i have directory structure like this:
-Myproject
-application
-controllers
-home
Welcome.php //This is my controller inside home directory
How to set Welcome controller as default controller?
I use below code
$route['default_controller'] = 'home/Welcome';
This routing works for previous versions of codeigniter.

By default, you are not allowed to do that. To get around this, you need to hack your system Router.php:
codeigniter/system/core/Router.php
Edit a few lines of code so that it becomes like this:
line 1. if (!sscanf($this->default_controller, '%[^/]/%[^/]/%s', $directory, $class, $method) !== 2)
line 2. if ( ! file_exists(APPPATH.'controllers'. DIRECTORY_SEPARATOR . $directory. DIRECTORY_SEPARATOR .ucfirst($class).'.php'))
line 3. $this->set_directory($directory);
Once you've done, you can call the default controller under directory.
$route['default_controller'] = 'home/Welcome';

You need not to change anything from files inside CODEIGNITER system folder. Codeigniter allows developer to extend their feature. You can create a file named as MY_Router.php.
<?php
class MY_Router extends CI_Router {
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.');
}
if (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2) {
$method = 'index';
}
if( is_dir(APPPATH.'controllers/'.$class) ) {
$this->set_directory($class);
$class = $method;
if (sscanf($method, '%[^/]/%s', $class, $method) !== 2) {
$method = 'index';
}
}
if ( ! file_exists(APPPATH.'controllers/'.$this->directory.ucfirst($class).'.php')) {
return;
}
$this->set_class($class);
$this->set_method($method);
$this->uri->rsegments = array(
1 => $class,
2 => $method
);
log_message('debug', 'No URI present. Default controller set.');
}
}
Note: Do not change the file name.

Try This in routes.php
$route['default_controller'] = 'welcome';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;

Related

Codeigniter 3.1.2 404 error

I'm try to moving some website from CI 2.x to CI 3.1.2,
but after I moving my old website to new CI I get 404 error when I'm access that page.
this is my CI structure :
Applications
- controller
-- back
-- front
--- Home.php
- libraries
-- front.php
- model
-- home_models.php
- views
-- back
-- front
--- elems
---- head.php
---- foot.php
--- pages
---- home.php
--- display
---- pages.php
Controller
Home.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Home extends CI_Controller {
var $data;
public function __construct(){
parent::__construct();
}
public function index(){
$data = array();
$this->front->pages('home',$data);
}
}
/* End of file welcome.php */
/* Location: ./application/controllers/welcome.php */
Libraries front.php
<?php
class Front {
protected $_ci;
function __construct(){
$this->_ci = &get_instance();
}
function pages($page, $data=null){
$data['head'] = $this->_ci->load->view('front/elems/head', $data, TRUE);
$data['content'] = $this->_ci->load->view('front/pages/'.$page, $data, TRUE);
$data['foot'] = $this->_ci->load->view('front/elems/foot', $data, TRUE);
$this->_ci->load->view('front/display/pages', $data);
}
}
?>
in my route :
$route['default_controller'] = 'front/home';
and in my autoload :
$autoload['libraries'] = array('front');
In old CI that's structure is work, but after I'm trying to implement that structure in 3.1.2 I can't access that page. What's wrong with this.
Read Upgrading from 2.2.x to 3.0.x
Update your CodeIgniter files
Update your classes file names
Replace config/mimes.php
Remove $autoload[‘core’] from your config/autoload.php
Update Database and Routes files.
etc ....
I found this way
Change my system core Router.php into
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) !== 2)
{
$method = 'index';
}
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);
// 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 it works, but if this is safe?

How to set default controller inside n subfolder in codeigniter 3

-Myproject
-application
-controllers
-subfolder1
-subfolder2
-subfolder3
-subfolder(..n)
Controller.php
And need to set routes.php
$route['default_controller'] = 'subfolder1/subfolder2/subfolder3/subfolder(..n)/controller';
According to the examples in the docs it does not appear that you can put a Controller more than one level deep inside a subdirectory.
example.com/index.php/subdirectory/controller/function
I also don't think your route looks correct. You would not have home/ at the start of the route unless "home" is a controller or subdirectory name. See examples here.
$route['default_controller'] = 'subdirectory/controller';
I have researched and found in codeigniter 3 system/core/Router.php library file's method _set_default_controller() can not support default controller in subfolder. So i have overrided/ customized this method _set_default_controller() and now it supports n level subfolders and working fine for me.
I have created application/core/MY_Router.php with the below code to override this method _set_default_controller()
<?php
/**
* Override Set default controller
*
* #author : amit
*
* #return void
*/
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?
$x = explode('/', $this->default_controller);
$dir = APPPATH.'controllers'; // set the controllers directrory path
$dir_arr = array();
foreach($x as $key => $val){
if(!is_dir($dir.'/'.$val)){
// find out class i.e. controller
if(file_exists($dir.'/'.ucfirst($val).'.php')){
$class = $val;
if(array_key_exists(($key+1), $x)){
$method = $x[$key+1]; // find out method i.e. action
}else{
$method = 'index'; // default method i.e. action
}
}else{
// show error message if the specified controller not found
show_error('Not found specified default controller : '. $this->default_controller);
}
break;
}
$dir_arr[] = $val;
$dir = $dir.'/'.$val;
}
//set directory
$this->set_directory(implode('/', $dir_arr));
$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.');
}
?>
Now we can set default controller in application/config/routes.php like below
// without action method name
$route['default_controller'] = 'subfoler1/subfoler2/subfolder3/subfolder(..n)/controller';
OR
// with action method name
$route['default_controller'] = 'subfoler1/subfoler2/subfolder3/subfolder(..n)/controller/action';
If we will pass the action method name it will detect that method as action and if we will not pass action name then it will assume index as a action.

Loading Codeigniter library from a different folder under application folder

Hi I am having an issue
Say I have a folder structure in CodeIgniter
application/
controllers/
models/
views/
gmail_library/
Now I have written a controller
class invite_friends extends CI_Controller {
function __construct() {
parent::__construct();
$this->load->gmail_library('Config'); // this line is giving me error
session_start();
}
}
How can I set this thing like this?
First of all, note that CodeIgniter doesn't use overloading by __call() to implement dynamic methods. Thus there is no way to get such a gmail_library() methods to work.
The conventional method
From the User Guide:
Your library classes should be placed within your
application/libraries folder, as this is where CodeIgniter will look
for them when they are initialized.
If you're using CI Loader class to load a library or helper, you should follow CI's conventions.
application/libraries/Myclass.php
$this->load->library('myclass');
$this->myclass->my_method();
Using relative paths
1) You put your library files in sub-directories within the main libraries folder:
application/libraries/gmail/Gmail_config.php
I renamed your Config.php file name to prevent the occurrence of conflict with CI config core class.
$this->load->library('gmail/gmail_config');
2) Also you can use relative path within the Loader::library() method to load the library file from the outside of the library folder, as follows:
The path to the file is relative. So you can use ../ to go one UP level in path.
Again: I renamed your Config.php file name to prevent the occurrence of conflict with CI config core class.
$this->load->library('../gmail_library/Gmail_config');
An old question, I know, but I came across this looking for a way to use classes (libraries) from outside the application folder and I liked to keep it in 'the CI way of doing this'. I ended up extending the CI_Loaderclass:
I basically copied the _ci_load_class function and added an absolute path
<? if (!defined('BASEPATH')) exit('No direct script access allowed');
class MY_Loader extends CI_Loader {
protected $absPath = '/home/xxxxx/[any-path-you-like]/common/';
/**
* Load class
*
* This function loads the requested class.
*
* #param string the item that is being loaded
* #param mixed any additional parameters
* #param string an optional object name
* #return void
*/
public function commonLibrary($class, $params = NULL, $object_name = NULL)
{
// Get the class name, and while we're at it trim any slashes.
// The directory path can be included as part of the class name,
// but we don't want a leading slash
$class = str_replace('.php', '', trim($class, '/'));
// Was the path included with the class name?
// We look for a slash to determine this
$subdir = '';
if (($last_slash = strrpos($class, '/')) !== FALSE)
{
// Extract the path
$subdir = substr($class, 0, $last_slash + 1);
// Get the filename from the path
$class = substr($class, $last_slash + 1);
}
// We'll test for both lowercase and capitalized versions of the file name
foreach (array(ucfirst($class), strtolower($class)) as $class)
{
$subclass = $this->absPath.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';
// Is this a class extension request?
if (file_exists($subclass))
{
$baseclass = BASEPATH.'libraries/'.ucfirst($class).'.php';
if ( ! file_exists($baseclass))
{
log_message('error', "Unable to load the requested class: ".$class);
show_error("Unable to load the requested class: ".$class);
}
// Safety: Was the class already loaded by a previous call?
if (in_array($subclass, $this->_ci_loaded_files))
{
// Before we deem this to be a duplicate request, let's see
// if a custom object name is being supplied. If so, we'll
// return a new instance of the object
if ( ! is_null($object_name))
{
$CI =& get_instance();
if ( ! isset($CI->$object_name))
{
return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
}
}
$is_duplicate = TRUE;
log_message('debug', $class." class already loaded. Second attempt ignored.");
return;
}
include_once($baseclass);
include_once($subclass);
$this->_ci_loaded_files[] = $subclass;
return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
}
// Lets search for the requested library file and load it.
$is_duplicate = FALSE;
foreach ($this->_ci_library_paths as $path)
{
$filepath = $this->absPath.'libraries/'.$subdir.$class.'.php';
// Does the file exist? No? Bummer...
if ( ! file_exists($filepath))
{
continue;
}
// Safety: Was the class already loaded by a previous call?
if (in_array($filepath, $this->_ci_loaded_files))
{
// Before we deem this to be a duplicate request, let's see
// if a custom object name is being supplied. If so, we'll
// return a new instance of the object
if ( ! is_null($object_name))
{
$CI =& get_instance();
if ( ! isset($CI->$object_name))
{
return $this->_ci_init_class($class, '', $params, $object_name);
}
}
$is_duplicate = TRUE;
log_message('debug', $class." class already loaded. Second attempt ignored.");
return;
}
include_once($filepath);
$this->_ci_loaded_files[] = $filepath;
return $this->_ci_init_class($class, '', $params, $object_name);
}
} // END FOREACH
// One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
if ($subdir == '')
{
$path = strtolower($class).'/'.$class;
return $this->_ci_load_class($path, $params);
}
// If we got this far we were unable to find the requested class.
// We do not issue errors if the load call failed due to a duplicate request
if ($is_duplicate == FALSE)
{
log_message('error', "Unable to load the requested class: ".$class);
show_error("Unable to load the requested class: ".$class);
}
}
}
Put the file MY_Loader.php in the application/core folder and load your libs with:
$this->load->commonLibrary('optional_subfolders/classname', 'classname');
$this->classname->awesome_method();

routes.php file not loading when using hmvc in codeigniter?

I have hmvc setup and working fine,
I have a gallery module.
The gallery module breaks down into three controllers and it's structure is as follows:
/modules/gallery/
/modules/gallery/config/
/modules/gallery/helpers/
/modules/gallery/controllers/
/modules/gallery/controllers/gallery.php
/modules/gallery/controllers/galleries.php
/modules/gallery/controllers/images.php
/modules/gallery/models/
/modules/gallery/models/galleriesmodel.php
/modules/gallery/models/imagesmodel.php
/modules/gallery/views/dashboard.tpl
/modules/gallery/views/galleries/dashboard.tpl
/modules/gallery/views/images/dashboard.tpl
anyway, I have a function inside my images.php controller called list_items
So I want to map the url
http://example.com/gallery/images/list to
http://example.com/gallery/images/list_items
So I thought, sweet as,
I will just add a /modules/gallery/config/routes.php with the route inside it.
But it seems the routes are not being included.
The routes from /application/config/routes.php are included and if I put a die('loaded') in the module routes.php the it does kill the script,
But running
print_r($this->router) from one of the controllers does not show up any of the routes from the module routes.php.
What's going on here?
As far as I know,
HMVC only looks for requested controllers inside each module, with different hierarchy models, but route overrides using routes.php within modules are never read.
Look into MX_Router::locate it never looks for routes.php inside any module.
Also it does not override CI_Router::_set_routing which looks for routes.php in config folder.
You will have to override CI_Router::_set_routing and read config/router.php in every available module for your module route overrides to work.
Broncha shows the way, I show you the code. I use this SOLUTION:
You have to edit _set_routing() in system/core/Router.php or extend this method (better) within MY_Router class (third_party/Router.php).
Now it should always load module/config/routes.php... (it's around line 140)
// Load the routes.php file.
if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
}
elseif (is_file(APPPATH.'config/routes.php'))
{
include(APPPATH.'config/routes.php');
}
// Include routes every modules
$modules_locations = config_item('modules_locations') ? config_item('modules_locations') : FALSE;
if(!$modules_locations)
{
$modules_locations = APPPATH . 'modules/';
if(is_dir($modules_locations))
{
$modules_locations = array($modules_locations => '../modules/');
}
else
{
show_error('Modules directory not found');
}
}
foreach ($modules_locations as $key => $value)
{
if ($handle = opendir($key))
{
while (false !== ($entry = readdir($handle)))
{
if ($entry != "." && $entry != "..")
{
if(is_dir($key.$entry))
{
$rfile = Modules::find('routes'.EXT, $entry, 'config/');
if($rfile[0])
{
include($rfile[0].$rfile[1]);
}
}
}
}
closedir($handle);
}
}
$this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route;
unset($route);
I hope it will help...

Yii - Eliminate default controller ID for a module from URL

I created a module and there exists a default controller inside that. Now I can access the index action (default action) in the default controller like /mymodule/. For all other action i need to specify the controller id in the url like /mymodule/default/register/ . I would like to know is it possible to eliminate the controller id from url for the default controller in a module.
I need to set url rule like this:
before beautify : www.example.com/index.php?r=mymodule/default/action/
after beautify : www.example.com/mymodule/action/
Note: I want this to happen only for the default controller.
Thanks
This is a little tricky because the action part might be considered as a controller or you might be pointing to an existing controller. But you can get away with this by using a Custom URL Rule Class. Here's an example (I tested it and it seems to work well):
class CustomURLRule extends CBaseUrlRule
{
const MODULE = 'mymodule';
const DEFAULT_CONTROLLER = 'default';
public function parseUrl($manager, $request, $pathInfo, $rawPathInfo)
{
if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) {
// Make sure the url has 2 or more segments (e.g. mymodule/action)
// and the path is under our target module.
if (count($matches) != 4 || !isset($matches[1]) || !isset($matches[3]) || $matches[1] != self::MODULE)
return false;
// check first if the route already exists
if (($controller = Yii::app()->createController($pathInfo))) {
// Route exists, don't handle it since it is probably pointing to another controller
// besides the default.
return false;
} else {
// Route does not exist, return our new path using the default controller.
$path = $matches[1] . '/' . self::DEFAULT_CONTROLLER . '/' . $matches[3];
return $path;
}
}
return false;
}
public function createUrl($manager, $route, $params, $ampersand)
{
// #todo: implement
return false;
}
}

Categories