2013-04-25 61 views
2

我有一個靜態函數被調用,這是一個奇怪的錯誤。下面是PHP代碼的示例: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發生此錯誤?

回答

6

你開始通過在靜態情況下進行的方法調用:

stat::isValid('two'); 

當你這樣做,PHP會「記住」從isValid內這是所謂的上下文特別是當它在方法體內看到類似static::的東西時,它可以解決要綁定的內容,確定您嘗試訪問的某個屬性是否可見,並且通常能夠實現一些OO-re相關的語言功能。

的實際方法isValidstatic,但PHP仍允許你調用它使用靜態方法語法(它確實給了E_STRICT警告有關)。但是,這具有isValid本身不參與修改(後期)靜態綁定的調用上下文的副作用。

結果:PHP看到static::$invalidNumbers它仍然認爲你是中途從foo類中進行靜態方法調用時!一旦你意識到這一點,很明顯爲什麼static::解析爲foo::,它最終在錯誤的地方尋找屬性。

如果你正確地聲明isValidstatic

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

然後在調用方法PHP 確實更新它的上下文內部和管理綁定到對象構件。

+0

好的答案!確實如此,當你聲明'foo :: invalidNumbers'時,這些代碼正在工作。雖然這是完全有道理的,但我之前並沒有意識到這一點。 – hek2mgl 2013-04-25 20:45:09

3

您正在嘗試靜態調用方法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 

你的error_reporting在php.ini中,你會看到這樣的消息:

Strict standards: Non-static method stat::isValid() should not be called statically, assuming $this from incompatible context in ...

+0

我意識到這個通知,但並沒有意識到它造成了這種差異。謝謝。 – Schleis 2013-04-25 20:32:50

+0

它使* *的差異;) – hek2mgl 2013-04-25 20:33:30

2

聲明static方法正確

替換

function isValid($number) { 

隨着

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