Отличный способ заставить единую точку входа (фронт-контроллер) работать с наиболее распространенными настройками веб-сервера
Это не будет легко, спасибо всем читающим это!:)
6 дней спустя: только кстати: это мой второй подход для решения этой проблемы: пересылка всех запросов в один файл index.php для несуществующих файлов, но * включая * сам index.php
И вот реальный код, который я пытаюсь решить это: https://github.com/kpion/point1
; TL; DR;
Как мы можем узнать, что является корнем документа независимо от настройки веб-сервера (nginx/apache/apache с hattacces). В случае, когда корнем htaccess является местоположение самого htaccess.
Вступление
Я постараюсь быть максимально информативным:)
Это все о пересылке всех запросов в один файл index.php (исключая существующие файлы). Да, довольно распространенные задачи.
Проект живет в: /var/www/html/point/point1
Это может быть как dev, так и prod env.
Я хочу, чтобы все запросы отправлялись в "index.php" с информацией о том, что на самом деле было запрошено.
подробности
Предполагая, что хостом проекта является 'point1', и он живет в /var/www/html/point/point1
-
Когда пользователь вводит http://point1/foo/bar - я хочу, чтобы веб-сервер запустил /var/www/html/point/index.php и отправил на него информацию о запрошенном URL (в данном случае /foo/bar).
Я хочу знать "foo" и "bar";
Это довольно просто с vhosts на apache и nginx. Например, в Apache:
<directory /var/www/html/point/point1>
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ index.php
</directory>
И nginx:
location /{
server_name point1;
root /var/www/html/point/point1;
try_files $uri $uri/ /index.php$is_args$args
}
location ~ \.php$ {
#...handle php
}
Это легко, потому что тогда мы можем легко получить "оставшуюся часть" в
var_dump($_SERVER['REQUEST_URI']);
"REQUEST_URI" var сообщает нам, что находится после "host".
Хорошо.
Теперь приходит.htaccess. Предполагая, что у пользователя нет доступа к настройкам веб-сервера, вот типичный способ:
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,L]
проблема
Я хочу, чтобы мой сценарий обрабатывал все эти ситуации. Это легко, если мы ограничим это "vhosts". В этом случае "корень документа" известен. Вот почему это работает:
$request = $_SERVER['REQUEST_URI'];
$file = $_SERVER['REQUEST_URI'][1];
$method = $_SERVER['REQUEST_URI'][2];
Мы знаем, что $file теперь относится к $_SERVER['DOCUMENT_ROOT'];
За исключением того, что когда я хочу поддержать.htaccess, это не так просто. Потому что я не знаю "document_root", то есть знаю - но это часто корень всех проектов - /var/www/html
Итак, что я получаю в "$_SERVER['REQUEST_URI']", это "/point/point1/foo/bar", и я не знаю, какая часть отвечает за "foo" и "bar";
Кажется, что в Symfony эта часть кода имеет дело с этим:
https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php
Но я не совсем уверен.
Что я сделал, так это то, что я добавил в.htaccess это:
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,L]
SetEnv USE_URI_PROTOCOL PATH_INFO
Как вы можете видеть, я устанавливаю переменную окружения, чтобы потом использовать ее в моей единственной точке входа php:
$uriProtocol = getenv('USE_URI_PROTOCOL')?:'REQUEST_URI';
$request = isset($_SERVER[$uriProtocol])?$_SERVER[$uriProtocol]:'';
//getting only what's before ? (uri query string) if it exists
if (($pos = strpos($request, '?')) !== false){
$request = substr($request, 0, $pos);
}
//trimming slashes
$request = trim($request, '/');
$requestArray = empty($request)? [] : explode('/', $request);
var_dump('controller',$requestArray[0] ?? 'undefined');
var_dump('method',$requestArray[1] ?? 'undefined');
Это работает. Но что-то говорит мне, что это не очень круто.
Надеюсь, мне ясно здесь? Речь идет об одном простом решении, которое можно сделать на передней панели контроллера.