В прошлом я успешно выполнял чтение этих значений из переменной суперглобального массива $_SERVER
.Чтобы использовать $_SERVER
(особенно из контекста RINIT
), вы должны убедиться, что его автоматический глобальный обратный вызов был вызван.PHP обычно вызывает это при первом доступе к пользовательскому пространству (другими словами, PHP лениво загружает суперглобальные переменные).
Чтобы сделать это, вы ищите значение zend_auto_global
из хеш-таблицы auto_globals
и вызываете auto globalПерезвоните.Вы должны всегда проверять, чтобы убедиться, что $_SERVER
не загружен заранее;хотя в вашем случае вы вызываете его из RINIT
, поэтому он не будет загружаться всегда.
После вызова автоматического глобального обратного вызова вы теперь можете обращаться к $_SERVER
, как и к любой другой глобальной переменной вsymbol_table
hashtable.
Вот пример из моего расширения под названием uniauth
(полный текст на Github см. по этой ссылке ):
/* Make sure $_SERVER is auto loaded already. */
if (!zend_hash_exists(&EG(symbol_table),"_SERVER",8)) {
if (zend_hash_find(CG(auto_globals),"_SERVER",8,(void**)&auto_global) != FAILURE) {
auto_global->armed = auto_global->auto_global_callback(auto_global->name,
auto_global->name_len TSRMLS_CC);
}
else {
zend_throw_exception(NULL,"could not activate _SERVER",0 TSRMLS_CC);
return 0;
}
}
Inэта конкретная часть кодовой базы, расширение генерирует URI перенаправления, используя информацию в $_SERVER
.Вот код, который показывает использование серверных переменных для генерации URI (см. эту ссылку для полного контекста на Github):
/* Get information about the protocol, host and port number from the _SERVER
* superglobal. We use HTTPS, HTTP_HOST and SERVER_PORT keys to resolve the
* scheme, host and port. I know of no better way to do this unfortunately
* with the PHP/ZEND API. The sapi globals just don't have what I need.
*/
if (zend_hash_find(&EG(symbol_table),"_SERVER",8,(void**)&arr) == FAILURE) {
zend_throw_exception(NULL,"no _SERVER superglobal",0 TSRMLS_CC);
return 0;
}
server = Z_ARRVAL_PP(arr);
if (zend_hash_find(server,"HTTPS",6,(void**)&val) != FAILURE) {
if (Z_TYPE_PP(val) != IS_STRING || strcmp(Z_STRVAL_PP(val),"off") != 0) {
https = 1;
}
}
if (zend_hash_find(server,"HTTP_HOST",10,(void**)&val) != FAILURE
&& Z_TYPE_PP(val) == IS_STRING)
{
host = Z_STRVAL_PP(val);
}
else {
zend_throw_exception(NULL,"no HTTP_HOST within _SERVER found",0 TSRMLS_CC);
}
В комментарии я оплакиваю фактчто нет способа сделать это без подражания тому, что вы делаете в коде пользовательского пространства.Вы можете получить доступ к глобальной структуре SAPI в расширении, но оно не обладает всей информацией, необходимой моему (и вашему) проекту.Подробнее см. соответствующие структуры в заголовках PHP.