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


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

我有三个类:

  1. 数据库
  2. 用户

每个人都按照其暗示的方式进行。

因此,UserPage都需要连接到数据库以获取其数据(用户信息,页面内容) - 它们都通过数据库的依赖注入来访问数据库,这完全没问题。但是,页面还需要显示用户获取的数据。

变得有问题,因为如果我将用户注入页面,这在技术上不会提示页面有两个数据库实例,它自己的和用户中存在的一个?这不是好的做法,对吗?

据我所知,在这种情况下,"扩展"也不是正确的解决方案。页面与用户没有直接关系,因此它们不需要成为用户

所以,我有两个问题:

    通过将用户注入页面
  1. 来将注入到用户中的数据库对象引导到页面是否"合适"?
  2. 而且,如果没有,正确的方法是什么?

我想你对引用的工作原理有一些误解。假设我创建了一个数据库对象:

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

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

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类。这样:

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

此时,$aUser$aPage 中的对象字段指向同一个Database对象:名为 $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();
  }
}

请记住:当您将一个对象"注入"到另外两个对象中时,您不是在复制该对象,而只是在复制对该对象的引用。许多对象保存同一引用的副本是合适的。

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

请注意,从彼此或从Database"扩展"PageUser完全不合适的。扩展类实际上是前一个类的"子集"或"更具体的形式"。User不是Database的特殊形式:MySqlDatabase。相反,我们知道User需要有一个数据库,它可以"持久化"它的状态。这就是为什么我们为其提供对某些Database对象的"引用"。我们应该为所有需要访问同一Database的此类对象提供相同的引用。许多对象可能包含对同一数据库对象的引用这一事实无关紧要:为什么这会导致问题?

(警告:我实际上并没有运行上面的代码,所以可能存在一些小错误。

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

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