HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

Passing anonymous functions and getting variables from an outer scope

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
anonymouspassinggettingscopevariablesandfunctionsfromouter

Problem

I'm doing something quite strange. I'm trying to create a tiny system for creating templates inline in PHP, so that I can refactor by creating multiple templates in the original script, and eventually move the templates to separate scripts.

Here's the silly/basic template library that just calls an anonymous function that gets passed in after some HTML header stuff, and then calls a footer:

".$title."";

    if(is_array($templates)){
        foreach($templates as $template_function){
            $template_function($data);
        }
    } else{
        $template($data); // Call & display the template.
    }

    echo "Footer";
    echo "";
}

?>


Here's where it's going to get strange. In the scripts I'm creating anonymous functions, saved to variables, and then passing them to the template library for outputting. To avoid having to call an array element (and check whether the element exists each time), I'm trying to export the array passed in to get standard variables in the template (e.g. $name instead of $data_array['name']). Is there a way to abstract away this behavior in PHP?

'no name');

// The page gets displayed at the bottom.

// =================== Templates ========================================
// Todo: Potentially namespace the stuff here.
// Define the anonymous template function here, has html and such in native php here.
$contact_us = function ($template_output_variables=null){
    extract($template_output_variables); // Pull the variables.
    // Leave php in the template function.
    ?>
    
    Hello World Body Text, Hello .
    

    
    Breaking news, There is a killer among us.

    $title), $template_output_variables);

?>


It's very strange, I know, but I'm trying to do a whole new approach to refactoring, and make use of some new PHP 5.3 features while doing it. The goal is to have inline templates that I can put in any script, as many as I want, and move anywhere I want later, or merge the templates, etc.

Solution

Something like this would get you most of the way there:

'.$template_body.'
    Hello World Body Text, Hello .
    '
);

$contact_us(array('name' => 'Johnny Boy'));


But it's evil, and you will likely end up with very odd, very hard-to-debug errors once your templates are of reasonable size/complexity. It's an interesting idea though -- if you pursue it, make sure you have a thorough set of test cases ;)

The easiest way to clean it up, IMO, would be to do away with allowing raw php in the templates. I'm pretty partial to Twig, you may be able to find some inspiration there.

Code Snippets

<?php
function h($val) {
    echo $val;
}

function template_function($template_body) {
    return function(array $template_output_variables = null) use ($template_body) {
        if ($template_output_variables !== null) {
            extract($template_output_variables);
        }
        $contents = eval('?>'.$template_body.'<?php');
        echo $contents;
    };
}


$contact_us = template_function('
    <body>
    Hello World Body Text, Hello <?php h($name);?>.
    </body>'
);

$contact_us(array('name' => 'Johnny Boy'));

Context

StackExchange Code Review Q#4656, answer score: 2

Revisions (0)

No revisions yet.