The M is for model, the V is for view, and the C is for controller. But what does it all mean?
MVC is best described as what is often known as a design pattern. A design pattern is best defined as a description of a reusable solution to a recurring problem given a particular context. Design patterns exist so that the challenges faced when designing large-scale applications may be approached in a consistent manner. Best practice can be achieved by tackling the architecture in a tried-and-tested manner.
In this case, the problem is how to best separate the user control of a program (the controller), its output (the view), and its inner processing and decision-making (the model) into a manner whereby they represent three distinct, separable components. The solution is, as you might have guessed, MVC. But why the need for this approach?
First, separation yields interchangeability. By keeping three components separate, yet having them talk to one other in a consistent manner, you can swap any component out should you need to. For example, if you need to rebuild your Web application to work on PDAs instead of Web browsers, you can swap out your View component for one that renders content especially for the PDA rather than the Web browser. If you need to accept data via voice input rather than mouse clicks, you can swap out your Controller component for one that uses VoiceXML.
Second, debugging to catch hard-to-trace bugs, as well as maintenance programming after release, are made immeasurably simpler if there is a separation of logic in sensible places. The rationale behind using object-oriented programming, detailed in the very first chapter of this book, also applies here. It's much better to have lots of small components that talk to each other than just a handful of huge, unwieldy files filled to the brim with code. A complex software architecture can be made a great deal simpler by separating components in this way.
Finally, you may wish to implement multiple controllers and views for your single-model application. To take our earlier example of PDAs, if you choose an MVC architecture, you can implement the necessary controllers and views to support traditional Web browsers, PDAs, cellular phones, voice, tablet PCs, and even legacy browsers, all of which will use the same model, even if they use different views and controllers. Without MVC, you'll find yourself unable to reuse the code behind the model, and you'll be burdened with all the problems associated with unnecessary duplication.
As you can see, MVC is a great design pattern and one that you should endeavor to use whenever possible. The following sections examine each of the three components in turn, how they interact with one another, and, most important, how MVC sits in the context of Web application architecture in PHP.
The model is the very heart of your application. Generally speaking, it refers to the suite of classes you have developed to handle the various processes involved in your application's behavior. It concerns itself with retrieving the data behind the output, as well as manipulating data as a result of user input. It also connects directly to both the controller and the view. The controller supplies the model with its instructions; the view manipulates the data retrieved from the controller into a human-usable output.
The view is at the user end of the application. It presents data from the model that the user has requested or information that the model considers that the user needs to know. The view also connects directly to the model. The model supplies data directly to the view for it to display in a manner appropriate to the display device in question. Arguably, the view also connects to the controller, in the sense that it provides the physical rendering of the necessary controls for input to be made to your application in the first place.
The controller represents the user's interface to your model. Generally, it offers the necessary input facilities that allow users to get data and requests for data into your application. The controller connects directly to the model, to which it supplies the data or request in question. The model then goes about fulfilling that request or storing that data as appropriate.
There is actually a fourth component to MVC the infrastructure. Put simply, the job of the infrastructure is to glue the model, view, and controller together. How this is accomplished varies enormously from language to language, but you'll learn how to handle it in PHP very shortly.
MVC is not a new concept. Indeed, it is considered by some to be the evolution of IPO (Input, Processing, Output), which was the best-practice model applied to the linear, text-only applications of yesteryear. The application of MVC in a Web context is relatively simple.
The model is represented by your suite of classes, assuming that you have followed an object-oriented approach in your application. In any Web language, these classes perform the core communication with any external data source, make critical application decisions, and perform parsing and processing on both input and output.
The view is represented by the Web browser, or rather what is displayed in it. Upon making a request, be it a simple request for a page or an instruction to update or query a database, the output determined by the model is actually displayed by the Web browser.
Perhaps confusingly, the controller is also represented by the Web browser or rather the user's actions within it. Whether just a series of links or a complex form, the GET and POST requests made by the user's browser represent the effort to get data into the model in the first place.
As discussed earlier, PHP's simplicity and accessibility can easily be abused to the point at which applications become unmaintainable. Specifically, this abuse takes the form of combining model, view, and controller into a single PHP script. In fact, the term script is appropriate only in such an approach. In a proper MVC application, there are no scripts, only components.
Ask any inexperienced PHP developer to create a guest book application and he or she will probably come up with a single file. The file would be called guestbook.php and would handle both displaying existing entries and adding new ones to the database. Stepping through the code, it might look something like this:
Look at the GET parameters passed to it to determine which page of the guest book to show.
If no page is specified, decide to show page 1.
See whether a parameter called NewGuestBookEntry has been passed. If so, check whether it conforms to various validity constraints (length and content) and enter it into the database. If not, write an error message and quit.
Get the current guest book entries from the database matching this page number.
Write them out in an HTML table (embedded right here in the script).
Write out the HTML form pointing to this same script, allowing the user to add an entry.
This approach has a number of problems, quite apart from using GET instead of POST to effect a change in a database (strictly speaking, the RFC in question says this is a bad idea).
If you think back to the reasons in favor of MVC, such as interchanging controllers and views, ease of maintenance and initial development, and multiple simultaneous controllers and views, you can see that in all three cases we encounter difficulties.
Instead, take a look at a more mature approach to development that allows you to follow the MVC design pattern.
The first rule of MVC in PHP is to split up your files. There are a number of possible approaches, but many favor taking the step of actually using different file extensions to represent different roles in the MVC pattern and then using require_once at the appropriate time to link them together.
The documented practice of naming files to be included or required with an extension .inc should not be followed. After all, it tells you nothing about the content of that file and thus encourages role overlap between files.
You may wish to try something like the following:
Behavioral logic the communications infrastructure between model, view, and controller
PHP Classes the heart of the application
The rendering of both the results of the user's input and the interface for the user to make further input
It may seem odd that we've combined the view and controller into just one file, but it does more closely match the physical separation we've described earlier. Because the user's Web browser handles both the interface (controller) and the display of data (view), it is not unreasonable for us to use a single file to provide both of these two corners of the MVC square.
If you are unsure as to what code should appear in which modules, you can rely on a few rules to ensure that you're following this methodology:
.php (control page) should never contain SQL queries or HTML.
.phpm (classes) should never contain HTML.
.phtml (templates) should never contain SQL queries, and only very basic PHP (for/if/ while).
What you are accomplishing in this separation is a very primitive form of templating known as native templating. In such a setup, PHP is used to render the output of the application in a separate template file (in this case, the .phtml file). That output is decided upon by presentation of the user's input by the logic file (the .php file) to the classes (the .phpm files).
This is implemented in practice as follows:
The .php file is the actual recipient of the GET or POST request (hence, there is no need to reconfigure Apache to support these new extensions).
The .php file is home to all require() statements needed to import the necessary classes (with each class stored in a .phpm file).
The .php file examines the input in GET and POST parameters and determines a course of action. It passes that data (either in a raw or processed form) into methods of these classes that have been made available to it through inclusion in the previous step.
The classes in question parse the input data, update and query databases or other data sources as necessary, and return data to the .php file.
The .php file then examines the output from those classes. It may make decisions based on that output, deliver the output in some processed state, or simply deliver it as is. The delivery is always, however, performed through the construction of a single supervariable (usually a hash) that contains, unformatted, the output we wish to display to the user.
The .php file then includes the appropriate .phtml file, which effectively takes over execution.
The .phtml file recurses that supervariable, displaying it in whatever form is appropriate and rendering whatever new user input components are required, such that the user is presented with the finished Web page.
This may sound more complex than it actually is; in fact, it is a remarkably simple process. You'll get to see some examples later in the chapter about how this native templating is best implemented. For now, you'll take a look at a few toolkit classes that can help you in the quest to use an MVC design pattern in PHP by vastly simplifying some of the steps set out previously.
Later, you'll learn how this toolkit integrates neatly with the native templating techniques just discussed.