PHP:将字符串变量中的占位符交换为相应的已定义变量值



我有一个PHP脚本,在全局命名空间中设置了一些变量:

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

我正在使用file_get_contents:将外部文件读取到脚本中的字符串变量中

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

外部文件(和字符串$file_contents)包含与变量名相对应的占位符。

127.0.0.1 {{domain}} {{hostname}}

我希望将变量$file_contents中的所有占位符替换为已经设置的各自的PHP变量。我希望它能通用地工作(不需要对占位符/变量名进行硬编码)。我不想编辑文件,只想编辑字符串的内容。

做这件事最简单的方法是什么?

  • 分析文件中{{和}}之间的项
  • 检查是否存在全局变量
  • 搜索并替换

像这样:

$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);
    }
}

免责声明:我不认为允许在任何模板中使用任意变量是个好主意。

函数get_defined_vars()variable_name => value的形式创建所有当前可用变量的数组(THIS包括SUPERGLOBALS LIKE$_SERVER AND$_GET!

字符串转换函数strtr(string $str, array $replace_pairs)可以将关联数组的键替换为它们在字符串中的值。

他们共同组成了一个强大但危险的联盟。以下代码将用$domain的值替换domain,依此类推:

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

添加{{...}}只需付出一点额外的努力:

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

负责任地使用它!记住不要相信任何用户输入。

您可以使用preg_replace_callback来执行此操作,但您需要将替换项放入数组中。

例如

    $domain = 'example.com';

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

为该特定正则表达式返回的匹配项将是数组

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

这就是为什么我们要用array_key_exists 进行检查

好吧,伙计们,我从其他答案中提取了一些零碎的东西,并提出了我认为对我来说最好的解决方案:

$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
);

这个答案结合了@TonyDeStefano、@dops和@fschmengler的观点。所以请投票给他们@BugaDániel也为他的评论提供了帮助。

您可以简单地使用str_replace来完成此操作。既然你知道位置持有者会是什么样的人,就试试这样的东西:

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

这将为全局变量做工作

<?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);

将输出:

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

最新更新