Я пытаюсь удалить 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);
}
Так да, 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();
это хорошо работает со мной после возврата значения
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;
}
надеюсь, это поможет вам
Чувак, ты используешь какой-то странный код в стиле 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
замещать {{}}
с другим разделителем.
Например:
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() );