【问题标题】:Objective oriented design in a PHP MVC FrameworkPHP MVC 框架中的面向目标设计
【发布时间】:2013-06-23 15:21:21
【问题描述】:

传统上,在 MVC 框架(例如 CodeIgniter 或 Kohana)中,我在创建不同页面时创建控制器。将有一个登录控制器,一个家庭控制器等。但最近我了解了更多关于面向目标编程的知识,并想开始使用它。即使框架使用类,它与对象的原理也不一样。

是的。登录控制器是一个对象。但是,例如,我应该在哪里编写我的“用户”类?我是否将它们写在库中并在需要时导入它们?这样做的正确方法是什么,如果有的话。

我只是对如何正确地做到这一点感到困惑。

【问题讨论】:

  • 您是一般性询问还是特定于 CI/Kohanna?
  • 我不想把它作为一个 Cl/Kohana 问题来结束。因为我确实认为我在其他框架中也看到了类似的结构。但是您可以通过各种方式认为它是特定于 Cl/Kohana 的。
  • 在创建不同页面时不会编写更多控制器。主要是编写更多的动作,其中动作是访问这些控制器的方法。换句话说,在 MVC 中,对象是控制器和模型。

标签: php oop model-view-controller


【解决方案1】:

<rant>

如果您从直接克隆 Rails 或受 Rails 架构严重影响的框架开始,您并没有真正实现 MVC。 Ruby on Rails 框架最初的目的是成为一个纯粹的快速原型设计框架,这意味着他们在“脚手架的祭坛”中牺牲了大部分 MVC 概念。

基于 Rails 的 PHP 框架用模板替换功能齐全的视图,用 active record 实例的一些集合替换模型层,并让“控制器”处理所有表示和应用程序逻辑。

</rant>

MVC 设计模式的基础是业务逻辑(包含在模型层中)和用户界面(由表示层管理)之间的分离。这两层各自包含不同的结构组。

User 不是模型。现代 MVC 中没有“模型”。相反,您的 User 实例是 domain object。此外,它不应直接暴露给控制器或其他表示层结构。

表示层和模型层之间的交互应该由服务来执行。模型层中的服务是结构,负责处理领域对象和存储抽象之间的交互(data mappers 直接或通过repositories 和/或units of work)。

namespace Controller;

class Authentication
{
    // .... snip
    public function postLogin( $request )
    {
        $service = $this->serviceFactory->create('Recognition');
        $service->authenticate( $request->getParameter('username'),
                                $request->getParameter('password') );
    }
    // .... snip
}

在这种情况下,User 实例位于识别服务内部,用于处理用户身份验证的不同业务逻辑方面。并且不要将其与授权混淆。对于 MVC 上下文中的授权,推荐的 approach 略有不同。

附注:如果您刚刚开始真正深入研究 OOP,您可能会发现 this list 在您的研究中很有用。

我的两分钱

【讨论】:

  • 如果您投反对票,发表评论被认为是一种常见的礼貌。我是不是写错了什么?还是这又是一次复仇投票?
  • 不是反对者。真的很喜欢这个答案。但我想问一个问题。你的意思是,在我在回答中提到的情况下,我需要一个名为 Actions 的类,并且在用户之间进行所有交互,另一个名为 Authentication 的类,其中所有登录详细信息和用户查询都在
  • @RoyalBg ,也许在某些方面,但正如我所读,您的 Actions 实例与 SRP 存在一些重大问题。
【解决方案2】:

最好把你的 User 类写成一个库,因为它不是一个控制器(假设),你不应该通过 URL 直接访问 User 类。因此,如果您希望它是面向对象的,最好的做法是编写一个类。或者,如果你想拥有静态函数,你可以创建一个帮助文件。

【讨论】:

  • 是的,库或帮助文件。但这是最好的做法吗?考虑到这些(Cl/Kohana)框架是建立在 OOP 本身之上的,难道它们不应该为开发人员编写某种预定义的面向目标的代码吗?
  • 我完全同意,并补充一点,如果您想要一种查看用户的方法,那么您将创建一个包含其他“域”对象和控制器的用户类,以便为每个域对象创建视图你想看。
  • 取决于您使用 User 类的目的。例如,在论坛或游戏中,用户是游戏/论坛/平台拥有的所有事物之一。所以你有一个 UserController 和 UserModel,用于用户的所有交互
【解决方案3】:

我认为这太个人化了。真的取决于构建什么样的应用程序。让我们考虑一下 CodeIgniter 或 Kohana,但要针对您的个人框架和个人应用程序。

如果您有简单的登录系统,其中用户只是一个名称和一个 ID,并且所有交互都在应用程序的其他阶段之间,而不是用户之间的交互,您的用户类只包含有关用户(对从users 表中检索某些信息的数据库进行简单查询),可以作为助手。

但在某些应用程序(本例中为平台)中,用户可能等同于其中的任何其他对象。

例如构建一个类似论坛的应用程序,您可能希望拥有警告级别、声誉、各种用户操作日志等。

此外,用户是一个平等的对象,如“主题”,也有喜欢/不喜欢、优先级等。

在这种情况下,您为用户构建模型和控制器。例如,在您的模型中,您将拥有像

这样的方法

createUser(), getUser(), getUserWarnActions(), updateUserActions(), logUserActionChange()等等等等

所有这些方法都将在一个名为 UserModel 的类中,它扩展了 Model 主类

例如,UserActions 是警告级别、电子邮件更改、用户名更改、声誉更改。

在您的控制器中,您可能希望拥有

updateWarnLevel() => 与 updateUserActions() 交互,告诉模型它的动作 = 警告级别,并按给定值更新它

所以这些方法将在一个名为 UserController 的类中,它扩展了 Controller 主类

但这完全取决于您如何看待您的 User 类。在我看来,将 Controller/Model 称为 Warn 级别是不好的做法,因为它是另一个抽象的一部分,而不是单独的抽象。

假设哪个是子级或父级,我会尝试创建一个结构,例如 db 结构,然后创建模型/控制器/帮助器。

如果您有以下数据库表:

  • 用户
  • user_reputation
  • user_warnlevels
  • 主题
  • topic_votes
  • warn_levels // 包含即 id |水平 | something_which_depends_on_the_level

这绝对意味着UsersTopics 将是您的应用程序中的模型/控制器,而warn_levels 不会是,因为它们是单独的表,只是因为它们有一些逻辑,但它们不是父表, 独生子女

【讨论】:

    猜你喜欢
    • 2010-12-23
    • 1970-01-01
    • 2014-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多