摘要工厂不可能在php< 5.3?

时间:2010-08-13 18:38:09

标签: php abstract-class factory-pattern late-static-binding

我正在开发一个抽象类来保存几个类的代码。这些类都是通过不同的静态调用实例化的工厂。我可以通过将所有这些方法放在抽象类中来保存一些代码。

但是,我遇到了一个迟到的静态绑定问题...因为我们的Web主机没有使用5.3或更高版本,所以我无法访问get_called_class。如果我有

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

在抽象类中,__CLASS__是抽象类的名称,当我真的希望它使用被调用的类时。

我在Web上看到了抽象工厂的示例,其中子类具有自己的实例化方法,并且不依赖于抽象父类。但是,在这种情况下,抽象类的唯一原因是保存代码,所以如果我不能在那里执行它,它的值会大大减少。

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 个答案:

答案 0 :(得分:1)

我见过的唯一解决方法是调用debug_backtrace来确定调用者的类名。这当然是一个巨大的黑客。我已经看到一些代码将回溯与结合起来实际打开调用文件并解析它来解决问题。奇怪,可怕的东西。

缺乏LSB将会回来并在以后咬你。立即升级,即使这意味着切换主机。实际上,特别是如果它意味着切换主机。 5.3已经出了一年了。

答案 1 :(得分: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];
   }
}

这使您可以在静态函数中确定调用函数的类名。这是一个有一些性能问题的解决方法,但它是我发现的唯一一个。如果有其他人我有兴趣知道。

答案 2 :(得分: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();