Quitting Smarty to do it manually

大城市里の小女人 提交于 2019-12-01 15:15:14

Another way could be to do something like this. I feel like this is probably closer to what a template engine ends up with, but with using the {block} syntax instead.

index.php

<?php
$blocks = array();
function add_block($name, $callback){
    global $blocks;
    ob_start();
    $callback();
    $output = ob_get_flush();
    $blocks[$name] = $output;
}

function get_block($name){
    global $blocks;
    if(!empty($blocks[$name])){
        return $blocks[$name];
    }
    return '';
}

//stop any errors from being output. 
ob_start();

//include the page code
include 'page.php';
$cleanup = ob_end_clean();

//now output the template
include 'template.php';

page.php

<?php

add_block('head', function(){
    ?><script type="text/javascript">/* Some JS */</script><?php
});

add_block('body', function(){
    ?><p>Some body text goes here</p><?php
});

template.php

<html>
    <head>
        <title>Site Title</title>
        <?php echo get_block('head'); ?>
    </head>
    <body>
        <?php echo get_block('body'); ?>
    </body>
    <?php echo get_block('after_body'); ?>
</html>

I'm not sure how smarty does it and have actually never used a templating engine myself. But maybe this could be how it's done.

Say we have:

index.php
page.php
template.php

When we go to index.php it could start and output buffer and include page.php. After the include catch the output buffer and use some regular expressions to match and blocks found within it and put them into variables.

Now do the same for the template.php and find all the blocks in there too and replace the blocks with the blocks found in page.php.

I don't actually think that's how templating engines do it. But that's one possible way.

A very tiny self made, templating engine based on regex replace using an array hook to "manually" parse templates

(but i grant you, smarty is more functional) To any question, feel free to answer me here

The regex match whole file's term like {term-_}, and replace it by a php condition who will be executed on at rendering time.

if a mark" doesn't found in $vars, it will simply replaced by an empty string

Engine

function parse($vars, $tpl)
{
    return preg_replace
    (
        '#\{([a-z0-9\-_]*?)\}#Ssie',
        '( ( isset($vars[\'\1\']) )
            ? $vars[\'\1\']
            : \'\'
        );',
        file_get_contents(TEMPLATE_DIR.$tpl)
    );
}

part of index

     <html>
          <head>...</head>
          {body}
     </html>

part of body

    <body>
         <div class='ui'>{username}</div>
    </body>

Usage

    <?php
    // include engine function
    define("TEMPLATE_DIR", __DIR__."templates/");
    require_once("library/parse.php");

    // just init $vars on top of index
    $vars = [];

    // and access and fill it anywhere
    $vars = ["username" => $_SESSION["user"]];

    // prepare the body including previous $vars declarations
    $vars["body"] = parse($vars, 'body');

    echo parse($vars, 'index');

Output

    <html>
         <head>...</head>
         <body>
             <div class='ui'>Stack Overflow :)</div>
         </body>
    </html>

You can improve it by using constant and prevent double wrap marker {{}} or more, or placing debug trace...

Add this to start of engine to prevent templates containing object bracket can be bad interpreted as a templates marker :

$out = file_get_contents(TEMPLATE_DIR.$tpl);
$out = str_replace("{{}}", "{}", $out);

To use constant, you can use perform as like :

    $empty = (DEBUG) ? "_EMPTY_" : "";
    return preg_replace
    (
        '#\{([a-z0-9\-_]*?)\}#Ssie', 
        '( ( isset($vars[\'\1\']) ) 
            ? $vars[\'\1\'] 
            : ( defined(\'_\'.strtoupper(\'\1\').\'_\') 
                ? constant(\'_\'.strtoupper(\'\1\').\'_\') 
                : $empty 
            ) 
        );',
        $out
    );

Note:

__DIR__ 

used in my code is valid for PHP >= 5.3.0 try but you can use

dirname(__FILE__)

For PHP < 5.3.0 try

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!