当部分依赖于业务逻辑时应该如何加载?
我使用术语“部分”来指代在许多视图中重复的一小部分演示代码。例如,侧边栏。在业务和表示逻辑混合的普通 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
。在每种情况下,这种情况只会变得更糟。请记住,将侧边栏作为部分内容取出的全部目的是为了避免复制它,而这种方法似乎违背了这一点。
这些解决方案是否是“正确”的解决方案?如果是,我该如何克服他们的问题?有更好的方法吗?
I'm using the term "partial" to refer to a small section of presentational code which is repeated on many views. For example, a sidebar. In vanilla PHP, where the business and presentation logic is mixed, including a sidebar is no trouble:
if($someCondition) {
include('sidebar.php');
}
However, in an MVC design pattern, the presentational logic must be kept in the view whilst the business logic must be kept in the controller. If I wish to include a partial unconditionally, then this is unproblematic since I can just have include('sidebar.php')
in my view. However, I can no longer do so conditionally because that if logic is banned from my view.
I have attempted a number of solutions but they all have problems. I am currently using Solution 2:
Solution 1
Create an include function in my view class which could conditionally include content from my controller. So in my controller I could have the following logic:
if($someCondition) {
$this->view->include('sidebar.php');
}
$this->view->show('index.php');
Problems: sidebar.php will need to be included into index.php at a specific point requiring the include method on the view object to do some sort of parsing.
Solution 2
Move control of the partials out of the view and put them into the controller:
if($someCondition) {
$this->view->show('header.php', 'sidebar.php', 'index.php', 'footer.php');
}
else {
$this->view->show('header.php', 'index.php', 'footer.php');
}
Problems: Moves a large portion of the presentational logic into the realm of the controller. It seems to be more natural to me for the view to decide whether or not to include the header. Indeed, every PHP MVC tutorial I can find, has partials under the control of the view and not the controller.
Solution 3
Duplicate the view and alter the clone so that it includes the sidebar. Then I could conditionally load one or the other in the controller:
if($someCondition) {
$this->view->show('indexWithSidebar.php');
}
else {
$this->view->show('index.php');
}
Problems: Duplication of code. Consider what would happen if I had 2 sidebars which I needed to be conditionally loaded. Then I would need index.php, indexWithSidebar1.php, indexWithSidebar2.php, indexWithSidebar1And2.php
. This only gets worse with every condition. Remember that the entire point of taking the sidebar out as a partial was to avoid replicating it anyway and this approach seems to defeat the point.
Are any of these solutions the "right" solution and if so, how can I overcome their problems? Is there a better approach out there?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
恕我直言:从架构的角度来看,我将业务逻辑进一步推向控制器之外。我们使用服务来处理所有业务逻辑和数据检索存储库。服务调用存储库,然后传回我们的数据模型以及为我们决定的所有业务逻辑。任何外部逻辑都是真正的 UI 逻辑(显示这个,隐藏那个),因为我们返回的数据可以(应该能够)在任何类型的应用程序中使用,无论是移动应用程序、Windows 应用程序还是 Web 应用程序。
您可以为您的控件使用扩展辅助方法,并且在部分模型中,如果您不希望呈现侧边栏,则可以返回 EmptyResult()。或者,更简洁地说:
然后在控制器中:
IMHO: From an architecture standpoint, I push my business logic further back, out of the controller. We use services to handle all the business logic and repositories for data retrieval. The services call the repositories and then pass back our data model with all the business logic decided for us. Any logic outside that is really UI logic (show this, hide that), as our returned data could be (should be able to be) used in any kind of application, whether it's a mobile app, windows app, or web app.
You could use an extension helper method for your control, and in the model for the partial you can return EmptyResult() if you don't wish to render the sidebar. Or, more succintly:
And then in the controller:
让您的控制器评估条件并将结果传递到您的视图。然后,视图可以决定是否包含部分。
例如,控制器可以检查变量
$foo
是否不为 null。它通过模型的属性$model->isFooed
将比较结果传递给视图。在这种情况下,视图可以根据$model->isFooed
的值显示侧边栏。Have your controller evaluate the condition and pass the result to your view. Then, the view can decide whether to include the partial.
For example, the controller can check whether a variable,
$foo
, isn't null. It passes the result of the comparison to the view via the model's property,$model->isFooed
. In this case, the view can display the sidebar based on the value of$model->isFooed
.