Search code examples
phppreg-replacepattern-matchingdatatemplatetemplate-engine

Preg_Replace pattern in a template


I am struggling with a way to make this more efficient. Is it possible to make the loop into a single line?

Edit: looking to replace the loop.

$template = "<div>[@ data]</div>";
$arrayData = array('hello', 'hi', 'hola');

foreach ($arrayData as $dataValue) {
    $fillPattern = '/\\[@ data\\]/is';

    $arrayTemplate .= preg_replace($fillPattern, $dataValue, $template);
}

$viewContent = preg_replace($pattern, $arrayTemplate, $viewContent);

Solution

  • Firstly, why you put the assignment to $fillPattern in the loop? Its value doesn't change for each iteration. You should put those statement outside the loop, before it. Like this:

    $template = "<div>[@ data]</div>";
    $arrayData = array('hello', 'hi', 'hola');
    $fillPattern = '/\\[@ data\\]/is'; //<-- put it here
    
    $arrayTemplate = '';
    foreach ($arrayData as $dataValue) {
        $arrayTemplate .= preg_replace($fillPattern, $dataValue, $template);
    }
    

    Secondly, you already have a way to make the loop into one line. Just use shorter variable names, remove the curly braces (because it is only one statement inside it), and write those 2 statements into one line. Like this:

    $tpl = "<div>[@ data]</div>";
    $data = array('hello', 'hi', 'hola');
    $pat = '/\\[@ data\\]/is';
    
    $res = ''; foreach ($data as $val) $res .= preg_replace($pat, $val, $tpl);
    

    But if you don't like the shorter variable names, good luck man. I don't think you can make a one line code with those long variable names. Except, you have a loooong looong line :D

    For the loop replacement, you should have an understanding about the functional programming. You can use array_map to replace the loop. To make it one line code (or one statement code I guess), you have to utilize anonymous function as the argument for array_map.

    With PHP 5.3 or newer you can use this code:

    $arrayTemplate = join('', array_map(
        function($x) use ($fillPattern, $template) {
            return preg_replace($fillPattern, $x, $template);
        }, $arrayData));
    

    But if you don't have PHP 5.3 or newer, you can use create_function like this:

    $arrayTemplate = join('', array_map(
        create_function('$x', 'global $fillPattern, $template;
            return preg_replace($fillPattern, $x, $template);'
        ), $arrayData));
    

    With the shorter variable names above, these code can be rewriten as follows:

    $res = join('', array_map(function($x) use ($pat, $tpl) {
        return preg_replace($pat, $x, $tpl);
    }, $data));
    

    or:

    $res = join('', array_map(create_function(
        '$x', 'global $pat, $tpl; return preg_replace($pat, $x, $tpl);'
    ), $data));
    

    You see, PHP was originally an imperative procedural language. It is not designed as a functional language in the first place. So, I guess the imperative way using foreach loop is still the better way to do it for now.