Code Igniter is a great framework, and has some awesome documentation for a lot of what it does, but one place it lacks is in Hooks. What are hooks, how are they used etc, it is explained but not really. So I thought since I just accomplished an awesome example of when to use Hooks in a CI project, I would share it with the world.

What are Hooks?

I'm going to let the folks at Code Igniter field this one:

CodeIgniter's Hooks feature provides a means to tap into and modify the inner workings of the framework without hacking the core files. When CodeIgniter runs it follows a specific execution process, diagramed in the Application Flow page. There may be instances, however, where you'd like to cause some action to take place at a particular stage in the execution process. For example, you might want to run a script right before your controllers get loaded, or right after, or you might want to trigger one of your own scripts in some other location.

So to clear that up, Hooks let you change the way Code Igniter works, without changing Code Igniter.

10K ft view:

So the problem I had recently was a page that loads a CSS class only when the user selects to change the theme. However it had to be done through a link and had to set the preference in the session to be stored throughout the users session.

To accomplish that I had planned to create a simple controller action called setCssTheme and pass the theme the user had selected. The only problem was I needed to send the user back to the page they had come from, and in some cases the referrer was not being set (different browsers handle things differently).

In order to solve this last problem I had decided to set in the session the last page visited on each page load. This works great in a constructor of a particular class but what if you want to do that site wide, on every single page load like I do?

Force all your site through a single controller? I think not.

Force all your controllers to have this same piece of code? I think not.

Let's get DRY (Don't Repeat Yourself).

The solution I decided on was using Hooks in Code Igniter to Hook the system process and set in the session the current page I am on. In order to be able to do this I have to be able to write to the session before the headers are sent to the browser, and so I had to choose the appropriate hook point. CI gives you the follow points to hook in:

  • pre_system Called very early during system execution. Only the benchmark and hooks class have been loaded at this point. No routing or other processes have happened.
  • pre_controller Called immediately prior to any of your controllers being called. All base classes, routing, and security checks have been done.
  • post_controller_constructor Called immediately after your controller is instantiated, but prior to any method calls happening.
  • post_controller Called immediately after your controller is fully executed.
  • display_override Overrides the _display() function, used to send the finalized page to the web browser at the end of system execution. This permits you to use your own display methodology. Note that you will need to reference the CI superobject with $this->CI =& get_instance() and then the finalized data will be available by calling $this->CI->output->get_output()
  • cache_override Enables you to call your own function instead of the _display_cache() function in the output class. This permits you to use your own cache display mechanism.
  • post_system Called after the final rendered page is sent to the browser, at the end of system execution after the finalized data is sent to the browser

From those you can see the logic answer is to hook the post_controller so that our controller has a chance to do it's work, and then to hack in out changes for the session, in this case add data to it.

How To:

Time to put rubber to the road, here is what I had to do to accomplish this task:

  1. Enable Hooks
  2. Configure Hook
  3. Write Hook

Enable Hooks:

To enable the hooks you simply edit

application/config/config.php

and find the line:

[sourcecode language="php"]$config['enable_hooks'] = false;[/sourcecode]

and change it to:

[sourcecode language="php"]$config['enable_hooks'] = TRUE;[/sourcecode]

Configure Hook:

Now in application/config/hooks.php you need to tell the system what file path, file, controller, method, and parameters you want to run on the hook.

[sourcecode language="php"] $hook['post_controller'] = array( 'filepath' => 'hooks', 'filename' => 'SessionHelper.php', 'class' => 'SessionHelper', 'function' => 'setCurrentPage', 'params' => array(), );[/sourcecode]

Here I tell CI that when the controller is done, load hooks/SessionHelper.php and fire off SessionHelper->setCurrentPage() (more or less).

Then I created the file mentioned above as follows:

[sourcecode language="php"] class SessionHelper extends CI_Hooks {
public $CI;

function construct() { parent::construct(); $this->CI = get_instance(); }

function setCurrentPage(){ $this->CI->session->setuserdata('currentpage', current_url()); } [/sourcecode]

This simply loads the current_url() into the session userdata.

Now on every final page load (redirects won't be caught if they are in the controller) the current_url is stored in the session. So I can check values and redirect back to the current page if needed.