Строковая переменная PHP, которая содержит переменные, не оценивает - PullRequest
2 голосов
/ 29 января 2012

Я застрял на чем-то в PHP

    $l = $par['Length'];
    $w = $par['Width'];
    $d = $par['Depth'];
    $length = $par['Expr_1'];
    $width = $par['Expr_2'];

$par - это массив, считанный из базы данных.Длина, ширина, глубина - это числа. Expr_1 и Expr_2 - это формулы, хранящиеся в виде строк, например:

($l + .0625) * ($w + .125) * ($l + .125) * ($w + .0625) + 1.625

Что должно произойти, это то, что $l $w следует заменить значениями.Если я echo $l,$w,$d независимо, они имеют правильные значения.Если я echo $length or $width это показывает формулу.

Даже когда я пытаюсь eval("$width = {$par['Expr_2']};");, это не вынуждает его вычислять вместо того, чтобы просто читать формулу.Я знаю, что формула верна, потому что, если я вставлю ее вручную в $length или $width, она будет работать нормально.

Ответы [ 4 ]

1 голос
/ 29 января 2012

Вместо использования eval для формул ... есть возможность использовать что-то вроде preg_replace() вместо ... просто для замены переменных формулы, поступающих из базы данных ... и затем преобразовать / типизироватьзаменил результат на (int) или любой другой тип данных, который вам нужен.Затем вычисление формулы оттуда.Хотя ... это может быть не так надежно, как eval.

http://php.net/manual/en/function.preg-replace.php

1 голос
/ 29 января 2012

Переменная интерполяция в строки происходит только тогда, когда эти строки оцениваются исходный код.Когда они являются просто значениями, хранящимися в переменных, присваивания не выполняют интерполяцию.


Лучше было бы хранить простой разбираемый формат, который не требует полноценного eval().Вот некоторый код, который может хранить формат, который выглядит следующим образом:

L,0.5;W,0.2;D,0.3:4.7

, который будет эквивалентен (L+0.5)*(W+0.2)*(D+0.3)+4.7:

$eqn_parts = explode(':', $input);
$add_part = $eqn_parts[1];
$mult_parts = explode(';', $eqn_parts[0]);

$accum = 1;
foreach($mult_parts as $part) {
    $bits = explode(',', $part);
    switch($bits[0]) {
        case "L":
            $accum *= ($length + (int)$bits[1]); break;
        case "W":
            $accum *= ($width + (int)$bits[1]); break;
        case "D":
            $accum *= ($depth + (int)$bits[1]); break;
    }
}
$accum += (int)$add_part;
0 голосов
/ 09 октября 2013

Предполагая, что вы не будете передавать "любые данные, предоставленные пользователем, без надлежащей проверки их заранее."

Кажется, что следующее работает хорошо.

$width = $par['Expr_2'];
eval('$width = '.$width .';');
0 голосов
/ 30 января 2012

Хотя решение янтаря сработало бы, я хотел сделать его простым и сделать всю работу по вводу формул в БД не пустой тратой.Я просто скомбинировал $ length / $ width в начале строки и: в конце и eval'd.

Спасибо всем

РЕДАКТИРОВАТЬ, чтобы добавить код, который я использовал:

 $l = $par['Length'];
    $w = $par['Width'];
    $d = $par['Depth'];
    $par['Expr_1'] = '$length='.$par['Expr_1'].';';
    eval($par['Expr_1']);
    $par['Expr_2'] = '$width='.$par['Expr_2'].';';
    eval($par['Expr_2']);
...