0

I need to call a static function from an object using the Singleton design, but using a variable as the class name.

The best way, $class::getInstance();, is only available in PHP 5.3, and the other way I found, call_user_func(array($class, 'getInstance'));, results in the maximum execution time being breached. Does anyone know why this is happening, or of a way for this to work / a workaround?

I know that this is not the best way for things to be done, and the Singleton design pattern would not be my first choice, but unfortunately it's not up to me.

Thanks in advance to anyone who contributes :)

I include the rest of the code involved:

abstract class Library
 {
  protected function __construct(){}
  final private function __clone(){}

  final public static function &getInstance()
   {
    static $libs = array();
    $lib = get_called_class();
    if(!isset($libs[$lib])) $libs[$lib] = new $lib();
    return $libs[$lib];
   }

 }

public function &loadLibrary($lib)
 {
  // Filter $lib, and load the library class file...
  // Following only works in PHP 5.3
  //   return $lib::getInstance();
  // Following results in maximum execution time being breached.
   return call_user_func(array($lib, 'getInstance'));
  }
}

$someLibrary =& loadLibrary('someLibrary');

someLibrary.php:

class someLibrary extends Library
 {
  protected function __construct(){}
  // Code...
 }

Soulmerge make a valid point saying that get_called_class() is only in PHP 5.3, and therefore I must be using it, but alas, I just cheat my way round things as I usually do (Thanks to Chris Webb from http://www.septuro.com/ for the code - far too complex to be any of my own!).

if(!function_exists('get_called_class'))
 {
  class classTools
   {
    static $i = 0;
    static $fl = null;
    static function get_called_class()
     {
      $bt = debug_backtrace();
      if(self::$fl == $bt[2]['file'].$bt[2]['line']) self::$i++;
      else {
       self::$i = 0;
       self::$fl = $bt[2]['file'].$bt[2]['line'];}
      $lines = file($bt[2]['file']);
      preg_match_all('/([a-zA-Z0-9\_]+)::'.$bt[2]['function'].'/', $lines[$bt[2]['line']-1], $matches);
      return $matches[1][self::$i];
     }
   }
  function get_called_class()
   {
    return classTools::get_called_class();
   }
 }

I shall go over all my code again, as there must be a loop somewhere. Back to the drawing board I go :(

2
  • 1
    do not use the reference operator (&) with classes in PHP5, that’s deprecated (although it won’t save your problem—i guess) Commented Sep 8, 2009 at 12:20
  • Probably just a typo rather than the source of your problem, but your loadLibrary method takes $lib as an argument, but references $class in the code. Commented Sep 8, 2009 at 12:51

2 Answers 2

2

You should start by determining what it is that takes you into an infinite loop. Does your constructor (someLibrary::__construct()) have any code that directly/indirectly calls Library::getInstance(), for example?

EDIT get_called_class() was introduced in PHP 5.3, so if your code actually works, you're already running 5.3

Sign up to request clarification or add additional context in comments.

Comments

0

you could try to solve this with eval().

To get you an idea:

$theVar = "relvantClassName";
$someObject = eval($theVar::getInstance());
$result = $someObject->performAction();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.