• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Hooks don't work

#1
[eluser]CoderReborn[/eluser]
I'm trying to use hooks to implement standard headers/footers on every page.


In my config file, I turned on hooks: $config['enable_hooks'] = TRUE;

Here's my hooks.php file:
Code:
$hook['pre_controller'] = array(
                      'class'  => 'Template',
                      'function' => 'header',
                      'filename' => 'template.php',
                      'filepath' => 'hooks'
                      );



$hook['post_controller'] = array(
                      'class'  => 'Template',
                      'function' => 'footer',
                      'filename' => 'template.php',
                      'filepath' => 'hooks'
                      );

Here's my template.php file:
Code:
<?php

/* Hook template functions */


class Template
{
    public function header()
    {
        $local_CI =& get_instance();
        $local_CI->load->view('header_view');
    }

    public function footer()
    {
        $local_CI =& get_instance();
        $local_CI->load->view('footer_view');
    }

}
?>

But when I run a test controller, I just get a HTTP 500 error code.
When I run the test controller without the hooks enabled, it works fine.

Do my header_view.php and footer_view.php files need to formatted in a special way?
Are there any restriction on what can/cannot be included in them as hook files?
They are just static HTML files now.


Thanks for your help!

#2
[eluser]erik.brannstrom[/eluser]
Could you tell us what the description of the 500 error is? My first thought is that you usually should load your views at the end of your controller since any output before that will interfere with setting your headers, but I can't really tell without any more information. Copy the error and we'll see what we can do.

#3
[eluser]danmontgomery[/eluser]
$local_CI->load doesn't exist pre_controller (your controller doesn't even exist pre_controller), you want to call that hook post_controller_constructor instead so that libraries are properly assigned

#4
[eluser]CoderReborn[/eluser]
I've got the post-controller hook working!

But the pre-controller hook still doesn't work - the screen goes blank when I run the program with it activated.
This is what I see in Firebug console:
Quote:"NetworkError: 500 Internal Server Error - http://localhost/

The key question is: How do I load a view in a pre-controller hook?

@noctrum: I have to load "header_view.php" in the pre-controller so it will appear at the top of the page. I tried loading the header_view in the post-controller, but it was placed at the bottom of the page.

I changed the Template code to the following, but am still getting the HTTP 500 error code:
Code:
class Template
{
    public function header()
    {
        $this->load->view('header_view');
    }

    public function footer()
    {
        $local_CI =& get_instance();
        $local_CI->load->view('footer_view');
    }

}

Thanks for your help!

#5
[eluser]erik.brannstrom[/eluser]
noctrum is right, you can't use the global CI object in your pre-controller hook since it doesn't exist, which I didn't think of. I guess you could probably create some hack that appends the header to the output class, but to be honest I doubt there will be any good way.

Since you will have to load your main view in each controller method anyway, why not create a template view that includes both the header and footer and pass the main view to that template?

Code:
// controller method
$this->load->view('template', array('partial_view' => $this->load->view('my_view', '', true);

// template.php
<html>
<!-- more header code.. -->
<?=$my_view?>
<!-- footer code.. -->
</html>

Or you could just pass the name of the view to the template, and let it load the partial view itself. Does this seem like a good solution to you?

#6
[eluser]mddd[/eluser]
It seems to me that using hooks for this kind of thing is just not the way to go. By using hooks for header/footer you are building a very inflexible system.
Not only do you have to jump through hoops to load a view in the 'header' hook - because some parts of CI aren't even loaded yet at that stage - but also you are making a system that will ALWAYS put out the same header. I thinks that is dumb.

What if you need a custom title in the header view? You can't do that because you probably don't know the title until you are in the controller. What if you want to put out a xml file (for instance for building an rss feed)? You can't, because no matter what you do, every call to CI will result in some html being outputted.

I'm all for making things easy. But putting out headers and footers using hooks is NOT making things easy. It's just creating restrictions.

Here's a crazy idea: put one line of code at the top of your 'content view':
Code:
$this->load->view('header_view');
. One more line on the bottom:
Code:
$this->load->view('footer_view');
. That's it, you're done. And the views will be able to use all the variables from your content view. And you can build specific views for other data types such as xml documents, css, whatever.

#7
[eluser]CoderReborn[/eluser]
@mddd - yes, your approach is what I decided to use. It provides more flexibility even if it means an extra 2 lines of code per controller.

BTW - still not sure when you would ever want to use pre-controller or post-controller hooks.

Thanks.

#8
[eluser]bretticus[/eluser]
If you don't like those extra lines of code, you could always extend the loader class and update view() to automatically load the header and footer. Not a big deal and a little inflexible again now. Just food for thought. Smile

#9
[eluser]Kamarg[/eluser]
If you want to use hooks for this, it seems like the appropriate hook would be display_override. Then you just need to do something like the below.
Code:
$CI =& get_instance();
$content = $CI->load->view('header_file') . $CI->output->get_output() . $CI->load->view('footer_file');
$CI->output->_display($content); // Maybe just echo $content?

Note that this could also be done by having a _output function within your MY_Controller and making sure all your controllers extend MY_Controller.

#10
[eluser]jeephnx[/eluser]
Hi Ive also just had trouble getting hooks to work with php5.2 and CI 1.7.2. Seems that CI is VERY case sensitive in this configuration. Filenames and class names must be capitalised as per the manual. (php4x seemed more forgiving in this regard)

I found this useful:
http://ellislab.com/codeigniter/user-gui...aries.html

In the end I gave up constructing a class in the hook file and went for a simple procedural function, just setting the class => '' in the config array as per this:
http://ellislab.com/codeigniter/user-gui...hooks.html

I do like CI but this stuff burns hours if you dont read the manual exactly!


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2020 MyBB Group.