An alternative approach to MVC

Recently I’ve developed a couple of smaller web applications using an alternative approach to MVC. I’d like to describe it to you and get some opinions on it.

Models:

  • All business logic, including filtering and validating, inserting and fetching data from database/webservices/whatever is handled by model classes. Each class is pretty straight forward and there’s no mapping a model class to a table or something like that. Just an appropriate named class with methods like add($post), delete($id), get($id) or getByName($name)…

Controllers:

  • Each controller action is a file. I might create a folder named articles, and in it put files named index.php, add.php and edit.php

Views:

  • The views, belive it or not, is in the same files as the controller actions (procedural approach). More explanation on that later.

I see an application as consisting of two main parts: The reusable components, and the specific usage and implementation of these reusable components. You can’t make an application of only reusable code. You have to get specific at some point. And that code which orchestra all your reusables into something specific, that’s the code you need to implement for every application you create.

So I see each controller action file as a construction site where I orchestra reusables into something usable and specific. And I don’t think it’s a problem that this code is procedural, because there won’t be that much of it and all of it belongs to the same scope.

The models are created with unit-testing in mind, and use dependency injection (which you can google if you don’t know what it is. Misko Hevery has some nice articles about it). In order to create a new instance of a model class, I use a static factory class, which will create a new instance and inject all the dependencies before returning the instance to me so that I can start using it right away.

Ok, time for a code example:
articles/add.php:


require '../includes/prepend.inc.php'; //The environment (baseController, initializer, or whatever you whish to call it

$form = new Form();
if (isset($_POST['save'])) {
  try {
      Factory::model('Articles')->add($_POST);
      redirect('index.php', _('The article was added'));
  } catch (ValidationException $e) {
      $form->populate($_POST);
      $form->setErrors($e->getErrors());
  }
}

Page::head(_('Add Article')); //Will print the header with title Add Article

echo '<h1>' . _('Add Article') . '</h1>';

echo '<form action="" method="post">';
  echo $form->label('title', _('Title:'));
  echo $form->text('title');

  echo $form->label('content', _('Content: '));
  echo $form->textarea('content');

  echo $form->submit('save', _('Add!'));
echo '</form>';

Page::foot();

In my experience, the views often become full of php when dealing with forms, translation and different kind of condtions. So then I might as well just implement them using reusable objects instead.

Pros with this approach (as I see it):

  • Lightweight, fast loading pages
  • Seperation of concerns is still used
  • Object oriented programming is still used (although you might argue that these are just static functions wrapped in a class)
  • Will just work on all kinds of servers (not having to mess around with mod_rewrite)
  • Easy to follow what’s going on

Cons:

  • Cannot be used when you want dynamic urls (like mapping a non-existent url to some content in a database)

I know it’s not perfect, but I like it a lot. It’s not all that object oriented either; doesn’t use much object composition, and lots of static functions are used.

Exceptions can be catched globally using the set_exception_handler.

What do you think?

What you describe is MVC. It is not, however, a front controller. You are describing the page controller pattern. It works just fine, although it can be a bit harder to reuse code across the application.

Surely you can. Just set up some mod_rewrite rules.

Ah, so it’s actually a pattern. I didn’t now that :slight_smile:

I wonder why nobody seems to be using it for newer projects these days. It seems like they all do the front-controller version of MVC. The typical page-controller applications I’ve seen will mix html, business logic and sql in one big page, which gets kinda messy.

This is how I use MVC, it may not necessaryily be correct but it does me:

Model (Queries) should be kept to a an object with the database object aggreated to it via the constructor. Each query returns its results to the controller of view which called it. The model objects don’t contain any “business logic” or presentational stuff (nothing like css, html, etc)

Controller: Each controller is an object, where the controllers need a model object, they create a new instance of the relevant model objects. The controllers contain the “business logic”. They return what is to be displayed to the view objects.

View: Each view is an object, with related sub-pages grouped into the same object. The views create new instances of the model and controller objects as need (the use of model objects directly by the view objects limited). The use of processing limited to for example messages "if no messages returned display “You have no messages” else display all the returned messages.

Page View: Looks at the url and loads the appropriate view object.

Page Controller: Looks at the action being sent via POST (the exception being of searchs via GET) and loads the approopate controller to execute that action.

The front controller style works more natural with an OOP setup (Eg. controllers are objects), where the page controller style lends itself to writing controllers as procedural scripts. Given that OOP is generally accepted as being a better paradigm to use, that probably explains a lot. That said, there are certainly people who use a page controller style. See Rasmus Lerdorf’s infamous no-framework-rant for example.

IMHO - front controller offers much more flexibility with regard to routing rules. If you choose page controllers, you must put eventual rules into .htaccess …

The front controller style works more natural with an OOP setup (Eg. controllers are objects), where the page controller style lends itself to writing controllers as procedural scripts. Given that OOP is generally accepted as being a better paradigm to use, that probably explains a lot. That said, there are certainly people who use a page controller style. See Rasmus Lerdorf’s infamous no-framework-rant for example.

Yes I’ve noticed that when using the front controller pattern it’s possible to make everything an object (as opposed to static classes). Page controller tends to require more functions and static objects (unless you pollute the global scope with lots of object variables). And the possibilites for dependency injection increases too.

However, you end up with a lot of classes; router, frontcontroller, basecontroller, views, request, response… just look at Zend Framework, there’s a lot of classes involved in routing and compiling the request and response. Now if you don’t use the front controller pattern, all of these classes seems to disappear, and apache or whatever webserver does most of it for you. So what’s to gain with all these extra classes?

The only benefit I can think of at the moment is to encapsulate the $_POST array and other super globals in case PHP should decide to deprecate them or change them. And depencency injection of course, but you wouldn’t run unit-tests on your controller actions, would you?

IMHO - front controller offers much more flexibility with regard to routing rules. If you choose page controllers, you must put eventual rules into .htaccess …

Could you give an example?

To be honest, I often end up cutting that because of time constraints, but it’s certainly something you can do, and some people do it a lot. It’s normally known as functional tests.

This is probably one of the main problems with a page controller style, although you can stub out the global side effects to remedy this. Another problem is code reuse. You can’t use inheritance in a procedural environment, and there is no natural place to put shared code. It’s not show-stoppers, but it does give an object oriented approach some benefits.

Yes, functional tests. I usually do them by clicking around to see if everything is working :slight_smile:

I’m still quite undecided on whether I think it’s best with page or front controller. Probably they both have their pros and cons but none of them perfect :slight_smile:

IMO, I think once you go Front, you never go back (ie: Page Controller). :stuck_out_tongue:

It is the natural progression which you will inevitably make, might as well save yourself time and trouble and move forward with a front controller.

You can save yourself more trouble by using Zend’s implementation, as there are surely to be caveats which are not overly obvious to a first time implementor.

My first dozen front controller implementations missed out on action forwarding, eventually I just called actions directly then realized the benefit to a true forwarding implementation.

Cheers,
Alex

Thing is, I’ve already used the Front Controller style in several projects, including the front controller in Zend Framework. But I’m still not convinced :slight_smile:

It always gets kinda messy when I do it. But perhaps that’s me not understanding things too well…

It always gets kinda messy when I do it. But perhaps that’s me not understanding things too well…

Well I tend to think, page controller approach is what every developer starts with as it’s the most intuitive, but quickly gets messy and complicated and thus forces you to eventually come to a front controller approach.

You might have 6 scripts initially each acting as a page controller, and sooner than later that explodes into 25 scripts. You then begin to partition those scripts into ‘action’ and ‘view’ scripts to distinguish those designed to deliver content and those just to carry out actions and redirect as required.

You start throwing common code into shared include files (DB.conn.php, etc) and things get a little cleaner but there is still tremendous duplication, etc. Many developers usually start with a single index.php and use a switch statement to centralize all requests. But internally each ‘case’ statement is the code from each action/view scripts. Those eventually get moved out into distinct files and sometimes become classes (for the more OOP approach).

Page controller is a fine approach but front controller will provide many advantages when you start building larger more robust applications. In fact, the technical benefits start the minute you have more than one action. What issues have you experienced specifically, which you feel were not assisted by front over page controller? Some examples might help everyone better underrstand :slight_smile:

Cheers,
Alex

At work, we implemented the Zend Frontcontroller in a project, and soon after, our boss said that we can’t use mod_rewrite because of some security issues. So we implemented a custom router which uses get parameters (module, controller, action). And since I thought we might want to use the index.php/model/controller/action method and maybe even go back to mod_rewrite later, or maybe change the key names for the get paramters, I created an url class for transparently handling the different types of url. So now we have to use this class for creating urls everywhere, including in javascript methods.

Think about how a form with method=get works. It submits to a given url and adds the form’s data to the url. Now if your page to submit to is identified via get parameters, you’ll have to add them as form elements. Except if you use one of the two other methods (mod_rewrite and pathinfo).

How does one detect if the system is using mod_rewrite and it’s working properly? What if one day some of the non-programmers in the IT department need to move the application to an IIS server?

All the views and some other files are a security risk if they’re not placed outside the document root, because you can view their content in a browser. My boss said that all of the files must be in the public directory, as it was a security issue to have PHP be able to access files outside the webroot.

Method names are usually camelCased, while urls are usually all lowercase with - or _ as seperators for words. This means you have to create some kind of logic to translate back and forth. And if you ask the Zend action controller for which action was called, what do you get? camelCased or the url version?

Redirects become like this: $this->redirect(Url::create(array(‘action’ => ‘index’))); Instead of: redirect(‘index.php’). And Zend’s built in _redirect method messes up the url if you provide your own base url, so you get the base url twice.

mod_rewrite adds overhead to every request because apache needs to re-route and start over each time a rewrite rule kicks in (unless you write your rules in httpd.conf instead of .htaccess). You also have to parse the url and create a frontcontroller and action controller instance and validate if the action controller exists and validate if the action exists and that it’s a method you’re allowed to call as a page.

Relative urls don’t work (redirect(‘…/articles/’)).

$_SERVER[‘SCRIPT_FILENAME’] makes no sense when trying to figure out which menuitem to highlight.

The page you requested doesn’t route to the correct action. What went wrong? Has someone disabled mod_rewrite? Has the application been copied from somewhere and the .htaccess file got lost in transition? Is the url parser not working correctly? Is there something wrong with the rewrite rules? The dispatcher? Am I missing the FollowSymlinks option? Is the controller directory set correctly? Is the view file missing? So many possible sources of error…

Anyway, I’ve had so many problems (side effects of bypassing apache’s number one feature: mapping url’s to files) with this. Almost everything seems so much more natural when using the page controller style. It just works. And you can throw away lots of code too, like the router, the dispatcher logic and the view class. I just include a script which sets up the environment before every page (a one-liner :slight_smile: ) and I can do whatever I want, be it just fetching something from the model and outputting it as json, or create a page with the template, or maybe output some csv document or something.

Just a thought, but using your approach it’s basically impossible to combine two different forms on a page, because both would check for $_POST[‘save’], so both would “think” they are submitted when only one of them is.

Of course you could implement something like $POST['save{model-name}'] to overcome this.

As to your approach, I’m not a fan of the Page Controller pattern, I like the front controller pattern better.

Also not a fan of dependency injection. It’s all happening “behind the screen” and I personally think I would loose overview of what’s going on exactly, and how every class instance gets its dependencies.

I like it more when a class has to get the dependencies it needs for itself, so I can see in the class itself what dependencies it has and how it gets those, instead of letting them be injected “from the outside world”.
For example in Yii the database is set in an ActiveRecord (Model) instance by calling Yii::app()->getDb().

Note that this is just my opinion, feel free to disagree :slight_smile:

I don’t see what’s different between using a page controller and a front controller here?

my comment on multiple forms was independent from the underlying pattern.

Just a thought, but using your approach it’s basically impossible to combine two different forms on a page, because both would check for $_POST[‘save’], so both would “think” they are submitted when only one of them is.

The “save” comes from the submit-button’s name attribute, and it can be changed to whatever you want. So if I’m not misunderstanding what you mean, it’s perfectly possible to have multiple forms on one page. One can even have multiple submit-buttons on each form.

Plus eventually they want “actions” on each page and that inevitably leads to a 5,000 line switch statement, with all business logic and designs being inside the case blocks, lol. Funny how its easier to discuss what NOT to do.

I think some of you guys need to use a real forms library, MVC library, etc… But thats just my opinion. You should at least be open minded to the possibility that you are re-inventing the wheel and wasting your time (directed @ OP not you PCspectra)

Post #13 just shows me that you’re waaaay over complicating it. With Zend_Form you can compose together “pieces” of forms and it handles nuisances like passing the request data around in arrays for you, and validating that data. Much more “orthogonal”. Coupling yourself directly to the request array (can) lead to ad-hoc solutions.

Anything easy seems natural at first because it is easy. But that easyness may have a cost that accumulates more heavily each time it is repeated.

“I can do whatever I want” is actually a key point to this, working on your own you follow your own personal standards on how something is implemented and a form of standardisation is formed by this which you are happy with. Throw more people into the equation things start to get more tricky, more rules have to put down what should be done and where as it is fundementally a coding free for all. The code will greatly vary on which developer wrote it and their understanding of structured programming.

Front page controllers can help with conformity, a pattern is laid down on how a new page should be implemented, what can be done and where. How a framework is implemented is as much about having code enfore coding guidelines using a sandbox and documentating this as about enabling functionality. Much the same with template engines( eg. how much processing logic should be allowed in the template ), too much means half the time it will end up in the PHP and the other half the time in template. My own belief is no logic should be allowed in the template as that stops it being a game of flipping a coin on what file to open to change conditional visual behaviour.

On bigger systems all what has to be be remembered is what conforms and what doesn’t. The more conformity the less mental resources are needed to work with it and the larger that system can grow and be maintanable. One deviation in an area of behavioural conformity cast complete doubt on that part in the rest of the system nullifying any benefit. HAving 30 pages can mean it is now 30 times more mental effort to keep organised just because that one thing on one page, it is also far more natural to have more trust if you have a large personal input versus a heavily shared one.

I think that a heavy singular perspective in software development is not the best footing to make design decisions, things get ugly when too many people have that perspective and have to work with each others code. You can only build so much on your own and bigger things have some very interesting challenges and their own set of problems. I used to have a more singular perspective before I managed people and had to clean up after them, I would say some of the stuff they created was pretty perverse which is why I understand now why sandboxes are put into place by design. That or cut fingers off, pretty tempting. Probably do it if they grew back and it was legal :wink:

Well that is part of the framework design and their implementation of the controller. Should it even be known? Dependent logic is now in two places, possibly that logical divergence should be handled by polymorphism. I don’t work with Zend as we use a custom framework from before Zend so I do not know of it’s limitations/religion, but to me any time a consistent workflow decision(such as action) has been made making other things duplicate that decision on a later layer just possibly shows a lack of design. Everything is known on page entry so what decisions will be always made can be made, having an include file works fine until 1/2 the pages need a second and then a quarter a third. Using page controller versus your own very basic form of Front Controller just makes it harder to keep things consolidated due to includes etc being duplicated all over the place.

After a while page controller just causes maintenance over head offering very little benefit, everything is known on page entry why need more than one entrance? What benefit is there copying the same thing to seperate files? By having that include file you already know the minimal point of divergance, switching to a front controller that deviates from that point offers no more restriction. Just more commitment to what you have been doing and new areas of learning as you make your own ( I actually don’t mind this too much though some might classify it as Not Invented Here Syndrome. It helps relate to existing ones and why those decisions were made and what problems they solved at the expense of other problems, which is what design decisions are all about ).

Or they become if you want to use it statically Url::createHome(). Whether it is mod written, will be mod rewritten etc. is completely not important to whatever is calling it. It is not it’s responsibility to know. Both of your described ideas, even though are heavily common, are as completely inflexible as one another. Want to make urls mod rewritten/not mod rewritten open one file and change that. Nothing except the parsing engine on the way back in ever has to know or care whether is ever was.

Not sure if over head, especially pretty minimal over head should ever be a point of issue that effects design.

Having this done in a uniform manner, especially with validation, what is allowed to be called by and who is very important logic to collate and remember. It always being at the same relative point has a lot of worth, spreading it out over many files in different points just makes it harder.

The more wasteful divergence in any system the more problematic things get as it gets bigger. Design is as much about deciding what should not be allowed as anything, once a bit of code is written it should be analysed and consideration has to be given to what the next person may do if they need to work in that code or with that code. Have you left an invitation to write bad code? How will you deal with them if they do? I don’t want to spend my life rummaging and cleaning up bad code from others due to the bad design decisions I have made or the thought laziness I allowed myself. Brain lazyness and typing lazyness are two different things. It is pretty common that brain lazyness is preferred over typing laziness, typing can feel really good as things are appear to be getting done.

Just a problem you need to solve, though overly greedy rule engines eating too much are a pain especially without good file system regulation. Just an organisational challenge, though I admit I do like the over greedy things as I have a networking/systems background as well. Having problems attackig it one way, attack it from a completely different way even if it is more effort at first before refinement ( Ie create a rule set for each action manually ). If people upload stuff to the server designate areas they can upload to that you will never use as an action etc.

Just out of curiosity as it really relies on imagination and personal tolerance I have some questions.
How big a project could you achieve like this on your own?
How many of those projects could you manage concurrently, and how long could you do it for?

There are always limits and how everyone works imposes imposes a limit before it becomes a physical actuality. I always ask myself those questions and in more pressured environments it is very handy with managing pressure.

It is also a set of questions that I don’t think gets asked enough. And working in a large code base that 20-30 other people have before you gives a lot of common behavioural tells of how smells can get in. There is a lot of ‘Me’ involved even if me is part of team.

Anyway a front controller doesn’t mean the code is necessarily better, just it’s real hidden ugliness( all systems have it ) is probably more visible and targetable/refactorable.

You can use Page Controllers and still do MVC
“The views, belive it or not, is in the same files as the controller actions”
This is what made the OPs solution “Not MVC”.

Respectfully disagree. ALthough he seems to know what MVC is he implemented it wrong. I can’t take his “view” and use it in another application. I can’t take his application and write a new view for it either.

Front Controller and MVC are completely different topics. If all logics are bundled in one file there is little or no re-use going on. Especially if it not scoped at least at the sub-routine level. Even then you are limiting yourself. It’s not MVC, its just 1 tier. Just really clean good 1-tier.

I think with any discussion like this it comes down to procedural vs OOP. mod_rewrite is always going to be best for small “dog grooming” sites. having a routing component in your MVC stack will always be better for translating URLs, and ensuring you never get broken links when you’d like to change stuff.

Also REGEX provides no mechanism for re-use. PHP code is a more complete language. I always opt to put complex stuff in the most powerful language (ex PHP, not stored procedures… or in this case a MVC framework instead of apache rewrites). When you want to do starts taking more than 50 lines, experienced developers start breaking things out in methods. Inexperienced developers look at this and see no value in it. But it is indeed useful to be able to mix & match methods to make them work together cohesively… REGEX has no mechanism for inheritance so it is all copy & paste.

Ex with a proper MVC framework I can write

<a href=“<?=$this->url( array(), ‘foo’ ,true )?>”>foo</a>

Later on I can go edit the URL that gets generated. I don’t have to look thru all my code to change the links that I generate. Everything is just consistent & “integrated”. Pure ubiquity.

Let’s just put it this way. If I can’t take every “action” in your application and make them work as ajax, or on the command line… you’re doing it wrong. The controller should be your applications “API” so other applications can use it as a black box. By choosing to couple your API to apache you limit yourself in future technologies, either from using better web servers, or a completely different paradigm if needed (ex. a 1-800 number users can call to get a PBX interface into the application?). Thats where you run into problems with hard coding views, using includes, and not at least wrapping your controllers in a class with sub-routines.