k47.cz  — každý den dokud se vám to nezačne líbit
foto Praha výběr povídky kultura
twitter FB RSS

get_calling_class() pro PHP 5.2

13. 6. 2010 — k47 (CC by) (♪)

Pomocí jed­noho oš­k­li­vého hacku je možné do PHP 5.2 do­pl­nit funkci get_calling_class(), která za­jiš­ťuje late static bin­ding.


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 bo­hu­žel fun­guje jenom u jed­no­řád­ko­vých volání a také musí být na jednom řádku pouze jedna metoda vy­u­ží­va­jící get_called_class, metoda by pak ne­roz­po­znala správ­nou třídu.

Takže MyClass::staticMethod($arg); bude fun­go­vat, ale na­pří­klad ná­sle­du­jící kód vyhodí vý­jimku.

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

Ná­sle­du­jící kód také nebude fun­go­vat správně. Před­po­klá­dejme, že obě metody staticMethod volají get_called_class, ale ta v obou pří­pa­dech chybně vrátí třídu MyClass.

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