Программирование на PHP и register_globals
Вплоть до версии PHP 4.2.0 значение по умолчанию параметра register_globals было "On". Большинство PHP-программистов использовали эту возможность для упрощения кодирования. Эта статья предназначена тем, кто хотел бы изменить свой стиль написания программ в связи с изменением значения по умолчанию для этого флага. Также статья должна помочь тем, кто хотел бы кодировать по старинке, но не имеет доступа к конфигурационному файлу.
Александр Войцеховский
Что такое register_globals? Это один из параметров php, определяемых в файле php.ini. Детальное описание можно найти в соответствующем разделе документации
Он может принимать два значения: on и off.
Вплоть до версии PHP 4.2.0 значение по умолчанию параметра register_globals было "On". Большинство PHP-программистов использовали эту возможность для упрощения кодирования. Эта статья предназначена тем, кто хотел бы изменить свой стиль написания программ в связи с изменением значения по умолчанию для этого флага. Также статья должна помочь тем, кто хотел бы кодировать по старинке, но не имеет доступа к конфигурационному файлу.
Одно из неоспоримых преимуществ PHP - его простота. PHP позволяет вставлять в HTML-разметку небольшие фрагменты кода, что упрощает освоение этого языка верстальщиками. Схожесть синтаксиса PHP с c++, слабая типизация, обилие документации и примеров делают первые шаги в программирование достаточно легкими. Но одно недавнее новшество существенно озадачило новичков: начиная с php 4.2.0, значение флага register_globals стало "Off". Это свело на нет одну из причин легкости освоения языка.
Почему это произошло? Разработчики решили, что с таким нововведением код станет более надежным и устойчивым к взлому. Надо быть очень внимательным ко всем данным, получаемым от пользователя. И давать клиенту возможность самостоятельно устанавливать значения некоторым переменным кода потенциально опасно. Более детальную мотивацию вы можете найти по ссылкам
Способы поступления данных в php-скрипт
Опытные программисты, которые сталкивались с данными GET / POST запросов, работали с переменными окружения, могут счесть этот раздел излишним.
Переменные в PHP возникают по многим причинам. Например, вы можете создать переменную самостоятельно, написав $var = 'value'. Этот фрагмент статьи посвящен ответу на вопросы: "Откуда возникают переменные в PHP?", "Как данные форм поступают на сервер?". Большая часть внимания уделяется объяснению того, как это происходило при register_globals=On.
Адресная строка
Это один из наиболее распространенных путей передачи данных. Более детальную информацию о том, как в php происходит разбор адресной строки, вы можете найти в соответствующем разделе документации
- Scheme - определяет протокол, используемый клиентом и сервером. Http и https являются наиболее распространенными протоколами.
- User и password - при необходимости данные для Basic-авторизации могут передаваться как часть адресной строки.
- Host - IP адрес или доменное имя сервера, на котором размещен запрашиваемый документ
- Port - TCP/IP порт сервера, значения по умолчанию: 80 для http и 443 для https
- Path - путь к запрашиваемому документу
- Query - данные запроса
- Fragment - указание якоря, размещенного непосредственно в html-разметке
Более всего нас интересует та часть адресной строки, в которой осуществляется передача переменных. При установленном в On флаге register_globals скрипт script.php автоматически инициализирует глобальные переменные $var = 'val' и $foo = 'bar';
Также каждый раз, когда какие-либо переменные передаются в адресной строке, php автоматически создает глобальный хеш-массив $HTTP_GET_VARS. В нашем примере этот массив будет выглядеть следующим образом: $HTTP_GET_VARS = array ('var' => 'val', 'foo' => 'bar');
Начиная с PHP 4.1.0, хеш-массив $_GET содержит те же значения, что и $HTTP_GET_VARS. В отличие от своего предшественника это суперглобальный массив, и его преимущества будут описаны ниже.
Формы (метод POST)
Формы - еще один достаточно распространенный способ передачи введенной пользователем информации. Рассмотрим пример:
Когда пользователь нажимает кнопку "Send", браузер отправляет скрипту script.php POST-запрос. Значения элементов ввода будут переданы в теле запроса. При установленном в On флаге register_globals скрипт script.php автоматически инициализирует глобальную переменную $foo = 'bar'.
Аналогично GET-запросу глобальный хеш-массив $HTTP_POST_VARS содержит все переданные браузером переменные, а в нашем примере он будет выглядеть следующим образом: $HTTP_POST_VARS['foo'] = 'bar'.
Начиная с PHP 4.1 и выше суперглобальный хеш-массив $_POST содержит аналогичные данные.
Cookie
По своей сути веб-страница (имеется в виду ее html-сущность, доступная человеку, просматривающему сайт), рождается при обращении к серверу на основании переданных в клиентском запросе данных и умирает, когда пользователь закрывает браузер. У разработчиков достаточно давно возникало естественное желание научиться сохранять некоторое состояние при переходе пользователя со страницы на страницу, чтобы более полно реализовать диалог взаимодействия. Именно так появилась технология Cookie, позволяющая сохранять на диске у клиента некоторую информацию и извлекать ее для дальнейшей обработки.
Пример кода, устанавливающего Cookie, выглядит таким образом:
/* Set Cookie for 1 day */
setcookie('foo', 'bar', time()+86400, '', $HTTP_HOST);
Примечание: в случае если register_globals = 'off' вместо $HTTP_HOST следует использовать $_SERVER['HTTP_HOST'].
Все установленные в пределах этого домена Cookies доступны для работы с ними в глобальном ассоциативном хеш-массиве $HTTP_COOKIE_VARS и суперглобальном хеш-массиве $_COOKIE.
Переменные окружения сервера
Окружающая среда операционной системы, точно так же как и веб-сервера, содержит множество переменных, которые могут быть использованы при написании скриптов. Например, они используются для определения имени выполняющегося скрипта или имени запрашиваемого хоста.
Для доступа к этим переменным PHP создает глобальные хеш-массивы $HTTP_ENV_VARS и $HTTP_SERVER_VARS. Начиная с PHP версии 4.1 и выше доступны суперглобальные хеш-массивы $_ENV и $_SERVER.
Использование суперглобальных массивов.
Обычно любая из переменных, используемых внутри функции, находится в ее локальном пространстве имен. Это означает, что если, к примеру, мы хотим обратиться к глобальной переменной $HTTP_GET_VARS, то мы обязательно должны написать global $HTTP_GET_VARS; перед любым обращением к этому массиву.
Суперглобальные переменные являются исключением из этого правила. Вы можете использовать переменные $_GET, $_POST, $_COOKIE, $_ENV, $_SERVER и $_SESSION внутри функций и вообще где-либо без предварительного объявления их глобальными. Также есть дополнительный суперглобальный массив - $_REQUEST, который содержит все, что могло быть отправлено пользователем, а именно: массивы $_GET, $_POST и $_COOKIE.
Примечание: вы не можете использовать переменные ссылки на суперглобальные массивы. Например, указанный ниже код не будет работать:
function foo($var)
{
$sg = '_GET';
return ${$sg}[$var];
}
?>
Функция foo(), описанная выше, не будет возвращать предполагаемые данные из суперглобального массива $_GET.
Особенности кодирования
С удивлением обнаружил в себе желание вернуться к привычному для меня стилю кодирования с использованием глобальных переменных. Но, принимая к вниманию вопросы безопасности и ряд других причин, было решено написать функцию, которая облегчит переход на новый стандарт.
/**
* return a value from the global arrays
*
* @author Jason E. Sweat
* @since 2002-02-05
* @param string $varname
* the name of the variable to register
*
* @param string $defval optional
* the value to return if not found
*
* @return string the value of the variable if
* registered, else the default
*/
function register($varname, $defval=NULL)
{
if (array_key_exists($varname, $_SERVER)) {
$retval = $_SERVER[$varname];
} elseif (array_key_exists($varname, $_COOKIE)) {
$retval = $_COOKIE[$varname];
} elseif (array_key_exists($varname, $_POST)) {
$retval = $_POST[$varname];
} elseif (array_key_exists($varname, $_GET)) {
$retval = $_GET[$varname];
} elseif (array_key_exists($varname, $_ENV)) {
$retval = $_ENV[$varname];
} else {
$retval = $defval;
}
return $retval;
}
?>
Эта функция позволяет "зарегистрировать" переменную, которую вы хотели бы использовать в скрипте. Для этого достаточно написать: $mode = register('mode');. Эта функция написана так, чтобы следовать значению по умолчанию опции variables_order конфигурационного файла php.ini. (Детальная документация доступна по ссылке
Правда, эта функция имеет один небольшой изъян: она всегда инициализирует каким-либо значением запрашиваемую переменную. Так как некоторые фрагменты моего кода использовали проверку при помощи функции isset, функцию пришлось слегка модифицировать:
/**
* set a global variable if the specified get
* or post var exists
*
* @author Jason E. Sweat
* @since 2002-04-25
* @param string $test_vars
* the array of the vars to
* register, will accept a string
* name for a single var as well
*
* @global the variable, if it is set
*/
function getpost_ifset($test_vars)
{
if (!is_array($test_vars)) {
$test_vars = array($test_vars);
}
foreach($test_vars as $test_var) {
if (isset($_POST[$test_var])) {
global $$test_var;
$$test_var = $_POST[$test_var];
} elseif (isset($_GET[$test_var])) {
global $$test_var;
$$test_var = $_GET[$test_var];
}
}
}
?>
Эта функция в качестве параметра принимает массив имен переменных, которые бы вы хотели сделать "глобальными". Если запрашиваемая переменная присутствует в массивах $_GET или $_POST, она будет инициализирована соответствующим образом. В противном случае она останется необъявленной, и вы по-прежнему можете использовать проверки при помощи функции isset().
Эта функция особенно полезна при написании обработчика формы, вы достаточно легко можете инициализировать все необходимые переменные:
getpost_ifset(array('username', 'password', 'password2'));
Замечание для ленивых
Если вы все-таки решили программировать по старинке, но не можете вернуть значение register_globals в On, возможно, вам помогут функции import_request_variables() и extract(). Руководство к ним доступно по ссылкам:
Заключение
Ознакомившись с материалами, приведенными в статье, вы должны иметь представление о том, откуда в PHP появляются переменные и как перейти на стандарт register_globals = Off.
Удачи вам, счастливого и безопасного написания программ.
Нет комментариев. Ваш будет первым!