The Model-View-Controller pattern in PHP
Join the DZone community and get the full member experience.
Join For FreeThe Model-View-Controller architectural pattern, usually referred to with the MVC acronym, is the foundation of many web frameworks and in particular of the first generation of PHP-based ones. Let's explore some implementations and discover how much pure the PHP approach is in relation to the original idea and the standards from other languages.
MVC in theory
The MVC pattern applies at a large scale, and it influences the design of an entire application. MVC prescribes the separation of every feature of the application in horizontal slices, which should be implemented into three separate components, the Model, View, and Controller. Model, View and Controller are (ideally) loosely coupled and each one should encapsulate most of their concerns from the other two. Each of them usually contains multiple classes, and you can refer with the term Model (or View, or Controller) to a class contained in the referred component.
In the diagram on the right, you can see the relationships between classes from the different components. Solid lines are object references that imply a dependency, while dashed lines are reference to an element only as a generic Observer (also known as Listener). For example, the Views keep references to objects from the Model, while the Model is aware of the Views existence only in the form of a generic Observer interface, which should be notified after a change in state. In statically typed languages, this distinction is very important as it breaks compile-time dependencies; it is also semantically different from associations (solid lines) as the Model can live without any attached Observer, while the View cannot work without an underlying model.
The Model is the center of the applications: it contains the business logic and usually it's an object model of the domain. The User, Post, Forum classes are the classical example of a Model as they maintain the state of the application, but also stateless services and domain-related Value Objects are part of the model. Infrastructure such as a database access layer reside in the Model only with their interface, since actual implementations.
The View (or possibly the Views) is the visible user interface of the application, which provides a readable access to the Model and a mechanism for generation of events which modify the Model itself. In the classical implementations, the Views listen for events from the Model to update themselves, providing decoupling between business and presentation logic.
The Controller is the connection between the View and the Model: it handles the user actions propagating the events to the Model, which knows best how to modify its state. Controllers deal with the translation of user requests into objects recognized by the Model.
An example of the original MVC pattern, being it pure or not, is implemented in the Swing Java framework. Standard Model interfaces are implemented by the Domain Model, so that Views can compose them for a simple implementation of the presentation layer. The Swing infrastructure provides generic hook points for Controllers to gather events from the Views, and default Views implementations that listen to the Model for changes.
MVC in PHP
The PHP implementations of the MVC pattern are always adaptations of the Model, View and Controller component adapted to the web architecture. The MVC term is overloaded: MVC in web-based applications conforms to the same principles of the original one (separation of concerns for example), but it's different due to the client-server paradigm of HTTP.
Basically, it's impossible for the Views (if they are produced as plain html) to listen for changes to the model. Moreover, the execution of PHP scripts last only seconds, a constraint that forces a different approach in the standard MVC implementations as the object graph, which comprehends the Model and Controller components, is usually instantiated in part during every request, and destroyed after the request has been satisfied.
The Model component is constrained by some PHP frameworks to be attached to an underlying database or class hierarchy (which in my opinion is a huge intromission by the framework), or left free for any object-oriented implementation to be used. The downside of the latter choice is the higher amount of glue code needed for the other components - but it is much more powerful and easier to design with.
The Controller of PHP MVC applications is, as the name suggests, a layer of Front Controller and multiple Page Controllers. The typical developer only have to implement the Page Controllers, which build the html pages via wiring one or more View, and configure the Front Controller, which acts as a single entry point for every HTTP request and route the different user actions to the Page Controllers. Controllers are the servlets of PHP applications: they are the uppermost layer which handles requests to produce responses in the form of html, xml, or a result in any supported mime type. Even in Ajax-based applications, the client-server separation has to conform to the HTTP protocol, so Controllers are still the entry point for every user-generated event, always represented as HTTP requests. The preferred technique to implement controllers is to not scatter business logic in them (keeping it in the Model) if it's not related to infrastructure or orthogonal tasks such as authorization, authentication, and response format. This technique is known as Skinny Controller, Fat Model, and often produces a good Domain Model easy to test and to employ in controllers code.
Finally, in PHP the View layer can be implemented as a set of objects or template scripts, unlike the Model and Controller components usually composed of classes and interface. The views can in turn use PHP or some more sophisticated language to produce an output. In the big picture, they are always used by the controllers, which query (or update) the Model and pass the Views the necessary data that results from the computation. In the good old days of header.php and footer.php, applications were simply Views which performed all the work. Most of the frameworks keep PHP as the Views' underlying engine, but still factoring out business logic (in the Model) and infrastructure tasks (in the Controllers).
The dependencies between components do not change from the original MVC concept: the Model is the core object graph, free of dependencies; the Views depend at least implicitly on the Model, and the Controllers depend on both, passing messages between them.
Code samples
I did not include any code in this post as I do not want to tie a specific, naive implementation to this description, and it seems that every developer worth of this name has implemented an open source MVC framework, in a way that leaded to a proliferation of them. However, if you want to see MVC in action, you can refer to the good documentation contained in Zend Framework's manual:
Zend Framework's approach is often considered bloated but it is very flexible and I would keep it as a reference implementation, given its similarity to more mature web frameworks written in other programming languages. By the way, the MVC stack will be refactored in the 2.x release branch to simplify it for better performance and maintenance. Remember that in Zend Framework's vision, your Model is your business only: that's why there is no Zend_Model component like in other PHP frameworks. You can take advantage of infrastructure such as Zend_Db or Doctrine to solve common problems like persistence for your own Model. I like this versatile, database-agnostic approach: MVC is a pattern meant to separate classes in cohesive packages and break dependencies between them.Opinions expressed by DZone contributors are their own.
Comments