Header and Footer and Menu on every page jedd

fernanfs edited this page Sep 30, 2012 · 11 revisions
Clone this wiki locally

Category:Approaches::Header and Footer and Menu on every page

Overview:

I have three things that I want to see everywhere:

  • header - page title, login status, and maybe some links
  • footer - links, page rendering stats, and some advertising back to the CI site!
  • menu - generated from an array (not DB) containing only category and sub-category levels

Because I want to see them all on pretty much every page, and I consider the creation of these data to be inexpensive, I am happy to have them generated on every page load.

If you don't want this, say because you only want to show these snippets on some of your pages, you could modify this approach by putting some smarts into MY_Controller to identify whether to create the vars or not - but I think this might be messier than other Approaches to the problem.

Approach (brief):

I extend the core Controller and make MY_Controller.php.

If you don't know what that means, then you should definitely read the MY Controller wiki page first - it explains the concept in lurid detail.

Within MY_Controller I call out to view files that generate sub-sets, typically

's or 's, and perhaps a few dozen lines of HTML. These are called using the load->view('view', $data, TRUE) feature - described in detail at the very bottom of the Views page in the CI User Guide.

These view outputs are stored into variables within the $this->data array. The primary view file then just displays these data using simple echo statements.

Approach (in detail):

Let's work backwards from the end result - I think this will make more sense.

This is roughly what my primary view file ( default.php ) looks like. Note that this is what all my pages are rendered through.


<html>
<head>
<?php
    echo "\n". link_tag('assets/stylesheets/COMMON.css');
    echo "\n". link_tag('assets/stylesheets/'. $theme .'.css');
?>


<title>
    <?php echo $title; ?>
</title>
</head>

<body>

<?php
?>

<div id="div_everything_wrapper">

    <div id="div_topbar_wrapper">
        <?php echo $top_bar_view; ?>
    </div>

    <div class="break">
    </div>

    <div id="div_torso_wrapper">

        <div id="div_navigation_menu">
            <?php echo $main_menu_view; ?>
        </div>

        <div id="div_main_content">
            <?php echo $main_content_view;  ?>
        </div>

    </div>

    <div class="break">
    </div>

    <div id="div_footer_wrapper">
        <table width="100%">
            <tr width="100%">
            <td width="25%" align="left">
                <b>
                <!-- Can't pre-render this, as it'll throw the reported results -->
                Rendered in {elapsed_time}s, and {memory_usage}.
                </b>
            </td>
            <td width="50%" align="center">
                $other_stuff
            </td>
            <td width="25%" align="right">
                Developed using
                <?php echo anchor_popup ("http://codeigniter.com/", "Code Igniter"); ?>
            </td>
            </tr>
        </table>
    </div>
</div>


</body>
</html>

Now let's look at what goes into one of those view snippets that I'm echo'ing there. My top view contains three divs, generated separately, so not a good candidate example. My menu is lengthy, but most people understand menus, and I happen to generate a slightly different menu if the logged in user is admin-equiv, so it's probably a quite instructive choice.

In MY_Controller I have the following code:


$tmp_data['menu_data'] = $this->_generate_menu_data();
$this->data['main_menu_view'] = $this->load->view ('common/create_table_main_menu', $tmp_data, TRUE);

Things to note here:

I'm using a private (to MY_Controller) function called _generate_menu_data that just produces a big array of menu data. No normal controllers will use that function.

I generate the physical - the HTML version - of my menu by throwing that data out to my view create_table_main_menu, which lives in a directory of common view components. (Most of my view files live in a sub-directory denoting the controller they belong to.)

The TRUE on that second line means that the view isn't rendered to the screen at this point - instead, CI returns the HTML back to me - and it's put into $this->data['main_menu_view'].

You'll also notice that in the primary view file, shown earlier, there is a line that is simply an echo $main_menu_view.

Actual page content:

You might be asking - But how do I generate my actual interesting and different-on-each page data?! -- and it's a good question, and shows that you've been paying some attention.

The hint is in the code above - in my primary view file, where I do this:


<div id="div_main_content">
     <?php echo $main_content_view;  ?>
</div>

So, in each of my normal Controllers, my logic is heading towards the generation of a $this->data['main_content_view'] variable, which is then passed out to the primary view, and it gets displayed just like the other prepared data.

Here's a very basic example from one of my Controller's index methods that I haven't worked out what I want to do in yet - it's a place-holder, in other words, but demonstrates the situation nicely enough:


$disptext  = "Location stuff happens in here somewhere.";
$disptext .= "<br />";

$this->data['main_content_view'] = $disptext;
$this->load->view ('default', $this->data);

Of course, in some of my more complex methods I'm actually building up my $disptext from a calls to several different views (generating tables usually) but the principle remains the same, and isn't substantively different from the 'conventional' approach.

Additional material:

For the sake of completeness I'll show you now my private MY_Controller functions to generate my menu data - though it's perhaps not hugely germane to this subject, it does show how you can generate subtly different information on each page load, depending on certain conditions.


private function  _generate_menu_data ()  {
    $menu_data_array = array (
                        "Lobby" => array (
                            "Front page"              => "meta/lobby",
                            "About this site"         => "meta/about",
                            ),
                        "Messaging" => array (
                            "Public Forums"           => "forum",
                            "Private Mail"            => "mail/inbox",
                            ),
 . . .

    $admin_menu_data_array = array (
                        "Admin Stuff" => array (
                            "Log analysis"           => "admin/activity",
                            "Recent changes"         => "admin/changes",
                            "User management"        => "admin/users",
                            ),
                        );

    /// If we're logged in, we get an extra menu item under People
    if ($this->session->userdata('login_name'))
        $menu_data_array["People"]["My details"] = "people/view/".
                                            $this->session->userdata('login_name');

    /// If we're admin, we get the special menu additions!
    /// (We merge, rather than a straight insert, as one day the admin menu
    /// additions may interweave with the user ones above.)
    if ($this->session->userdata('admin'))  {
        $admin_menu_array = array_merge_recursive ( $admin_menu_data_array , $menu_data_array );
        return ($admin_menu_array);
        }

    /// Otherwise, the boring ol' menu gets delivered.
    return ($menu_data_array);
    }