我有三个类:
- 数据库
- 用户
- 页
每个人都按照其暗示的方式进行。
因此,User和Page都需要连接到数据库以获取其数据(用户信息,页面内容) - 它们都通过数据库的依赖注入来访问数据库,这完全没问题。但是,页面还需要显示用户获取的数据。
这变得有问题,因为如果我将用户注入页面,这在技术上不会提示页面有两个数据库实例,它自己的和用户中存在的一个?这不是好的做法,对吗?
据我所知,在这种情况下,"扩展"也不是正确的解决方案。页面与用户没有直接关系,因此它们不需要成为用户。
所以,我有两个问题:
- 通过将用户注入页面
- 来将注入到用户中的数据库对象引导到页面是否"合适"?
- 而且,如果没有,正确的方法是什么?
我想你对引用的工作原理有一些误解。假设我创建了一个数据库对象:
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
"扩展"Page
或User
是完全不合适的。扩展类实际上是前一个类的"子集"或"更具体的形式"。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() );
?>