CodeIgniter: Load controller within controller
Asked Answered
E

10

44

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.

Eliciaelicit answered 22/5, 2011 at 22:0 Comment(2)
Looks like you're using Controllers for elaborating datas. I suggest you using models for that, this way you'll have just to call the models' method independently from the controller you're in (MVC 'skinny controller, fat model')Tonnie
I'm rather talking about widgets or partials – I'd love to have consistent modules to put in a site template. This would more or less require to instantiate controllers.Eliciaelicit
E
29

If you're interested, there's a well-established package out there that you can add to your Codeigniter project that will handle this:

https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc/

Modular Extensions makes the CodeIgniter PHP framework modular. Modules are groups of independent components, typically model, controller and view, arranged in an application modules sub-directory, that can be dropped into other CodeIgniter applications.

OK, so the big change is that now you'd be using a modular structure - but to me this is desirable. I have used CI for about 3 years now, and can't imagine life without Modular Extensions.

Now, here's the part that deals with directly calling controllers for rendering view partials:

// Using a Module as a view partial from within a view is as easy as writing:
<?php echo modules::run('module/controller/method', $param1, $params2); ?>

That's all there is to it. I typically use this for loading little "widgets" like:

  • Event calendars
  • List of latest news articles
  • Newsletter signup forms
  • Polls

Typically I build a "widget" controller for each module and use it only for this purpose.

Evonevonne answered 23/5, 2011 at 1:8 Comment(0)
R
63

Load it like this

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

and call the following method:

$this->instructor->functioname()

This works for CodeIgniter 2.x.

Raven answered 4/1, 2013 at 15:11 Comment(7)
Thanks for this. Note that CodeIgniter treats the controller as a singleton, so I discovered that once you load the other controller, your original controller will no longer work normally. After loading the other controller, make sure you don't try to use $this->load or any loaded models in the original controller; instead, use $ci = get_instance() and access models only via $ci (e.g. $ci->user_model).Paraffinic
Even beside your comment the origional controllers works fine.Raven
plus 1 even though I didn't know instructor was actually controllerDramatic
This can be called only once. If you try to call another controller, you will get an Undefined property.Experiential
this is the best answer for meMarra
Unable to locate the specified class: Session.php i got this error when i try to load controller like thisSpinthariscope
I am also getting the same error @ShanKhaliq. Is there any solution?Minoru
E
29

If you're interested, there's a well-established package out there that you can add to your Codeigniter project that will handle this:

https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc/

Modular Extensions makes the CodeIgniter PHP framework modular. Modules are groups of independent components, typically model, controller and view, arranged in an application modules sub-directory, that can be dropped into other CodeIgniter applications.

OK, so the big change is that now you'd be using a modular structure - but to me this is desirable. I have used CI for about 3 years now, and can't imagine life without Modular Extensions.

Now, here's the part that deals with directly calling controllers for rendering view partials:

// Using a Module as a view partial from within a view is as easy as writing:
<?php echo modules::run('module/controller/method', $param1, $params2); ?>

That's all there is to it. I typically use this for loading little "widgets" like:

  • Event calendars
  • List of latest news articles
  • Newsletter signup forms
  • Polls

Typically I build a "widget" controller for each module and use it only for this purpose.

Evonevonne answered 23/5, 2011 at 1:8 Comment(0)
R
8

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.

Reunion answered 1/12, 2011 at 20:51 Comment(0)
S
8

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();
Sideling answered 12/6, 2013 at 8:47 Comment(1)
Hi, this solution was for CI 2.x. Seems CI 3.x no longer permits this, now I'm not working with CI 3.x so I can't help you much. Check this forum forum.codeigniter.com/thread-744-page-2.html maybe you can get some information there. And here is a github issue maybe is related to your problem github.com/bcit-ci/CodeIgniter/issues/3480.Sideling
E
6

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!

Experiential answered 3/5, 2013 at 8:20 Comment(0)
F
2

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

Firth answered 24/12, 2012 at 11:20 Comment(0)
U
1

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.

Undertook answered 6/6, 2014 at 8:4 Comment(0)
V
1

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.

Vulnerary answered 24/6, 2015 at 8:44 Comment(0)
L
0

You can use this:

self::index();
Luwian answered 19/12, 2013 at 11:21 Comment(0)
D
0

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.

David answered 29/6, 2016 at 14:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.