MVC in PHP: Is it considered a bad practice to have the model load additional classes it needs?

Hello,
I have recently returned to web development and became interested in the MVC pattern, so please have patience as there might be stupidity down the post… Bash freely, just please be constructive.

I don’t use any frameworks, just pure PHP. Recently I made my second attempt to implement MVC in a web app, and it follows this basics:
Model hold the heavy logic, View queries the Model for the data it needs and displays it (usually with templates), Controller is listening for requests with actions and translates those to methods on the model.
I believe I got this at least close to the way it should be…

Now here’s my question: I read lot of people saying that they use several models on one page, some mentioned using different models for accessing different database portions. Does this mean they include absolutely all the logic in the Model? To me it looks very logical to simply include the required classes in my models whenever needed, sort of like loading libraries whenever needed. And I was wondering, perhaps I am implementing MVC wrong?
Is this considered a bad practice, or is it a valid design pattern for MVC?

I will describe a scenario to better explain myself:
I have a class for DB handling (how original of me), and a Model for User Management by administrators. So the code would look like this (just consent code):

class UserModel{
    public function search($name, $l_name, $id){
        $db = new DB;
        $query = "...";
        $db->query("$query");
        ...
    }
}

Why would the User model contain all the DB mambojambo…?

I’ve been following a series of vids on Youtube which showed me that what I thought was MVC actually wasn’t. The 1st one in the series is linked below, i’ve watched most of the 11 now, for some things done in the series there may well be other equally valid and safe methods that you can use.

1 Like

Try not to think of it as the model, as if it were a single concrete class. Try to think of it as a layer, almost like an independent library, a set of classes to solve a particular problem domain. That set of classes would include entities/value objects that hold state and represent a concept such as “User” or “Post”. The set of classes would also include repository objects that serialize and unseralize entities from a persistent storage such as a database. The set of classes would even include validator objects, because ensuring that your entities hold valid data is part of solving the problem domain.

More or less.

The descriptions of MVC can vary quite a lot. A lot of the confusion is because MVC was originally a pattern for desktop software. But the problems and solutions for desktop software are a different beast than for server-side web software. The best we can do is adapt the principles of MVC for the Web.

Martin Fowler describes (Web) MVC like this:

The basic responsibilities of a Page Controller are:

  • Decode the URL and extract any form data to figure out all the data for the action.
  • Create and invoke any model objects to process the data. All relevant data from the HTML request should be passed to the model so that the model objects don’t need any connection to the HTML request.
  • Determine which view should display the result page and forward the model information to it.

And Paul Jones describes it like this:

User Agent sends a Request
Router/Dispatcher invokes Controller
Controller manages flow, invokes Model(s) that encapsulate domain
Controller assigns values to View template
Controller invokes View and sets into Response (with headers)

I’d also suggest reading From Flat PHP to Symfony2. I really like this article for learning MVC because it starts with plain old spaghetti PHP and takes you step-by-step through refactoring it into MVC.

Paul Jones is wrong

CONTROLLERS NEVER TOUCH TEMPLATES

The controller does not sit between the models and views. This is a very, very common misconception about the MVC pattern, and all it does is create busy box double coding where values are first loaded into the controller, then placed into the view. It really needs to stop.

The view layer is not just templates, it’s the code that manages them as well. Further, it is quite ok for views to query the model layer for data requisite for their display. The controller’s job is to insure the correct view has been loaded for the user’s request, and that the user meets the criteria necessary to have access to that view.

What distinguishes the model layer is it only answers questions. It never asks anything of the other two layers. It provides data on demand to the other layers but it doesn’t initiate contact with them.

The controller layer starts up the model layer, often fetches its routing map from the model and based on that loads the views required for the response and then sends the response back once the view has composed them. But there’s significant division of these tasks between several classes. A Dependency Injector has the business of loading classes, Page Controllers interpret user requests, Routers determine page controllers. There is no master “controller” class.

Views (not templates, and certainly not controllers despite the misconception) load data from models required to display whatever it is they are displaying. It’s the view classes that manage the template bindings to the data. A view class is not the same thing as a template or template engine (if you’re stupid enough to use one of those in PHP - but that’s a whole other rant).

One area of constant tripping is the instantiation of objects. This job goes to a Dependency Injection Controller, which is perhaps a framework’s most fundamental piece. These controllers abstract out the process of providing objects with their dependencies. These days they hash this out using PHP’s Reflection API and type hinting which allows objects to call out their needs in their __construct method. The configuration of this controller will determine if any given class is a singleton or not - if it is then it will pass a reference to that existing object to the newly started object, and if it isn’t a singleton it will start a new copy of the dependency for the new object.

A controller’s job in this setup isn’t as Paul incorrectly states “assign values to view template” - its job is to assign the models themselves to it. Views do not need and therefore should not know how to start new classes. However, they do know what models they need and will state those needs in their constructor. The Page Controller class that starts the view doesn’t and shouldn’t know what models the view needs, this is double coding and a waste. Instead the Dependency injector is the part of the control layer that provides the model to the view, and it does this according to the view’s construct arguments. The page controller itself has no role to play in this. Once the view starts it can ask its model for data.

This goes down the chain. Say the model class is for a table in the database. It will need a copy of the connection object to the database. Again, neither it nor the page controller know how to get this object, that’s on the dependency injector, and the dependency injector only knows to do this because of the model’s construct statement. The page controller may need the model for its own purposes, particularly to post data into it, but it doesn’t always need to do this. That’s why, unlike the model and view classes, it has a reference to the dependency injector itself and can arbitrarily request classes from the injector - something only classes in the control layer should be allowed to do.

The dependency injector is the lynchpin. An excellent one was written by Tom Butler who used to be a particularly vocal member of this board, though I haven’t seen him around lately…

That page goes into even more details on how dependency injection works.

So with all the above in mind, let’s re-examine program flow under MVC - the right way.

  1. Boot code loads the configuration, readies the Dependency Injection controller, and uses it to load the Router/Dispatcher.
  2. The router determines specific Page Controller required, loads it, and passes control to it. This may or may not involve invoking a specific method on the Page Controller, depending on the framework’s design.
  3. The Page Controller performs the actions of the request, particularly if its a post, and handles authentication and the like. If an error occurs the page controller for handling errors is loaded, otherwise the Page Controller loads the appropriate View.
  4. The View has its relevant models as part of its construct statement, so these will be provided to it by the Dependency Injection controller as it is created.
  5. The View queries its Models for the specific data needed to fulfill the user request provided to the view by the controller. It puts that data into the template and evals the template (or has a template engine parse it)
  6. The output of this step passes back to the controller, which hands it off to a response object.
  7. The response object sends the http headers and echos the response. Some frameworks may then pass program flow back to the dispatcher to handle caching and shutdown tasks before script termination, or the script may enter a wait state for the next user request if its designed for persistent connections.

The goal of any design pattern is to restrict and regulate the scope of each block of code’s responsibility, and how much each can talk to the others. Each layer has specific and limited lines of communication to the others in order to maintain testable code. However confusing these lines, as so often happens with MVC, or proceeding with an incomplete understanding of their intent can lead to redundant busy-box code which has the opposite effect of making the code harder to debug and more brittle to change.

Also keep in mind that, from a certain point of view, the PHP code is entirely a controller. The true model is the database engine. The view is the browser. Strictly speaking, the output of the PHP these days is also only a model - HTML documents are a model, CSS comprises the view by controlling the actual appearance and format of the data, and JavaScript are controllers in their own right that happen to execute client side. The server PHP provides pointers to the correct CSS and JS in the response, but it rarely actually loads them since they are static files. In some setups the PHP doesn’t even send HTML anymore, but instead sends a JSON object to allow JavaScript to compose the DOM. So PHP is in this case transforming the model data from one format to another and controlling the access to it. Currently the HTML structure has some control of the appearance of the data, but as CSS continues to evolve the structure of the HTML is becoming increasingly less significant to layout, particularly in browsers that support flex layouts that can reorder content blocks.

That said the divisions between areas of concern in a large PHP program remain useful so long as they are correctly understood and implemented.

And Martin Fowler too? Fowler always seemed to be Tom Butler’s go-to software engineer, yet not even Fowler backs Tom on this. When Fowler applies MVC to web, he tells us to do all the things that TomB always insisted were wrong.

The root problem is that MVC was originally a desktop pattern, and some of the solutions for desktop software just doesn’t make sense for server-side web software. For example, the original MVC says that the model should implement the observer pattern. The idea is, if you have multiple desktop windows open displaying the same data in different ways, then if you change the data in one window, the others should update themselves. The way that would work is, the window that was directly manipulated by the user would invoke changes on the model, and the model in turn would notify its observers (the other windows) of the changes.

But none of that will ever happen in a server-side web program. Web programs receive a single input, the HTTP request, and generate a single output, the HTTP response, then they’re done. It’s a client/server, request/response environment. If you tried to implement the original MVC word-for-word, then you’re going to end up doing some very weird stuff that doesn’t make any sense in a web program. And that’s the sort of problem I always thought Tom’s solutions suffered from. His stated goal was to implement the original MVC, so it shouldn’t be surprising that some of the solutions he came up with were just weird for a web program.

If we acknowledge that implementing the original MVC word-for-word in a server-side web program doesn’t make sense, then we can start talking about how best to adapt MVC for the web. The good news is that there seems to be broad agreement on how that adaptation should look. The components and relationships that Fowler described, that Jones described, that the major frameworks use… they’re all the same. It would probably be less confusing if we gave this adaptation a new name, but alas we still call it MVC.

1 Like

A small addition, not entire Web programs create/receive a single input/output, JavaScript based Applications are able to realize real MVC pattern since theyre running in a process, you have a JavaScript object which lasts as long as you dont refresh/leave the page(like a desktop app) using then websockets/ajax to external source you could even store data but javascript is really hard to manage for me(no interfaces to describe required methods nor typehints and the callbacks just everywhere… :smiley: just personal oppionion)

I didn’t specify Martin because his wording was in line with what I said and how I interpret the paradigm. He said, “Determine which view should display the result page and forward the model information to it.” The process of forwarding the model information can include the whole model.

When I say the view queries the model, I mean that it gets data from the model class in general requests - not by running direct queries. It’s up to the model to determine if it will pull data from the db or use the cache.

Tom and I have butted heads from time to time - I think I’ve butted heads with everyone at least once for better or worse. I’m not suggesting using a strict MVC pattern in PHP either, but there are some conceits of many of the adaptations that do not work well at all. One very frequent one is the controller having to act as a courier between the model and the view, resulting in any change to the model or view that involves that data to require editing the controller as well. For example, if you add a new field to a table that you intend to show the user the model will need to be edited to handle the field and the view to display it - that’s complicated enough - why drag the controller into the process by requiring it’s courier code to be adapted as well.

One in house software I had to work with years ago was so obtuse it required 5 changes to get a field to display - 1 for the template, 1 in the template engine, 1 in the view class, 1 in the model and 1 in the controller. It was rather insane.

Martin has always been an advocate of keeping classes and methods as small as they can possibly be - I distinctly remember him once quipping that no class should ever be more than 100 lines, and if it was it was trying to do too much. That’s a bit on the extreme side, but I understand the sentiment.

Also, the major frameworks I’ve used - Symphony 2 and Yii2 do not have the controller acting as a courier between the model and view in the manner I was protesting against above.

I don’t really like the idea of having models in the view unless it’s a restricted version of it only allowing pulling data and based on domain knowledge, not hard coded queries (i.e. $this->getMostActiveUsers() vs $this->users->findWhere(...)). Things get messy if you’re working on a large scale application where certain developers only work on the front-end and that’s it. What’s to stop them from littering views with business logic? Nothing, it happens a lot unless restrictions and guidelines are set beforehand.

Separations of concerns is a core foundation of anything object-oriented.

I think I see the confusion. When Jones says “values”, he doesn’t mean only primitives. You can still assign entity objects to the view, for example.

I don’t realy like the idea of having models in the view unless it’s a
restricted version of it only allowing pulling data and based on domain
knowledge, not hard coded queries (i.e. $this->getMostActiveUsers() vs $this->users->findWhere(…)).

Agreed. When I say the model object, I mean that with the presumption that it has methods where the model determines whether or not a query is running. Your second example is poor though, views often need to set a range on results in order to do pagination.

What’s to stop them from littering views with business logic? Nothing,
it happens a lot unless restrictions and guidelines are set beforehand.

The only real recourse there is to fire the offending dev if they keep doing it. It’s a fool’s errand to try to write a framework that will utterly prevent a developer from coding poorly. In the system I’m alluding to above nothing stops a dev from having a view request the injection container or the database connection in its constructor, but either of those should fail code review by peers on the project followed by a explanation as to why.

Further, there are edge cases and deadlines in the real world and on rare occasion sticking such a bit of logic in the view is the only way to meet the deadline. An accumulation of these sort of rushed, bad decisions is what makes up a technical debt. It takes discipline to insure a stopgap solution to meet a hard deadline doesn’t become a permanent one.

When I tried to find the ‘right’ method among them endless debate on MVC in PHP Tom Butler’s articles were really helpful, his approach where the view get’s it’s data from the model helped to understand things and get out of the misconception that the controller sits between the model and the view, and that the view is a mere template.

I decided to write without frameworks with built-in ‘MVC’ and it turned out to be a good decision, both experience-wise and in terms of flexibility.

If you choose to work from Tom’s guides, that’s fine, but I just want to make sure you do so with full awareness of how it relates to the rest of the web community. There seems to be broad agreement among prominent software engineers and major frameworks for how MVC should be implemented in server-side web programs. But, the way Tom does MVC is different from how the rest of the world does MVC. If you learn from Tom’s guides, then you won’t be learning industry accepted practices. You can view that as a positive or negative as you wish.

I understand this. I don’t consider it devine truth. You allways progress by learning.

Well PHP’s MVC, especially the so-called MVC used in popular frameworks like Zend, CakePHP, Symfony, are not the MVC as Martin Fowler originally described. In fact, it is PAC, or Presentation Abstraction Control, which differs significantly from what MVC is. Read this article on wikipedia and you will know the difference:

It’s worth mentioning that Fowler himself applied the principles of MVC to server-side web applications, and the architecture he came up with matches with popular frameworks like Zend, CakePHP, Symfony.

umm do you have source for this? My point was just a restatement from a post made by TomB, though I agree with him.

Patterns of Enterprise Application Architecture, by Martin Fowler

I even posted some screenshots from the ebook version for you once before.
http://www.sitepoint.com/community/t/designing-a-true-mvc-framework-how-feasible-is-this/37155/7?u=jeff_mott

I read this entire book myself already last year, and unfortunately I came out with the opposite viewpoint as yours. To me Fowler’s MVC is clearly different from popular PHP frameworks MVC, just like TomB described.

Can you be more specific about what parts gave you the opposite viewpoint? Chapters? Quotes? Diagrams?

Chapter 15, Web Presentation Patterns, is probably the most relevant here. In the first section in that chapter, he talks about MVC in a broad fashion: its history, how it relates to rich clients, to web presentations, to command-line interfaces, to remote APIs, and he talks about the principle separations.

Then in the next several sections, he talks about web presentations specifically. That’s where he has Page Controller, Front Controller, and Template View, for example. These are the patterns that match modern frameworks almost verbatim, and they often tell us the exact opposite of what TomB has always insisted on.

TomB always insisted that the controller doesn’t pick the view. Fowler seems to say the exact opposite.



TomB always insisted that the controller doesn’t query and forward model information to the view. Fowler seems to say the exact opposite.


TomB always insisted that the view isn’t just a template. Fowler seems to say the exact opposite.



And finally (the smoking gun?), from Chapter 4 Web Presentation:

This is exactly what the modern frameworks do, word for word.

Just posted today and very relevant to this discussion:

1 Like