PHP - 如何组合三个或更多相互依赖的 类?
PHP - How to combine three or more classes that each depend on each other?
我有三个类:
- 数据库
- 用户
- 页数
各行其是。
所以,User 和 Page 都需要连接到数据库来获取他们的数据(用户信息,页面内容)——他们两者都通过 Database 的依赖注入访问数据库,这非常好。但是,Page also 需要显示 User.
获取的数据
这会出现问题,因为如果我将 User 注入 Page,技术上不会提示 Page 有 两个 个数据库实例,它自己的和一个存在于 User 中?这不是好习惯,对吗?
据我所知,在这种情况下,'extending' 也不是正确的解决方案。 Page 与 User 没有直接关系,因此他们不必成为一个。
那么,我有两个问题:
- 通过注入 将注入 User 的数据库对象引导到 Page 会不会是 'proper'用户进入页面?
- 如果不是,正确的方法是什么?
在数据库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' Page
或 User
来自彼此或来自 Database
.扩展的 class 实际上是前一个的 'subset' 或 'more specific form'。 User
不是 Database
的特殊形式:MySqlDatabase
是 。相反,我们知道 User
需要有一个数据库,它可以 'persist' 它的状态。这就是为什么我们为某些 Database
对象提供 'reference' 的原因。我们应该为所有需要访问相同 Database
的对象提供相同的引用。许多对象可能持有对同一数据库对象的引用这一事实并不重要:为什么这会导致问题?
(注意买者:我实际上不是 运行 上面的代码,所以可能有小错误。)
我有三个类:
- 数据库
- 用户
- 页数
各行其是。
所以,User 和 Page 都需要连接到数据库来获取他们的数据(用户信息,页面内容)——他们两者都通过 Database 的依赖注入访问数据库,这非常好。但是,Page also 需要显示 User.
获取的数据这会出现问题,因为如果我将 User 注入 Page,技术上不会提示 Page 有 两个 个数据库实例,它自己的和一个存在于 User 中?这不是好习惯,对吗?
据我所知,在这种情况下,'extending' 也不是正确的解决方案。 Page 与 User 没有直接关系,因此他们不必成为一个。
那么,我有两个问题:
- 通过注入 将注入 User 的数据库对象引导到 Page 会不会是 'proper'用户进入页面?
- 如果不是,正确的方法是什么?
在数据库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' Page
或 User
来自彼此或来自 Database
.扩展的 class 实际上是前一个的 'subset' 或 'more specific form'。 User
不是 Database
的特殊形式:MySqlDatabase
是 。相反,我们知道 User
需要有一个数据库,它可以 'persist' 它的状态。这就是为什么我们为某些 Database
对象提供 'reference' 的原因。我们应该为所有需要访问相同 Database
的对象提供相同的引用。许多对象可能持有对同一数据库对象的引用这一事实并不重要:为什么这会导致问题?
(注意买者:我实际上不是 运行 上面的代码,所以可能有小错误。)