PHP静态vs自变量和继承

时间:2014-05-17 20:18:44

标签: php oop static

我有一个由User和Post扩展的PHP Model类。他们都共享一个构造函数。我有一个静态变量用于'架构'每个对象,以便我得到描述'每个对象类型只从数据库中获取一次,当第一个实例化时。我以为我可以使用static :: _ schema在创建每个对象时引用变量,但如果我创建用户然后发布,则post引用用户_schema变量。如果我使用self :: OR static ::它会这样做。我不明白这个区别吗?得到我想要的结果我做错了什么?

下面是Model中的构造函数和getSchema函数(类Post和User都扩展)。但是如果我在创建用户之后在Post上调用getSchema,它将返回用户架构。

public function __construct($params = array())
{
    $this->_tableName = static::getTableName();
    $this->_className = static::getClassName();

    $this->getSchema();
}

public function getSchema()
{
    if (!static::$_schema) {
        $query = "DESCRIBE {$this->_tableName};";
        $sth = self::$db->prepare($query);
        $sth->execute(static::$bindings);
        $fields = $sth->fetchAll();

        foreach ($fields as $info) {
            static::$_schema[$info->Field] = array(
                'type' => $info->Type,
                'null' => $info->Null,
                'key' => $info->Key,
                'default' => $info->Default,
                'extra' => $info->Extra
            );
            if ($info->Key === 'PRI') {
                $this->_idField = $info->Field;
            }
        }
    }
    return static::$_schema;
}

1 个答案:

答案 0 :(得分:3)

晚期静态绑定

PHP的Late Static Binding是一个非常棒的概念,当你了解它时。实际上,它允许您对对象进行编码以处理子(扩展)类中包含的数据。然后,您可以更改子类,因此父(基)类将以不同的方式执行某些操作。

  

简而言之,后期静态绑定是继承感知self调用 [我的引用,随意在别处使用]

'模型'

快速回顾一下。 模型是图层。它是MVC中的。任何告诉你他们有“用户模型”或“帖子模型”的人都不知道他们在说什么。

随意重新限制how should a model be structured in MVC,并开始将这些(应该是)“哑巴对象”称为实体。您有一个User实体和一个Post实体。

扩展

扩展对象时,您说ExtendingObject 是-a ParentObject。通过User扩展Model,您说User 是-a Model,我们已经根据定义建立了 无效。你最好拥有一个通用的DB对象并通过Dependency Injection传递它。

构造

您的构造函数应该具有无业务逻辑。创建对象时,您将在特定状态下创建它。这可以通过构造函数参数,类型提示和无效标量参数的异常来强制执行。创建对象后,然后就像getSchema()一样在其上运行一个方法。

所以,重新上限:

  • User 不是 Model
  • 模型是图层,而不是对象
  • 通过依赖注入传递其他对象并遵守SRP
  • 您的构造函数应该没有业务逻辑

对于aphillips的LSB

我们将忽略上面列出的仅用于教育目的的最佳做法,因为在学习它如何运作之后,您当然会重新考虑这一点。

您的目标(我可以收集的内容):在基类Model中提供正确的表名,具体取决于当前正在扩展的对象({{1} }或User)。

Post

到目前为止,您有一个abstract class Model { /** Child classes MUST override this (you can enforce this if/however you like) **/ const TABLE_NAME = ""; public function __construct() { printf('Created table: %s', static::TABLE_NAME); } } 对象无法直接实例化,因为它是抽象的。因此,必须扩展使用。很酷,让我们创建你的POST对象。

Model

创建class Post extends Model { const TABLE_NAME = "POST TABLE"; } 对象时,它将使用Post中的继承构造函数。在Model构造函数中,它使用Model而不是static::来回显表名。如果它已使用self::,它将回显'创建表:'。相反,因为self::使用了static::的继承感知版本,所以它使用继承的var

因此调用self::的结果将是“Created table:post”。

假设您也创建了一个$post = new Post;对象:

User

每个对象在创建它们时都会回显它自己的表名:

class User extends Model
{
    const TABLE_NAME = 'User';
}

结论

您不必使用常量(尽管如此)。您可以使用类属性来完成它。但是不要让它们公开(全局可变状态很糟糕)。

根据上述信息,您应该可以轻松地使用$x = new User; // echoes User Table $x = new Post; // echoes Post Table 方法getSchema()方法static::SCHEMA_NAME方法同时getSchema()Post