Пользовательская функция парсинга PHP - PullRequest
0 голосов
/ 17 октября 2018

Я пытаюсь удалить 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);
}

Ответы [ 4 ]

0 голосов
/ 28 октября 2018

Заменить {{}} другим разделителем.Например:

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() );
0 голосов
/ 23 октября 2018

это хорошо работает со мной после возвращаемого значения

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

надеюсь, это поможет вам

0 голосов
/ 25 октября 2018

Итак, да, eval() часто ненавидят как одно из «зол» высшего порядка в php.В большинстве случаев, когда задача поддается решению с помощью eval() или переменных-переменных (которые в основном представляют собой плохо упакованные массивы), это является признаком неправильно сохраненных / объявленных данных, и часто лучшим вариантом действий является полное переосмысление..

Чтобы решить отдельный вопрос без фундаментальной переписки пользовательской функции, я предложу меньшее «зло» (но, на мой взгляд, все еще «зло», поскольку при его использовании есть риски) - GLOBALS & global ...

Код: ( Демо )

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 данные в массиве, чтобы иметь ассоциативные отношения для использования.( Демо )

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().( Демо )

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();
0 голосов
/ 21 октября 2018

Человек, которого вы используете в каком-то странном 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

...