Задача В общем ситуация была такова, что на предоставленном проекту хостинге версия PHP была 5.2, а сам проект был написан под 5.3. Наверняка каждый, кто работает с PHP, знает, что в версии 5.3 появилась возможность доступа к имени класса, полученному с помощью позднего статического связывания.
Например:
И теперь любой наследник этого класса будет Синглтон `ом.<Эphp class Singleton { static $instances = Array(); private function __construct() {} private function __clone() {} private function __wakeup() {} static function model(){ $class = get_called_class(); if (!isset(self::$instances[$class])) { self::$instances[$class] = new $class(); } return self::$instances[$class]; } }
class Test extends Singleton {
public function say(){
return 'Hi Habr!';
}
}
echo Test::model()->say();
Этот прием возможен благодаря появлению новой функции get_known_class в версии 5.3. Понятно, что в более ранних версиях это не будет работать.
Но что, если код уже написан, а последняя версия PHP недоступна?
Решение
Решение — сменить хостинг или установить последнюю версию PHP :).Но у меня, например, была ситуация, когда сейчас это невозможно, но проект должен работать, поэтому пришлось выкручиваться.
<Эphp
if(!function_exists('get_called_class')) {
function get_called_class() {
$obj = false;
$backtrace = debug_backtrace();
foreach($backtrace as $row){
if($row['function'] == 'call_user_func'){
$obj = explode('::', $backtrace[2]['args'][0]);
$obj = $obj[0];
break;
}
}
if(!$obj){
$backtrace = $backtrace[1];
$file = file_get_contents($backtrace["file"]);
$file = explode("\n", $file);
for($line = $backtrace["line"] - 1; $line > 0; $line--) {
preg_match("/(?<class>\w+)::(.
*)/", trim($file[$line]), $matches);
if (isset($matches["class"])){
return $matches["class"];
}
}
throw new Exception("Could not find");
}
return $obj;
}
}
class Singleton {
static $instances = Array();
private function __construct() {}
private function __clone() {}
private function __wakeup() {}
static function model(){
$class = get_called_class();
if (!isset(self::$instances[$class])) {
self::$instances[$class] = new $class();
}
return self::$instances[$class];
}
}
Вполне подойдет как временное решение проблемы.
Ну и для решения проблем, связанных с возможностью обращения к классу с помощью переменной: $class_name::model();
Заменен на: call_user_func($class_name. '::model');
Вот и все.
Спасибо за внимание.
Теги: #php 5.3 #php 5.2 #singleton #php
-
Образ, Созданный Asp.net
19 Oct, 24 -
Иконки Для Хабрахабра — Подход Суперхабра?
19 Oct, 24 -
Талмуд По Формулам В Google Spreadsheet
19 Oct, 24