【问题标题】:PHP const/static variables not usable in static context by parent class父类在静态上下文中不能使用 PHP const/static 变量
【发布时间】:2011-02-16 17:40:50
【问题描述】:

由于某种原因(哪个?),在子类中定义的 PHP const/static 变量在父类的静态上下文中不可用。

为什么?

示例 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 

($query = ...的行)

示例 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

(同一行)

【问题讨论】:

  • 因为self指向父级,其中没有定义常量或静态变量?

标签: php oop class inheritance constants


【解决方案1】:

PHP5.3 引入了late static binding——这就是你要找的。​​p>

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

【讨论】:

  • 这比我的 $class= get_call_class() 解决方案还要好(见下文)!
  • @MPV:请阅读我更新后的答案 - 添加了一些重要说明。 ;)
【解决方案2】:

我在这里找到了答案: How can I get the classname from a static call in an extended PHP class?

解决方案:

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();

【讨论】:

    【解决方案3】:

    都有。

    在静态上下文下,您应该使用late static binding,这样代码就会变成:

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

    出于理智的原因,我还建议您使用常量。

    【讨论】:

    • 我完全同意常量,我只是尝试使用类变量,因为常量不起作用但问题仍然存在。
    猜你喜欢
    • 1970-01-01
    • 2019-03-17
    • 2011-11-30
    • 1970-01-01
    相关资源
    最近更新 更多