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.
精彩评论