Gnuffo1
Gnuffo1

Reputation: 3546

How do I use the same object for multiple hooks in CodeIgniter?

I have the following hook config (in hooks.php)

$hook['post_controller_constructor'][] = array(
    'class'     => 'MY_DataCollection',
    'function'  => 'init',
    'filename'  => 'MY_DataCollection.php',
    'filepath'  => 'hooks'
);

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

What I want to do is have the class instantiated in the post_controller_constructor and then have the init method run. Then for post_controller run the post_controller but using the very same instance. CodeIgniter is instantiating the class again however.

Next I tried something slightly clever I thought:

require_once APPPATH . 'hooks/MY_DataCollection.php';
$collection = new MY_DataCollection;

$hook['post_controller_constructor'][] = array(
    'function'  => array($collection, 'init'),
    'filename'  => 'MY_DataCollection.php',
    'filepath'  => 'hooks'
);

$hook['post_controller'][] = array(
    'function'  => array($collection, 'post_controller'),
    'filename'  => 'MY_DataCollection.php',
    'filepath'  => 'hooks'
);

That doesn't work, as the hook class in CI does a require and I get:

Fatal error: Cannot redeclare class MY_DataCollection in /var/www/application/hooks/MY_DataCollection.php on line 7

So I got rid of the file path info:

require_once APPPATH . 'hooks/MY_DataCollection.php';
$collection = new MY_DataCollection;

$hook['post_controller_constructor'][] = array(
    'function'  => array($collection, 'init')
);

$hook['post_controller'][] = array(
    'function'  => array($collection, 'post_controller')
);

Doesn't even attempt to run, as in the CI_Hooks class there is this check in _run_hook:

if ( ! isset($data['filepath']) OR ! isset($data['filename']))
{
    return FALSE;
}

I think I'm going to have to override this function by extending this class, but I just can't believe that this situation hasn't been encountered by someone else before and that there's not any easier way of solving it.

Thanks

Upvotes: 4

Views: 1615

Answers (2)

tomexsans
tomexsans

Reputation: 4527

This issue is already solved on the CI3 here is how to fix it on CI2

  • Just create a MY_Hooks.php on your app/core directory
  • Copy the Hooks.php class on the CI 3 Repository and put it in your MY_Hooks.php but the class name will be MY_Hooks Extends CI_Hooks it is located on system/core/hooks.php
  • change the call_hook function to _call_hook (just add a underscore '_')
  • change the private _run_hook to public
  • next step, is lay back and drink beer

Here is to test if it is working

class Hook_hook{
    private $init = 'function inits not called';

    public function inits(){
        $this->init = 'function inits called';
    }

    public function load(){
        echo '<script>alert("'.$this->init.'")</script>';
    }
}

Sample config on config/hooks.php

$hook['post_controller_constructor'][] = array(
    'class'     => 'Hook_hook',
    'function'  => 'inits',
    'filename'  => 'Hook_hook.php',
    'filepath'  => 'hooks'
);

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

Upvotes: 3

Alfred_P
Alfred_P

Reputation: 792

Hmmz, it seems you need to store the instance of the needed class somewhere. Maybe you could do something like this:

class MyHooks 
{
    public static $object_you_need;

    public function init() 
    {
        $object = new MyObject();
        $object->init();
        self::$object_you_need = $object;
    }

    public function post_controller()
    {
        $object = self::$object_you_need;
        // do stuff with that object
    }
}

Doesn't feel pretty, but I think it works.

Upvotes: 4

Related Questions