我有一个由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;
}
答案 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
我们将忽略上面列出的仅用于教育目的的最佳做法仅,因为在学习它如何运作之后,您当然会重新考虑这一点。
您的目标(我可以收集的内容):在基类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