2011-02-16 13 views
2

由於某種原因(哪個?),子類中定義的PHP常量/靜態變量在父類中不可用於靜態上下文中。通過父類在靜態上下文中不可用的PHP常量/靜態變量

爲什麼?

例1:

class Model{ 
    function getAll(){ 
    $query = "SELECT * FROM " . self::DATABASE_TABLE_NAME; 
    // ... 
    } 
} 

class Post extends Model{ 
    const DATABASE_TABLE_NAME = 'post'; 
} 

$p = Post::getAll(); 

當我跑,我得到:

Fatal error: Undefined class constant 'DATABASE_TABLE_NAME' on line 3 

(以$查詢行= ...)

例2:

class Model{ 
    function getAll(){ 
     $query = "SELECT * FROM " . self::$DATABASE_TABLE_NAME; 
     // ... 
    } 
} 

class Post extends Model{ 
    static $DATABASE_TABLE_NAME = 'post'; 
} 

$p = Post::getAll(); 

然後我得到:

Fatal error: Access to undeclared static property: Model::$DATABASE_TABLE_NAME on line 3 

(同一行)

+1

因爲`self`指的是父母,其中常量或靜態變量沒有定義? – BoltClock 2011-02-16 17:44:20

回答

5

PHP5.3介紹late static binding —這就是你要找的。

class ParentClass { 
    public function getAll() { 
     var_dump('Get all from ' . static::TABLE_NAME); 
    } 
} 

class ChildClass extends ParentClass { 
    const TABLE_NAME = 'my_table_name'; 
} 

$c = new ChildClass(); 
$c->getAll(); // Get all from my_table_name 

編輯:

但是你應該設計您的類有點不同。上面的解決方案依賴於語言動態(你可以引用一些甚至不存在的東西(例如類常量))。在這樣一個簡單的例子中,一切都很好,但是在實際情況下,這會導致維護代碼的可怕性和難度。

它最好能夠迫使交付類(ChildClass)來實現一些返回表名法:

abstract class ParentClass { 
    // getAll function 

    abstract protected function getTableName(); 
} 

class ChildClass extends ParentClass { 
    // You have to implement this method 
    protected function getTableName() { 
     return 'table name'; 
    } 
} 
+0

這甚至比我的$ class = get_called_class()解決方案更好(見下文)! – MPV 2011-02-16 18:04:14

0

有一應俱全。

下你應該使用late static binding這樣代碼將成爲靜態上下文:

$query = "SELECT * FROM " . static::$DATABASE_TABLE_NAME; 

我也建議你使用常量理智的原因。

+0

我完全同意常數,我只是嘗試使用類變量,因爲常量不起作用,但即使在那裏,問題依然存在。 – MPV 2011-02-16 18:06:01