Pragmatic PHP MVC

I recently completed an A-Level project in PHP. It went quite well, but I was still keen to improve on my design methodology. To a “weekend silicon warrior” this may seem unnecessary, but I assure you the bigger applications you write, the more consideration you’ll find yourself putting into the design to stop headaches later. Specifically I was interested in MVC programming, as I was really annoyed at the repetition of code involved in generating other views in my web-application (part of the A-Level project involved generating PDFs). So I’ve been hanging around Sitepoint’s PHP Application Design forum and reading various sites such as PHPPatterns trying to glean information.

Suffice to say a whole new vocabulary opened up to me. It was a bit daunting at first, but I wholeheartedly recommend learning at least some of it. The “pattern” names themselves are essentially just ways to easily identify abstract coding methodologies so everyone knows what they’re talking about. Basically this allows people to drop acronyms like “MVC” into normal conversation, even though it in itself isn’t anything, it being an idea composed of three coding practices:

Model: Where all your “business” logic is stored.

View: How the output of the model is displayed (going back to my little PDF generation problem).
Controller: The thing that glues the model and view together according to what the user wants.
Unfortunately definitions like that are always up for dispute and alteration/addition but essentially as long as you always keep in mind the goals behind code separation you can’t go wrong; as MVC is more a frame of mind than set-in-stone rules. It’s best to keep a strictly pragmatic view when deciding what’s best for your application: just because something looks cool doesn’t mean it will instantly benefit you. Going back to my PDF generation problem I wanted to use MVC so that I could:

Generate raw output from my business logic. (Database queries and things)

Give that to the appropriate view. (According to user request HTML or PDF)

Not repeat any business logic.

Which fits into the MVC paradigm nicely. Obviously if you had a relative simple PHP application, like a mailer, then you wouldn’t want to add all the extra MVC bother. A signature I saw somewhere on Sitepoint springs to mind, it was actually referring to XML, but to paraphrase regarding MVC:

I once had a problem, that you can read in a Web Hosting Hub review, so I decided to use MVC. Now I have two problems.

However now I tend to recommend you lean towards MVC as it simply means that your application will be more flexible if you did want to include another view/interface to your system. This can be especially useful in–surprise, surprise–web applications where you must keep up with the times to allow users to access your content in different ways, which we’ve seen with the advent of RSS etc.

Unfortunately things are rarely a simple case of decide and go with it, as I found out while hacking on the backend to my latest website project. The problem I had was to do with the way I was handling user authentication through sessions. Before reading on, I suggest you have a look at some notes on Front Controller implementation with PHP to fully understand my predicament. See also diagram on the right.
Diagram showing flow chart for the front controller

Basically I wanted something different from the Zend framework’s all requests being routed through one file approach (see comment) I wanted to split up the Front Controller into smaller chunks. My sentiments are summed up by a post to a Sitepoint thread regarding the subject. Summed up my gripes are:

Everything being routed through one file creates a dependency on that file, thus impairs the modularisation of code. For instance any project would have to also implement the Front Controller pattern for the code to be easily integrated into.

The Front Controller needs to know about every action the user could request, or otherwise it wouldn’t know what controller to dispatch.

Leading on to this, it means the Front Controller would require some sort of data set that maps actions to controller files. As PHP is intrinsically designed to initialize a fresh environment on every startup, this means that it will have to continually reload this data set, which would grow in size in proportion to the application making it potentially a bottleneck in the system.

You could solve this bottleneck by making some kind of include system, perhaps implementing a dynamic string concatenation system to get to your required controller, instead of a data set, but at the end you’re still left with the problem of code modularity. Incidentally this is what the Zend Framework does (see comment below) but other frameworks I am aware of don’t, and you’re left with the problems as aforementioned.

Diagram showing the Page Controller pattern

Those points are basically rehashing what was in that post. My “solution” to this problem was to use the Page Controller pattern. See the diagram left.

“The Page Controller has one input controller for each logical page of the Web site.”

However that approach generated some problems for me. The reason that the Front Controller is a popular pattern is that you can call Intercepting Filters. I was getting some problems without using them:

I was getting code duplication by having my Page Controller also deal with the whole process of authentication by in turn using more methods in the Model. Each additional Controller and Model page would also need all this code.

This in turn affected the Page Views, I needed to create views to send out all the authentication messages etc.

I even considered multiple inheritance (luckily not possible with PHP), since multiple inheritance usually suggests something’s going wrong…

However I managed to find a lovely piece of code that looks at Intercepting Filters in a very concise way. The use of chained methods is reminiscent of Linked Lists if you’ve ever done Computer Science (I haven’t, I’ve just read about them).

My current system uses Page Controllers with those Intercepting Filters, but instead of having the Intercepting Filter classes output anything, I instead just put a header redirect to a page more suited to dealing with the new task(s). For instance if a user needs to be authorized to access any particular page, the Intercepting Filter class checks, then if they’re not header-redirects them to the appropriate page (login.php).

When the system is all up and running in hopefully a month or so, I’ll post some code.