Вот проблема, с которой я столкнулся в последнее время - неправильно настроенный apache на веб-хосте. Это означает, что все скрипты, использующие $_SERVER['DOCUMENT_ROOT'], ломаются. Самый простой обходной путь, который я нашел, - это просто установить переменную в некоторых глобальных включаемых файлах, которые являются общими, но больно не забыть об этом. У меня вопрос: как программно определить правильный корень документа?
Например, на одном хосте настройка выглядит так:
$_SERVER['DOCUMENT_ROOT'] == '/htdocs'
Настоящие корни документов:
test.example.com -> /data/htdocs/example.com/test
www.example.com -> /data/htdocs/example.com/www
И мне нужен сценарий, запускаемый с www.example.com/blog/ (по пути /data/htdocs/example.com/www/blog), чтобы получить правильное значение /data/htdocs/example.com/www.
На другом хосте настройка немного отличается:
$_SERVER['DOCUMENT_ROOT'] == '/srv'
test.example.com -> /home/virtual_web/example.com/public_html/test
www.example.com -> /home/virtual_web/example.com/public_html/www
Есть ли решение этого? Или это единственный способ просто никогда не полагаться на $_SERVER['DOCUMENT_ROOT'] и исправить все программное обеспечение, которое я использую на своих сайтах? Исправить это на стороне хостинга, похоже, не вариант, я еще не встречал хоста, на котором это было настроено правильно. Лучшее, что у меня получилось, это корень документа, указывающий на www.example.com, который, по крайней мере, находился внутри open_basedir - они использовали еще одну схему именования, www.example.com указывал на /u2/www/example_com/data/www/.






PHP должен устанавливает текущий каталог на тот, в котором находится скрипт, так что пока он не сломан, вы сможете определить корень документа, используя $_SERVER['SCRIPT_FILENAME'] и getcwd(). (Я не могу вспомнить все переменные $ _SERVER в голове, возможно, в phpinfo () есть что-то более полезное.)
В PHP5 есть магическая константа __FILE__, которая содержит абсолютный путь к файлу, в котором она появляется. Вы можете использовать его в сочетании с dirname для вычисления корня документа.
Вы можете поместить в файл конфигурации такую инструкцию
define ('DOCUMENT_ROOT', dirname(__FILE__));
это должно сработать
Уловка заключалась в использовании как абсолютного имени файла (либо из магической константы, либо из переменных сервера), так и в сочетании его со знанием абсолютного пути к корню документа из SCRIPT_NAME.
Начиная с PHP 5.3, это также использование __DIR__ вместо dirname(__FILE__).
Но это просто возвращает папку текущего файла, которая не обязательно является реальной корневой папкой веб-сервера.
Да, @Chuck, вы правы, но, если вы не можете полагаться на конфигурацию $ server (я бы не стал полагаться на все ее значения, если бы это не было принудительно) и у вас нет константы, вы должны прибегнуть к обходному пути . Тот, который я предложил, предназначен для решения, а лучше для того, чтобы дать подсказку к решению этого очень конкретного случая.
Нет необходимости изменять все скрипты.
Вы можете запустить файл PHP перед запуском любого сценария, используя auto_prepend_file.
$_SERVER - это просто массив, вы может модифицируете его и устанавливаете правильный $_SERVER['DOCUMENT_ROOT'].
Бесполезно запускать этот скрипт * при каждом запуске.
Бесполезно запускать этот скрипт при запуске каждый. Лучше обработайте это с помощью какого-нибудь .htaccess вместо того, чтобы его устанавливать.
Вы можете использовать php_value в .htaccess, чтобы установить auto_prepend_file, но автор вопроса упомянул сервер IIS, который, как я полагаю, не поддерживает это.
На самом деле, меня не волнует IIS, просто исходное решение должно было быть «независимым от платформы», и я не уверен, что оно будет работать и после этого. Но это автоматическое добавление выглядит интересно, спасибо за подсказку!
Почему бы не потребовать, чтобы ваш хостинг правильно настроил свои серверы?
такие вещи, как правило, незаметно задерживаются в вашем коде и никогда не удаляются (но остаются активными), пока кто-то наконец не исправит сервер. Тогда все снова сломается.
Или переместите свои вещи на хост, который будет работать. Если это сломано, кто знает, что вы найдете дальше.
Я не уверен, можно ли правильно настроить хост, похоже, проблема с mod_vhost_alias (согласно комментарию к webmasterworld.com/apache/3640691.htm).
Это одна из причин, по которой люди перекачивают все через загрузочный файл /index.php, используя htaccess и / или строки запроса. Вы можете использовать описанный выше трюк dirname( __FILE__ ) и таким образом получить общедоступную базу вашего приложения.
Если вы слишком далеко зашли в него, чтобы переключиться на единую точку входа, я видел, что люди используют общий заголовок для своего сценария, который проходит вверх по дереву каталогов в поисках файла, уникального для базового каталога:
function findAppBase( $dir ) {
if ( file_exists( "$dir/unique_file.txt" ) ) {
return $dir;
return findAppBase( dirname( $dir ) );
}
$base = findAppBase( dirname( __FILE__ ) );
Этот код не был протестирован, и может быть более удачный способ использования vars в $_ENV или $_SERVER, который будет делать то, что вы хотите ...
К счастью, это не проблема, у меня есть только одна точка входа. Просто я запускаю одно и то же программное обеспечение на нескольких доменах и хостах, и мне нужно исправить это для каждого домена. Я лучше отправлю исправление в апстрим, чтобы больше не заботиться об этом.
На основе http://www.helicron.net/php/:
$localpath=getenv("SCRIPT_NAME");
$absolutepath=getenv("SCRIPT_FILENAME");
$_SERVER['DOCUMENT_ROOT']=substr($absolutepath,0,strpos($absolutepath,$localpath));
Мне пришлось изменить трюк с базовым именем / реальным путем, потому что он возвращал пустую строку на моем хосте. Вместо этого я использую SCRIPT_FILENAME. Это, вероятно, больше не будет работать в IIS (но исходные сценарии, которые использовали переменную $ _SERVER, вероятно, тоже не будут).
Некоторые сценарии, которые я установил, «слишком умны» и знают, в какой каталог (относительно теоретического корня документа) они установлены, и добавляют его в корень документа (после того, как они получили его из базы данных). Мне все равно придется изменить код для каждого каталога, чтобы удалить каталоги ... или нет?