Не могу понять синтаксическую ошибку, неожиданный ‘=’ в коде eval () ‘d

Я искал разные формы, но не понял, как решить проблему, впервые найденную здесь (первая ссылка, вторая ссылка) но это дает мне ошибку в Eval. Я не могу понять, как решить этот код в цикле foreach.

foreach($_POST as $key => $value) {
if(!strstr($key, 'removeFile')){
//initialize variables using eval
eval("$" . $key . " = '" . sanitize($value) . "';");
}
}

0

Решение

Во-первых, у меня есть проблемы с вашим кодом:

  1. eval очень, очень редко и крайне опасно, используйте с осторожностью. Я занимаюсь разработкой на PHP более 10 лет и никогда действительно столкнулся с ситуацией, которая требовала eval, Это не исключение. Eval не требуется
  2. Вы дезинфицируете весь $_POST массив. Это здорово, но для этого есть специальные функции, такие как: filter_input_array, array_filter и многое, многое другое … не говоря уже о готовых проектах и ​​инфраструктурах с открытым исходным кодом, которые уже содержат надежный компонент проверки запросов.
  3. Всегда проверяйте возвращаемые значения функций, которые вы, кажется, делаете с strstr, но будьте утомлены функциями, которые возвращают различные типы (например, strstr: возвращается false если игла не найдена, но возвращается 0 если игла найдена в начале строки стога сена). Ваш if утверждение может работать не так, как задумано.
  4. Вы предполагаете sanitize($value) значения не будут содержать одинарные кавычки. Зачем? Потому что, если они это сделают, вы получите синтаксическую ошибку в вашей уклоненной строке

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

$sanitized = array_filter($_POST, 'sanitize');//call sanitize on all values
foreach ($sanitized as $key => $value)
{
if (!isset($$key) && strstr($key, 'removeFile') === false)
$$key = $value;
}

Но действительно, $_POST Значения принадлежат друг другу, они являются частью запроса и должны оставаться сгруппированными … либо в массиве, либо в каком-либо объекте. Не присваивайте каждое значение своей собственной переменной, потому что довольно скоро вы потеряете представление о том, какие переменные установлены, а какие нет. Использование неустановленной переменной создает эту переменную, присваивая значение nullИтак, что у вас сейчас есть для очень подверженный ошибкам код:

//request 1: POST => id=123&foo=bar
foreach ($sanitized as $k => $v)
$$k = $v;
$query = 'SELECT x, y, z FROM tbl WHERE id = ?';//using posted ID as value
$stmt = $db->prepare($query);
$stmt->execute(array($id));

Все хорошо, потому что $id был установлен, но никогда не доверяй сети, не думай, что только потому, что $_POST установлено, все ключи будут установлены, и их значения будут правильными:

//request 2: POST => foo=bar&page=2
foreach ($sanitized as $k => $v)
$$k = $v;
$query = 'SELECT x, y, z FROM tbl WHERE id = ?';//using posted ID as value
$stmt = $db->prepare($query);
$stmt->execute(array($id));//id is null

Теперь у нас есть проблема. Это просто один пример того, как ваш код может вызвать проблемы. Представьте, что скрипт немного растет, и посмотрите на это:

//request 3: POST => id=123&foo=bar&page=2
foreach ($sanitized as $k => $v)
$$k = $v;
//$id is 123, $foo is bar and $page = 2
$query = 'SELECT x, y, z FROM tbl WHERE id = ? LIMIT 10';//using posted ID as value
//a lot more code containing this statement:
$page = someFunc();
$log->write('someFunc returned log: '.$page);
//more code
$offset = 10*($page-1);//<-- page is not what we expected it to be
$query .= sprintf(' OFFSET %d', $offset);
$stmt = $db->prepare($query);
$stmt->execute(array($id));

Теперь это может показаться надуманным и идиотским, но поверьте мне: все эти вещи случаться, больше, чем я хочу знать. Добавление некоторого кода, который случайно перезаписывает существующую переменную, которая используется ниже, происходит постоянно. Особенно в процессуальном кодексе. Не просто слепо распаковывать массив. Сохраните эту единственную переменную и используйте ключи, чтобы избежать:

  • седые волосы
  • внезапное резкое облысение
  • потеря здравомыслия
  • кровоточащие язвы
  • В рабочей среде: катастрофическая потеря данных
  • Внезапная потеря работы
  • … потому что такой код заставляет единорогов плакать, и bronies выследит тебя
2

Другие решения

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

Бонусная нота

Существуют более элегантные решения проблемы, которую вы пытаетесь решить. Лучшее решение, которое я могу придумать, это использование extract функция. Это дает два основных преимущества.

  1. Работает со всеми ассоциативными массивами
  2. Вы можете указать различные флаги, которые помогут вам отличить извлеченные переменные и избежать внедрения переменных.

Один флаг, который вы можете использовать, EXTR_PREFIX_ALL, Это префикс всех извлеченных переменных с вашим собственным префиксом. Затем вы получите доступ к переменным с префиксом «PREFIX_», как показано ниже:

$array = [
'variable1' => 'foo',
'variable2' => 'bar'
];

extract($array, EXTR_PREFIX_ALL, 'PREFIX_');

$value1 = $PREFIX_variable1; // Equals: foo
$value2 = $PREFIX_variable2; // Equals: bar

Немного о внедрении кода

Предположим, у вас есть код:

$login = false;

$login Переменная определяет, вошел ли пользователь в систему или нет.
Затем где-то вы используете функцию «извлечения» с массивом следующего без использования каких-либо флагов.

$array = [
'login' => true,
'foo'   => 'bar'
];

extract($array);

Теперь ваш $login переменная будет установлена ​​в true и пользователь, публикующий данные, перезаписал бы начальную настройку и получил бы доступ к вашему веб-сайту без действительного логина. Имейте в виду, что это слишком упрощенный пример, но тем не менее действительный.

Чтобы преодолеть это, вы можете использовать флаг EXTR_SKIP или префикс их, как я ранее показал. EXTR_SKIP flag пропустит элемент массива, если переменная с таким именем уже определена. Так что теперь ваш код не будет перезаписывать ваш $login переменная.

extract($array, EXTR_SKIP); // Skip existing variables
// Or
extract($array, EXTR_PREFIX_ALL, 'prefix'); // Prefix them all.

Надеюсь, что это может помочь сделать правильный выбор для ваших нужд.

С уважением.

1

По вопросам рекламы [email protected]