我正在从Globals和Singletons(=坏?)转向PHP中的依赖注入(=好?),我对它很新。
我已经阅读了很多关于Stack Overflow的相关主题,但我仍然无法理解DI的主要原则。
请告诉我,如果我做得对(它只是缩短了伪代码):
// first connect to DB
$sql = new Sql();
// create logger (I'm writing logs to Database so I need to pass $sql to it)
$log = new Log($sql);
// restore logged in user, get info about user, unread messages...
// class "User" needs access to Database and Logs:
$user = new User($sql, $log);
// now we need to collect all the data of current section of my Website
// I'm using Model and Controller:
$model = new FrontPageModel($sql, $user, $log);
$pageController = new FrontPageController($model);
虽然在这一步可能看起来不错,但如果我需要访问更多类,如Config,Session等,该怎么办?
我的代码应该转换成这个吗?
$model = new FrontPageModel($sql, $user, $log, $config, $session);
已经不是太多了吗?
我知道有人可以建议使用一种大的“应用程序”类,并将Config,Session,Log,Db对象放在这个类中,但我觉得这不是一个好主意。
下一个问题 - 如果我需要在FrontPageController中记录用户ID,该怎么办?我没有将“User”的实例传递给FrontPageController,但它之前(在链中)传递给了FronPageModel。
class FrontPageController{
private $model;
function __construct($model){
$this->model = $model;
}
function getData(){
echo $this->model->user->id; // is it right way?
}
}
“$ this-> model-> user-> id”对我来说似乎有些过分。
答案 0 :(得分:4)
它可能不是最漂亮的,但你肯定不是“错误”。您正在演示分类构造函数注入,但您可以重构以保持一些不同的对象分离更多。
我的建议是查看已建立的PHP DI容器。了解它们的工作原理,在几个应用程序中使用它们,以及(1)您将拥有更多可测试的应用程序,以及(2)您将更加熟悉DI。
请查看以下一项或多项内容:
答案 1 :(得分:3)
像所有快乐的东西一样,它取决于。
我会将所有内容放在工厂类中,或者将几个工厂类放在不同的子系统中。
class AppFactory {
protected $_sql;
public function getSql()
{
if (!empty($this->_sql))
return $this->_sql;
$this->_sql = new Sql();
}
}
然后在应用程序运行时初始化它。如果需要,请进行配置。
$factory = new AppFactory();
// set config
// $factory->internallyGenerateSingletons = true;
现在每个其他班级都可以使用它。当然,你有注射将工厂放在里面。
$model = new FrontPageModel($factory);
// or
// $model->useFactory($factory);
关于其他问题。这是正确的方法。
...
$this->model->user->id
...
我会说没关系,但击球手就是使用这样的方法:
...
$this->model->getUser()->id
..
因此,您可以在进行单元测试时模拟用户类。它使应用程序更加灵活。
答案 2 :(得分:2)
看起来你已经有了依赖注入的想法。你甚至质疑Symfonies关于DI的想法(在评论中),这表明了更成熟的理解。
解决问题的下一步是避免将技术信息从一个层泄漏到另一个层。例如,您的控制器并不关心他们是否与模型交谈。你的模型并不关心它与sql或nosql数据库的对话。
另一个是关于责任。用户真的需要做所有这些吗?用户负责记录吗?这可能是一个正确的选择,但似乎你要求它做很多事情。用户是否自行构建,更新自身?等
$this->model->user->id; // is it right way?
这不是正确的方法。 1)这是非常强的耦合。 2)你需要用户的id吗?用户只是作为从属关系来获取它的东西?也许像$this->user->showUserInfo($userInfoDisplay)
这样的东西可以用吗?