PHP in Action Rotating Header Image

The one-line web framework

The core of your average web framework is a Front Controller. Front Controllers are commonly considered complex and esoteric. That’s a myth. I sometimes brag that I can construct a Front Controller in 15 minutes. Actually, it’s doesn’t take quite that long. In PHP, a Front Controller can be simplified to just one line of code:

call_user_func($_REQUEST['action']);

Warning: Do not use this in a real application.

There is one and only one good reason why you shouldn’t: it’s totally insecure. Except for that, it’s simple but perfectly viable. Your actions will be just plain functions, which is pretty simplistic and will be hard to handle if you build many of them. But it’s a huge improvement over the average PHP script with no systematic handling of the PHP request.

If you want to do something more like the frameworks such as Zend Framework, you want your actions as methods grouped into classes (called Controllers in ZF).

Now you need two lines. The following script demonstrates this:

// Pretend we have an HTTP request
$_REQUEST = array('controller' => 'Contacts', 'action' => 'edit');

// Front controller
$controller = new $_REQUEST['controller'];
call_user_func(array($controller,$_REQUEST['action']));

// The action controller class
class Contacts {
    function edit() {
        echo \"ok\n\";
    }
}

You can start with something like it (assuming that security has been taken care of) and add features as you need them.

In case you’re wondering how to what exactly the security issues are, the most obvious problem is the fact that any user can run any method in any class that is available to this script. The way to avoid that append or prepend some fixed string to the class and the method name. For instance, in Zend Framework, the action name edit will activate the method editAction().

Beyond that, the security problems are the usual ones. You need to filter input, And in general you should beware of $_REQUEST, since it can also contain cookie data.

Share/Save/Bookmark

20 Comments

  1. Manfred says:

    Not sure if this way is more secure. I define the urls within an array like this:

    $urls = array(
    ‘^/blog/’ => array(‘controller’=>’blogController’,'action’=>’indexAction’),
    ‘^/blog/page/’ => array(‘controller’=>’blogController’,'action’=>’pageAction’),
    )

    and the front controller then loops through that array and calls [call_user_func] the matching entry.

    Nice post! Thank you!

  2. Manfred, I am doing exactly that in my framework (http://www.pluf.org).

    The really nice part of doing so is that you have full control over the layout of your urls and this is something I like a lot. It is like Django (http://www.djangoproject.com/).

  3. Manfred, this is exactly what I am doing in my Pluf framework (http://www.pluf.org).

    The real advantage of such approach, in my case inspired by Django (http://www.djangoproject.com/) is that you have full control over the URLs in your pages.

  4. Manfred says:

    Hey Loïc, that’s amazing:

    Look my framework is inspired by django too:

    http://code.google.com/p/dschini/

    :) Best Regards

  5. Robert says:

    Exactly what I do! Comforting to see others doing that, it must mean that it’s not horribly wrong =p

  6. Mike says:

    Code that takes longer to explain the security problems than it does to describe the benefits makes me awfully wary.

  7. Donald says:

    Re: Mike I am glad you thought the same as I did.

  8. another random php dev says:

    dagfinn, for the most useless and dangerous php related post of the year!

    Additional points were rewarded for being able to mix bad practice and major security issues with the least amount of code.

    Let’s count the problems, shall we:
    1. Blatantly obvious security implications (at least a warning was provided)
    2. Usage of $_REQUEST (Because $_POST or $_GET is too hard?)
    3. Completely missing the point that the primary benefits of frameworks are to provide MVC separation of logic from ui and increase manageability of the code base.
    4.”The way to avoid that append or prepend some fixed string to the class and the method name” == lol
    5. No mention, whatsoever, of the fact that the only way to secure that (horrid) code is via whitelist. Instead, just a link to Shifflets post on input filtering.

    Thanks so much dagfinn, because there definitely weren’t enough ways for inexperienced php developers to shoot themselves in the foot when they google for code snippets.

  9. dagfinn says:

    “…mix bad practice and major security issues with the least amount of code. You, on the other hand, seem to mix the maximum amount of vitriol with the least amount of technical disagreement. Maybe there should be an award for that, too.

  10. Luke says:

    @another random php dev

    Yeah, if you look at the code sample it’s insecure and poor practice.

    But if you look at the code as demonstrating a way to think of a complex architectural pattern in very simple terms then I think the post is great.

    It tears down a typical MVC frameworks huge object-oriented walls and shows you essentially what a FC does.`

  11. dagfinn says:

    Exactly. I’m trying to explain the process rather than show the final result.

  12. Richard@Home says:

    … go about expanding this example to pass parameters into the the edit function?

    http://www.example.com?controller=foo&action=edit&id=2

    would map to

    class foo { function edit($id) {} }

    ?

  13. Jaimz says:

    I’d never do this, and in fact, I’d fire my developers if I caught them doing this. It’s not the easiest way, it’s not the best way, it’s not even an option in real production code.

    It is however the laziest way to do it.

    as for writing it in one line, that’s what you did. and you lived up to the subject of your post. However, I’d have to put a big yellow and black warning label on this article telling people that this is how to NOT make something like this.

    As for what “another random php dev” said, i agree with 1,2,4, and 5. but point #3.. well that’s dump to say that the main point of a framework is to prodive MVC. MVC is a programming pattern, not a benefit. I’ve made plenty of frameworks that don’t even have a front controller. Another random php dev, you seem a little too narrow minded to say things like that, get some experience then come back.

  14. dagfinn says:

    You’re welcome to disagree with me. Let me just make sure I’ve made myself clear about what I’m doing. This is an example of “the simplest thing that could possibly work” (http://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html)
    You start out with something dirt simple. Then you find out what’s lacking and add it. (Security is just the most obvious thing in this case.) If instead you start out with something that’s more complex than it needs to be, your code will stay more complex than it needs to be, unless you’re extremely good at–and committed to–removing bloat. And the wider security issue is that overly complex code gives bugs, including security bugs, a place to hide. Simplicity enables transparency.

  15. Jaydee says:

    Frankly, the only purpose that this post could serve is as a very very bad example. This can be harmful if picked up by the just-getting-started PHP developer, which could be a lot if this blog gets traffic from in-links.

  16. calenti says:

    Couldn’t you improve this by just defining the call_user_func function to perform the trimming and security/magic checks before determining where to reflect the request to?

    Can’t controller’s constructor/initializer perform the checks before exiting, and if it finds something it doesn’t like it just returns a “eat cheese, rugrat” static string?

  17. dagfinn says:

    I find it interesting that several people believe this blog post is dangerous. I may write another one on the implications. For now, let me try to comment briefly. The critcs’ hypothetical premise appears to be that there are hordes of novice PHP programmers that are liable to copy and paste a line of code while ignoring the warning in bold on the next line. But that’s not just inexperience, that’s (probably incurable) stupidity. Besides, at that level of ignorance, they would have no clue what a Front Controller is and would have no idea what to do with it. Also, the critics are not seeing the forest for the trees. There is no way to make secure web apps without actually *understanding* security. Contributing to that understanding is what really matters, and any article that discusses security is likely to do more good than harm.

  18. dagfinn says:

    @calenti: I’m not sure I understand what you mean, but I would want to do as many checks as possible before calling call_user_func.

  19. ErlangFTW says:

    Thanks for the interesting post, these ‘evangelists’ should read some php security groups/mlists before shouting ‘it’s the end of the world’ and completely missing the point… geez.. btw, MVC is so 90’s :)

  20. janogarcia says:

    Security concerns aside, this could be the “Hello world” equivalent for a Front Controller.

    I think this post blog post does more good than harm, demystifying and giving a simplified (though others will refer it as oversimplified) example of a Front Controller.

    Through simplification the author has been able to transmit the message in a clear and direct form, removing all the noise added by complementary, but *absolutely* required for production, code (validation, security…)

Leave a Reply