Background
Trying to recreate StackOverflow-style pretty URLs using Apache's mod rewrite and PHP.
Problem
This works great:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ([0-9]+)$ index.php?id=$1 [L]
</IfModule>
URLs like http://localhost/home/script/5 redirect to http://localhost/home/script/index.php?r=5. The CSS content loads flawlessly.
URLs like http://24.68.226.186/recipes/recipe/5/seo-text redirect, but the relative path for the CSS files is then incorrect:
<link rel="StyleSheet" hreF="css/theme.css" type="text/css" media="screen,print" id="css-theme" />
Directories
The directory structure for the script (index.php) resembles:
htdocs/home/script
htdocs/home/script/.htaccess
htdocs/home/script/index.php
htdocs/home/script/css
htdocs/home/script/images
Question
How do you use mod rewrite to tell Apache to use the "script" directory when serving files instead of any sub-directory appended to the URL?
In other words, how would you use mod rewrite to lop off the "seo-text" part of the URL and (1) ensure it reflects the actual title [sourced from a database]; (2) redirect the browser to the new URL [if necessary]; and (3) tell Apache to ignore all paths beyond the ID in the URL?
I would rather not use absolute paths in the CSS.
Thank you!
Used Logan's advice:
<base href="/home/script/" target="_self" />
This does not work with IE8, due to a bug.
Related
i have .htaccess file and this is a script within it:
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^register/$ index.php?c=Page&a=register [L]
</IfModule>
in my layout file, i load css and js with absolute path like this:
<link href="/public/assets/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="/public/assets/bower_components/bootstrap-extension/css/bootstrap-extension.css" rel="stylesheet">
and i access localhost/project/register/ but
the css/js file is not loaded bacause of error:
GET http://localhost/public/assets/bootstrap/dist/css/bootstrap.min.css net::ERR_ABORTED
why it directly access to /public after localhost? it should be localhost/project/public not localhost/public
if i remove first / at css link it access to localhost/project/register/public
Your css link is not correct. It is starting with /public which means Apache will attempt to find it in the public folder under site root.
You should update your path to relative one:
<link href="public/assets/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="public/assets/bower_components/bootstrap-extension/css/bootstrap-extension.css" rel="stylesheet">
And then add this just below <head> section of your page's HTML:
<base href="/project/" />
so that every relative URL is resolved from that base URL and not from the current page's URL.
Alternative to <base ../> tag in HTML, you can use this redirect rule in your .htaccess as very first rule:
RewriteRule ^public/.+\.(?:css|js)$ /project%{REQUEST_URI} [L,NC,NE,R=301]
However do note that a redirect rule (even with R=301) will still make a new client to send 2 requests to your web server. First with /public/... URI and 2nd a /project/public/... URI after redirect.
It seems that you have two separate questions.
For your question, there is nothing in that .htaccess rule you've shown which would change the way that an existing .css or .js file would be displayed. And so, very likely either your links weren't working before, or you had some other content in the file before to rewrite the URLs differently that you have removed. That file is simply stating that if a URL is given and there is no file or directory which matches it, then rewrite the URL for a certain URL. That does seem to be a mistake, since the URL either exists or does not.
Your second question is about the URLs and why you don't have /project in them. I'm not certain why you believe they should have /project in them, but I'm assuming that you had assumed that because your original HTML is in that directory. You are starting your link with a /, as in /public/assets/bootstrap/dist/css/bootstrap.min.css". That / means that the path is absolute, rather than relative, meaning that the path is started directly after the hostname. If you remove the initial /, then the path would be relative to the URL that it is called from.
If you want to load these files relative to the domain root and the public directory is not in the domain root, you'll need to provide the full domain relative path:
<link href="/project/public/assets/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="/project/public/assets/bower_components/bootstrap-extension/css/bootstrap-extension.css" rel="stylesheet">
When I use rewrite rules to clean my URL, I can't access my CSS files. Without the rewrite rules my page works fine, but with the rewrite rules images,CSS and JS documents cannot be linked. What could be the problem?
My .htaccess codes
RewriteEngine On
RewriteRule ^index?$ index.php
RewriteRule ^product_details/([0-9]+) product_details.php?id=$1
Now I don't understand why my edit.php is unable to locate external files even though it loads from the correct path on server-side (mysite.com/). And it does not show the URL in an extra directory (in this case mysite.com/e/).
Mod Rewrite will redirect www.example.com/product_details/123 to product_details.php?id=123 on server-side.
Your browser thinks that /product_details/ points to a directory and resolves relative links accordingly.
The solution is to use absolute paths or add <base href="//www.example.com/"> to your html head element.
Here comes a question because my current solution is not really satisfying me for the following problem:
I have an own PHP Framework with MVC pattern in development. And my Router works perfect and all but I have one question I could not find a solution for.
Well I route every incoming request to index.php file which is located in the base-path of my framework. Ofcourse it is no problem to work with relative paths when including css such as:
<link rel="stylesheet" type="text/css" href="style/include/css/style.css" />
This works perfect in the browser. Ofcourse it does not matter what I enter in the URL because every request gets redirected as stated above to the index to make a reasonable routing possible.
However when my url contains multiple slashes which look like subfolders, for example: "/manual/details/1_2" then I get a normal routing process but the browser cannot find the css file unless I add "../" for each "/" in my url to map backwards to my base-path.
For example for the above URL this would work instead:
<link rel="stylesheet" type="text/css" href="../../style/include/css/style.css" />
My curent solution:
I wrote a PHP function in my Routing class that determines the required amount of "../" pattern and I always cast the function before implementing a resource to build the exact
path at any time.
Example:
<link rel="stylesheet" type="text/css" href="<?=Router::getInstance()->getSubdirectoryPrefix()?>style/include/css/style.css" />
Needless to say that this is very unhandy and also sucks if you forget to place that function. If your route ever changes or you forget that you are in a subdirectory you will wonder why your resource could not be found.
I also know about putting an alias such as Alias /public style/ in my Virtual-Host configuration of Apache but I want to find another - project and PHP internal way without having an unhandy crap such as pasting the alias function all the time and without setting up a virtual-host option so the framework can stay lightweight and does not require any nasty external options like modifying Virtual-Host.
I'd love to hear your solutions, best would be .htacces - oh and by talking over it I leave my .htaccess code here aswell:
RewriteEngine On
Options -Indexes
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php [L]
Thanks in advance for your help~
You must use absolute paths instead of relative paths for your html links (css, javascript, images, etc).
For example:
<link rel="stylesheet" type="text/css" href="/style/include/css/style.css" />
The leading slash (before style) means to begin from document root folder, then go into style folder, and so on... (you may have another prefixed directory if it's not in root folder)
You had some problems because some of your rules can create virtual directories (e.g: http://domain.com/some/directory/subdirectory/etc/).
Also, in your htaccess, it wouldn't hurt to use a leading slash (or a RewriteBase)
Options -Indexes
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /index.php [L]
or (both are the same)
Options -Indexes
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php [L]
I have used htaccess to rewrite my links on my page
RewriteEngine On
RewriteRule ^search/([^&]+)$ search.php?q=$1 [L]
RewriteRule ^login/?$ login.php [L]
# etc..
On my PHP pages I have made all my links absolute like this
<?php require("/incl_head.php"); ?>
<link href="/css/css_file.css" rel="stylesheet" type="text/css">
<img src="/images/image.jpg">
This works fine locally, but now I want to test it online, and I have to put it into a subfolder, since my old page is still active.
My subfolder will be test so that my domain will be www.mydomain.dk/test/
But then my pages dosent work, since all my links are absolute, and dont have /test/ in front
Is it somehow possible to make all links have /test/ in front for example using htaccess file (without interrupt my other rules)?
Or what should I do?
Have seen some html base possibilities or some where they save root in vaiable and include in front of all links. But if I add that into a file and tries to include it, I would have the same problem with those includes on every page.
Hope someone can help me
Option 1:
Try this rule in your DOCUMENT_ROOT/.htaccess file:
RewriteRule !^test/ /test%{REQUEST_URI} [L,NC,R]
Option 2: You can try adding this in your page's header:
<base href="/test/" />
I'm having a go at mod_rewrite so that the client can list better urls on Google
So I've created a page (www.cruiseandmaritime.com/cruise_details_by_name.php which is where I send things like
www.cruiseandmaritime.com/cruises/French-Leave
works fine, the page loads with the right data, but there is no stylesheet loaded so it's all just unformatted
Now I'm guessing, that because I have created the imaginary directory 'cruises' its something to with that... ?
Here is my line in the .htaccess file
RewriteEngine On # Turn on the rewriting engine
RewriteBase /
RewriteRule ^cruises/([A-Za-z0-9-]+)?$ cruise_details_by_name.php?id=$1 [NC,L] # Handle requests for all cruises
once again, any help greatly appreciated !
Rich:)
I don't think that's a mod_rewrite problem.
In your html code there's a link to your css file:
<link rel="stylesheet" type="text/css" href="stylesheets/anytime.css" />
Currently the browser is trying to load the file located at http://www.cruiseandmaritime.com/cruises/stylesheets/anytime.css
If you let the file path start with / this should work. That way an absolute uri is used instead of a relative one.