PHP - 如何组合三个或更多相互依赖的 类?

PHP - How to combine three or more classes that each depend on each other?

我有三个类:

  1. 数据库
  2. 用户
  3. 页数

各行其是。

所以,UserPage 都需要连接到数据库来获取他们的数据(用户信息,页面内容)——他们两者都通过 Database 的依赖注入访问数据库,这非常好。但是,Page also 需要显示 User.

获取的数据

这会出现问题,因为如果我将 User 注入 Page,技术上不会提示 Page两个 个数据库实例,它自己的和一个存在于 User 中?这不是好习惯,对吗?

据我所知,在这种情况下,'extending' 也不是正确的解决方案。 PageUser 没有直接关系,因此他们不必成为一个。

那么,我有两个问题:

  1. 通过注入 将注入 User 的数据库对象引导到 Page 会不会是 'proper'用户进入页面?
  2. 如果不是,正确的方法是什么?

在数据库class中使用构造函数并将其设置为class 属性。 假设它在用户和页面 classes 中都可用,因为您从它扩展我们的。

<?php
class Database
{

}
class MySql extends Database
{
    private $sDbName      = '';
    private $sUsername    = '';
    private $sPassword    = '';
    private $sHost        = '';
    private $oConnection  = null;

    public function __construct()
    {
        $this->oConnection = new PDO( 
            'mysql:host=' 
            . $this->sHost 
            . ';dbname=' 
            . $this->sDbName, 
            $this->sUsername, 
            $this->sPassword 
            );
    }
    public function getDb()
    {
        return $this->oConnection;
    }
}

class User extends MySql
{

}
class Page extends User
{

}

$oPage = new Page;
var_dump( $oPage->getDb() );
?>

我认为您对引用的工作方式有一些误解。假设我创建了一个数据库对象:

class Database {
  function talkToDb(){
    //does some database stuff
  }
}

现在,假设我想要一个 User class 来访问 Database 对象——大概是为了读取和写入持久层:

class User {
  persistence = null; //This 'points' to a database object that is injected on object instantiation.
  function __construct(Database $db) {
    $this->persistence = db;
  }
}

要创建 User,您需要在代码中的某处执行以下操作:

$db = new Database();
$aUser = new User($db);
$bUser = new User($db);

此时 $aUser$bUser 正在使用 相同的 Database 对象。让我们谈谈 Page:它的实例化与 User:

出奇地相似
class Page {
  $persistence = null;
  $someUser = null;

  function __construct(Database $db, User $user) {
    $this->persistence = $db;
    $this->someUser = $user;
  }
}

然后您将再次在代码中的其他地方创建 Page class。像这样:

$db = new Database();
$aUser = new User($db);
$aPage = new Page($db, $aUser);

此时,$aUser$aPage 中的 对象字段 指向 same Database 对象:named $db(至少在我们创建的范围内被命名)上面)。 $aPage 持有$aUser 的引用。因为它有两个引用 - 一个给用户,一个给数据库 - 它可以理论上 可以通过两种方式访问​​相同 数据库对象:

class Page {
  ... //construct everything as above

  function accessExample() {
    //The following two lines call the exact same function on the exact same object
    $this->persistance->talkToDb();
    $this->someUser->persistance->talkToDb();
  }
}

记住:当您 'inject' 一个对象到另外两个对象时,您并不是在复制该对象,您只是在 复制对该对象的引用 。许多对象持有相同引用的副本是合适的。

可以以任何一种方式访问​​数据库的事实并不意味着您应该这样做。您可以通过将 User 的数据库设为私有来从 Page 中屏蔽它。也就是说,不这样做只是代码清洁度的问题:您仍然可以 .

请注意,完全不适合 'extend' PageUser 来自彼此或来自 Database .扩展的 class 实际上是前一个的 'subset' 或 'more specific form'。 User 不是 Database 的特殊形式:MySqlDatabase 。相反,我们知道 User 需要有一个数据库,它可以 'persist' 它的状态。这就是为什么我们为某些 Database 对象提供 'reference' 的原因。我们应该为所有需要访问相同 Database 的对象提供相同的引用。许多对象可能持有对同一数据库对象的引用这一事实并不重要:为什么这会导致问题?

(注意买者:我实际上不是 运行 上面的代码,所以可能有小错误。)