k47.cz
mastodon twitter RSS
bandcamp explorer

get_calling_class() pro PHP 5.2

— k47 (CC by)

Pomocí jednoho ošklivého hacku je možné do PHP 5.2 doplnit funkci get_calling_class(), která zajišťuje late static binding.


if (!function_exists('get_called_class')) {
	function get_called_class()
	{
		// dirty hack for php 5.2
		$trace = debug_backtrace();

		// last statically called method in trace
		$revtrace = array_reverse($trace);
		foreach ($revtrace as $t) {
			if (isset($t['type']) && $t['type'] === '::') {
				$back = $t;
				break;
			}
		}

		// open source file and read class name from source code
		$method = $back['function'];
		$fp = fopen($back['file'], 'r');

		for ($i = 0; $i < $back['line'] - 1; $i++) {
			fgets($fp);
		}
		$line = fgets($fp);
		fclose($fp);

		if (!preg_match('~([a-zA-Z0-9]+)s*::s*' . $method . 's*\(~', $line, $m)) {
			throw new Exception("Static calling class not found (using multiline static method call?)");
		}
		return $m[1];
	}
}

Tento trik bohužel funguje jenom u jednořádkových volání a také musí být na jednom řádku pouze jedna metoda využívající get_called_class, metoda by pak nerozpoznala správnou třídu.

Takže MyClass::staticMethod($arg); bude fungovat, ale například následující kód vyhodí výjimku.

MyClass::staticMethod(array(
  'arg1' => 'xyz',
  'arg2' => 123,
));

Následující kód také nebude fungovat správně. Předpokládejme, že obě metody staticMethod volají get_called_class, ale ta v obou případech chybně vrátí třídu MyClass.

MyClass::staticMethod(AnotherClass::staticMethod());
píše k47, ascii@k47.cz