代码之家  ›  专栏  ›  技术社区  ›  Rupert Madden-Abbott

当部分依赖于业务逻辑时,应该如何加载它们?

  •  0
  • Rupert Madden-Abbott  · 技术社区  · 15 年前

    我使用术语“部分”来指代在许多视图中重复出现的表示代码的一小部分。例如,侧边栏。在普通的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');
    }
    

    问题: 代码的复制。考虑一下,如果我有两个侧边栏,我需要有条件地加载它们,会发生什么。那我就需要 index.php, indexWithSidebar1.php, indexWithSidebar2.php, indexWithSidebar1And2.php . 这只会在各种情况下变得更糟。记住,将侧边栏作为一个部分删除的整个要点是无论如何都要避免复制它,并且这种方法似乎击败了这一点。

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

    2 回复  |  直到 15 年前
        1
  •  1
  •   Josh    15 年前

    但是,在MVC设计模式中, 表象逻辑必须保持在 视图同时业务逻辑 必须保存在控制器中。

    imho:从体系结构的角度来看,我把我的业务逻辑进一步推回控制器之外。我们使用服务来处理所有用于数据检索的业务逻辑和存储库。服务调用存储库,然后用为我们决定的所有业务逻辑返回我们的数据模型。除此之外的任何逻辑都是真正的用户界面逻辑(显示这个,隐藏那个),因为我们返回的数据可以(应该能够)用于任何类型的应用程序,无论是移动应用程序、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
  •  1
  •   Jeff Mattfield    15 年前

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

    例如,控制器可以检查变量, $foo 不是空的。它通过模型的属性将比较结果传递给视图, $model->isFooed . 在这种情况下,视图可以根据 $model->是fooed .

    推荐文章