2010-08-13 4 views
0

Я работал над абстрактным классом, чтобы сэкономить на некотором коде для пары классов. Эти классы - все фабрики, которые создают себя через разные статические вызовы. Я мог бы сэкономить некоторый код, поместив все эти методы в абстрактный класс.Реферат Фабрики невозможны в php <5.3?

Тем не менее, я столкнулся с проблемой поздней статической привязкой ... поскольку наш веб-хост не использует 5.3 или новее, у меня нет доступа к get_called_class. Если у меня есть

$class = __CLASS__; 
return new $class(); 

в абстрактном классе, __CLASS__ этого имя абстрактного класса, когда я на самом деле хочу, чтобы использовать названный класс.

Я видел примеры абстрактных фабрик в Интернете, где дочерние классы имеют свои собственные методы создания экземпляров и не полагаются на абстрактного родителя для него. Однако в этой ситуации единственной причиной абстрактного класса является сохранение кода, поэтому, если я не могу этого сделать, значение его значительно уменьшится.

Есть ли обходной путь в php < 5.3? debug_backtrace()?


Edit:

Я сделала тест, и он кажется 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 

ответ

0

После того, как способ сделать это, чтобы переопределить различные методы создания экземпляра, и передать имя класса непосредственно:

<? 

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(); 
+0

Он не использует 5.3, поэтому у него нет '__CLASS__ 'константа для начала ... – Charles

+0

Я - ОП;)' __CLASS__' был доступен с 4.3: http://php.net/manual/en/language.constants.predefined.php. Я использую 5.2.6, и я использую его все время. – user151841

+0

Мне нужно научиться читать, хе-хе. – Charles

1

Единственный способ решения проблемы я видел для этого включает в себя вызов debug_backtrace определить имя класса вызывающего абонента (ов). Это, конечно, гигантский взлом. Я видел некоторый код, который объединяет обратную трассировку с , фактически открывая вызывающий файл и анализируя его, чтобы разобраться в деталях. Необычный, ужасный материал.

Отсутствие LSB собирается вернуться и укусить вас позже. Обновляйте сейчас, даже если это означает переключение хостов. На самом деле, особенно если это означает переключение хостов. 5.3 уже в течение года.

+0

Я сделал тест, и вызов 'debug_backtrace()' в абстрактный 'создать () 'свойство не имеет элемента, который ссылался на исходный класс! Я бы подумал, что он будет там, но я думаю, поэтому мы нуждаемся в позднем статическом связывании: P – user151841

+0

Проверьте код m1tk4, тогда он может быть умнее ... – Charles

1

Вот что я никогда использую до перехода на 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]; 
    } 
} 

Это позволяет определить, в статической функции, что имя класса функция была вызвана с. Это обходное решение, которое имеет некоторые проблемы с производительностью, но это единственный, который я нашел. Если есть другие, мне было бы интересно узнать.

Смежные вопросы