一尘不染

我可以从视图中调用模型吗?

php

我正在设计一个最适合我的用途,而不是使用成熟的PHP MVC。我已经完成了基本框架,并编写了运行网站所需的模型和控制器。

现在,我进入“视图”,遇到了一个小难题。我的方法对我来说很好,但是为了将来参考,我想知道我在做什么是否有不好的习惯。

我正在尝试做的是:

在我的视图中,我正在调用一个运行身份验证系统的模型,并请求用户的登录状态。然后,我使用该布尔值来决定是否在视图中显示某些元素,以及在其他位置放置其他元素。

我应该为每种登录状态设计单独的视图,还是这种方法很好?但是,如果要在为客户执行的工作中实施此MVC,则需要使用最佳实践。

任何意见,将不胜感激!


阅读 302

收藏
2020-05-29

共1个答案

一尘不染

我可以从视图中调用模型吗?

是的你可以。 只要您保持M,V和C之间 的关注分离
,就可以从视图中自由调用模型(或控制器)。大多数MVC图至少在View和Model之间显示双向连接。但是,您不想执行的操作是将模型(或控制器)中的
逻辑/代码 放入视图中,而您不想从那里修改模型。

例如,您的页面上可能有一个小部件,该小部件汇总了网站每个页面上您喜欢的博客中最新的十个博客文章标题。您可以通过MyFavFeeds::getLatest();在模型中说出来来获得头条新闻。您现在有什么选择?

  1. 可以 添加代码以将标题获取到控制器中,但是这将要求您在每个控制器操作中都将其复制,这违反了DRY原理。同样,控制器的关注点在于 处理针对特定动作的用户输入, 并且获取每个呼叫的标题可能甚至与这些动作无关。
  2. 如果您的体系结构支持它,则可以通过某种preDispatch挂钩获取该数据,即,将标题从插件或回调中加载并注入到View中。那将是DRY,但是第二个开发人员可能不知道该插件,并意外覆盖了保存其控制器操作标题的变量。在某些情况下,您可能不想加载标题,例如,仅在提交表单提交的确认页面时,因此必须具有禁用该插件的机制。有很多考虑。
  3. 您可以将对(而非代码)的调用MyFavFeeds::getLatest()放入“视图”或“布局”模板,或者更好的是,将ViewHelper封装到模型类的调用并呈现小部件。这样,您不必担心会覆盖任何变量或重复。而且,当您不需要视图上的标题时,只需不添加它即可。

关于您的其他问题:

在我的视图中,我正在调用一个运行身份验证系统的模型,并请求用户的登录状态。然后,我使用该布尔值来决定是否在视图中显示某些元素,以及在其他位置放置其他元素。

身份验证是您希望在调用任何控制器操作之前在应用程序流程的早期进行的事情。因此,您不应在View中 运行(整个)身份验证系统
。实际的身份验证不是与视图相关的逻辑。另一方面,只需在身份验证后请求用户状态即可。例如,如果要渲染一个显示用户名并提供登录/注销按钮的小部件,则可以执行以下操作

<?php //UserHelper
class UserMenuHelper
{
    public function getUserMenu()
    {
        $link = '<a href="/user/logout">Logout</a>';
        if(MyAuth::userHasIdentity()) {
           $link = sprintf('<a href="/user/logout">Logout %s</a>',
                            MyAuth::getUsername());
        }
        return $link;
    }
}

如果您要通过用户角色来修改GUI的较大部分,则可能需要将View分为部分块并根据状态将其包括在内,而不是将所有HTML都写入View Helper。

如果您只想基于用户角色呈现导航,请查看Zend Framework Zend_NavigationZend_Acl查看其操作方式。

2020-05-29