开发者

PHP const/static variables not usable in static context by parent class

For some reason (which?), PHP const/static variables defined in a child class are not usable in a static context by the parent class.

Why?

Example 1:

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

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

$p = Post::getAll();

When I run tha开发者_如何学Ct I get:

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

(The row with $query = ...)

Example 2:

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

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

$p = Post::getAll();

Then I get:

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

(Same row)


PHP5.3 introduced late static binding — that's what you're looking for.

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

EDIT:

However you should design your classes a little bit different. The above solution relies on language dynamics (you can refer to something (eg. a class constant) that doesn't even exists). In such a simple example everything is fine but in real word cases this leads to producing horrible and hard to maintain code.

It'd be better to force the delivered class (ChildClass) to implement some method that returns table name:

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';
    }
}


I found the answer here: How can I get the classname from a static call in an extended PHP class?

Solution:

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

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

$p = Post::getAll();


There all available.

Under the static context you should be using late static binding so that the code would become:

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

i would also advise you to use constants for sanity reasons.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜