Суперглобальные массивы и register globals
PHP ранних версий работал с данными, приходящими от пользователя, следующим образом.
Массивов $_GET, $_POST и т.п. не было. Все данные записывались в глобальные переменные. Например, значение поля name из GET-формы попадало в переменную $name, IP-адрес посетителя - в переменную $REMOTE_ADDR, и т.д. Порядок заполнения переменных - что немаловажно, так как GET-формы, POST-формы, серверные переменные и т.д. - определялся следующим образом:
- Переменные среды окружения (environment)
- GET-параметры (QUERY_STRING)
- POST-форма
- Данные из cookies
- Серверные данные (переменные REQUEST_URI, REMOTE_ADDR и т.п.)
При этом следующие данные "затирают" предыдущие, то есть, значение поля GET-формы с именем REMOTE_ADDR будет перезаписано одноименной серверной переменной, содержащей IP-адрес посетителя.
Эта последовательность настраиваема с помощью конфигурационной переменной в php.ini, но в ее изменении нет никакой необходимости: указанный порядок наиболее разумен. Регистрирует ли PHP эти глобальные переменные, зависит от настройки register_globals в php.ini. Во времена PHP3 никто и не думал отключать ее - настройка register_globals=on была общепринятым стандартом.
Конечно, написание скриптов при таком подходе становится максимально простым - как назвал поле формы, такую переменную и смотри. А если уж нужно брать информацию из конкретного места - есть массивы $HTTP_GET_VARS и им подобные (которыми при таких длинных названиях и необходимости явного объявления видимости внутри функций с помощью global мало кто пользовался). Это все прекрасно для небольших скриптов строк по 50-100. Но в объемных программах такой подход приводит к путанице: поди упомни, откуда какая переменная. Что еще хуже, такой способ программирования допускает серьезные ошибки, приводящие к огромным дырам на сайте. Пример (утрированный, конечно, но аналогичным образом были взломаны сотни сайтов):
<? if (проверка_имени_пользователя_и_пароля()) { $auth = true; } if ($auth == true) { доступ_к_администрированию(); } ?>
Вводим в адресной строке http://адрес/скрипт.php?auth=1 - и, благодаря register_globals=on - получаем доступ к администрированию, не зная паролей.
Конечно же, разработчики PHP не могли не отреагировать на существование данной проблемы:
В версии PHP 4.1.0 ввели $_XXX - массивы, называемые суперглобальными, и рекомендовали установить register_globals=off и пользоваться данными массивами. По их именам очевидно их назначение:
- $_GET
- $_POST
- $_COOKIE
- $_SERVER
- $_ENV
- $_SESSION (для работы с сессиями - тут есть своя специфика)
- $_REQUEST ($_COOKIE + $_POST + $_GET)
В версии PHP 4.2.0 установили значение по умолчанию register_globals=off.
Проблеме register_globals также посвящена страница http://www.phpfaq.ru/globals. Если вы привыкли к register_globals=on, или вам надо "завести" старый скрипт, написанный 8 лет назад - там все подробно разжевано.