Welcome Guest, Not a member yet? Register   Sign In
Best way to define default global content
#1

[eluser]splufdaddy[/eluser]
My application is using multiple controllers, and one main view. My layout has a left side bar and main content area. The main content area will be different everytime, but sometimes the left content bar will be the same across controllers.

Currently, every controller passes in $this->layout to the view, and I add data needed in the view to $this->layout. In MY_Controller, I've defined
Code:
$this->layout['left_column'] = $this->load->view('default_left', $leftColumnData, true)
Then in each controller, if I want to change the left column I re-assign $this->layout['left_column'].

My concern is that the default content I'm assigning in MY_Controller uses a few db queries, and if that's going to be overridden later, I'd rather not make those db calls.

What's the best way to define default content, and avoid making extraneous db calls? I'd like to avoid using a template library, unless it's absolutely necessary. Thanks!
#2

[eluser]splufdaddy[/eluser]
I'm going to answer my own post here, in the hopes of educating others, and hearing improvements to what I've found.

What I want to do is be able to define a navigation, and have each method in each of my controllers be able to modify that navigation to indicate where you currently are. At first in MY_Controller I had this:
Code:
$this->ci->layout['navigation']  = $this->ci->load->view('util/navigation', $this->ci->layout, true);
That code loaded the navigation variable with the navigation html, but I couldn't change it after the MY_Controller constructor. The other scenario was to put that line of code in every method of every controller, so I could first add a variable to $this->layout indicating where we are in the navigation.


My solution was pretty simple, but I haven't seen it anywhere. It involved using a display_override hook. I added this to my application\config\hooks.php file:

Code:
$hook['display_override'] = array(
                                'class'    => 'MY_DisplayOverride',
                                'function' => 'override',
                                'filename' => 'MY_DisplayOverride.php',
                                'filepath' => 'hooks'
                                );

This allows me to define a navigation array in MY_Controller constructor, and a sub navigation array in all of my other controller's constructors (each controller is a "section" of the site). I've since added a layer of complexity, and my page array also indicates if the page should be displayed in the navigation if the user is logged in, logged out or both:
Code:
$this->ci->layout['pages'] = array(
                    array(    'pageName' =>'Edit',
                        'url' =>'/profile/edit/',
                        'login' => 'yes'),
                    array(    'pageName' =>'Register',
                        'url' =>'/profile/register/',
                        'login' => 'no'),                
                    array(    'pageName' =>'All',
                        'url' =>'/all/',
                        'login' => 'all'),
                    array(    'pageName' =>'All2',
                        'url' =>'/all2/')
                        );

Each constructor indicates where it is in the navigation, and each method of each controller indicates where it is in the subnav:
Code:
// MY_Controller constructor:
$this->ci->layout['section'] = 'Section 1';
//method in random controller
$this->ci->layout['page'] = 'Edit';

My navigation template displays the navigation. It's not rendered until the hook, which is key because data can be edited throughout the execution of the controller (ie a login/logout, etc):
Code:
<?
        $sep = "";
        $isLoggedIn = isset($userObj) ? true : false;        
        foreach ($pages as $pg) {
            if((isset($pg['login']) && (($pg['login'] == 'yes' && $isLoggedIn == true) || ($pg['login'] == 'no' && $isLoggedIn == false) || $pg['login'] == 'all')) || !isset($pg['login'])) {
                $style = '';
                if($pg['pageName'] == $page) $style="style='text-decoration:underline;'";
                ?>    
                &lt;?=$sep;?&gt;<a href="&lt;?=$pg['url'];?&gt;" title="&lt;?=$pg['pageName'];?&gt;" &lt;?=$style;?&gt;>&lt;?=$pg['pageName'];?&gt;</a>                
            &lt;?
                $sep = " | ";
            }
        }
        ?&gt;

Finally, MY_DisplayOverride, which does the magic:
Code:
&lt;?
if (!defined('BASEPATH')) exit('No direct script access allowed');
class MY_DisplayOverride{

    var $ci;
    function MY_DisplayOverride(){
        $this->ci =& get_instance();
    }

    function override() {        
        if($this->ci->load->uri->router->scaffolding_request != 1) {        //we dont want scaffolding to use this
            // Note:  We use globals because we can't use $CI =& get_instance()
            // since this function is sometimes called by the caching mechanism,
            // which happens before the CI super object is available.
            global $BM;
            // Parse out the elapsed time and memory usage
            $this->ci->layout['elapsedTime'] = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end');                    
            $this->ci->layout['memory_usage'] =  ( ! function_exists('memory_get_usage')) ? '0' : round(memory_get_usage()/1024/1024, 2).'MB';          
            $this->ci->layout['queryCount'] = $this->ci->db->query_count;
            $this->ci->layout['navigation'] = $this->ci->load->view('util/navigation', $this->ci->layout, true);
          
            $this->ci->load->view('layout', $this->ci->layout);            
        }
        print $this->ci->output->get_output();
    }
}

?&gt;
I added elapsedTime and memory_usage to my display_override hook, because these functions are implemented in the normal display function that you're overriding. Thus, they're unavailable when you override.

Some future plans for this:
I can define some default modules to show up in my left hand column in MY_Constructor controller. Then I can override those modules later on, and the original default modules will never be rendered (thus saving db queries), because my override function will actually do the loading of the data & view.

I need to add a variable to $this->ci->layout[] that determines if I'm using my primary layout view or not. If I wanted to make an ajax request, right now it would serve that request in my layout template. I'll add some logic to the scaffolding if statement so ajax requests can get through without any modification.

Well that's it. It's not rocket science and may be considered a hack, but it makes my life much easier. Let me know what you think, including suggestions to improve.
#3

[eluser]tonanbarbarian[/eluser]
I always thought of hooks more of a way to allow other developers to modify how your app works without having to modify the app
So in that case I would change the way I was doing things
Rather than using the display override hook why not use the _output method of the controller
Processing Output

You could do the same thing that you are doing in the hook in your MY_Controller and leave the hooks free to be used by others who might want to extend what you have already got.
#4

[eluser]splufdaddy[/eluser]
Wow, can't believe I missed that. That's much more logical than adding a hook. I like it, thanks for the tip.




Theme © iAndrew 2016 - Forum software by © MyBB