9

I have the following data flow for a simple login form.

User access controller PHP file. Controller includes model.php and view.php

User submits form, controller sends POST data to model methods, and gets a result back.

User is logged in, and forwarded to a different view (login success message) by the controller.

Currently my views are static HTML (no PHP), so here is my question. What is the correct way to then pass the user a welcome message, e.g "Hello, Craig!"?

Is the view allowed PHP snippets, e.g

<?php echo $username; ?> 

since the model is loaded before it in the controller file?

Thanks!

Edit: Is it better practice then to allow the view to access specific class methods e.g

<?php $user->getUsername(); ?>

as opposed to just variables?


Based on other answers, I have found a very useful article, which you may also be interested in.

http://www.nathandavison.com/posts/view/7/custom-php-mvc-tutorial-part-5-views

jjnguy
  • 136,852
  • 53
  • 295
  • 323
Craig Wilson
  • 463
  • 5
  • 8
  • 19
  • 1
    Dynamic content should be passed from action to view and displayed there, so it's allowed to use php variables in views. – Leri Jul 27 '12 at 13:53
  • i think model is containing the class if you use oops you can call method whenever you want thus you will get the data from the controller but it will be more complicated and use more server (since it have more query ) – NullPoiиteя Jul 27 '12 at 13:58
  • https://youtu.be/Z7vXAI0z5I8 – Peternak Kode Channel Apr 16 '19 at 11:54

2 Answers2

19

Here are few things you must consider:

  • You cannot do classical MVC in PHP. Instead we have MVC-inspired patterns
  • There exists 1:1 relation between view and controller instances, when implemented for web
  • Model in MVC is not a class. It is a layer, that contains a lot of different classes
  • View is not a dumb template, but an instance of class, which deals with presentation logic

View in Web-based MVC

As stated above, views in MVC and MVC-inspired patterns are responsible for presentation logic. That encompass things like showing error messages and pagination. To do this, each view can handle several templates.

View receives information from the model layer, and acts accordingly. The way how the information from model layer ends up in views is one of most significant differences in MVC-ish patterns:

  • classical MVC pattern

    Structures from model layer send the information to view, when state of model has been altered. This is done via observer pattern.

  • Model2 MVC and HMVC patterns

    View has direct access to the model layer and is able to request information from it. This is the closest to the original pattern.

  • MVVM and MVP patterns

    View receives information through controller, which has in turn requested it from model layer. The further difference in patterns stems from what the do with data before passing it to view.

What you seem to have now is actually just a template. Similar to one, that is described in this article. You end up with a structure, that has no place to contain the presentation logic. In long-run this will cause the presentation logic to be pushed into controller.

So what about that "welcome" message ?

To show the welcome message, your view should request from model layer the name of current user. If the model layer returns some sort of error state, view pick the error message template and inserts into the layout.

In case if name of the user was retrieved from model layer without problems, view pick the template which would contain the greeting, sets the value in the template and renders it.

In what order parts should be loaded ?

The idea, that controller should initialize model and view, comes from very primitive interpretation of MVC for web. Pattern know as page controller, which tried to graft MVC directly on static web pages.

In my opinion, this should be the order:

  1. Model

    You initialize the structure, through which you will deal with model layer. It most likely would be some sort of service factory, which would let you build things like Authentication service for logins and Library service for handling documents. Things like that. I wrote a bit long'ish comment on model layer's structure earlier. You might find it useful.

  2. View

    You create a view instance based on information, that you collected from routing mechanism. If you are implementing Model2 or HMVC, then your view will require an instance of Service Factory in the constructor.

    If you are implementing MVVM or MVP, then view's constructor has no special requirements.

  3. Controller

    This is the last structure, which you create, because controller is responsible for sending commands to both view and model layer, which then change then change the state of both. Therefore controller should expect to receive both view and service factory in the constructor.

After basic elements of MVC have been initialized, you call a method on the controller, and render current view.

Just keep in mind that this is very simplified description.

Community
  • 1
  • 1
tereško
  • 58,060
  • 25
  • 98
  • 150
  • "Therefore controller should expect to receive both view and service factory in the constructor." Just to clarify, you mean the controller should be responsible for instantiating (assuming oop) the model and the view, passing them both parameters from the route - right? – Sam Selikoff Jan 31 '13 at 16:51
  • @SamSelikoff, I'm not sure what you understand with "route" but: **NO**, controller does not initialize views or model layer structures. The view gets injected in the controller an the initialization of model layer elements gets done in the factory. – tereško May 11 '13 at 21:57
  • @tereško I understand that for Model 2 MVC the `View` interacts with the Model Layer, but why is this through the `ServiceFactory`? Isn't the purpose of a `ServiceFactory` to build certain services such as `AuthenticationService`, and then **return** the built object to the controller, where it is then envoked? Why does the `View` need the `ServiceFactory` - it shouldn't be building anything, right? It just needs data from particular services.. – tgun926 Feb 24 '14 at 09:01
  • @tgun926 well ... this probably will be quite confusing, but here we go. The services itself are used to contain the *"application logic"*(basically: the interaction between domain an persistence abstractions). The use of `ServiceFactory` in this context is actually a workaround. View does not need the factory. It **actually** needs the `AuthenticationService` instance, which it shares with the controller. To facilitate such sharing in an OOP way, you have two ways: initialize the instance "outside" and pass it to both view an controller objects **OR** .. – tereško Feb 24 '14 at 09:23
  • .. pass a builder/factory, which will initialize the instance only once, stores it and reuses when next time queried for it. Passing the the service itself *would be* the **correct way**. But, when implementing a complete application (not a "hello world" example), that would require a use of Dependency Injection Container. And implementing DI Container is a lot harder then a factory for services. For some perspective on the subject, I would recommend [this](http://www.youtube.com/watch?v=RlfLCWKxHJ0) and [this](http://www.youtube.com/watch?v=-FRm3VPhseI) lecture. – tereško Feb 24 '14 at 09:24
  • @tereško That made a lot of sense. So in this case, the `ServiceFactory` is sort of a warehouse for different services, and not just a simple `return new xService;` class? – tgun926 Feb 24 '14 at 09:34
  • 1
    @tgun926 , yes. In the simplest implementation, it could looks something like in code example, here: http://stackoverflow.com/a/15959396/727208 ... thought in a real-world situation it will be a bit more complicated. **On a different note:**, when working with OOP adherent code, you will notice that it is better to use namespaces `Services\Authentication` instead of `AuthenticationService` suffixes. Makes for easier autoloading. – tereško Feb 24 '14 at 09:52
9

You can really put anything in a view that you'd like, but to better adhere to the MVC way of doing things you should restrict PHP in the view to simple echos or prints (possibly really small loops as well, although even those can be pre-calculated in the controller/model). Since that is the only way to get dynamic content, it would be a little silly to say that they are not allowed.

The idea of the view is to let it have a more HTML look-and-feel, so that front-end developers or people who don't know PHP can easily be able to work with the file without getting confused.

Update

To learn more about MVC in general, you can see any of these (there's a ton of tutorials out there):

http://blog.iandavis.com/2008/12/09/what-are-the-benefits-of-mvc/

http://php-html.net/tutorials/model-view-controller-in-php/

http://www.tonymarston.net/php-mysql/model-view-controller.html

To see concrete examples of PHP using MVC, I suggest downloading some of the more prevelant frameworks (such as CodeIgniter, Symfony or Drupal) and just looking through the code. Try to figure out how it works and then recreate the functionality for a simple article-based system.

Jeff Lambert
  • 24,395
  • 4
  • 69
  • 96
  • is mvc worthy to use when all developer have got gud knowledge of php ? – NullPoiиteя Jul 27 '12 at 13:56
  • 2
    of course. It's all about separation of concerns, because neither you nor anybody else knows whats going to happen in the future (you may loose people on your project or decide it's cheaper to higher someone who only knows HTML). Also, the architecture lends itself to increased security by strictly allowing only certain information to make it to the presentation layer. – Jeff Lambert Jul 27 '12 at 13:58
  • 1
    How would the controller / model pre-calculate loops without violating [SRP](http://en.wikipedia.org/wiki/Single_responsibility_principle) in a way the view can use it? – PeeHaa Jul 27 '12 at 14:00
  • @PeeHaa I said they could, I didn't say they should :) – Jeff Lambert Jul 27 '12 at 14:02
  • +1 for you explanation. would you mind give me any link to learn how to use mvc in depth i have got the basic mvc knowledge and good php with oops – NullPoiиteя Jul 27 '12 at 14:02
  • 2
    @Mayankswami Whatever you do don't use Codeingiter as guideline if you want to learn the right way. You may want to look at [Symfony2](https://github.com/symfony/symfony/) it is one of the better (less bad) ones out there. – PeeHaa Jul 27 '12 at 14:13
  • 2
    -1 for suggesting such awful pieces of code as codeigniter and drupal. And linking to tutorials which misrepresent MVC pattern. – tereško Jul 27 '12 at 14:22
  • 1
    @Mayankswami also a word of advice, watch out for fanboys and purists out there. – Jeff Lambert Jul 27 '12 at 14:42
  • 3
    Also, why did you link to the Symfony 1.x site? Lemme guess, you had heard that "symfony is quite ok" from developers, but were not aware of how different the 1.x and 2.x versions are. – tereško Jul 27 '12 at 15:49
  • @JeffLambert Since you answered this question so eloquently, for 300 points could you take a look at my centralized `index.php` and `Router` class and post an answer? I promise to give it full consideration. http://stackoverflow.com/questions/42172228/is-this-how-an-mvc-router-class-typically-works By the way, I agree about using variables in the view, but I make sure there are never any loops. – Anthony Rutledge Feb 14 '17 at 15:29