我可以从视图调用模型吗?
我没有使用成熟的 PHP MVC,而是设计一种最适合我的用途的.我已经完成了基本框架,并编写了运行网站所需的模型和控制器.
现在我要转向 Views,但我遇到了一个小难题.我的方法对我来说效果很好,但为了将来参考,我想知道我正在做的事情是否是一个坏习惯.
我想做什么:
在我的视图中,我正在调用一个运行我的身份验证系统的模型,并请求用户的登录状态.然后我使用该布尔值来决定是否在视图中显示某些元素,以及将其他元素放置在哪里.
我应该为每个登录状态设计单独的视图,还是这种方法合适?但是,如果我要将这个 MVC 实施到我为我的客户所做的工作中,我需要使用最佳实践.
任何建议将不胜感激!
解决方案我可以从视图中调用模型吗?
是的,您可以.只要您保持 M、V 和 C 之间的关注点分离,您就可以自由调用模型(或控制器) 从视图.大多数 MVC 图至少显示了视图和模型之间的双向连接.但是,您不想做的是将逻辑/代码从模型(或控制器)放入视图中,并且您不想从那里修改模型.
例如,您的页面上可能有一个小部件,用于汇总网站每个页面上您最喜欢的博客的最新十篇博客文章标题.您可以通过在模型中调用 MyFavFeeds::getLatest();
来获取头条新闻.你现在有什么选择?
- 您可以添加代码以将标题提取到控制器中,但这需要您在每个控制器操作中复制它,这违反了 DRY 原则.此外,控制器关注的是处理特定操作的用户输入,并且获取每次调用的标题甚至可能与这些操作无关.
- 如果您的架构支持它,您可以在某种 preDispatch 挂钩中获取该数据,也就是说,标题从插件或回调中加载并注入到视图中.这将是 DRY,但第二个开发人员可能不知道该插件并意外地覆盖了他的控制器操作中包含标题的变量.在某些情况下,您可能不想加载标题,例如当仅呈现表单提交的确认页面时,因此您必须具有禁用插件的机制.这需要考虑很多.
- 您将对
MyFavFeeds::getLatest()
的调用(而不是其代码)放入 View 或 Layout 模板,或者更好的 ViewHelper,它封装了对模型类的调用并呈现小部件.这样您就不必担心覆盖任何变量或重复.当您的视图中不需要标题时,您只需不包含它即可.
关于您的其他问题:
<块引用>在我看来,我正在调用一个模型运行我的身份验证系统,以及请求用户的登录状态.然后我使用那个布尔值来决定是否显示某些元素在视图中,以及放置的位置其他.
身份验证是您希望在应用程序流程的早期,在调用任何控制器操作之前进行的事情.因此,您不应在视图中运行您的(整个)身份验证系统.实际的身份验证不是与 View 相关的逻辑.另一方面,仅在身份验证后请求用户状态是可以的.例如,如果您想呈现一个显示用户名并提供登录/注销按钮的小部件,那么执行类似
如果您的 GUI 的大部分要由用户的角色修改,您可能希望将您的视图分成部分块并根据状态包含它们,而不是将所有 HTML 写入视图助手.
如果您只想根据用户角色呈现导航,请查看 Zend Framework 的 Zend_Navigation
和 Zend_Acl
以了解它们是如何实现的.>
Rather than use a full-blown PHP MVC, I'm designing one that will best-fit my uses. I have the basic framework done, and have coded the models and controllers I'll need to run my website.
Now I'm moving onto the Views, and I've encountered a small dilemma. My approach is working fine for me, but for future reference, I want to know if what I'm doing is a bad habit to get into.
What I'm trying to do:
In my View, I'm calling a Model that runs my authentication system, and requesting the login status of a user. I then use that boolean to decide whether to show certain elements within the view, and where to place others.
Should I be designing separate views for each login status, or is this approach fine? However, if I'm going to be implementing this MVC into the work I'm doing for my clients, I need to use the best practices.
Any advice would be appreciated!
解决方案Can I call the model from the View?
Yes, you can. As long as you maintain the separation of concerns between M,V and C, you are free to call upon the Model (or the Controller) from the View. Most MVC diagrams show a bidirectional connection at least between View and Model. What you don't want to do though, is place logic/code from the Model (or the controller) into the View and you don't want to modify the model from there.
For example, you might have a widget on your page that aggregates the latest ten blog posts headlines from your favorite blogs on each page of your website. You get the headlines by calling, say MyFavFeeds::getLatest();
in your model. What are your options now?
- You could add the code to fetch the headlines into the controller, but that would require you to replicate it in each and every controller action, which is against the DRY principle. Also, the controller's concern is handling user input for specific actions and fetching the headlines on each call is likely not even related to these actions.
- If your architecture supports it, you could fetch that data in some sort of preDispatch hook, that is, the headlines get loaded and injected into the View from a plugin or callback. That would be DRY, but a second developer might not be aware of that plugin and accidently overwrite the variable holding the headlines from his controller action. And there might be cases in which you wouldn't want to load the headlines, e.g. when just rendering confirmation pages for form submissions, so you'd have to have mechanism for disabling the plugin then. That's a lot to consider.
- You place the call to (not the code of)
MyFavFeeds::getLatest()
into the View or Layout template or, better, a ViewHelper, that encapsulates the call to your model class and renders the widget. This way you don't have to worry about overwriting any variables or repetition. And when you don't need the headlines on your view, you simply don't include it.
About your other question:
In my View, I'm calling a Model that runs my authentication system, and requesting the login status of a user. I then use that boolean to decide whether to show certain elements within the view, and where to place others.
Authentication is something you will want to do early in the application flow, before any controller actions are called. Thus, you should not run your (entire) authentication system in the View. The actual authentication is not View-related logic. Just requesting the user status after authentication, on the other hand, is okay. For instance, if you want to render a widget showing the user name and giving a login/logout button, it would be fine to do something like
<?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;
}
}
If you got larger portions of your GUI to be modified by a User's role, you might want to break your View apart into partial blocks and include them based on the status, instead of writing all the HTML into a View Helper.
If you are only looking to render a navigation based on the user role, have a look at Zend Framework's Zend_Navigation
and Zend_Acl
to see how they do it.
相关文章