Есть ли безопасный способ автоматического назначения ключей в размещенном массиве? Ниже приведены два примера неправильных способов …
foreach( $_POST as $key => $value ) { $$key = $value; }
или
extract($_POST)
Есть ли лучший способ, или лучше всего код:
$foo = $_POST('foo'); $bar = $_POST('bar'); ....
для всех 50 входов в моей форме?
(размещенная информация будет вставлена в базу данных).
Еще один осторожный способ одновременного извлечения всех полей ввода:
extract( $_POST, EXTR_OVERWRITE, "form_" );
Таким образом, все ваши входные переменные будут называться $form_foo
и $form_bar
как минимум. Избегайте делать это в глобальном масштабе – не потому, что глобальное зло, а потому, что никто там не чистится.
Однако, поскольку в основном вы делаете это в локализованной области, вы также можете применять htmlentities, если, например, вам нужны все поля только для вывода:
extract(array_map("htmlspecialchars", $_POST), EXTR_OVERWRITE, "form_");
Для этого нет никакой причины.
Для обработки пользовательских входов массив в 100 раз лучше, чем отдельные переменные
Мне нравится подход, в котором вы позволяете динамическим геттерам и сеттерам в классе выполнять всю работу за вас. Вот как я его код.
Во-первых, создайте класс басов для хранения данных:
class FormParameterHandler { protected $parameters; public function __construct($associative_array) { $this->parameters = array(); foreach($associative_array as $key => $value) { $this->{$key} = $value; } } public function __get($key) { $value = null; if(method_exists($this, "get_$key")) { $value = $this->{"get_$key"}(); } else { $value = $this->parameters[$key]; } return $value; } public function __set($key, $value) { if(method_exists($this, "set_$key")) { $this->{"set_$key"}($value); } else { $this->parameters[$key] = $value; } } }
Затем создайте определенный класс для использования в определенной форме, где есть что-то особенное для проверки. Используйте свою свободу в качестве программиста здесь, чтобы реализовать ее так, как вы хотите. И помните, поскольку мы используем рефлексию для поиска методов setter, мы можем написать конкретные методы настройки для известных проблемных областей, например, например, для проверки равных паролей в форме «зарегистрировать пользователя»:
class RegisterFormParameterHandler extends FormParameterHandler { private $passwords_are_equal = null; public function __construct($register_form_parameters) { parent::__construct($register_form_parameters); } public function has_equal_passwords() { return $this->passwords_are_equal; } public function set_password($password) { $this->parameters['password'] = $password; $this->compare_passwords(); } public function set_password_repeat($password_repeat) { $this->parameters['password_repeat'] = $password_repeat; $this->compare_passwords(); } private function compare_passwords() { if(isset($this->parameters['password']) && isset($this->parameters['password_repeat'])) { $this->passwords_are_equal = ($this->parameters['password'] === $this->parameters['password_repeat']); } } }
Наконец, используйте производный класс в потоке «register user», чтобы легко узнать, соответствуют ли два введенных пароля:
$registerFormParameterHandler = new RegisterFormParameterHandler($_POST); if($registerFormParameterHandler->has_equal_passwords()) { print "are equal"; //register user } else { print "are not equal"; }
Вы можете проверить это, создав форму HTML, которая имеет одно поле ввода с именем «пароль» и другое поле ввода с именем «password_repeat».
Чтобы получить доступ к любой из данных формы, используйте имя переменной объекта данных формы, а затем оператор доступа «тире больше чем» ->, а затем имя параметра. В приведенном выше примере, если было поле ввода с именем «имя_пользователя», к нему можно было бы получить доступ посредством вызова
$registerFormParameterHandler->user_name
Rr, если вы определили имя поля, которое хотите получить в какой-либо другой переменной, используйте отражение:
$registerFormParameterHandler->{$settings['form_data_user_name']}
Повеселись! 🙂
Безопасный способ извлечения переменных в локальную область не должен . Вы вводите переменные в свою локальную область, что является проблемой, но вы это делаете. Даже если вы ограничиваете переменные только несколькими избранными, которые не будут сталкиваться с другими именами переменных в области теперь , если вы начнете добавлять элементы в свою форму, вы можете быть в беде позже.
Массивы предназначены специально для хранения неограниченного количества именованных значений без переполнения пространства имен переменных. Используй их! Возможно, вам придется набрать немного больше, но это подходит для курса.
Хотя лучше всего ссылаться на них с помощью $_POST['variablename']
, можно расширить только переменные, которые вы ожидаете.
$expected = array('name', 'telephone', /* etc */); foreach ($_POST as $key => $value) { if (!in_array($key, $expected)) { continue; } ${$key} = $value; }
Или я предпочитаю это:
foreach ($_POST as $key => $value) { switch ($key) { case 'name': case 'telephone': /* etc. */ ${$key} = $value; break; default: break; } }
Ответ на ваш вопрос зависит от знания компьютера, языка и безопасности программиста. Начальная последовательность обработки $ _POST похожа на начальный ход игры в шахматы. Многие используют foreach
петли, не понимая, что foreach
сделает копию содержимого $ _POST так, как вы его использовали (Programming PHP: Chapter 5, p.128-129). Было бы смешно, если бы вы вызвали переполнение буфера, просто используя foreach
!
Один из комментаторов подразумевал, что все должно работать только с $_POST
суперкоммутатором $_POST
. Для этого есть некоторые достоинства … Однако, забыв кэш-память на мгновение, доступ к значениям массива медленнее, чем прямой доступ к переменной.
Поскольку у вас есть 50 (50) элементов управления для проверки (с потенциально большим содержимым), я, возможно, не хочу, чтобы производительность доступа к массиву достигала более 50 раз (исходные обращения к доступу). Более того, если вы беспокоитесь о том, чтобы писать безопасные процедуры проверки входных данных, ваша хорошая стирка (неаудированный ввод) отдельно от вашего чистого (проверенного ввода) – это хорошая идея. Тем не менее, вам может понадобиться чистый массив в любом случае (отсюда ответ адвоката $ _POST), но по крайней мере вы уменьшаете риск в процессе, сохраняя надежду на то, что он отлично отделен от потенциально плохого .
Есть ли безопасный способ автоматического назначения ключей в размещенном массиве?
Я мог бы начать вот так:
Библиотека функций для этого примера.
function all_controls_submitted($controls) { $postKeys = array_keys($_POST); foreach($controls as $key) { if(! array_key_exists($key, $postKeys)) { return false; } } return true; } function all_controls_set($controls) { foreach($controls as $key) { if(! isset($_POST[$key])) { return false; } } return true; }
if(is_array($_SERVER) && isset($_SERVER['REQUEST_METHOD'], $_SERVER[REQUEST_URI]) && $_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/contact.php') { $newForm = true; } elseif (is_array($_SERVER) && isset($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['REQUEST_URI'] === '/contact.php') { $newForm = false; $controlNames = array('firstName', 'lastName', 'e-mail', 'company', 'subject', 'message', 'captcha'); define('NUM_CONTROLS_EXPECTED', count($controlNames)); //Seven (7) if(is_array($_POST) && count($_POST) === NUM_CONTROLS_EXPECTED && all_controls_submitted($controlNames) && all_controls_set($controlNames)) { //Begin input validation } } else { header('location: http://www.nsa.gov'); }
Обратите внимание, что я готовлю вещи с массивом $controlNames
, поэтому мне не нужно задавать $_POST
для ключей. В конце концов, я должен их знать! 🙂 Две пользовательские функции all_controls_submitted()
и all_controls_set()
– это два основных вопроса, которые необходимо задать перед тем, как попытаться использовать любые значения в $_POST
(я так или иначе говорю). По общему признанию, я использую $_POST
в all_controls_submitted()
, но только для получения имен представленных элементов управления, а не значений.
$postKeys = array_keys($_POST);
Однако, кто должен сказать, что сами контрольные имена не могут быть ядовитыми и нуждаться в проверке ввода? !! То же самое касается значений в $ _SERVER. Смотрите, игра в шахматы.
Есть ли безопасный способ автоматического назначения ключей в размещенном массиве? Я не могу вам точно сказать, но, возможно, что-то вроде кода выше может помочь? По крайней мере, у вас есть ключи.
Программирование PHP: глава 5, с.125
Попробуйте встроенный метод / function filter_input
URL ссылки: вход фильтра функции php.net