Welcome Guest, Not a member yet? Register   Sign In
Controller Code Reuse (partial solution).
#1

[eluser]MPress[/eluser]
Hello. I just started looking at CI yesterday and I almost immediately took notice to the fact that you cannot load a controller within another controller. So I started modifying the core today and got pretty far with it. Eventually, after enough modifications, I noticed that all autoloads began loading twice and I started receiving the associated fatal errors for anything that required instantiation. The problem lies in the fact that the constructor for the Controller class is what invokes the autoload calls. Therefore, upon instantiating a second controller class, all of the calls to include/instantiate all autoloads in the autoload.php file were made for a second time.

So I scrapped that idea and came up with a simple partial solution that allows one to at least share controller logic in the application scope.

First make one simple modification to CodeIgniter.php:
Code:
load_class('Application_controller', FALSE);
... around line 131, right after the regular controller is loaded.

Then in the 'system/application/libraries' directory, create an Application_controller.php file:
Code:
class ApplicationController extends Controller{

    function ApplicationController(){
        
        parent::Controller();
    }
}

Now all of your controllers should extend ApplicationController.


Example usage:
Code:
class Home extends ApplicationController{

    function Home(){
        
        parent::ApplicationController();
    }
    
    function index(){
        
        $this->render('home', 'Title for home page.');
    }
}
Code:
class ApplicationController extends Controller{

    function ApplicationController(){
        
        parent::Controller();
    }
    
    function render($view, $title = '', $show_side_bar = true){
    
        $data = array();
        $data['content'] = $this->load->view($view, '', true);
        $data['title'] = $title;
        
        if($show_side_bar){
            
            $sidebar_data = array();
            #.....etc.
            
            $data['side_bar'] = $this->load->view('side_bar', $sidebar_data, true);
        }
        
        $this->load->view('layout', $data);
    }
}
#2

[eluser]CI miller[/eluser]
How is that different than sending the $show_side_bar value directly to the "layout" view via the $data variable?

Being able to make multiple controller requests via a app_controller should mean more than that
A controller analyses the requests (url, get and post values) and determines what operation to be performed.
To make an app_controller you need to be able to add_remove operations and/or display partial views.

For example you have a blog article and you want to display the comments in the same page. If you have a master_controller you could call the operations: retrieve_and_display_blog_article and retriev_and_display_article_comments. The CI approch forces you to have only one operation: retrieve_and_display_blog_article_with_comments

Now, since you have an request (url+get+post) for the blog article that is used automatically by the controller you need to be able to force the controller to analyze other requests made internaly.

But I think that if you use models correctly and thorougly this can be achieve without changing the controller and core of CI but just the "views"
#3

[eluser]MPress[/eluser]
[quote author="CI miller" date="1191003644"]How is that different than sending the $show_side_bar value directly to the "layout" view via the $data variable?[/quote]
For one thing, you centralize the logic rather then having to repeat it in all of your controllers. '#.....etc.' above could be database operations or other non-trivial tasks. Why not send $show_side_bar values directly to the "layout"? What if this value is to be FALSE. Then we are making needless database calls for data we will never use. It's not really about $show_side_bar anyways. Instead of having to nest all of the partial views into the layout view in all of the controllers every time you want to output the page, you now have a simple 'render' function, which is available application-wide in every controller, that does the dirty work for you.

[quote author="CI miller" date="1191003644"]Being able to make multiple controller requests via a app_controller should mean more than that
A controller analyses the requests (url, get and post values) and determines what operation to be performed.
To make an app_controller you need to be able to add_remove operations and/or display partial views.[/quote]
Absolutely. This is just an example of one operation. You can do all sorts of things with this kind of setup.

By the way, do you know if there are future plans to support dynamic controller loading?
#4

[eluser]MPress[/eluser]
So I'm going to start working on my first site using CI. Since I'm new to the framework, I'd just like to know if this ApplicationController concept that I first introduced in this thread is a good idea, or has something better already been implemented somewhere else?
#5

[eluser]Rick Jolly[/eluser]
Creating an application/base/parent controller is a great idea, but imo modifying the core isn't. There are many ways to create an application controller without core modifications.
#6

[eluser]MPress[/eluser]
[quote author="Rick Jolly" date="1191133747"]Creating an application/base/parent controller is a great idea, but imo modifying the core isn't. There are many ways to create an application controller without core modifications.[/quote]
Yeah, I'm not usually crazy about core modifications myself, and I would rather do this without touching base CI code. Can you point me in the right direction?

Much appreciated.
#7

[eluser]Rick Jolly[/eluser]
Maybe have a look at this thread:
http://ellislab.com/forums/viewthread/60169/
It outlines a few options:
1. Extend the Controller library in your libraries folder the CI way (MY_Controller).
2. Create an application controller that extends Controller and simply require/include it.
3. If you don't like requiring classes as in option #2, you can use autoload with php 5.

I prefer option #2. I don't mind using require/include since it documents what files I'm using and where they are located. This option also allows for any number of parent controllers including multiple inheritance. For example, an back-end admin parent controller could extend a site-wide parent controller.
#8

[eluser]MPress[/eluser]
[quote author="Rick Jolly" date="1191138821"]Maybe have a look at this thread:
http://ellislab.com/forums/viewthread/60169/
It outlines a few options:
1. Extend the Controller library in your libraries folder the CI way (MY_Controller).
2. Create an application controller that extends Controller and simply require/include it.
3. If you don't like requiring classes as in option #2, you can use autoload with php 5.

I prefer option #2. I don't mind using require/include since it documents what files I'm using and where they are located. This option also allows for any number of parent controllers including multiple inheritance. For example, an back-end admin parent controller could extend a site-wide parent controller.[/quote]
Autoloading it does not work (and shouldn't) due to the fact that the autoloads are only called after the Controller constructor is invoked (and thus ApplicationController will not have been previously included). Unless I'm missing something?

I like option 1 the best (I just changed 'MY_' to 'Application_' in the config file). Thanks for your help.
#9

[eluser]Rick Jolly[/eluser]
[quote author="MPress" date="1191143536"]Autoloading it does not work (and shouldn't) due to the fact that the autoloads are only called after the Controller constructor is invoked (and thus ApplicationController will not have been previously included). Unless I'm missing something?
[/quote]
My apologies - I should have been more specific. I was referring to the php __autoload() function as opposed to CI autoloading.




Theme © iAndrew 2016 - Forum software by © MyBB