Tutorial - PHP Templating - Braceless Syntax and Short Tags

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Tutorial - PHP Templating - Braceless Syntax and Short Tags

    This is a short tutorial on using braceless syntax and PHP short tags to produce elegant and easily readable PHP template files, as well as a short intro on how to use such templates in an MVC situation without relying on template engines such as patTemplates or Smarty. Only entry level PHP experience is expected here, nothing major.

    First, on Short Tags. PHP short tags are an optional part of the PHP engine that can be turned on or off in the PHP.ini file. For this reason most all PHP based software products don't use them. I do for the following reason - it is impossible to block access to short tags while blocking access to mod_rewrite. If you have the latter you will have the former. Short tags can be turned on in an .htaccess file with the first of the three commands below:

    PHP Code:
    # A recommended series of php settings.
        
    php_flag short_open_tag on 
        php_flag register_globals off
        php_flag magic_quotes_gpc off 
    Register globals is evil hacker friendly stuff - don't use it. Magic quotes is even more evil. By turning these off in our .htaccess file we can save a lot of misery in our php code.

    The short tags themselves look like this


    PHP Code:
    <html>
        <body>
            <?php echo 'this is a snippet of php code in the familiar tags' ?>
            <script type="php"> echo 'this snippet is in the rarely if ever used script tag (usually used for javascript only)' </script>
            <? echo 'This is a php short tag #1' ?>
            <?= 'This string will be echoed out too - short tag #2 for echoing stuff' ?>
        </body>
    </html>
    Note the missing semicolons. Semicolons are only necessary for multiple statements within a tag block. If the parser sees ?> after your statement it will treat that ?> as a line ending statement. You can put a semicolon in if you want though without incident.

    Braceless syntax works by putting a colon after the condition and an ending statement to close the group. They look like this


    PHP Code:
    <!-- A braceless if statement block -->
    <? if ( $a == $b): ?>
        <p><?= $a ?> equals <?= $b ?></p>
    <? elseif ( $a > $b): ?>
        <p><?= $a ?> is greater than <?= $b ?></p>
    <? else: ?>
        <p><?= $a ?> is less than <?= $b ?></p>
    <? endif ?>
        
    <!-- A braceless for in block -->
    <ul>
    <? for($a = 1; $a < 11; $a++): ?>
        <li>#<?= $a ?></li>
    <? endfor ?>
    </ul>
    And in similar manner endforeach closes foreach, endwhile and endswitch are also valid. This approach allows us to be free of brace hunting leading to clean templates like this error template out of my framework.

    <
    PHP Code:
    ? include($this->findTemplate('exceptionPageStart')) ?>
    <div id="page">
        <? if( PAMWF_DEBUG ): ?>
        <p style="font-weight: bold;"><?= $title ?> in file <?= $file ?> at line <?= $line ?>.</p>
        <h4>Message</h4>
        <p style="font-style: italic;"><?= $message ?></p>
        <h4>Stack Trace</h4>
        <p><?= $trace ?></p>
        <h4>Included Files</h4>
        <p><?= $includes ?></p>
        <? else: // Don't be chatty in production mode - just inform the user an error occured. ?>
        <p>We're sorry, but an internal server error occured.  A log has been made
        of this error and the administrators have been notified.</p>
        <? endif; ?>
    </div>
    <? include($this->findTemplate('exceptionPageEnd')) ?>
    The goal here is legibility and clarity. In PHP blocks that don't have any HTML interspersed braces are just fine (unless you're a fan of python but that's another issue entirely). When PHP and HTML heavily collide, as they must in templates, braces can get lost in the character shuffle, especially when statements become nested.

    Now, stick around this forum long enough and you'll see talk of the MVC design pattern and the importance of separating view from control and model. It is to this end that template engines in PHP were written, but those engines were written in defiance of the simple fact that PHP is itself a template engine. Even the lightest ones add a huge amount of overhead to the site code. Separation of logic is, in my opinion, a matter of programmer self discipline.

    PHP templates can be easily isolated off from the rest of your PHP code's variables by including them into a function like so

    PHP Code:
    <?php
    function parseTemplate$template ) {
        include( 
    $template );
    }
    ?>
    Of course the simple example above isn't too useful - your controller will need to give the template some output. The easiest way is to package everything you want to give the template into an array - then extract the array into the function namespace like so

    PHP Code:
    <?php
    function parseTemplate$template$output ) {
        
    extract($output);
        include( 
    $template );
    }
    ?>
    This still isn't as useful as it could be since we may not want to echo out our information right away. This is why PHP has output buffers built right in - again, no reason to use a template engine.

    PHP Code:
    <?php
    function parseTemplate$template$output ) {
        
    extract($output);
        
    ob_start();
            include( 
    $template );
        return 
    ob_get_clean();
    }
    ?>
    Finally you'll note in the view I gave above the appearance of $this. This is because my parseTemplate function is the member of the controller class, and $this refers to that class allowing me to read off values the controller has prepared. The inclusion of $this also guarantees a forcible error should any attempt be made to include and execute the view code outside the context of a class.

    Well, that's about it. Comments and discussion welcome and I'll answer what questions I can. Information provided in the hopes it will be useful and all that.
    BakGat
    Code:
    class Counter {
    public:
      void Count();
      int  ReadDisplay();
    private:
      int  CurrentCount;
    };








    Back up my hard drive? How do I put it in reverse?
    My Community
    BakGat
    sigpic
Working...
X