Search code examples
phpcodeignitersingletoncodeigniter-2

Library as Singleton in Codeigniter?


I've created a custom library using singleton pattern. Why by this way? because I need to be able to call my functions without $this-> reference, for example, I could execute the code below:

function foo() {
    MyLibrary::instance()->foo();        
}

then I could call my functions in controllers like this:

function foo();

instead of

$this->mylibrary->foo();

I am in trouble because CodeIgniter try to instantiate my library when the best way to do is "read" the static instance.

Why I need to do this?

My custom library must register "hooks" from external php files located in /plugins directory outside of application folder. Look:

  • /application
  • /plugins
  • /plugins/helloworld.php

This is my Loader library:

class Loader{

    public static $instance;
      protected $hooks;

    private function __construct($params = array()){
        $this->hooks= array();
        $this->includePlugins();
    }

    public static function instance()
        {
            if (!self::$instance)
            {
                self::$instance = new Loader();
            }

            return self::$instance;
        }

    public function includePlugins()
    {
        include_once "/plugins/helloworld.php";  
    }

    public function do_action($hook= "after")
    {
        foreach ($this->actions[$hook] as $function)
        {
            call_user_func_array($function, array());
        }

    }

    public function add_action($hook, $function, $priority)
    {
        if ($hooks !== false)
        {
        $this->actions[$hook][] = $function;
        }
        else
        {
        echo "hook name is unavalaible";
        }
    }

}



/**
 * Functions using the Singleton instance !!!
*/

function do_action($hook)
{
    Loader::instance()->do_action($hook);
}

function add_action($hook, $function, $priority)
{
    Loader::instance()->add_action($hook, $function, $priority);
}

No, my helloworld.php (plugin) looks like this:

add_action('right_here', 'show_message', 11);
function show_message()
{
    echo "hello world!";
}

Finally, I could call my the function do_action in my controller/view in order to print the message, like this:

do_action('right_here');

Note that all my important functions are called by a global function that allow me to use the singleton instance. But I am experiencing two issues:

  1. Codeigniter needs that my contruct be public in order to instantiate. Here I need to take my singleton.
  2. If I let it public, several instances will be created and the library will no longer works as expected.

Solution

  • I've solved the problem :)

    In order to create a singleton library you must:

    • Include your library at system/core/Codeigniter.php like this: require_once("/path/to/library.php");

    • Make your instance return with & symbol, like this:

    Singleton:

    public static function &instance()
    {
        if (!self::$instance)
            {
                self::$instance = new Loader();
            }
    
            return self::$instance;
    }
    
    • Ready to uses your functions as well. Also, you can include th CI object in you library.