【问题标题】:Do conditional statements belong in the model or controller in a php mvc?条件语句是否属于 php mvc 中的模型或控制器?
【发布时间】:2012-02-08 03:05:22
【问题描述】:

如果您使用 mvc 来构建用户配置文件,最好使用条件语句来计算模型或控制器中的函数内的 cmets 的显示类型,如下所示:

例如 我有 3 节课

  • 评论
  • 会员
  • 管理员(扩展成员)

一些例子使用了缺少函数的伪代码

选项 1

依赖于登录 showComments 函数返回 cmets 的用户类型将返回不同的信息。

class user {

    function isLoggedIn() { //Check if a user is logged in }

    function getUserType() { // return user type }

    function showComments($id) { //comments code }
}

class admin extends user {
    function showComments($id) { //comments code }
}

然后使用控制器内的代码来确定取决于登录的用户类型显示哪个?

$profileContent = $user->getOtherContent();

if ($user->isLoggedIn() && $user->getUserType() == "member") {
    $member = new member();
    $comments = $member->showComments($profileId);
}
elseif ($user->isLoggedIn() && $user->getUserType() == "admin") {
    $admin = new admin();
    $comments = $admin->showComments($profileId);
}
else
    $comments = $user->showComments($profileId);

require 'templates/profile.php';

选项 2

由于这是一个自定义框架,我可以将所有内容移动到模型中的一个函数中,并在用户中有一个函数来检查要显示的评论类型:

abstract class user {

    function isLoggedIn() { //Check if a user is logged in }

    function getUserType() { // return user type }

}

class profile {

    function showComments($profileId, $user) {

        if (User::isLoggedIn() && User::getUserType() == "member") {
            $comments = //database query and formatting for member
        }
        elseif (User::isLoggedIn() && User::getUserType() == "admin") {
            $comments = //database query and formatting for admin
        }
        else
           $comments = //database query and formatting for guest

        return $comments;
    }
}

使用如下控制器:

$profile = new profile($profileId);
$comments = $profile->showComments();

require 'templates/profile.php';

【问题讨论】:

  • 您使用的是特定框架吗?你提到你有一个模型和控制器,但是视图呢?
  • 哎呀我错过了那部分,在控制器中的 if/else 之后需要视图。 cmets 以$comments 的形式传递给它
  • 对于你的要求没有规则,所以尽你所能。
  • 嗨@Silver89!问题在于根据用户类型显示 cmets 视图的代码,还是用于从数据库为每种用户类型获取数据的代码?

标签: php oop model-view-controller class


【解决方案1】:

技术上两者都是正确的。 MVC 模式是有意抽象的,关于模型与控制器的正确域是什么存在一些争论。

根据您使用的确切框架,可能会有一个“更好”的答案。否则,做你认为最有意义的事情。

更新 - 鉴于您问题的变化,我想稍微调整一下我的答案:

对于选项 1,这样设计模型会更有意义:

class user {
    function isLoggedIn() {}
    function getUserType() {}
    function showComments() {}
}

class admin extends user {
    function getUserType() {}
    function showComments() {}
}

class member extends user {
    function getUserType() {}
    function showComments() {}
}

在控制器中,$user 应该被实例化为管理员、成员或用户(这可以通过静态工厂或直接在控制器中完成)。之后你的控制器就是

if ($user->isLoggedIn()) {
    $comments = $user->showComments($profileId);
}

(为了更智能,可以将 profileId 设置为类属性(除非用户有多个配置文件?)

选项 2,otoh,是对模型到模型设计的巧妙运用。

我看到的唯一真正的区别是你如何概念化评论。您是否认为他们是用户的一部分(与个人资料的联系较弱)?还是个人资料的一部分(与用户的联系较弱)?这两种方法都没有我一开始就看到的任何特定痛点,因此最好的选择是使用对您最有意义的方法。

【讨论】:

  • +1 框架很重要,因为它们通常倾向于将意见合并为自己的“最佳实践”
【解决方案2】:

我想这一切都取决于您对模型/视图/控制器代表什么的解释。这是我的 2 美分:

型号

一个模型应该处理一个且只有一个应用程序逻辑。如果您有一个 User 模型,那么在该模型内部应该只有与 User 相关的方法和属性。也就是说,如果可能的话,尽量不要在 User 模型中包含 Comments 逻辑。它们属于 Comments 模型。在当前模型中创建调用另一个模型的条件将是对应用程序另一部分的交叉。这就是控制器的用途。

模型应始终以抽象结构响应。模型不应该以格式化或基于字符串的方式响应。它通常应该是一个数组、一个对象、一个简单的 int(最好是模型常量)或布尔值。

控制器

控制器应该处理输入数据(即使是普通的网页视图也是输入数据)并且基于该数据,它应该调用应用程序逻辑。

在您的控制器中,您应该具有与调用一个或另一个模型相关的所有条件。

基于抽象结果,它应该调用另一个模型,或者收集响应并将其合并,以便可以将其作为简单结构传递给视图(尽量不要将对象传递给视图,但如果你遇到将复杂结构作为模型返回值,将它们收集到一个数组中并将其传递给视图)。

查看

视图是三者中最直接的。它应该使用仅处理显示的简单指令格式化响应(或者在某些情况下,控制器响应的序列化或转换为另一个应用程序可查看的内容 - 浏览器或调用 api 的第三个应用程序)


这一切都归结为您对 MVC 架构的惊叹。尝试在整个项目中保持持续的开发“策略”。

希望对你有帮助

【讨论】:

    【解决方案3】:

    业务逻辑属于控制器。数据逻辑属于模型。

    因此,如果您需要根据用户输入显示某些数据,那么这属于控制器。但是,实际上获取/存储数据属于模型。

    【讨论】:

    • 那么调用一个构建类来获取该页面所需的所有数据与从控制器调用每个类来获取相同数据之间没有区别吗?使用第二种方法,只是控制器会有更多代码吗?
    【解决方案4】:

    我尝试将处理数据(检索、操作等)的任何逻辑移至模型。这有时包括条件语句。

    就个人而言,我会为 User 类创建“showComments”和实例方法,但这实际上是一个见仁见智的问题(也被有强烈意见的人称为“最佳实践”)。

    Fat Model, Skinny Controller 看起来很谨慎时,我倾向于采用这种方法。

    【讨论】:

    • 如果这样做,showComments 怎么知道它是哪种类型的用户?我有点坚持以其他方式对其进行编码,因为我现在的想法是采用这种方法,但我无法从另一个更适合它的方向看到它?
    • 这取决于您使用的框架。如果您从数据库记录中实例化用户,则该用户应该有一个与之关联的 id。像 $userComments = findComments($this->ID);希望这是有道理的(可能不是)。
    • 我已更新问题,选项 2 现在显示更多我认为您的意思?
    • @Silver89 这更接近我会做的事情。我不确定为什么 Profile 类中的实例方法需要它自己的 ID ($profileId) 作为参数传递。
    • 这很好,是否可以将对象 $user 传递给配置文件 showComments 函数来验证 userType?如果我尝试在 showComments 中创建一个新用户,我会得到 Cannot instantiate abstract class User
    【解决方案5】:

    我相信这属于模型。我觉得用户身份验证和验证不属于 Controller,最终它是使用和验证 data 以及在 Model 中完成的 MVC。

    出于另一个原因,我认为这不适合控制器。它让它太聪明了。 Controller应该只知道它需要给View提供一些cmets。为什么控制器需要知道登录的用户类型?它不应该,它应该只知道模型说它应该拥有的数据。

    【讨论】:

      猜你喜欢
      • 2012-09-03
      • 2012-10-26
      • 1970-01-01
      • 1970-01-01
      • 2018-10-27
      • 1970-01-01
      • 1970-01-01
      • 2016-01-25
      • 1970-01-01
      相关资源
      最近更新 更多