PHP OOP Modular CMS Objects design
我想听听您对如何在模块化CMS系统中设计对象的建议。我已经找了好几个小时了,但还是找不到正确的答案。
如何设计与事物交互的类?假设我有这些课程:
1 2 3 4 | cDb() // for database interactions cUser() // for all user actions cSession() // for interactions with session data. cAnotherObject // multiple another objects from future modules |
如果我以某种方式扩展它们,那么最后,我会得到一个这样的对象:
1 | $myvar = new cLatestClass(); |
[会话扩展CDB,CUSER扩展CSession…等
如果是这样,如何处理模块中动态加载的类?仅仅使用多个
1 2 3 | $user = new cUser(); $session = new cSessions(); ... etc. |
我真的希望这里有人能回答我,希望能教我如何正确地做。
首先,我建议退后一步,学习什么是面向对象。创造了"面向对象编程"一词的Alan Kay曾经这样描述:
I thought of objects being like biological cells and/or individual
computers on a network, only able to communicate with messages.
(source)
在PHP(以及大多数面向对象语言中)中,这些消息通常是方法调用,或者在公共属性的情况下,是获取和设置它们的值。
因此,把系统中的对象想象成一个更大的有机体中的单个细胞,它们协同工作以实现更大的目标,而不是试图将所有需要的行为混合到一个对象中。
这是一个大主题,许多书都写在上面,但就你在问题中提到的对象而言,我首先要区分它们所属的不同类别。一个数据库或会话对象可以被认为是一种"服务",其他对象(例如,如果您使用的是MVC框架,您的控制器)将依赖于它。正如其他人所提到的,依赖注入是处理此类服务的一个很好的解决方案,但在大多数情况下,我不建议将其用于类似用户类的东西,因为每个用户都应该有一个实例(当然不是字面意义上的——您只需要将特定的用户对象加载到您需要处理特定请求的内存中,在许多情况下,只是当前用户的一个实例)。
为了了解更多关于依赖注入的信息,我建议在这篇文章中,MartinFowler创造了这个术语,并且在这里他提到了一个更简单的替代服务定位器的依赖注入容器。
(依赖注入容器方法更健壮,但也更复杂;幸运的是,它有一个好的开源库)。
用户、文章和类别都是CMS中域对象的示例。这些是MVC"M"(模型)的一部分(也称为域模型)。当然,您仍然需要一种方法来将这些对象进出数据库,因此您可能还需要某种类型的存储库或查询类(存储库类可以视为服务)。并不是所有的PHP系统都有真正的域对象;许多系统只是有返回数组或stdclass对象的类似存储库的类(简单的匿名对象,创建如下:
面向对象编程的真正目的比我上面提到的要深:它是关于在一个系统中设计对象来反映我们的心理模型(一个包含最终用户和程序员视角的联合心理模型)。这是另一个很好的引述,这一次来自Trygve Reenskaug,他发明了MVC模式:
I think of the difference between procedure oriented and object
oriented programming as being that procedure oriented answers the
question:"What happens?". Object oriented answers an additional
question:"Who does it?" (source)
最后,我建议阅读一本专门介绍PHP中面向对象编程的书。一个很好的例子是Matt Zandstra的PHP对象、模式和实践。
Should I somehow extend them all, so in the end, I end up with one object like this:
不,你当然不应该。扩展类时,您应该有一个
会话不是数据库。用户当然不是会话。您所看到的可能是依赖注入。
假设您的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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); |
如果您将数据库查询从
同样作为一个cs注释:为什么你要用
关于您的模块系统。这将取决于您将如何设置模块,但您可能需要查看依赖项注入容器以将动态模块连接在一起。