【问题标题】:Replace placeholders in text by referencing a translation variable通过引用翻译变量替换文本中的占位符
【发布时间】:2018-10-17 11:04:11
【问题描述】:

我正在尝试从以下函数中删除 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);
}

【问题讨论】:

  • 我认为 str_replace 不起作用?
  • @Barry 它正在工作。我想知道的是为什么$val=${trim($res[1])}; 不起作用
  • 您能否构建变量名称及其值的散列并使用该散列来解析字符串中的扩展,而不是评估任意变量?这样会更安全,也更容易调试。
  • 也许是$val=@trim($res[1]); return empty($val) ? $res[0] : $val;?无论如何,$res 是什么,你能 var_dump($res);那里?
  • $res 是 preg_replace 的结果数组。

标签: php eval preg-replace-callback custom-function variable-names


【解决方案1】:

所以,是的,eval() 经常被厌恶为 php 中最高级别的“邪恶”之一。在大多数情况下,当一项任务需要通过eval() 或变量变量(基本上是打包不良的数组)来解决时,这是数据存储/声明不当的症状,通常最好的行动方案是彻底重新思考.

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

代码:(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

...那么为什么这种解决方法是一个“坏主意”,好吧,想象一下你有一个包含{{ $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();

【讨论】:

    【解决方案2】:

    返回值后它对我很有效

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

    希望对你有帮助

    【讨论】:

      【解决方案3】:

      你正在使用一些奇怪的 Perl 风格的代码。问题是被 PHP 调用的双 $$。一旦你修剪了一个$,它就可以工作了。

      <?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的输出

      【讨论】:

      • 不起作用...它返回Undefined variable: pippo
      • 嗯,对我有用。你需要 PHP 7 sandbox.onlinephpfunctions.com/code/…
      • 我正在使用 php 7 老兄
      • @Vixed 那么我不知道问题可能是什么。检查我在上面评论中提供的链接,然后单击按钮执行代码。它返回Looking for a good Pizza
      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-05-11
        • 1970-01-01
        • 1970-01-01
        • 2020-06-03
        • 2012-01-12
        • 2014-05-02
        • 2020-04-26
        相关资源
        最近更新 更多