我使用术语“部分”来指代在许多视图上重复的一小部分表示代码。例如,侧边栏。在vanilla PHP中,业务和表示逻辑混合在一起,包括侧边栏没有问题:
if($someCondition) {
include('sidebar.php');
}
但是,在MVC设计模式中,必须将表示逻辑保留在视图中,同时必须将业务逻辑保存在控制器中。如果我希望无条件地包含部分,那么这是没有问题的,因为我可以在我看来include('sidebar.php')
。但是,我不能再有条件地这样做,因为如果我的观点禁止使用逻辑。
我尝试了很多解决方案,但都有问题。我目前正在使用解决方案2:
在我的视图类中创建一个include函数,它可以有条件地包含来自我的控制器的内容。所以在我的控制器中我可以有以下逻辑:
if($someCondition) {
$this->view->include('sidebar.php');
}
$this->view->show('index.php');
问题: sidebar.php需要包含在index.php中的特定点,要求视图对象上的include方法进行某种解析。
将局部控件移出视图并将其放入控制器:
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教程都有局部视图而不是控制器。
复制视图并更改克隆,使其包含侧栏。然后我可以在控制器中有条件地加载一个或另一个:
if($someCondition) {
$this->view->show('indexWithSidebar.php');
}
else {
$this->view->show('index.php');
}
问题:代码重复。考虑如果我有2个侧边栏需要有条件地加载会发生什么。然后我需要index.php, indexWithSidebar1.php, indexWithSidebar2.php, indexWithSidebar1And2.php
。每种情况都会变得更糟。请记住,将侧边栏视为局部的整个要点是避免复制它,这种方法似乎打败了这一点。
这些解决方案中的任何一个都是“正确”的解决方案吗?如果是这样,我怎样才能克服他们的问题?那里有更好的方法吗?
答案 0 :(得分:1)
让控制器评估条件并将结果传递给您的视图。然后,视图可以决定是否包含部分。
例如,控制器可以检查变量$foo
是否为空。它通过模型的属性$model->isFooed
将比较结果传递给视图。在这种情况下,视图可以根据$model->isFooed
的值显示侧栏。
答案 1 :(得分:1)
然而,在MVC设计模式中, 必须保持表象逻辑 业务逻辑的视图 必须保存在控制器中。
恕我直言:从架构的角度来看,我将业务逻辑推回到控制器之外。我们使用服务来处理所有业务逻辑和存储库以进行数据检索。服务调用存储库,然后传回我们的数据模型,其中包含为我们决定的所有业务逻辑。外面的任何逻辑都是真正的UI逻辑(显示这一点,隐藏它),因为我们的返回数据可以(应该可以)用于任何类型的应用程序,无论是移动应用程序,Windows应用程序还是Web应用程序。 / p>
您可以为控件使用扩展辅助方法,如果您不希望渲染侧边栏,则可以在partial的模型中返回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();
}