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

时间:2009-12-29 06:25:22

标签: php model-view-controller

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

现在我正在转向观点,我遇到了一个小困境。我的方法对我来说很好,但是为了将来的参考,我想知道我正在做什么是一个坏习惯进入。

我正在尝试做什么:

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

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

任何建议都将不胜感激!

4 个答案:

答案 0 :(得分:16)

  

我可以从View中调用模型吗?

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

例如,您的网页上可能有一个小部件,用于汇总您网站每个页面上您最喜欢的博客的最新十个博客帖子标题。您可以通过在模型中调用MyFavFeeds::getLatest();来获取头条新闻。你现在有什么选择?

  1. 可以添加代码以将标题提取到控制器中,但这需要您在每个控制器操作中复制它,这违反了DRY原则。此外,控制器关注的是处理特定操作的用户输入,并且在每次调用时获取标题甚至可能与这些操作无关。
  2. 如果您的架构支持它,您可以在某种preDispatch挂钩中获取该数据,也就是说,标题会从插件或回调中加载并注入到View中。这将是DRY,但是第二个开发人员可能不会意识到该插件并且意外地覆盖了控制器操作的头条新闻变量。并且可能存在您不想加载标题的情况,例如当只是为表单提交呈现确认页面时,所以你必须有机制来禁用插件。这需要考虑很多。
  3. 您将调用MyFavFeeds::getLatest()(不是代码)放入View或Layout模板,或者更好的是ViewHelper,它封装了对模型类的调用并呈现窗口小部件。这样您就不必担心覆盖任何变量或重复。如果您不需要在视图上显示标题,则根本不包括它。
  4. 关于您的其他问题:

      

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

    在调用任何控制器操作之前,您需要在应用程序流的早期进行身份验证。因此,您不应该在视图中运行您的(整个)身份验证系统。实际身份验证不是与视图相关的逻辑。另一方面,仅在认证后请求用户状态是可以的。例如,如果您想要呈现一个显示用户名并给出登录/注销按钮的小部件,那么可以执行类似

    的操作。
    <?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,了解他们是如何做到的。

答案 1 :(得分:4)

可以,但你不应该。除了一些极端情况(根据登录状态分支您的视图绝对不是“极端情况”),从视图中调用模型内容几乎总是一个坏主意。

在您的情况下您可能想要做的是通过控制器将布尔值传递给视图。这样,如果您更改了User模型的某些内容,则只要控制器保持行为相同,视图就不必知道。

答案 2 :(得分:0)

好的,我真的会尽量让我的观点尽可能没有逻辑。如果你需要根据例如模型方法的结果,将控制器放在委托渲染的位置。

请确保遵循以下基本想法:在模型中完成您的工作,告诉您的模型从您的控制器中做什么,并告诉您的视图从您的控制器显示什么。

答案 3 :(得分:-1)

虽然我对MVC足够了解让自己陷入困境,但我一直都认为,除非你的观点是严格的用户界面,否则它不应该存在。

此外,我还提到了瘦控制器,胖模型的想法。

关于这些,我建议在您的身份验证系统模型中添加一个方法,该方法返回适当的视图以进行渲染并将其传递给视图。