通过引用翻译变量替换文本中的占位符

Replace placeholders in text by referencing a translation variable

我正在尝试从以下函数中删除 eval。我尝试使用 sprintf${} ,但仍然找不到解决方案。

这里是函数:

function parseDbString(string $value = 'Looking for a good {{ $pippo }}'){
    $pippo='Pizza';
    return preg_replace_callback('/{{(.*?)}}/', function($res) use ($pippo) {
      // $val=${trim($res[1])}; Returns "Undefined variable: $pippo"
      $val=@eval("return ".trim($res[1]).";"); // Returns "Looking for a good Pizza"
      return isset($val) ? $val : $res[0];
    },$value);
}

伙计,你正在使用一些奇怪的 Perl 风格的代码。问题是 PHP 调用的双 $$。一旦你 trim 一 $ 离开它就可以了。

<?php

function parseDbString(string $value = 'Looking for a good {{ $pippo }}'){
    $pippo='Pizza';
    return preg_replace_callback('/{{(.*?)}}/', function($res) use ($pippo) {
      $val=${substr(trim($res[1]), 1)}; // here trim the $ away from the matched string
      return isset($val) ? $val : $res[0];
    },$value);
}

echo parseDbString(); // prints "Looking for a good Pizza"

检查http://sandbox.onlinephpfunctions.com/code/86b3f37ac6c315d8e9a757c827455281df21fc89

的输出

在 return 值

之后它对我很有效
function parseDbString(string $value = 'Looking for a good {{$pippo}}') {
    $pippo = 'Pizza';
    return preg_replace_callback('/{{(.*?)}}/', function($res) use ($pippo) {
        // $val=${trim($res[1])}; Returns "Undefined variable: $pippo"
        $val = @eval("return " . trim($res[1]) . ";"); // Returns "Looking for a good Pizza"
        return isset($val) ? $val : $res[0];
    }, $value);

    return $value;
}

但如果你想让它更动态,你可以使用它下面的函数你可以将 $data 作为数组传递,如 ['$pippo'=>'pizza'] 并在第二个参数

中传递字符串
function parseDbString2($data , $string) {
    $parsed = preg_replace_callback('/{{(.*?)}}/', function ($matches) use ($data) {
        list($shortCode, $index) = $matches;

        if (isset($data[$index])) {
            return $data[$index];
        } else {
            throw new \Exception("Shortcode {$shortCode} not found ", 1);
        }
    }, $string);

    return $parsed;
}

希望对您有所帮助

所以,是的,eval() 作为 php 中排名最高的 "evils" 之一经常被人厌恶。在大多数情况下,当一项任务适合由 eval() 或变量-变量(基本上是封装不良的数组)来解决时,这是不适当的 stored/declared 数据的症状,通常是最好的行动方案是一个完整的反思。

为了在不从根本上重写自定义函数的情况下解决您的孤立问题,我将提供一个较小的 "evil"(但在我看来仍然是 "evil",因为它的使用存在风险)-- GLOBALS & global...

代码:(Demo)

function parseDbString(string $value = 'Looking for a good {{ $pippo }}'){
    global $pippo;                        // declare $pippo as a global variable
    $pippo = 'Pizza';
    return preg_replace_callback('/{{ $(.*?) }}/', function($m) use ($pippo) {
        echo "Global: " , $GLOBALS['pippo'];
        echo "\n{$m[1]}\n";
        return $GLOBALS[$m[1]] ?? $m[0];  // null coalescing operator provides fallback
    },$value);
}
echo parseDbString();

输出:

Global: Pizza                    # <-- for demonstraton purposes
pippo                            # <-- for demonstraton purposes
Looking for a good Pizza         # <-- desired output

...那么为什么这个解决方法是 "bad idea",好吧,假设你有一个包含 {{ $db }} 的字符串——这样一个通用变量名很可能存在于你的全局变量列表中变量。因此,如果您的字符串中的 {{ variable }} 匹配全局范围内的任何变量,您将得到错误的结果。


现在,您应该做什么?只需在数组中声明您的 $pippo 数据,以便您可以利用关联关系。 (Demo)

function parseDbString(string $value = 'Looking for a good {{ $pippo }}'){
    $lookup = ['pippo' => 'Pizza'];
    return preg_replace_callback('/{{ $(.*?) }}/', function($m) use ($lookup) {
        return $lookup[$m[1]] ?? $m[0];  // null coalescing operator provides fallback
    }, $value);
}
echo parseDbString();

根据您对输入数据的控制程度,您现在可以删除输入字符串中 pippo 之前的 $ -- 这会在此处消除一些不必要的字符,并且那里。

如果您还在阅读,可以使用 strtr()str_replace() 来清理整个内容。 (Demo)

function parseDbString(string $value = 'Looking for a good {{ $pippo }}'){
    $lookup = ['{{ $pippo }}' => 'Pizza'];  // this can be extended all you like!
    return strtr($value, $lookup);
}
echo parseDbString();

用另一个分隔符替换{{}}。 例如:

class Test {
  protected $item1 = 'I`m item-1';
  protected $item2 = 'I`m item-2';
  public function parseDbString($value = 'Looking for a good 1:$$item1 2:$$item2 5:$$item5 blabla'){
     $m = '';
     $result = $value;
     if( preg_match_all('~$$(.+?)\s~s', $value, $m)){
       foreach( $m[1] as $var ){
         if( property_exists( $this, $var )){
           $result = str_replace('$$' .$var, $this->{$var}, $result);
         } else {
           $result = str_replace('$$' .$var, 'UNDEFINED', $result);
         }
       }
     }
     return $result;
  }
}
$test = new Test();
var_dump( $test->parseDbString() );