Абстрактные фабрики невозможны в PHP <5.3?
-
28-09-2019 - |
Вопрос
Я работал над абстрактным классом, чтобы сохранить на некоторых коде для нескольких классов. Эти классы - это все фабрики, которые создавали себя через различные статические вызовы. Я мог сэкономить какой-код, положив все эти методы в абстрактный класс.
Тем не менее, я столкнулся с Позднее статическое обязательство Проблема ... Поскольку наш веб-хост не использует 5,3 или позже, у меня нет доступа к get_called_class. Если у меня есть
$class = __CLASS__;
return new $class();
в абстрактном классе, __CLASS__
Название абстрактного класса, когда я действительно хочу, чтобы он использовал под названием класс.
Я видел примеры абстрактных фабрик в Интернете, где у детей-классов есть собственные методы создания инсультаций, и не полагаются на абстрактный родитель для него. Однако в этой ситуации единственная причина для абстрактного класса состоит в том, чтобы сохранить код, поэтому, если я не могу сделать это там, значение оно значительно уменьшается.
Есть ли обходной путь в PHP <5.3? debug_backtrace()
?
Редактировать:
Я сделал тест, и кажется debug_backtrace()
не будет работать! Я думаю, вот почему нам нужно Позднее статическое обязательство.
<?
abstract class abstractFactory {
public function create() {
print_r(debug_backtrace());
$class = __CLASS__;
return new $class();
}
}
class concreteFactory extends abstractFactory {}
$chimborazo = concreteFactory::create();
И результат:
$ php test.php
Array
(
[0] => Array
(
[file] => /var/www/test.php
[line] => 13
[function] => create
[class] => abstractFactory
[type] => ::
[args] => Array
(
)
)
)
Fatal error: Cannot instantiate abstract class abstractFactory in /var/www/test.php on line 7
Решение 3
Размещение способа сделать это, чтобы переопределить различные методы создания инсультаций и передайте имя класса напрямую:
<?
abstract class abstractFactory {
public function create($class) {
return new $class();
}
public function instantiate($class) {
return new $class();
}
}
class concreteFactory extends abstractFactory {
public function create() {
parent::create(__CLASS__);
}
public function instantiate() {
parent::instantiate(__CLASS__);
}
}
$chimborazo = concreteFactory::create();
$chimborazo = concreteFactory::instantiate();
Другие советы
Единственный обходной путь, который я видел для этого, включает в себя звонить debug_backtrace. Определить название класса абонента (ы). Это, конечно, гигантский взлом. Я видел какой-нибудь код, который сочетает в себе задницу с на самом деле открытие вызова файла и разбирая его понять вещи. Причудливые, ужасные вещи.
Недостаток LSB собирается вернуться и укусить вас позже. Обновите сейчас, даже если это означает коммутационные хосты. На самом деле, особенно если это означает коммутационные хосты. 5.3 уже в течение года.
Вот что я использовал до перехода на 5,3:
if (!function_exists('get_called_class')) {
/**
* Implementation of get_called_class() for pre-5.3 PHP
*
* @return string
*/
function get_called_class()
{
$bt = debug_backtrace();
$lines = file($bt[1]['file']);
preg_match('/([a-zA-Z0-9\_]+)::'.$bt[1]['function'].'/',
$lines[$bt[1]['line']-1],
$matches);
return $matches[1];
}
}
Это позволяет определить в статической функции, какое имя класса была вызвана функция. Это обходной путь, который имеет некоторые проблемы с производительностью, но это единственное, что я нашел. Если есть другие, мне интересно узнать.