У меня есть проект, работающий локально на WampServer. Это MVC-подобная структура; переписывает URL index.php?url=$1
, Полный .htaccess
:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
Когда я хочу отправить пользователя на другую страницу, используя PHP location: <location>
это не делает это должным образом из-за переписывания (все-хотя я технически всегда в index.php
).
Например, если я нахожусь на http://localhost/project_name/controller/method/
и конструктор или метод этого контроллера пытается отправить меня к:
header('location: another_controller/method');
отправляет меня вhttp://localhost/project_name/controller/method/another_controller/method/
header('location: /another_controller/method');
отправляет меня вhttp://localhost/another_controller/method/
Но я хочу, чтобы он отправил меня так:
header('location: /another_controller/method');
отправляет меня вhttp://localhost/project_name/another_controller/method/
Теперь единственное решение, которое я нашел, это:
define('BASE_URL','http://localhost/project_name');
header('location: '.BASE_URL.'/another_controller/method/');
Но это также не идеально, потому что это заставляет меня изменить эту определенную константу BASE_URL
всякий раз, когда меняется имя домена или папки. Я мог бы также создать метод в моем BaseController
который создает абсолютные URL, но этот метод в основном просто предваряет BASE_URL
тоже.
Замечания: Та же проблема не возникает с HTML src
а также href
атрибуты, которые могут использовать относительные пути (без project_name
папка в пути). Однако я не понимаю, почему. Потому что, если заголовок location
заставляет браузер добавлять относительный URL к текущему местоположению, почему при поиске он не работает так же .css
или же .js
файлы.
Так… это поднимает пару вопросов для меня:
src
а также href
атрибуты не разделяют это поведение?Теперь единственное решение, которое я нашел, это:
define('BASE_URL','http://localhost/project_name'); header('location: '.BASE_URL.'/another_controller/method/');
Но это тоже не идеально, потому что это заставляет меня менять
это определенная константа BASE_URL всякий раз, когда имя домена или папки
изменения.
Вам не нужно менять определенную константу. Эти значения могут быть найдены динамически.
Пример:
if ($_SERVER['DOCUMENT_ROOT'] == dirname($_SERVER['SCRIPT_FILENAME'])) {
define('BASE_PATH', '/');
} else {
define('BASE_PATH', dirname($_SERVER['SCRIPT_NAME']) . '/');
}
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
define('BASE_URL', $protocol . $_SERVER['SERVER_NAME'] . BASE_PATH);
Кроме того, вместо того, чтобы беспокоиться о том, указывать ли абсолютный URL или путь, вы можете заключить перенаправление в функцию, которая может обрабатывать оба:
function redirect($path = null) {
if (isset($path)) {
if (filter_var($path, FILTER_VALIDATE_URL)) {
header('Location: ' . $path);
} else {
header('Location: ' . BASE_URL . $path);
}
} else {
header('Location: ' . BASE_URL);
}
exit;
}
Наконец, как отметил @HarshSanghani в комментариях, базовый путь в вашем .htaccess
файл должен сопоставьте базовый путь в вашем коде. Так что если BASE_PATH
(на основе приведенного выше примера) /project_name/
тогда ваш .htaccess
следует учесть это:
RewriteBase /project_name/
Чтобы ответить на ваши вопросы:
$baseUrl = dirname($_SERVER['SCRIPT_NAME']);
, Таким образом, вам не придется менять код, если ваша папка или домен изменятся.src
а также href
интерпретируются вашим браузером, который учитывает <base>
тег. Все пути на странице с <base>
тэг изменяется соответственно вашим браузером.Заголовки HTTP, которые вы отправляете со своего сервера (для перенаправления), не имеют ничего общего с отправляемой вами HTML-страницей и поэтому не обновляются.
$baseUri
как-то.Вы должны указать RewriteBase в вашем файле htaccess. Используйте относительные пути в своих ссылках, и вам больше ничего не нужно.
RewriteBase /project_name/
RewriteEngine on
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]