Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP静态变量与自变量及继承_Php_Oop_Static - Fatal编程技术网

PHP静态变量与自变量及继承

PHP静态变量与自变量及继承,php,oop,static,Php,Oop,Static,我有一个PHP模型类,它由用户和Post扩展。它们都共享一个构造函数。我为每个对象的“模式”都有一个静态变量,这样当第一个对象被实例化时,每个对象类型只能从数据库中获得一次“描述”。我想我可以在创建每个对象时使用static::schema来引用变量,但是如果我创建user然后post,post就是引用user_schema变量。如果我使用self::或static::,它就会这样做。我对差异的理解错了吗?为了得到我想要的结果,我做错了什么 下面是模型内部的构造函数和getSchema函数(类P

我有一个PHP模型类,它由用户和Post扩展。它们都共享一个构造函数。我为每个对象的“模式”都有一个静态变量,这样当第一个对象被实例化时,每个对象类型只能从数据库中获得一次“描述”。我想我可以在创建每个对象时使用static::schema来引用变量,但是如果我创建user然后post,post就是引用user_schema变量。如果我使用self::或static::,它就会这样做。我对差异的理解错了吗?为了得到我想要的结果,我做错了什么

下面是模型内部的构造函数和getSchema函数(类Post和用户都进行了扩展)。但是,如果在创建用户后在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;
}
后期静态绑定 PHP是一个非常棒的概念,当你了解它的时候。实际上,它允许您编写一个对象来处理子(扩展)类中包含的数据。然后可以更改出子类,因此父(基)类将执行不同的操作

简而言之,后期静态绑定是一个继承感知的调用。[我的引文,请随意在其他地方使用]

“模型” 简单回顾一下模型是一个层。它是MVC中的层。任何人告诉你他们有一个“用户模型”或“后模型”,都不知道他们在说什么

请随意重新限制并开始将这些(应该是什么)“哑对象”称为实体。您有一个
User
实体和一个
Post
实体

延伸 扩展对象时,您说的是
ExtendingObject
is-a
ParentObject
。通过从
模型
扩展
用户
,您的意思是
用户
是一个
模型
,我们根据定义已经建立的模型是无效的。您最好使用一个通用的
DB
对象,并通过

建设者 您的构造函数应该没有业务逻辑。创建对象时,就是在特定状态下创建对象。这可以通过构造函数参数、类型提示和无效标量参数的异常来实现。一旦创建了对象,然后对其运行一个方法,如
getSchema()

因此,要重新设置上限:

  • 用户
    不是
    型号
  • 模型是一个层,而不是一个对象
  • 通过依赖项注入传入其他对象并遵守
  • 您的构造函数应该没有业务逻辑
蚜虫LSB 我们将仅出于教育目的而忽略上面列出的最佳实践,因为在了解其工作原理后,您当然会重新考虑这一点

您的目标(据我所知):根据当前扩展它的对象(
User
Post
),在基类
Model
中提供正确的表名

到目前为止,您有一个
模型
对象,因为它是抽象的,所以无法直接实例化。因此,必须对其进行扩展以供使用。好极了,让我们来创建您的POST对象

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

因此调用
$post=newpost的结果将被“创建表:post”

假设您也创建了一个
用户
对象:

class User extends Model
{
    const TABLE_NAME = 'User';
}
创建每个对象时,都会回显其自己的表名:

$x = new User; // echoes User Table
$x = new Post; // echoes Post Table
结论 您不必对常量执行此操作(尽管我会这样做)。您可以使用类属性来实现这一点。但不要公开它们(全局可变状态是不好的)


有了以上信息,您应该能够轻松地拥有一个
getSchema()
方法,该方法在
getSchema()中使用
static::SCHEMA\u NAME
Post
User

的方法问题在于$\u模式只在User中定义,而不在Post中定义,因此始终使用相同的变量。解决方法之一是生成$\u模式和数组,并生成键get\u类($this)。所以在这个场景中使用self还是static都无关紧要?我假设static绑定到被调用的类。你的第一句话是真的。静态只是改变它查找你想要的东西的位置。若您在User中有一个函数,并使用self::它将在User中查找。如果您使用static,它将首先在Post中查找。但是,如果没有在那里定义_schema,它将退回到User.But User和Post这两个扩展模型,在这里定义了_schema变量和getSchema函数。所以我假设通过继承,每一个都会得到它自己的模式变量实例,但我猜它们都只是回到了模型,这个模型是由用户的模式设置的,因为这是我首先实例化的?
$x = new User; // echoes User Table
$x = new Post; // echoes Post Table