2

我想请您就如何在模块化 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 ...等]

如果是这样,如何在模块中动态加载类?只使用多个vars 持有对象会更好吗?

$user = new cUser(); 
$session = new cSessions();
 ... etc.

我真的希望这里有人能回答我,并希望能教我如何正确地做到这一点。

4

2 回答 2

3

首先,我建议退后一步,了解面向对象的全部内容。创造了“面向对象编程”一词的艾伦·凯曾这样描述它:

我认为对象就像网络上的生物细胞和/或个人计算机,只能与消息通信。 (资源)

在 PHP(以及大多数面向对象的语言)中,这些消息通常是方法调用,或者在公共属性的情况下,获取和设置它们的值。

因此,将系统中的对象视为更大有机体中的单个细胞,它们协作以实现更大的目标,而不是试图将您需要的所有行为混合到一个对象中。

这是一个很大的话题,已经写了很多书,但是就您在问题中提到的对象而言,我将首先对它们所属的不同类别进行区分。可以将数据库或会话对象视为一种“服务”类型,其他对象(例如您的控制器,如果您使用 MVC 框架)将依赖它。正如其他人所提到的,依赖注入是处理此类服务的一个很好的解决方案,但在大多数情况下,我不建议将它用于像 User 类这样的东西,每个用户应该有一个实例(当然不是字面意思 - 你'd 只会将特定的用户对象加载到您需要处理特定请求的内存中,在许多情况下只是当前用户的实例)。

要了解有关依赖注入的更多信息,我推荐这篇文章Martin Fowler 创造了这个术语,并且他在其中提到了一个更简单的依赖注入容器替代方案,称为服务定位器。

(依赖注入容器方法更健壮但也更复杂;幸运的是,它有一个很好的开源库)。

用户、文章和类别都是CMS中域对象的示例。这些是 MVC(也称为域模型)的“M”(模型)的一部分。当然,您仍然需要一种将这些对象进出数据库的方法,因此您可能还需要某种 Repository 或 Query 类(可以将 Repository 类视为一种服务)。并非所有 PHP 系统都有真正的域对象;许多只是具有返回数组或 stdClass 对象的类似存储库的类(像这样创建的简单匿名对象:)$someObj = new stdClass,这意味着这些系统缺乏真正的面向对象编程,但做出这样的决定通常有实际原因。

面向对象编程的真正目的比我上面提到的更深:它是关于设计系统中的对象以反映我们的心智模型(一个包括最终用户和程序员视角的联合心智模型) . 这是另一个很好的引用,这次来自发明 MVC 模式的 Trygve Reenskaug:

我认为面向过程和面向对象编程之间的区别在于面向过程回答了这个问题:“会发生什么?”。面向对象回答了一个额外的问题:“谁做的?” (来源

最后,我建议阅读一本专门介绍 PHP 中的面向对象编程的书。一个很好的例子是 Matt Zandstra 的PHP Objects, Patterns and Practice

于 2013-06-23T02:04:17.377 回答
1

我是否应该以某种方式扩展它们,所以最后,我会得到一个像这样的对象:

不,你当然不应该。扩展类时,您应该有一个is-a关系。

会话不是数据库。一个用户当然不是一个会话。您正在寻找的可能是依赖注入

假设您的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?

关于您的模块系统。这将取决于您将如何设置模块,但您可能需要查看依赖注入容器来将动态模块连接在一起。

于 2013-06-23T01:31:31.747 回答