Reputation: 435
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?Upvotes: 11
Views: 2395
Reputation:
You should specify RewriteBase in your htaccess file. Use relative paths in your links and you need nothing more.
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]
Upvotes: 2
Reputation: 311
$baseUri
somehow.Upvotes: 2
Reputation: 6252
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/
Upvotes: 4
Reputation: 297
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.
Upvotes: 2