我想就如何在模块化CMS系统中设计对象提出建议。我一直在寻找几个小时,但我找不到正确的答案。
如何设计与事物互动的类?可以说我有这些课程:
cDb() // for database interactions
cUser() // for all user actions
cSession() // for interactions with session data.
cAnotherObject // multiple another objects from future modules
我应该以某种方式扩展所有这些,所以最后,我最终会得到一个像这样的对象:
$myvar = new cLatestClass();
[cSession扩展cDb,cUser扩展cSession ......等等]
如果是这样,如何在模块中动态加载类?是否只使用多个var
来保存对象?
$user = new cUser();
$session = new cSessions();
... etc.
我真的希望有人在这里能回答我,希望能教会我如何正确地做到这一点。
答案 0 :(得分:3)
首先,我建议退后一步,了解面向对象的方方面面。创造“面向对象编程”一词的Alan Kay曾将其描述如下:
我认为物体就像生物细胞和/或个体 网络上的计算机,只能与消息通信。 (source)
在PHP(以及大多数面向对象语言)中,这些消息通常是方法调用,或者在公共属性的情况下,获取和设置它们的值。
因此,将系统中的对象视为一个更大的有机体中的单个细胞,协作以实现更大的目标,而不是试图将您需要的所有行为混合到一个对象中。
这是一个很大的主题,很多书都写在上面,但就你在问题中提到的对象而言,我首先会区分它们所属的不同类别。数据库或会话对象可以被视为一种“服务”,其他对象(例如,您的控制器,如果您使用的是MVC框架)将依赖于该服务。正如其他人所提到的,依赖注入是处理此类服务的一个很好的解决方案,但在大多数情况下我不建议将它用于像User类这样的东西,每个用户应该有一个实例(当然不是字面上的 - 你'只将特定用户对象加载到处理特定请求所需的内存中,在许多情况下只是当前用户的实例。)
要了解有关依赖注入的更多信息,我建议使用this article Martin Fowler创造这个术语的地方,以及他提到的一个更简单的替代方案,称为服务定位器的依赖注入容器。
(依赖注入容器方法更健壮,但也更复杂;幸运的是有good open-source library for it)。
用户,文章和类别都是CMS中域对象的示例。这些是MVC的“M”(模型)的一部分(也称为域模型)。当然,您仍然需要一种方法将这些对象放入和放出数据库,因此您可能还需要某种Repository或Query类(Repository类可以被视为服务)。并非所有PHP系统都有真正的域对象;许多只是具有类似于存储库的类,它们返回数组或stdClass对象(简单的匿名对象,如下所示:$someObj = new stdClass
),这意味着这些系统缺乏真正的面向对象编程,但通常有实际的原因,做出这样的决定。
面向对象编程的真正目的比我上面提到的更深入:它是关于在系统中设计对象来反映我们的心理模型(一个包含最终用户和程序员)。这是另一个好的引用,这一次来自Trygve Reenskaug,他发明了MVC模式:
我想到了面向过程和对象之间的区别 面向程序设计就是面向程序的答案 问题:“会发生什么?”面向对象的答案是额外的 问题:“谁做到了?” (source)
最后,我建议您阅读一本专门介绍PHP中面向对象编程的书。 Matt Zandstra是一个非常好的PHP Objects, Patterns and Practice。
答案 1 :(得分:1)
我应该以某种方式扩展所有这些,所以最后,我最终会得到一个像这样的对象:
不,你当然不应该。扩展课程时,您应该有is-a
关系。
会话不是数据库。用户肯定不是会话。您所看到的可能是dependency injection。
假设您的User
类需要数据库连接。这看起来像是:
class User
{
private $dbConnection;
public function __construct(\PDO $dbConnection)
{
$this->dbConnection = $dbConnection;
}
public function doSomethingWithDb()
{
$this->dbConnection->query('SELECT...');
}
}
$dbConnection = new PDO('/* dsn string */', 'user', 'pass');
$user = new User($dbConnection);
如果你要从User
类中提取数据库查询,那么你就更好了,这样你就不必使用数据库了。
另外作为CS说明:为什么要在c
之前添加课程?
关于您的模块系统。这将取决于您将如何设置模块,但您可能需要查看依赖注入容器以将动态模块连接在一起。