2

According to the Codeignitor docs here: http://ellislab.com/codeigniter/user-guide/general/hooks.html it states:

pre_controller Called immediately prior to any of your controllers being called. All base classes, routing, and security checks have been done.

However, if I create a hook pre_controller hook with:

$hook['pre_controller'][] = array(
'class'    => 'tester',
'function' => 'test',
'filename' => 'tester.php',
'filepath' => 'models',
//'params'   => array('beer', 'wine', 'snacks')
);

and the file tester.php is:

class tester extends CI_Model
{
  public function __construct()
  {
    parent::__construct();

    $this->load->library('migration');
  }

  public function test()
  {
    echo "hi";
    exit;
  }
}

I get this error:

Fatal error: Class 'CI_Model' not found in ******.php

Why is it not loading CI_Model? If I put a require_once('system/core/Model.php'); in the hooks.php file above the pre_controller definition, I get this error:

Fatal error: Call to a member function library() on a non-object in ****.php

Since it's not actually loading the CI_Model, functions such as library() would not work. How can I force it to bootstrap the CI_Model.

The first person that says "Use post_controller_constructor" will be shot on sight as that does not answer the question. I need it to load BEFORE it runs any constructor functions from the controller classes. I need access to extend the CI_Model class from the pre_controller hook.

Logan Wayne
  • 6,001
  • 16
  • 31
  • 49
user3488435
  • 23
  • 1
  • 4

2 Answers2

6

The short answer is that CodeIgniter doesn't work the way you want it to. At the stage that you're trying to access a model, CodeIgniter hasn't loaded the required classes and it isn't available. Depending on exactly what you're trying to achieve, there may be another way to achieve this - without using a hook/using a later hook?

Viewing /system/core/CodeIgniter.php will show when each hook is called and when other tasks are performed; loading routing, loading global functions etc.

If you insist on using this hook, then you could add this: load_class('Model', 'core'); at the top of your model file (before you declare the class), but this would be a very dirty fix.

Make sure your class names follow the correct naming convention - tester should be Tester.


Edit: as you want to run the same code on every call (assuming every controller call), this is a possible solution:

Extend the core controller, and use this new controller as a base controller for all other controllers (as they will be sharing the same functionality). In the constructor of this new base controller, add the functionality that you want to run on every call. The code in this constructor will be called before any other code in any of your controllers.

Create the following file, application/core/MY_Controller.php.

class MY_Controller extends CI_Controller {
    function __construct()
    {
        parent::__construct();
        // Do whatever you want - load a model, call a function...
    }
}

Extend every controller in application/controllers, with MY_Controller, rather than CI_Controller.

class Welcome extends MY_Controller {
    function __construct()
    {
        parent::__construct();
    }
    // Your controllers other functions...
}
jleft
  • 3,457
  • 1
  • 23
  • 35
  • Dirty fix is fine so long as it works and doesnt require a different hook :D I'm disappointed that the docs were incorrect though. I would consider the Model class a part of core. Even the load_class suggestion suggests that its a core item ;) I am going to give this a try in a few mins and will report back on if this works. – user3488435 Apr 02 '14 at 18:19
  • Well, this doesnt do anything other than result in the same error I get if I simply require_once the model class file. If I use this, I get: Fatal error: Call to a member function library() on a non-object in ****.php which I have been tracking down and think it has something to do with the loader class. – user3488435 Apr 02 '14 at 18:34
  • I agree that the docs are misleading - I'd consider models part of the core too! Sorry that didn't fix it. I've pinpointed the problem - in `CodeIgniter.php`, line 308, `$CI = new $class();`, is required to load a library. This is after the _pre controller_ hook. Move it before the hook and it should work. I don't know if there are any other repercussions though - use this at your own risk! What are you actually trying to achieve? – jleft Apr 02 '14 at 19:04
  • I am a Drupal dev trying to mimic a hook_init(). I'd like some code to run on every call to CI but before anything from the controllers are run. Essentially resulting in pretty much a hook_init() type of functionality. The CI hooks are pretty bad compared to Drupal hooks lol. But I didnt choose the framework or I would have gone with symphony2 ;) CI is still new to me but I've been using it ok with the exception of the hooks system which I've found to be inferior to other hooks type systems for other frameworks so far. – user3488435 Apr 03 '14 at 00:59
  • The tricky part is that the code I want to run on every single call is the migration class so that I can run $this->migration->latest(); and keep the schema up to date without having to muck with it everytime a change is made on all 3 servers (dev/staging/production). – user3488435 Apr 03 '14 at 01:21
  • Well, I ended up using $autoload['model'] as it appears to load before controllers but I'm not to sure it's the right way to implement what I wanted to do. It does seem to work though. – user3488435 Apr 03 '14 at 02:38
  • I'm pleased that you have found a solution (eventually!). I've updated my answer to give an alternate approach - if I've understood what you want to achieve, then hopefully you may find useful! – jleft Apr 03 '14 at 08:34
  • Even if I didnt use your alternative, someone else may. I may even use it later on as it is a good way alternative to the autoload approach. The autoload seemed a bit clunky to me but it did work. So its good to find two different methods to get the functionality I needed. – user3488435 Apr 04 '14 at 03:26
-1
/*application/config/hooks.php*/
$hook['pre_controller'][] = 
array(
     'class'    => 'MyClass',
     'function' => 'Myfunction',
     'filename' => 'Myclass.php',
     'filepath' => 'hooks',
     'params'   => array('beer', 'wine', 'snacks')
                                );
/*application/config/config.php*/
$config['enable_hooks'] = TRUE;

/hooks/Myclass.php/

kenlukas
  • 3,616
  • 9
  • 25
  • 36
meenu
  • 1