抽象工厂在 php < 中是不可能的5.3?

发布于 2024-09-14 10:11:34 字数 1327 浏览 14 评论 0 原文

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

但是,我遇到了后期静态绑定问题...由于我们的网络主机未使用 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

I was working on an abstract class to save on some code for a couple of classes. These classes are all factories that instantiate themselves through different static calls. I could save some code by putting all those methods in an abstract class.

However, I ran into a late static binding problem... since our web host isn't using 5.3 or later, I don't have access to get_called_class. If I have

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

in the abstract class, __CLASS__ is the name of the abstract class, when I actually want it to use the called class.

I've seen examples of abstract factories on the web where the child classes have their own instantiation methods, and don't rely on the abstract parent for it. However, in this situation, the only reason for the abstract class is to save code, so if I can't do it there, the value of it diminishes greatly.

Is there a workaround in php < 5.3? debug_backtrace()?


Edit:

I did a test and it seems debug_backtrace() will not work! I guess this is why we need late static binding.

<?

abstract class abstractFactory {
    public function create() {
            print_r(debug_backtrace());
            $class = __CLASS__;
            return new $class();
    }
}

class concreteFactory extends abstractFactory {}

$chimborazo = concreteFactory::create();

and the result:

$ 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

清引 2024-09-21 10:11:34

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

LSB 的缺乏稍后会回来咬你。立即升级,即使这意味着切换主机。事实上,尤其是当这意味着更换主机时。 5.3 已经发布一年了。

The only workaround I've seen for this involves calling debug_backtrace to determine the class name of the caller(s). This is of course a giant hack. I've seen some code that combines a backtrace with actually opening up the calling file and parsing it to figure things out. Bizarre, horrible stuff.

The lack of LSB is going to come back and bite you later. Upgrade now, even if it means switching hosts. In fact, especially if it means switching hosts. 5.3 has been out for a year now.

慈悲佛祖 2024-09-21 10:11:34

以下是我在升级到 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];
   }
}

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

Here's what I've been using until moving to 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];
   }
}

This lets you determine in a static function what class name the function has been invoked with. It's a workaround that has some performance issues but it's the only one I've found. If there are others I'd be interested to know.

放手` 2024-09-21 10:11:34

一种方法是重写各种实例化方法,并直接传递类的名称:

<?

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

Once way to do it is to override the various instantiation methods, and pass the name of the class directly:

<?

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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文