我将尝试尽可能地解释这一点,请原谅我,如果部分没有完全合理。我正在构建一个用于教育目的的PHP库/框架。我正在使用单例模式构建它但遇到了一些问题,最近似乎也读到它不应该被使用,因为它不是非常可测试的(虽然我并不担心这是可测试的,但我想学习如何做到这一点),而应该使用依赖注入。
我想要的是一个共享变量,如果你愿意的话,它包含许多不同的类。例如$ app->数据库; $ APP->图; $ APP->会议;等等,我不确定我是否正确行事。所有课程也都是自动加载的。
我有bootstrap / start.php初始化主变量(有这个名字吗?):
$app = new App(new Database, new Views, new Session);
在我主要使用的App.php类中:
public $database;
public $views;
public $session
public function __construct(Client $client, Views $views, Session $session)
{
$this->database = $database;
$this->views = $views;
$this->session = $session;
}
我的问题是:我应该像这样初始化构造函数中的所有类吗?最重要的是...如何在我的Views.php类中使用$ database变量而不创建可能会覆盖Database类中某些属性的全新实例?
非常感谢对此的一些见解。
答案 0 :(得分:1)
你应该真正了解类似MVC的架构,它们所基于的整个点称为关注点分离(SoC)。
为什么要在视图中访问数据库连接?显然是因为您想要执行查询并在那里显示结果。这就是打破SoC的原因。为了显示数据,你必须访问模型中的数据库连接,如果需要,以某种方式解析,然后简单地将准备好的数组传递给视图,这样视图甚至不知道数据库存在这样的东西,他们只知道有一个数组,需要以某种方式显示。这种方法引入了一个主要优点 - 您可以轻松交换数据库引擎(使用SOAP / REST,Mongo等),而无需触及视图!
至于你的问题,你可以通过创建一个抽象类来解决这个问题,这个抽象类将被称为AbstractApplication
并将所有那些初始化逻辑放在那里。然后你可以简单地继承这个基类。
您拥有的另一种方式是使用所谓的服务定位器来接近它。您创建一个包装器,将所有依赖项放在那里,然后只需为需要它的类注入Service Locator。这不是最好的方法,但它是处理大量依赖项的唯一方法(在现实世界中,你需要注入4个以上的参数)
答案 1 :(得分:-1)
您的代码看起来不错,但我会推荐这些更改,将变量设为私有并生成getter和setter。
<?php
Class App {
private $database;
private $views;
private $client;
private $session;
/**
*
* @param type $database
* @param type $views
* @param type $client
* @param type $session
*/
function __construct($database, $views, $client, $session) {
$this->database = new $database;
$this->views = new $views;
$this->client = new $client;
$this->session = new $session;
}
/**
*
* @return type
*/
function getDatabase() {
return $this->database;
}
/**
*
* @return type
*/
function getViews() {
return $this->views;
}
/**
*
* @return type
*/
function getClient() {
return $this->client;
}
/**
*
* @return type
*/
function getSession() {
return $this->session;
}
/**
*
* @param type $database
*/
function setDatabase($database) {
$this->database = $database;
}
/**
*
* @param type $views
*/
function setViews($views) {
$this->views = $views;
}
/**
*
* @param type $client
*/
function setClient($client) {
$this->client = $client;
}
/**
*
* @param type $session
*/
function setSession($session) {
$this->session = $session;
}
}
//and in bootstrap or where you loading just do this and make database, view and all other singleton.
$database = database::getInstance();
$views = views::getInstance();
$client = client::getInstance();
$session = session::getInstance();
$App = new App($database, $views, $client, $session);