#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 здесь?
Ответ №7:
Несколько лет назад было еще хуже, параметр amp;x= в URL отображался как global $ x . Кстати, если вы не используете $ _GET, кроме как в framework, он не существует.