user636044
user636044

Reputation:

PHP: Swap placeholders in string variable for corresponding defined variable values

I have a PHP script with some variables set in the global namespace:

$domain = 'example.com';
$hostname = 'www.' . $domain;

I am reading an external file into a string variable in my script using file_get_contents:

$file_contents = file_get_contents('external_file.tpl');

The external file (and the string $file_contents) contains placeholders which correspond to variable names.

127.0.0.1 {{domain}} {{hostname}}

I would like to have all the placeholders in the variable $file_contents replaced with their respective PHP variables already set. I want this to work generically (without hard-coding placeholder / variable names). I do not want to edit the file, just the contents of the string.

What's the easiest way to do this?

Upvotes: 1

Views: 231

Answers (6)

user636044
user636044

Reputation:

Alright guys, I took some bits and pieces from other answers and came up with what I think is the best solution for me:

$domain = 'example.com';
$hostname = 'www.' . $domain;
$file_contents = '127.0.0.1 {{domain}} {{hostname}}';

$result = preg_replace_callback(
    "/{{(.+?)}}/",
    function ($matches) {
        return $GLOBALS[$matches[1]];
    },
    $file_contents
);

This answer combines ideas from @TonyDeStefano, @dops, and @fschmengler. So please up-vote them. @BugaDániel also helped with his comments.

Upvotes: 1

dops
dops

Reputation: 800

You could use a preg_replace_callback to do this, you will need to put your replacements into an array though.

e.g

    $domain = 'example.com';



    $newString = preg_replace_callback(
        '/{{([^}}]+)}}/',
        function ($matches) {
            foreach ($matches as $match) {
                if (array_key_exists($match, $_GLOBALS))
                    return $replace[$match];
            }
        },
        $file_contents
    );

The matches returned for that particular regex would be an array

array [
    '{{hostname}}',
    'hostname',
    '{{domain}}',
    'domain'
]

Which is why we would do a check with array_key_exists

Upvotes: 1

Fabian Schmengler
Fabian Schmengler

Reputation: 24551

Disclaimer: I don't think it's a good idea to allow arbitrary variables to be used in whatever this template is going to be.

The function get_defined_vars() creates an array of all currently available variables in the form variable_name => value (THIS INCLUDES SUPERGLOBALS LIKE $_SERVER AND $_GET!)

The string translation function strtr(string $str, array $replace_pairs) can replace keys of an associative array with their values in a string.

Together they form a mighty but dangerous alliance. The following code will replace domain with the value of $domain and so on:

echo strtr(file_get_contents('external_file.tpl'), get_defined_vars());

Adding {{...}} is possible with a little extra effort:

$vars = get_defined_vars();
$replace = array();
foreach ($vars as $key => $value) {
    $replace['{{' . $key . '}}'] = $value;
}
echo strtr(file_get_contents('external_file.tpl'), $replace);

Use it responsibly! Remember not to trust any user input.

Upvotes: 1

Alex Kalmikov
Alex Kalmikov

Reputation: 2183

This will do the work for global variables

<?php

$domain = 'example.com';
$hostname = 'www.' . $domain;
$file_contents = "127.0.0.1 {{domain}} {{hostname}}";

foreach($GLOBALS as $key => $value){

    if(!is_string($value) && !is_numeric($value)){
        continue;
    }

    $file_contents = str_replace('{{'.$key.'}}', $value, $file_contents);
}

var_dump($file_contents);

Will output:

string '127.0.0.1 example.com www.example.com' (length=37)

Upvotes: 0

Tony DeStefano
Tony DeStefano

Reputation: 829

  • Parse file for items between {{ and }}
  • Check to see if a global variable exists
  • Search and replace

Like so:

$matches = array();
preg_match('/\{\{([a-zA-Z0-9_]+)\}\}/', $file_contents, $matches);

foreach ($matches as $match)
{
    // You might want to check to make sure the variable is a string
    if (isset($GLOBALS[$match]))
    {
        str_replace('{{'.$match.'}}', $GLOBALS[$match], $file_contents);
    }
}

Upvotes: 2

Ethan22
Ethan22

Reputation: 747

You could simply use str_replace to do this. Since you know what the place holders are going to be, try something like this:

str_replace(['{{domain}}','{{hostname}}'],[$domain, $hostname], $file_contents);

Upvotes: 0

Related Questions