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 = 'Logout';
if(MyAuth::userHasIdentity()) {
$link = sprintf('Logout %s',
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.
You can, but you shouldn't. Except for a few extreme cases (and branching your view based on logged-in status is definitely not an "extreme case"), it's pretty much always A Bad Idea to call model stuff from a view.
What you probably want to do in your situation is pass the boolean to the view through the controller. That way, if you change something about the User model, the view doesn't have to know, so long as the controller keeps the behavior the same.
While I only know enough about MVC to get myself in trouble, I've always lived by the fact that unless your view is STRICTLY user interface, then it shouldn't be there.
Also, I've also ran with the idea of thin controllers, fat models.
Going off of these, I'd suggest adding a method to your authentication system model that returns the appropriate view to render and passes that to the view.
Okay, I would really try to keep my Views as logic-free as possible. If you need to switch anything based on e.g. the result of a model method, put a controller in place that delegates the rendering.
Just make sure you follow the basic idea: Do your stuff in the models, Tell your models what to do from your controllers and also tell your views what to show from your controllers.
Related
there are cases when i require to run the same logic both in controller and view, i thought they may have a shared code, for example when to display an edit link and the same logic should check for edit permission in controller , where should i keep such code so that same can be used in controllers as well as views, I am okay to write a a component wrapper and a view wrapper for this method but the core logic should be common.
Some mentioned bootrap is a place but putting there do i have all the cake defined parameters or constants available from that location? or there is a better place
EDIT
I gave only authentication related example but there can be more cases like, a view helper for displaying data/time based on offset time set in database (system time + offsetime), i have been forced to use of same code in controllers also (ajax output). What does it imply that in common code we not only have shared logic but also some shared data too, so for only session classes appears to be providing shared data!
On the whole, I'm inclined to say you're not going about this the right way. If you have to include the same piece of logic in both the controller and the view, chances are you're doing the same work twice, which is always a bad idea. DRY (Don't Repeat Yourself) is something you probably heard about a million times before.
However, in the case you mention (authentication): this is done in the Controller, which relies on the Model layer to find out if the user has the permissions to see/use edit links.
Based on the data the controller receives from the Model layer, it should do one of the following things:
choose to render a specific view (with/without edit links)
Present the user with an error view
redirect to the login
For the first case, an editable and non-editable view, you can choose to use the same view script, and use a helper to pass on the session information to the view. Effectively giving the view the means to check a users' session, check if the user in question has the rights required to see the edit links and render them...
Another simple fix would be to set a property of the view to true for editable and false for non-editable in the controller, and check that bool flag in the view. No extra logic required.
The main thing here is that what you're after is authenticating the user. By the time you reached the view, the route is a given, there's no way back. If you find yourself still having to validate the users' identity, you've made a mistake at an earlier point: the controller, and model layer is where this kind of core logic should reside.
A view contains no logic other than its own: a loop or 2, some if-else's... nothing more.
The rule of thumb, then is: the first thing the controller does is authenticate the user. The authentication itself is the concern of the Model layer: no actual core/business logic should be in the controller. Based on the findings the model layer returns (authentication failed, or user has rights to do X, but not Y), the controller can redirect, throw errors or choose to render a specific view.
Only after all these things are performed the view is brought in. If there's a user in play, the view can assume that this user is valid, and has the rights required to see its contents. The view does not validate data, nor does it authenticate users.
To authenticate a user the Cake-specific way there's a core Authentication component that seems to be quite well documented. See if you can't use that...
You can add simple functions to bootstrap, but another option would be to create a class in app/Lib/ using static methods. Then from any controller you can include the library and use the methods defined:-
App::uses('MyLibrary', 'Lib');
If all controllers need to use these just include the library in AppController.
For your views I'd then consider defining a View Helper that would apply the methods used in MyLibrary.
If I get this right than function of the Controller is processing POST data and technically making changes to the state of the application (e.g. DB) via Model.
As far as I understand, View also gets data from the Model.
So this is how I understand the workflow:
Client request --> App Front Controller --> (if method = POST --> Controller) --> View --> back to Client
Here Model is used by Controller to read and write data and by View to read data.
So controller is not used every time the page is loaded, in fact, only when app data is added/updated. Most of the times Controller is bypassed.
Thus, how come almost every resource about MVC is talking about Controller sending data to views?
I am trying to write an app using MVC-like pattern. So in my app views always get data for the page from the Model. When Model is updated, I add specific model update time to Memcache. At runtime each View looks up last update time(s) of related model(s) and last time cache for this view was generated. If model was updated before cache was saved, view reads cache, otherwise re-renders based on updated model.
The controller is responsible for presenting views based on the data that is requested. It's there so neither the model nor the view need to know about the request. Yes, the view gets data from the model, but not always directly; the controller may have to make some decisions as well depending on the request.
It's something like having waiters in a restaurant so they can take orders from and serve dishes to customers. It's not the chefs who bring out the meals after preparing them; it's the waiters. It's not the customers who go to the kitchen asking for meals; it's the waiters who take their orders then let the chefs know what to prepare for whom. In the same way, the controller is there to handle client requests, whatever their nature may be. It's a very rough comparison though, but I hope you get the picture.
Unless I misinterpreted your question: The problem is with the view accessing the model directly. That's not supposed to happen as it defeats the reason for the MVC pattern. The view shouldn't know anything about the model itself, so the model can be exchanged for something else - the controller should supply the data (at most times it a flattened or projected way) to the view.
If I did: The controller is never bypassed. Just because it doesn't do anything with the data, doesn't mean it isn't needed - it provides a layer of abstraction between model and view. The point is to be able to exchange the model without having to adjust the view.
The controller is never bypassed as it is required to instruct which views are shown and what data (if any) is used in those views. Each get or post request to an MVC site uses the controller to control what is shown or collected to/from the client.
At its core MVC is used to separate concerns. The model works with the data, the views handle presentation and the controller provides the logic between the two.
If you are a person that learn faster by getter hands dirty with codes or looking to something visual , like me ....
I will suggest you to follow the tutorial in railsforzombies.org . It pretty much explain all the basic using rails , including MVC. In the tutorial , It mention that if you put all those logic in view , It will be messy. The code will sux a little bit because the guys that want to use your code will be confused with codes. By putting all the logic in controller and output it in view. It will be very clear for the person that look into your codes.
Usually Controller uses Model, and passes proccessed data to View. View shouldn't see Model. Main goal is - to keep View separately from Model!
MVC for dummies: why does controller
have to send anything to views?
This is the main point of MVC: to create loose coupling by separating and distinguishing the application's concerns. You have the View, Model, and Controller doing specific tasks.
Why the need for separation because it's hard to debug and fix a one gigantic godzilla app. Imagine fixing a car made from stone. There are no bolts. Everything is chiseled from a big rock. How hard is fixing that if you just want to change the wheels. You will need to chisel out the rock itself.
The main job of the controller is to handle requests and display the appropriate view. That it's job. It's like asking why does the mailman need to send the mail. Because that's his job.
I use php and usually structure my application into model-view-controller so its always accessed via index.php with class and method attributes. Class attribute passed as part of URL specifies controller class and method simply method to be called. This seems to be pretty common, but then I'm always having trouble in figuring out what controllers shall I create. What is the best, easiest and most applicable way to decide on what controllers should be created? I understand it depends on web application itself but must be some general way of thinking to get this process started.
I've found that building controllers based on your application's objects works well, and can take care of most actions you'll want for your app.
Take a look at SO -- there's URLs starting with /questions, /tags, /users, etc. I'd suggest a design which starts by creating a different controller for each object. /questions (or /questions/list) returns a list of all the questions. /questions/[0-9]+ returns the details of a particular question with that id number. /questions/ask returns the Ask Question interface.
As you continue building your app, you might find that the controller-based-on-objects method doesn't meet all your needs. For example, on my site (http://www.wysiap.com), I eventually made a /list controller to simplify my Grails URL mapping. But in most cases I did use this method and it's easy to figure out which controller should be doing different actions.
I recommend to think about the pages you'll need in your applications to accomplish all the requested tasks. You'll group similar tasks on the same page and create as many pages as you need. A page can be sliced in different views for specific actions.
With this in mind you could have one controller per page. Each view of the page can have its own method (action) in the controller. And inside the method of each view you can have a switch() that will enable you to have several tasks for the view. Example:
index.php (Dashboard controller)
/question-list (QuestionList controller, action index, display the whole page)
/question-list/add (QuestionList controller, action add, manage the "add" view with tasks like show-form, validate-form, insert-question)
/profile (Profile controller, action index)
/profile/edit (Profile controller, action edit, manage all the tasks requested for your profile)
...
I design most of my web applications this way and using Zend-Framework
I’m trying to learn and fully understand mvc pattern and learn php at the same time. I decided to built basic mvc framework that I could use on various projects later on. Having read lots of posts in here regarding mvc and coupling between models/views/controllers I’m a bit lost.. At the moment my understanding is that in web application controllers deal with coming request from browser and, if necessary, calls methods on model classes telling models to change its state. Then controller instantiate appropriate view class that will be responsible for displaying interface.
Here's the bit I don’t understand...
Now should controller pass appropriate model object to view and view should pull out all the data from model when needed?
Or controller should grab data from model and pass it to view, possibly wrapping it all into single wrapper object that view will access and grab data from there?
Or view should simply instantiate appropriate model when needed and pull out data directly from model object?
From what I read here
http://www.phpwact.org/pattern/model_view_controller
I’d lean towards the 3rd option where controller doesn’t pass anything to view and view instantiates model it needs. This is because:
view and controller should have same access to model
controller shouldn’t act simply as mediator in between view and model.
Is there really one correct way to do it or it rather depends on project? Also what approach would you recommend to someone who has decent understanding of OOP but is relatively new to php and not too clear on mvc architecture. Or maybe I should go with whatever seems right to me and learn from my mistakes (would like to avoid this one though ;)?
Now, please let me know if my question is not clear will try to better explain then.. Also I read lots of posts on stackoverflow and numerous articles on different sites, but still would appreciate help so thanks in advance for all answers.
Personally, I've always been a proponent of #2. The view shouldn't care about the model. The view shouldn't have any processing at all for that matter. It should do what it's supposed to do, format data.
The basic flow of control should be thus: The controller recieves a request from a browser. It processes the request, decides what data is needed, and retrieves it from the model/s. It then passes the data into the view which format the data and displays it.
As an extension, user input is processed inside the controller, and saved into a model if needed, then feedback is fed into a view, etc. The key point to take away is that processing happens inside the controller.
Personally, I've always been a proponent of #3. The view shouldn't care about the controller. The view shouldn't have any dependency on the controller for that matter. It should do what it's supposed to do, show a view of the model.
The basic flow of control should be thus: The controller receives a request from a browser. It makes any updates to the model, that is relevant, and then selects a view. The control is then passed to the view, which gets data from the model and renders it.
As an extension, user input can be consider part of the model, and both the controller and the view may read from it. The key point to take away is that Controller and View should have no dependency on each other. That's why the pattern is called MVC.
Now, personally, I find MVC a bit too tedious, and so I usually conflate Controller and View more than this. But then that isn't really MVC.
Web MVC and Desktop MVC are two very different beasts.
In Web MVC, a link in a View calls a method on a Controller, which updates a Model, and then redirects to an appropiate View, which opens up a Model and shows what it needs.
In a Desktop MVC, option 3 is wrong because both the view and the model should use the same reference. In Web, there's no choice.
Option number 2 is not MVC. It's MVP, wherein the Presenter is a mediator.
A Controller has Write-Access to a Model; a View has only Read access.
This is a very interesting question.
From my experience most implementations in php assign a model variable to the view:
$this->view->my_property = $modelObj->property
This is common practice.
The common reasoning for this is that if you send the object then you can call methods that modify the object from the view.
//in the controller file
$this->view->myObject = $modelObj;
//in the view file, you could call an object modifying method
$this->myObject->delete();
And modifying the model from the view is considered bad practice. Some people thing that they don't want their designers being able to call model modifying methods from the view.
That being said. I don't agree with the common practice and tend to assign the whole object to the view and display it from there. And just discipline my self to not make operations there.
And a third option is to assign the whole object to the view. but some how in the objects disable methods when they are called from the view.
I think this is just a generic argue about what is better "push" or "pull" model. There is no "absolutely" best solution.
I had a very similar question earlier. I find helpful to think of it as follows:
MVC
Model -- Data store, alerts Views of changes
View -- Displays model, provides hooks for user interaction
Controller -- Handles user input
You would use MVC more often in non-web apps, where lots of classes are interacting with eachother simultaneous.
In a web application MVC means MVT (Model-View-Template)
Model -- Strictly a data store, typically an ORM solution
View -- Handles web requests, provides for user input/output
Template -- Actually displays content (HTML, Javascript, etc.)
So in a web application the presentation is handled in the Template, the logic behind the application is handled in the View (or classes called by the view), and the model is responsible for holding data.
The reason why so many developers today can't get the knock of MVC is because the abbreviation of MVC was incorrectly stated from day one when it arrived into software development, but the concept is correct back then and also today. Since I am from the old school, let me explain it for you; when you are creating an object you first create a Model so the customer can View it, once it is approved you will have full Control on how the object is going to be made. That's how it is to this day in product manufacturing.
In today’s web application development such term should be VCM. Why! You View what's on the web browser, and then you click a button for action, that is known as the Controller. The controller alerts the Model, which is the instruction or logic to produce a result (that is your script). The result is then sent back to the user for viewing. In software engineering, you can refer to it as CMV; because the user won't able to view anything until the apps is compiled and installed. So we will need a Controlling device (PC); the OS as the Model and a monitor to View the results. If you can understand those concepts, MVC should start to look much more appetizing. I hope this concept will help someone to understand MVC.
I tend toward having the controller act as an intermediary between the model and the view, but generally this is literally a single line of code that connects the three together. If your model, view, and controller are properly decoupled it should make very little difference which you use.
1) Where does the homepage of your website fit into "controllers"? I've seen some people use a "page" controller to handle static pages like, about, home, contact, etc., but to me this doesn't seem like a good idea. Would creating a distinct controller just for your homepage be a better option? After all, it may need to access multiple models and doesn't really flow well with the whole, one controller per model theory that some people use.
2) If you need a dashboard for multiple types of users, would that be one dashboard controller that would have toggle code dependent upon which user, or would you have say a dashboard action within each controller per user? For example, admin/dashboard, account/dashboard, etc.
3) It seems to me that using the whole simple CRUD example works like a charm when trying to explain controllers, but that once you get past those simple functions, it breaks down and can cause your controllers to get unwieldy. Why do some people choose to create a login controller, when others make a login function in a user controller? One reason I think is that a lot of us come from a page approach background and it's hard to think of controllers as "objects" or "nouns" because pages don't always work that way. Case in point why on earth would you want to create a "pages" controller that would handle pages that really have nothing to do with each other just to have a "container" to fit actions into. Just doesn't seem right to me.
4) Should controllers have more to do with a use case than an "object" that actions can be performed on? For all intensive purposes, you could create a user controller that does every action in your whole app. Or you could create a controller per "area of concern" as some like to say. Or you could create one controller per view if you wanted. There is so much leeway that it makes it tough to figure out a consistent method to use.
Controllers shouldn't be this confusing probably, but for some reason they baffle the hell out of me. Any helpful comments would be greatly appreciated.
1) I use a simple homebrew set of classes for some of my MVC stuff, and it relates controller names to action and view names (it's a Front Controller style, similar to Zend). For a generic web site, let's assume it has a home page, privacy policy, contact page and an about page. I don't really want to make separate controllers for all these things, so I'll stick them inside my IndexController, with function names like actionIndex(), actionPrivacy(), actionContact(), and actionAbout().
To go along with that, inside my Views directory I have a directory of templates associated with each action. By default, any action automatically looks for an associated template, although you can specify one if you wish. So actionPrivacy() would look for a template file at index/privacy.php, actionContact() would look for index/contact.php, etc.
Of course, this relates to the URLs as well. So a url hit to http://www.example.com/index/about would run actionAbout(), which would load the About page template. Since the about page is completely static content, my actionAbout() does absolutely nothing, other than provide a public action for the Front Controller to see and run.
So to answer the core of your question, I do put multiple "pages" into a single controller, and it works fine for my purposes. One model per controller is a theory I don't think I'd try to follow when working with Web MVC, as it seems to fit an application with state much better.
2) For this, I would have multiple controllers. Following the same methods I use above, I would have /admin/dashboard and /account/dashboard as you suggest, although there's no reason they couldn't use the same (or portions of the same) templates.
I suppose if I had a gazillion different kinds of users, I'd make things more generic and only use one controller, and have a mod_rewrite rule to handle the loading. It would probably depend on how functionally complex the dashboard is, and what the account set up is like.
3) I find CRUD functionality difficult to implement directly into any layer of MVC and still have it be clean, flexible and efficient. I like to abstract CRUD functionality out into a service layer that any object may call upon, and have a base object class from which I can extend any objects needing CRUD.
I would suggest utilizing some of the PHP ORM frameworks out there for CRUD. They can do away with a lot of the hassle of getting a nice implementation.
In terms of login controller versus user controller, I suppose it depends on your application domain. With my style of programming, I would tend to think of "logging in" as a simple operation within the domain of a User model, and thusly have a single operation for it inside a user controller. To be more precise, I would have the UserController instantiate a user model and call a login routine on the model. I can't tell you that this is the proper way, because I couldn't say for sure what the proper way is supposed to be. It's a matter of context.
4) You're right about the leeway. You could easily create a controller that handled everything your app/site wanted to do. However, I think you'd agree that this would become a maintenance nightmare. I still get the jibbly-jibblies thinking about my last job at a market research company, where the internal PHP app was done by an overseas team with what I can only assume was little-to-no training. We're talking 10,000 line scripts that handled the whole site. It was impossible to maintain.
So, I'd suggest you break your app/site down into business domain areas, and create controllers based on that. Figure out the core concepts of your app and go from there.
Example
Let's say I had a web site about manatees, because obviously manatees rock. I'd want some normal site pages (about, contact, etc.), user account management, a forum, a picture gallery, and maybe a research document material area (with the latest science about manatees). Pretty simple, and a lot of it would be static, but you can start to see the breakdown.
IndexController - handles about page, privacy policy, generic static content.
UserController - handles account creation, logging in/out, preferences
PictureController - display pictures, handle uploads
ForumController - probably not much, I'd try to integrate an external forum, which would mean I wouldn't need much functionality here.
LibraryController - show lists of recent news and research
HugAManateeController - virtual manatee hugging in real-time over HTTP
That probably gives you at least a basic separation. If you find a controller becoming extremely large, it's probably time to break down the business domain into separate controllers.
It will be different for every project, so a little planning goes a long way towards what kind of architectural structure you'll have.
Web MVC can get very subjective, as it is quite different from a MVC model where your application has state. I try to keep major functionality out of Controllers when dealing with web apps. I like them to instantiate a few objects or models, run a couple of methods based on the action being taken, and collect some View data to pass off to the View once it's done. The simpler the better, and I put the core business logic into the models, which are supposed to be representative of the state of the application.
Hope that helps.