1

我正在使用一个使用 MVC 范例的框架。它是 CodeIgniter,但我的问题不在于具体的框架 - 它更普遍地涉及使用 MVC 时的最佳实践。

我正在使用 $_SESSION 变量来维护一些状态变量(用户选择、一些临时首选项、一些数据过滤选项)。这很容易做到,但我发现我在模型和控制器之间拆分了这些变量的使用。有时我会在控制器中更新一个,然后在模型中查找它。这开始“闻起来”很有趣,因为在我看来,让模型“意识到”所有这些设置可能不是一个好主意。模型不应该只接受获取/操作数据的请求,而只关心请求中明确包含的内容(无需查找外部变量)吗?

这是一个示例: 我有一个名为 $_SESSION['regionFilter'] 的会话变量。这是在控制器中创建和更新的,代表用户想要“深入”到的销售区域。当控制器从模型请求一些数据时,我目前让模型查找 $_SESSION['regionFilter'] 变量,并在为数据库创建 SQL 时使用它。似乎让模型在程序状态方面“哑巴”可能更有意义,如果需要,让控制器以某种方式将 $_SESSION['regionFilter'] 变量捆绑到其请求中。

有什么想法吗?谢谢!


编辑: 谢谢大家的讨论。我知道有重叠的问题,但是很难找到关于该主题的一般性讨论——我对“MVC 模型程序状态”的搜索出现了大量关于 ASP.NET-MVC 特定讨论的问题,这些讨论陷入了困境细节。

我已将问题标记为已关闭。再次感谢您的想法!

4

3 回答 3

4

我认为你担心它闻起来很有趣是完全正确的。您刚刚在模型中引入了与模型无关的东西。

我认为为模型提供过滤器没有任何问题,也许是采用代表您所在地区的字符串。如果您想将会话传递给它,那么请随意,但是通过将会话内容(甚至阅读)放入 Model中,您已经将两者内在地联系在一起......一个模型到一个会话状态。

在模型中提供一个适当过滤的方法,然后从控制器传入会话变量,但模型不知道过滤器来自会话变量。它只是一个过滤器。

编辑:为了澄清,我想说会话状态是控制器的一部分,绝对不是模型

于 2011-01-28T15:50:43.957 回答
2

一般来说,我有仅是状态的域模型。我知道这对于 Evan 理论的一些纯粹主义者来说并不是一个好兆头,但它对于创建可移植的模型非常有效,即使是跨异构系统也是如此。换句话说,这对 SOA 很有效(尽管我们可以争论代理模式在以后是否更优越?)

当您升级到 MVC 时,您处理的是 UI 模型而不一定是域模型,尽管许多示例融合了这两个概念。您的模型是与视图结合的模型(MVVM 模式中的 ViewModel)。如果您有这种逻辑分离,您的视图模型可以是原始“模型”(域模型?)和您需要显示的任何其他信息的组合。这也使关注点清晰分离,这很好。

于 2011-01-28T15:50:54.720 回答
1

如果您的搜索类中需要您的区域过滤器,则使用依赖注入将其传递给它。您的区域过滤器实际上应该是一个域模型类。该区域过滤器应该不知道您在请求之间存储它的数据的位置。只要确保区域过滤器在需要时拥有它。

作为一个领域模型类,它属于Controller,而是属于Model。请注意,模型不仅仅是数据库,而是除了 UI 之外的所有内容。控制器是 UI 层的一部分。它的唯一目的是将当前请求委托给适当的模型。

换句话说,你应该做这样的事情:

public function searchAction()
{
    $customerSearch = new CustomerSearch;
    $customerSearch->setFilter(new RegionFilter($_SESSION));
    $results = $customerSearch->fetchResults();

    // do something with $results on User Interface
}

请注意,我不同意本页其他地方给出的会话数据或状态属于控制器的答案。它没有。会话数据只是持久化数据。与任何其他持久化数据一样,它属于持久层(也是模型的一部分)。忘记它是会话数据。它是区域过滤器数据。

$_SESSION围绕(或任何超全局)添加 API 以防止与特定环境的耦合是有意义的。但是一个RegionFilterStorage_Session类仍然是一个模型类。

于 2011-01-28T16:24:54.840 回答