• Email this article Print this article

    PHP Done Right, part 1: Church and StateAugust 31, 2010

    This is part 1 of a series of PHP lessons learned through over a decade of development. Inspiration for the points we're presenting is taken from ProtoMan, our in-house Django-like PHP framework.

    PHP Done Right?

    Yep. While it's very easy to put <?php echo echo "Hello, World!"; ?> in a text file surrounded by HTML, it's a little harder to build a large-scale, maintainable site unless you know not just how to use the language, but how to use it efficiently.

    While that's certainly an oversimplification, PHP enables (and sometimes even encourages) a lot of things we'd just as soon not see. The first one we're going to address is the separation of presentation and logic -- that is, keeping as much PHP as possible/practical/feasible out of your templates.

    Why? Inline PHP works just as well.

    Technically... perhaps. Your server may incur a little overhead by having to process multiple files per request,* and your code can produce exactly the same results while taking a little less time to write when you drop it straight into your HTML, but the cost comes later -- when you need to upgrade, debug, re-skin, etc.

    Writing inline PHP will get you where you're going faster, but then, jumping out of a plane will get you to the airport faster than waiting for your flight to land. It's all about risk analysis.

    * This is easily mitigated with bytecode caching, but that's a topic for another post.

    OK, so you were rambling about various risks?

    Yes! We do that. Let's touch on them in a little more detail.

    • Upgrading. It's very common that you'll build a site for a client and find out that it's not what they wanted, want or will continue to want. When it comes time to change your code, you'll find that it's easier to change the HTML without working around large blocks of PHP, and it's easier to rewrite your logic when it's not wrapped in excessively verbose PHP tags and alternate embedded PHP syntax.
    • Debugging. As soon as you have to scan 500 lines of HTML template to find one if statement that has an operator typo, you'll probably start to agree that it'd be easier to debug the same code if it were 400 lines of template powered by 100 lines of clear, unobfuscated PHP.
    • Re-skinning. Unless your designer is perfect and can adjust absolutely any part of your project with a few tweaks to your CSS files (hope you didn't use inline styles), at some point you're likely to end up adding to or changing around the HTML that's actually rendered by your templates. Just like debugging embedded PHP, this becomes a bigger hassle when you're trying to tweak your HTML only to stumble over clusters of logic breaking up your presentation code.

    ASSUMING you're right... what do you suggest?

    Thank you for humoring us! Since we're leaving the question of procedural vs. object-oriented PHP for next time, we'll have a simple procedural example with a little input and a little output:

    // controller.php
    
    function example_view($confirmation)
    {
        $context = array();
    
        if ($confirmation == 'yes')
        {
            $context['confirmation'] = "Yep!";
        }
        else
        {
            $context['confirmation'] = "No, sorry.";
        }
    
        return $context;
    }
    
    if ($_GET['view'] == 'example')
    {
        $context = example_view($_GET['confirmation']);
    
        require_once('templates/example.php');
    }
    
    // templates/example.php
    
    <html>
        <body>
            Did you send "yes" to "confirmation" in your GET string?
            <?php echo $context['confirmation']; ?>
        </body>
    </html>
    

    See? It's not that bad. Granted, we wrote a little more code than we might've otherwise... however, note that this little bit of extra work enables a few very useful things:

    • Argument changes. We're not stuck with "yes" or "no," and we actually save time if we need to rewrite that conditional as a switch/case later on, as opposed to implementing it with lots of <?php ?> blocks.
    • Multiple views. We tested for $_GET['view'] in our controller; the implication here is that it's going to be handling more than one argument, i.e. multiple views. If we just used one HTML file with inline PHP, we'd effectively end up with multiple pages being served from one template, which could get hard to read and update very quickly if they're large pages.
    • Multiple templates. Since we're loading that template from our PHP, it's a trivial matter to put header and footer code into other templates and load them before and after our argument-selected body template, respectively.

    Well, that's at least worth considering.

    ...at least, that's the reaction we're hoping for.

    While this doesn't hit every reason to keep your logic out of your templates, we hope it's enough to show you that there are definitely tangible benefits to this approach. Making this a habit will actually clarify other advantages more effectively than reading about it in a blog, so try it out!

    Note: The implementation above is a very simple front controller, which is a common pattern for building human-readable URL's, particularly for PHP websites; mod_rewrite or something similar would generally be used to turn www.xyz.com/test/args into www.xyz.com/controller.php?test/args for parsing.

    blog comments powered by Disqus
   

Tweets From The Chair