【问题标题】:How should partials be loaded when they are dependent on business logic?部分依赖于业务逻辑时应该如何加载?
【发布时间】:2011-04-06 10:44:34
【问题描述】:

我使用术语“部分”来指代在许多视图中重复的一小部分演示代码。例如,侧边栏。在 vanilla PHP 中,业务和表示逻辑混合在一起,包括一个侧边栏是没有问题的:

if($someCondition) {
    include('sidebar.php');
}

但是,在 MVC 设计模式中,表示逻辑必须保留在视图中,而业务逻辑必须保留在控制器中。如果我希望无条件地包含一个部分,那么这是没有问题的,因为我可以在我看来只有include('sidebar.php')。但是,我不能再有条件地这样做,因为如果我认为逻辑被禁止的话。

我尝试了许多解决方案,但它们都有问题。我目前正在使用解决方案 2:

解决方案 1

在我的视图类中创建一个包含函数,它可以有条件地包含来自我的控制器的内容。所以在我的控制器中,我可以有以下逻辑:

if($someCondition) {
    $this->view->include('sidebar.php');
}   
$this->view->show('index.php');

问题:sidebar.php 需要包含在 index.php 中的特定点,需要视图对象上的 include 方法进行某种解析。

解决方案 2

将部分控件移出视图并将它们放入控制器中:

if($someCondition) {
    $this->view->show('header.php', 'sidebar.php', 'index.php', 'footer.php');
}
else {
    $this->view->show('header.php', 'index.php', 'footer.php');
}

问题:将大部分表示逻辑移动到控制器领域。对我来说,决定是否包含标题似乎更自然。事实上,我能找到的每个 PHP MVC 教程都有部分在视图而不是控制器的控制之下。

解决方案 3

复制视图并更改克隆,使其包含侧边栏。然后我可以有条件地在控制器中加载一个或另一个:

if($someCondition) {
    $this->view->show('indexWithSidebar.php');
}
else {
    $this->view->show('index.php');
}

问题:代码重复。考虑一下如果我有 2 个需要有条件加载的侧边栏会发生什么。然后我需要index.php, indexWithSidebar1.php, indexWithSidebar2.php, indexWithSidebar1And2.php。这只会在每种情况下变得更糟。请记住,将侧边栏作为部分删除的全部目的是为了避免复制它,而这种方法似乎违背了这一点。

这些解决方案中的任何一个都是“正确”的解决方案吗?如果是,我该如何克服它们的问题?有没有更好的方法?

【问题讨论】:

    标签: php model-view-controller view controller partials


    【解决方案1】:

    但是,在 MVC 设计模式中, 表示逻辑必须保留在 业务逻辑的视图 必须保存在控制器中。

    恕我直言:从架构的角度来看,我将我的业务逻辑推到更远的地方,远离控制器。我们使用服务来处理所有业务逻辑和存储库以进行数据检索。服务调用存储库,然后将我们的数据模型与为我们决定的所有业务逻辑一起传回。真正的 UI 逻辑之外的任何逻辑(显示这个,隐藏那个),因为我们返回的数据可以(应该能够)用于任何类型的应用程序,无论是移动应用程序、Windows 应用程序还是 Web 应用程序。

    您可以为您的控件使用扩展辅助方法,如果您不希望呈现侧边栏,则可以在局部模型中返回 EmptyResult()。或者,更简洁地说:

    <% Html.RenderAction<MyController>(x => x.Sidebar({params})); %>
    

    然后在控制器中:

    public ViewResult Sidebar({params})
            {
                SidebarModel model = new SidebarModel();
    
                //...get/build model
    
                if ({someCondition})
                {
                    return View("MySidebarPartialView", model);
                }
    
    
                return new EmptyResult();
    
            }
    

    【讨论】:

      【解决方案2】:

      让您的控制器评估条件并将结果传递给您的视图。然后,视图可以决定是否包含部分。

      例如,控制器可以检查变量$foo 是否不为空。它通过模型的属性$model-&gt;isFooed 将比较结果传递给视图。在这种情况下,视图可以根据$model-&gt;isFooed的值显示侧边栏。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-29
        • 2011-09-14
        • 2011-06-01
        • 2011-06-28
        • 1970-01-01
        相关资源
        最近更新 更多