php - URL absoluta desde la carpeta base con reescritura
.htaccess mod-rewrite (4)
Para responder tu pregunta:
- Depende de cómo se configurarán sus hosts virtuales.
- Simplemente puede generar su BASE_URL dinámicamente:
$baseUrl = dirname($_SERVER[''SCRIPT_NAME'']);
. De esta forma, no tendrá que cambiar ningún código si su carpeta o dominio cambia. - No necesitas la parte de dominio.
- Los html
src
yhref
son interpretados por su navegador, que tiene en cuenta la etiqueta<base>
la página. Todas las rutas en una página con una etiqueta<base>
se cambian según su navegador.
Los encabezados HTTP que envía desde su servidor (para redirección) no tienen nada que ver con la página html que envía y, por lo tanto, no se actualizan.
Tengo un proyecto ejecutándose localmente en WampServer. Es una estructura similar a MVC; reescribe la URL a index.php?url=$1
. Completo .htaccess
:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
Cuando deseo enviar al usuario a otra página usando la location: <location>
PHP location: <location>
no hace esto correctamente debido a la reescritura (aunque técnicamente siempre estoy en index.php
).
Por ejemplo, si estoy en http://localhost/project_name/controller/method/
y el constructor o método de este controlador intenta enviarme a:
-
header(''location: another_controller/method'');
me envía ahttp://localhost/project_name/controller/method/another_controller/method/
-
header(''location: /another_controller/method'');
me envía ahttp://localhost/another_controller/method/
Pero quiero que me envíe así:
-
header(''location: /another_controller/method'');
me envía ahttp://localhost/project_name/another_controller/method/
Ahora la única solución que he encontrado es:
define(''BASE_URL'',''http://localhost/project_name'');
header(''location: ''.BASE_URL.''/another_controller/method/'');
Pero esto tampoco es perfecto porque me obliga a tener que cambiar esta constante definida BASE_URL
siempre que BASE_URL
el nombre del dominio o de la carpeta. También podría crear un método en mi BaseController
que crea direcciones URL absolutas, pero este método básicamente también precedería a BASE_URL
también.
Nota: El mismo problema no surge con los atributos src
y href
HTML, que pueden usar rutas relativas (sin la carpeta project_name
en la ruta). No entiendo por qué sin embargo. Porque si la location
del encabezado hace que el navegador anexe la URL relativa a la ubicación actual, ¿por qué no tiene el mismo comportamiento cuando busca archivos .css
o .js
?
Entonces ... esto plantea un par de preguntas para mí:
- ¿Tendría este problema si tuviera hosts virtuales?
- ¿Cuál es la mejor manera de resolver este problema?
- ¿Es mejor simplemente tener la URL absoluta completa?
- ¿Por qué los atributos
src
yhref
HTML no comparten este comportamiento?
Ahora la única solución que he encontrado es:
define(''BASE_URL'',''http://localhost/project_name''); header(''location: ''.BASE_URL.''/another_controller/method/'');
Pero esto tampoco es perfecto porque me obliga a tener que cambiar esta constante definida BASE_URL siempre que cambie el nombre del dominio o de la carpeta.
No debería necesitar cambiar la constante definida. Estos valores se pueden encontrar dinámicamente.
Ejemplo:
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);
Además, en lugar de preocuparse por especificar una URL absoluta o una ruta, puede ajustar la redirección en una función que pueda manejar ambos:
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;
}
Finalmente, como @HarshSanghani mencionó en los comentarios, la ruta base en su archivo .htaccess
debe coincidir con la ruta base en su código. Entonces, si BASE_PATH
(basado en el ejemplo anterior) genera /project_name/
, su .htaccess
debe acomodarlo:
RewriteBase /project_name/
- Tendrá este problema si tiene su proyecto configurado en un subdirectorio. El uso de servidores virtuales sería una forma de evitar el problema si desea configurarlos en say, project_name.localhost.
- En mis proyectos, utilizo una variable de entorno para cargar un archivo de configuración diferente para desarrollo, montaje o producción. En esto establecí un
$baseUri
alguna manera. - Es una buena práctica usar las URL absolutas (incluido el dominio) tanto para la solución de este problema como para el SEO. En términos de funcionalidad, no necesita la parte del dominio.
- Las etiquetas src y href generalmente funcionan de la misma manera, pero como Andreas mencionó, podrían verse afectadas por la etiqueta base.
Debe especificar RewriteBase en su archivo htaccess. Use rutas relativas en sus enlaces y no necesita nada más.
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]