Должен ли я использовать PHP Superglobals или фильтровать входные данные для извлечения данных $ _GET?

#php #superglobals

#php #суперглобалы

Вопрос:

Я действительно ненавижу глобальные переменные — возможно, это во мне программист C #, но когда я работаю на PHP, я стискиваю зубы каждый раз, когда мне приходится делать что-то подобное:

 $strUsername = $_GET['username'];
  

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

Я наткнулся на эту функцию в руководстве по PHP (вы действительно узнаете что-то новое каждый день): filter_input_array().

Итак, теперь, технически, я могу сделать это вместо того, чтобы брать все из GET superglobal:

 $GETdata = filter_input_array(INPUT_GET);
  

…. и так далее, и тому подобное с другими, такими как POST, REQUEST и т.д. Мой вопрос таков: должен ли я использовать filter_input_array и таким образом избежать бедствия суперглобалов, или есть какая-то причина придерживаться их и забыть об использовании функций filter_input? Каков опыт всех остальных в этом?

РЕДАКТИРОВАТЬ: Я забыл одну вещь — функции filter_input не реагируют на любые изменения на уровне скрипта, которые вы вносите в суперглобальные файлы, поэтому, если я сделаю: $_GET['cheese'] = 'puff'; попытка сделать filter_input(INPUT_GET, 'cheese'); позже вернет null. Это нормально, поскольку я внедряю зависимость от всего, но это может застать кого-то врасплох позже, если они не знают.

Комментарии:

1. С точки зрения производительности, вы действительно хотите фильтровать входные данные каждый раз, когда они вам понадобятся? например, вы вызываете foo() и очищаете их там, но что, если bar() они также нужны? Проводите ли вы повторную очистку?

2. Если вам не нужна никакая фильтрация — зачем беспокоиться о 1 бессмысленном вызове функции?

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

4. не слишком ли драматично звучит «бич суперглобалов»? :]

5. @BradChristie amp; @zerkms — Мой вопрос на самом деле не о фильтрации, санитарной обработке, проверке или чем-то еще. Речь идет о первом, начальном захвате данных GET и POST, которые навсегда вводятся в зависимость. Модели обрабатывают свою собственную проверку и фильтрацию, а представления обрабатывают выходные данные для очистки.

Ответ №1:

Использование filter_input_array по-прежнему использует суперглобальные данные, потому что он все еще получает свои данные из одного из суперглобальных массивов.

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

htmlentities для html, подготовленная строка для pdo, mysql_real_escape_String для mysql_ функций и т.д…

Комментарии:

1. Неверно. filter_input_array(INPUT_SERVER) не вернет REQUEST_TIME или REQUEST_TIME_FLOAT . Таким образом, filter_input_array() получает значения без использования суперглобальных значений. Реальный вопрос в том, что если вы создаете Request объект, должны ли вы заполнить его с помощью $_SERVER или filter_input_array() . В конечном счете, перенос значений, полученных из суперглобальных значений и функций, проще, но есть другой способ: php://input

Ответ №2:

Почему глобальные переменные плохие?

Общий аргумент заключается в том, что вы вводите ненужные зависимости во внешнее состояние.

Ваше решение не предотвращает это, оно только скрывает это.

Лучшим решением было бы, имхо, предоставить $ _GET в качестве аргумента, как в

 function myController($get) {
   $user = Model::get_user($get['userid']);
   render_view('user.html', $user);
}

myController($_GET)
  

поскольку это устраняет причину, по которой глобальные переменные считаются плохими.

Комментарии:

1. Да, и это называется dependency injection . Чтобы немного улучшить ваш код, было бы неплохо переименовать его $get во что-то вроде $request .

2. я только что записал это, я даже не помню соглашения об именовании PHPs, так как я оставил это для sweet python :). может быть, также интересный термин для поиска: закон деметры.

3. Я упоминал в исходном вопросе, что все вводится в зависимости. Ничто так не раздражает меня, как натыкание на плавающий объект $ _GET в середине метода класса. И да, я понимаю, что я просто скрываю проблему.

4. @jarrod — итак, тогда почему вы пытаетесь заменить $ _GET эквивалентным оператором вместо того, чтобы перенести указанный код в свой улучшенный стиль, используемый в вашем фреймворке?

Ответ №3:

Я использую PHP superglobals, но только на уровне библиотеки в моей платформе. Это фреймворк, в котором все контроллеры имеют доступ к объекту запроса, который, в свою очередь, получает доступ к суперглобальным файлам. Это позволяет вам писать тесты для вашего контроллера, создавая объект mock request, заполненный вашими тестовыми параметрами. Все дело в хорошем OO-дизайне и хороших шаблонах проектирования.

Прямой доступ к суперглобальным файлам везде без какой-либо абстракции является антишаблоном.

Ответ №4:

Я действительно ненавижу эти глобальные переменные. Я бы определенно использовал filter_input_array и использую массив всякий раз, когда это необходимо. Это устраняет множество ошибок, связанных с глобальными данными, и избавляет вас от необходимости тратить часы на отладку этих труднодоступных глобальных файлов.

Я думаю, что filter_input_array это wtg!

Комментарии:

1. кроме ненависти, в чем смысл? каким образом statmement, эквивалентный глобальной переменной, лучше, чем глобальная переменная

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

3. Будьте осторожны с $_SERVER и filter_input_array(INPUT_SERVER) . Они не возвращают одинаковый вывод.

Ответ №5:

Я не думаю, что кто-то знает идеальный ответ 🙂

Иногда я использую это, иногда я получаю данные точно так же, как $_GET['data'] , иногда я даже использую import_request_variables() .

В каком-то проекте у меня есть специальный класс, который обрабатывает POST , GET REQUEST и делает что-то вроде этого: POST::getValue('username') или GET::getValue('session_id') или COOKIE::getValue('last_time_seen')

Комментарии:

1. К сожалению, import_request_variables() теперь это устарело, хотя вы все еще можете использовать extract($_GET) для выполнения того же самого.

2. не совсем, import_request_variables работает с $_POST массивами $_GET и $_COOKIE .

3. Вы правы, extract($_REQUEST) хотя это сработало бы.

4. Не совсем. Что, если у вас есть $_GET['city'] = 1; , $_POST['city'] = 2; и $_COOKIE['city] = 3; ? 😉

5. Тогда последние переопределили бы другие, как import_request_variables и было бы сделано. Единственное отличие заключается в том, что вы можете выбрать порядок, в котором они импортируются, используя $types аргумент.

Ответ №6:

Если вам действительно не нравятся суперглобальные значения, почему бы не написать свою собственную реализацию для очистки, такую как класс vB_Input_Cleaner здесь?

http://members.vbulletin.com/api/

Ответ №7:

Несколько лет назад было еще хуже, параметр amp;x= в URL отображался как global $ x . Кстати, если вы не используете $ _GET, кроме как в framework, он не существует.