【问题标题】:PHP Late Static Binding referencing calling classPHP Late Static Binding 引用调用类
【发布时间】:2013-04-19 21:33:46
【问题描述】:

我有一个正在调用的静态函数,它给出了一个奇怪的错误。下面是一个php代码示例:

class foo {
     public $stat;
     public function __construct() {
         $this->stat = stat::isValid('two');
     }
}

class stat {
     protected static $invalidNumbers = array('one', 'two');
     function isValid($number) {
         return in_array($number, static::$invalidNumbers);
     }
}

$foo = new foo();
var_dump($foo->stat);

此代码导致以下错误:

Fatal error: Access to undeclared static property: foo::$invalidNumbers

但是,将 static:: 更改为 self:: 会使代码按预期运行。我的印象是在这种情况下使用static:: 应该可以工作。

为什么使用static会出现这个错误?

【问题讨论】:

    标签: php late-static-binding


    【解决方案1】:

    您正在尝试静态调用方法stat::isValid(),但尚未声明它static。将stat 类更改为:

    class stat {
         protected static $invalidNumbers = array('one', 'two');
    
         // needs to be declared static
         static function isValid($number) {
             return in_array($number, static::$invalidNumbers);
         }
    }
    

    请注意,如果添加

    | E_STRICT
    

    到您在 php.ini 中的 error_reporting,您会看到如下消息:

    严格标准:不应静态调用非静态方法 stat::isValid(),假设 $this 来自...中的不兼容上下文

    【讨论】:

    • 我知道该通知,但不知道它造成了这种差异。谢谢。
    • 它使 与众不同 ;)
    【解决方案2】:

    正确声明static方法

    替换

     function isValid($number) {
    

    public static function isValid($number) {   
             ^--- here  
    

    【讨论】:

      【解决方案3】:

      您首先在静态上下文中进行方法调用:

      stat::isValid('two');
      

      当您执行此操作时,PHP 会“记住”在其中专门调用 isValid 的上下文,以便当它在方法主体中看到类似 static:: 的内容时,它可以解析要绑定的内容,确定您是否有某些属性正在尝试访问是可见的,并且通常能够实现一些与OO相关的语言功能。

      isValid 的实际方法是 not static,但 PHP 仍然允许您使用静态方法语法调用它(它确实给出了 E_STRICT 警告)。但是,这有一个副作用,即isValid 本身不参与修改(后期)静态绑定的当前调用上下文。

      结果:当 PHP 看到 static::$invalidNumbers 时,它仍然认为你在 foo 类中进行静态方法调用已经完成了一半!一旦你意识到这一点,很明显为什么static:: 解析为foo:: 并最终在错误的地方寻找属性。

      如果您正确地将isValid 声明为static

       static function isValid($number) {
           return in_array($number, static::$invalidNumbers);
       }
      

      然后在调用方法时,PHP 在内部更新其上下文并设法绑定到预期的成员。

      【讨论】:

      • 好答案!确实如此,当您声明 foo::invalidNumbers 时,相关代码正在运行。虽然这完全有道理,但我以前没有意识到这一点。
      猜你喜欢
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-07
      相关资源
      最近更新 更多