I have a project running local on WampServer. It's an MVC-like structure; it rewrites the URL to index.php?url=$1
. Full .htaccess
:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
When I want to send the user to another page using PHP location: <location>
it doesn't do this properly because of the rewriting (all-though I am technically always in index.php
).
For example if I am on http://localhost/project_name/controller/method/
and this controller's constructor or method tries to send me to:
header('location: another_controller/method');
sends me to
http://localhost/project_name/controller/method/another_controller/method/
header('location: /another_controller/method');
sends me to
http://localhost/another_controller/method/
But I want it to send me like this:
header('location: /another_controller/method');
sends me to
http://localhost/project_name/another_controller/method/
Now the only solution I have found is:
define('BASE_URL','http://localhost/project_name');
header('location: '.BASE_URL.'/another_controller/method/');
But this isn't perfect either because it causes me to have to change this defined constant BASE_URL
whenever the domain or folder name changes. I could also create a method in my BaseController
that creates absolute URLs, but this method would basically just prepend BASE_URL
too.
Note: The same problem doesn't arise with HTML's src
and href
attributes, which can use relative paths (without project_name
folder in path). I don't understand why however. Because if the header location
causes the browser to append the the relative-URL to the current location, why doesn't it have the same behavior when looking for .css
or .js
files.
So... this raises a couple of questions for me:
src
and href
attributes not share this behavior?Now the only solution I have found is:
define('BASE_URL','http://localhost/project_name'); header('location: '.BASE_URL.'/another_controller/method/');
But this isn't perfect either because it causes me to have to change this defined constant BASE_URL whenever the domain or folder name changes.
You shouldn't need to change the defined constant. These values can be found dynamically.
Example:
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);
Additionally, rather than worrying about whether to specify an absolute URL or a path, you can wrap the redirect into a function which can handle both:
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;
}
Finally, as @HarshSanghani mentioned in the comments, the base path in your .htaccess
file should match the base path in your code. So if BASE_PATH
(based on the example above) outputs /project_name/
, then your .htaccess
should accommodate it:
RewriteBase /project_name/
To answer your questions:
$baseUrl = dirname($_SERVER['SCRIPT_NAME']);
. This way you won't have to change any code if your folder or domain changes.src
and href
are interpreted by your browser which takes into account the page's <base>
tag. All paths on a page with a <base>
tag get changed accordingly by your browser.The HTTP headers you send from your server (for redirect) have nothing to do with the html page you send and are therefore not updated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With