[php] CodeIgniter: Load controller within controller

I have a home controller with an index action that displays a set of featured products. However, the products are managed through a product controller including a proprietary model and views.

How do I access product information from within the index action in the home controller? Instancing product won't work as the class isn't loaded at runtime and CodeIgniter doesn't provide a way to dynamically load controllers. Putting the product class into a library file doesn't really work, either.

To be precise, I need the product views (filled with data processed by the product controller) inserted in the index view. I'm running CodeIgniter 2.0.2.

This question is related to php codeigniter

The answer is


Based on @Joaquin Astelarra response, I have managed to write this little helper named load_controller_helper.php:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

if (!function_exists('load_controller'))
{
    function load_controller($controller, $method = 'index')
    {
        require_once(FCPATH . APPPATH . 'controllers/' . $controller . '.php');

        $controller = new $controller();

        return $controller->$method();
    }
}

You can use/call it like this:

$this->load->helper('load_controller');
load_controller('homepage', 'not_found');

Note: The second argument is not mandatory, as it will run the method named index, like CodeIgniter would.

Now you will be able to load a controller inside another controller without using HMVC.

Later Edit: Be aware that this method might have unexpected results. Always test it!


In this cases you can try some old school php.

// insert at the beggining of home.php controller require_once(dirname(__FILE__)."/product.php"); // the controller route.

Then, you'll have something like:

Class Home extends CI_Controller
{
 public function __construct()
 {
  parent::__construct();
  $this->product = new Product();
  ...
 }

 ...
 // usage example
 public function addProduct($data)
 {
  $this->product->add($data);
 }
}

And then just use the controller's methods as you like.


I know this is old, but should anyone find it more recently, I would suggest creating a separate class file in the controllers folder. Pass in the existing controller object into the class constructor and then you can access the functions from anywhere and it doesn't conflict with CI's setup and handling.


With the following code you can load the controller classes and execute the methods.

This code was written for codeigniter 2.1

First add a new file MY_Loader.php in your application/core directory. Add the following code to your newly created MY_Loader.php file:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

// written by AJ  [email protected]

class MY_Loader extends CI_Loader 
{
    protected $_my_controller_paths     = array();  

    protected $_my_controllers          = array();


    public function __construct()
    {
        parent::__construct();

        $this->_my_controller_paths = array(APPPATH);
    }

    public function controller($controller, $name = '', $db_conn = FALSE)
    {
        if (is_array($controller))
        {
            foreach ($controller as $babe)
            {
                $this->controller($babe);
            }
            return;
        }

        if ($controller == '')
        {
            return;
        }

        $path = '';

        // Is the controller in a sub-folder? If so, parse out the filename and path.
        if (($last_slash = strrpos($controller, '/')) !== FALSE)
        {
            // The path is in front of the last slash
            $path = substr($controller, 0, $last_slash + 1);

            // And the controller name behind it
            $controller = substr($controller, $last_slash + 1);
        }

        if ($name == '')
        {
            $name = $controller;
        }

        if (in_array($name, $this->_my_controllers, TRUE))
        {
            return;
        }

        $CI =& get_instance();
        if (isset($CI->$name))
        {
            show_error('The controller name you are loading is the name of a resource that is already being used: '.$name);
        }

        $controller = strtolower($controller);

        foreach ($this->_my_controller_paths as $mod_path)
        {
            if ( ! file_exists($mod_path.'controllers/'.$path.$controller.'.php'))
            {
                continue;
            }

            if ($db_conn !== FALSE AND ! class_exists('CI_DB'))
            {
                if ($db_conn === TRUE)
                {
                    $db_conn = '';
                }

                $CI->load->database($db_conn, FALSE, TRUE);
            }

            if ( ! class_exists('CI_Controller'))
            {
                load_class('Controller', 'core');
            }

            require_once($mod_path.'controllers/'.$path.$controller.'.php');

            $controller = ucfirst($controller);

            $CI->$name = new $controller();

            $this->_my_controllers[] = $name;
            return;
        }

        // couldn't find the controller
        show_error('Unable to locate the controller you have specified: '.$controller);
    }

}

Now you can load all the controllers in your application/controllers directory. for example:

load the controller class Invoice and execute the function test()

$this->load->controller('invoice','invoice_controller');

$this->invoice_controller->test();

or when the class is within a dir

$this->load->controller('/dir/invoice','invoice_controller');

$this->invoice_controller->test();

It just works the same like loading a model


Load it like this

$this->load->library('../controllers/instructor');

and call the following method:

$this->instructor->functioname()

This works for CodeIgniter 2.x.


According to this blog post you can load controller within another controller in codeigniter.

http://www.techsirius.com/2013/01/load-controller-within-another.html

First of all you need to extend CI_Loader

<?php

class MY_Loader extends CI_Loader {

    public function __construct() {
        parent::__construct();
    }

    public function controller($file_name) {
        $CI = & get_instance();
        $file_path = APPPATH.'controllers/' . $file_name . '.php';
        $object_name = $file_name;
        $class_name = ucfirst($file_name);

        if (file_exists($file_path)) {
            require $file_path;

            $CI->$object_name = new $class_name();
        }
        else {
            show_error('Unable to load the requested controller class: ' . $class_name);
        }
    }
}

then load controller within another controller.


There are plenty of good answers given here for loading controllers within controllers, but for me, this contradicts the mvc pattern.

The sentence that worries me is;

(filled with data processed by the product controller)

The models are there for processing and returning data. If you put this logic into your product model then you can call it from any controller you like without having to try to pervert the framework.

Once of the most helpful quotes I read was that the controller was like the 'traffic cop', there to route requests and responses between models and views.


Just use

..............

self::index();

..............


Just to add more information to what Zain Abbas said:

Load the controller that way, and use it like he said:

$this->load->library('../controllers/instructor');

$this->instructor->functioname();

Or you can create an object and use it this way:

$this->load->library('../controllers/your_controller');

$obj = new $this->your_controller();

$obj->your_function();

Hope this can help.