Friday, October 8, 2010

Codeigniter Loading Singleton

I tried many times to register at the codeigniter forum, but the captcha is not letting me through. So I'll do my update here.

From this: http://codeigniter.com/forums/viewthread/150117/
Ketama has an example to load a library that is a singleton. However, if you are on PHP 5.2 and lower, you will have a problem. You will get a "Paamayim Nekudotayim" error.


Basically, before PHP 5.3, you cannot call a static method where the class is a variable. So the line below will give you an error.
$CI->$classvar = $name::getInstance($config);

$name cannot be used to make a call to the static method of getInstance. There are two ways around this. First is to use the eval() command, but this is deemed to be up to 10 times slower (read this somewhere...no link), while the second solution of being 3 times slower seems to be the acceptable method. It is to do this:

$CI->$classvar = call_user_func_array(array($name,'getInstance'), $config);

By using the call_user_func_array() function, this will work with PHP versions older than PHP 5.3.

I've also made some minor changes to the code proposed to more suit my liking (in MY_Loader.php [CI version 1.72], subclass from CI_Loader and copy and paste the _ci_init_class() function and make the following change).
// Instantiate the class
$CI =& get_instance();
// modification start
if ($config !== NULL)
{
  if (isset($config['singleton']) ? 
    $config['singleton'] === TRUE : FALSE)
  {
    // for PHP 5.3 and above
    //$CI->$classvar = $name::getInstance($config); 
    $CI->$classvar = call_user_func_array(array($name,'getInstance'), $config);
  } else
  {
    $CI->$classvar = new $name($config);
  }//End If. Added support for singleton Libraries
} else
{
  $CI->$classvar = new $name;
}
// modification ends

To use, put the MY_Loader.php and your singletone file both into your system/applications/libraries/ directory. Then in your controller put in the following:

$this->load->library('MYLogger', array('singleton'=>TRUE));

That's all!