Я искал разные формы, но не понял, как решить проблему, впервые найденную здесь (первая ссылка, вторая ссылка) но это дает мне ошибку в Eval. Я не могу понять, как решить этот код в цикле foreach.
foreach($_POST as $key => $value) {
if(!strstr($key, 'removeFile')){
//initialize variables using eval
eval("$" . $key . " = '" . sanitize($value) . "';");
}
}
Во-первых, у меня есть проблемы с вашим кодом:
eval
очень, очень редко и крайне опасно, используйте с осторожностью. Я занимаюсь разработкой на PHP более 10 лет и никогда действительно столкнулся с ситуацией, которая требовала eval
, Это не исключение. Eval не требуется$_POST
массив. Это здорово, но для этого есть специальные функции, такие как: filter_input_array
, array_filter
и многое, многое другое … не говоря уже о готовых проектах и инфраструктурах с открытым исходным кодом, которые уже содержат надежный компонент проверки запросов.strstr
, но будьте утомлены функциями, которые возвращают различные типы (например, strstr
: возвращается false
если игла не найдена, но возвращается 0
если игла найдена в начале строки стога сена). Ваш if
утверждение может работать не так, как задумано.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));
Теперь это может показаться надуманным и идиотским, но поверьте мне: все эти вещи случаться, больше, чем я хочу знать. Добавление некоторого кода, который случайно перезаписывает существующую переменную, которая используется ниже, происходит постоянно. Особенно в процессуальном кодексе. Не просто слепо распаковывать массив. Сохраните эту единственную переменную и используйте ключи, чтобы избежать:
В качестве первого ответа на пост, на который вы ссылаетесь, проблема заключается в том, что при использовании двойных кавычек PHP считает, что eval()
код начинается с переменной. Поскольку это не так, у вас есть два варианта. Используйте одинарные кавычки и не забывайте избегать одинарных кавычек, объявляющих строку в коде, или избегать знака доллара.
Бонусная нота
Существуют более элегантные решения проблемы, которую вы пытаетесь решить. Лучшее решение, которое я могу придумать, это использование extract
функция. Это дает два основных преимущества.
Один флаг, который вы можете использовать, 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.
Надеюсь, что это может помочь сделать правильный выбор для ваших нужд.
С уважением.