I want to replace all the dashes from my PHP filenames but I don't know how to do it.
Basically I have something like this:
http://localhost/category-activity.php
And I want to end up with this:
http://localhost/category/activity
I also need that the script scans for ALL dashes meaning that if I have something like:
http://localhost/category-activity-subactivity.php
Ends up in something like:
http://localhost/category/activity/subactivity
I am already using the following code to remove the extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php
Try this:
# not an existing directory and is a php file
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
# make sure there are no slashes and doesn't already end with .php
RewriteCond %{REQUEST_URI} !^/.+/.+
RewriteCond %{REQUEST_URI} !\.php$
RewriteRule ^(.*)$ $1.php [L]
# not an existing directory or file (this needs to take place so existing paths won't get / replaced with -
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)/(.*)$ /$1-$2 [L]
Mod-rewrite will continue to reapply rules until the URI doesn't get rewritten, so uri's like /category/activity/subactivity will continue to get rewritten until it goes through all the rules untouched.
Related
I want to add another language to my website (an app written in PHP 7).
I found out, good SEO practices say that every page on my site should be accessible from differend URLs, depending on the language.
Currently my .htaccess looks something like this:
RewriteEngine on
Options +FollowSymLinks
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^([a-zA-z0-9-]+)$ $1.php [NC,L]
So when user types in (or clicks a link) http://example.com/contact they get page contact.php (if exists).
What I want to achieve is, to redirect http://example.com/en/contact to the very same file contact.php, but with $_GET argument and still redirecting /contact to contact.php (without this argument). I thought that would be:
... everything from above code sample and then:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^en/([a-zA-z0-9-]+)$ $1.php?lang=en [NC,L]
But it doesn't work. Any ideas why and how to make this work?
Last condition checks that en/file.php exists, which is never the case. That's why the rule is never met. Either you remove it (but it will be applied even on nonexistent files) or you use this workaround by rewriting the faulty condition
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1\.php -f
RewriteRule ^en/([^/]+)$ /$1.php?lang=en [NC,L]
To be more complete, you can also redirect users that try to access /contact.php?lang=en directly (better for SEO). Here is how your final htaccess should look like
RewriteEngine On
# if url is /file.php?lang=en and file exists then redirect to /en/file
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{THE_REQUEST} \s/([^/\s\?&]+)\.php\?lang=en\s [NC]
RewriteRule ^ /en/%1? [R=301,L]
# if url is /en/file and /file.php exists then internally rewrite to /file.php?lang=en
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1\.php -f
RewriteRule ^en/([^/]+)$ /$1.php?lang=en [NC,L]
Note: the above code is specific to en language, but you can easily adapt it to multiple languages
Can you please help me to write correctly .htaccess file. I have this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
So it rewrites from domanname.com/page.php to domanname.com/page - but if I type in domanname.com/page/ it goes to 404 page. What should I change to correct this problem.
Thanks.
Adding a trailing slash at the end
I received many requests asking how to add a trailing slash at the end. Ignore the first snippet and insert the following code. The first four lines deal with the removal of the extension and the following, with the addition of the trailing slash and redirecting. Link to the HTML or PHP file as shown above. Don’t forget to change the code if you want it applied to an HTML file.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/$ $1.php
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
More info: http://alexcican.com/post/how-to-remove-php-html-htm-extensions-with-htaccess/
If you want to match a pattern whether or not there's a trailing slash, add the trailing slash followed by the regex optional operator ?.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^\.]+)/?$ $1.php [NC,L]
Also, added a RewriteCond to prevent existing directories from matching.
You can use this rule to allow for an optional trailing slash:
RewriteCond %{DOCUMENT_ROOT}/$1\.php -f [NC]
RewriteRule ^(.+?)/?$ /$1.php [L]
I have this rewrite rule that adds a .php extension to urls.
Url's entered look like this : http://localhost/Home
Url's read look like this : http://localhost/home.php
The problem i'm having is that some urls may look likes this:
http://localhost/sub/123
I should explain, this isn't actually a subdirectory. The sub part is the file and the 123 is used as a get variable. It looks cleaner this way.
If this happens you get a 500 error;
Here's what it is at the moment
#add php extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php
And here's what i've tried but doesn't work.
#add php extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)|(.*)/(.*)$ $1.php
Change your code with this to solve your problem:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteCond %{REQUEST_URI} !^/(phpscripts|js)/ [NC]
RewriteRule ^([^/]*)(?:/(.*?|))?/?$ /$1.php?$2 [L]
I use PHP.
A working htaccess-file
RewriteEngine On
RewriteBase /folder/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule .*[^/]$ $0/ [L,R=301]
RewriteCond $1 !^(index\.php)
RewriteRule ^(.+)$ index.php/$1 [L]
Look at the row with a # comment. When uncommented it adds a redirect to a slash. I use URL rewrite with toroPHP.
I want to rewrite to ending slash
I want to redirect to ending slash from rewritten URLs, just like the code above.
I don't want ending slash from real files, like jquery.js, style.css.
Example (updated 2012-12-21)
/category/test should be /category/test/
http://www.test.com/myjsfile.js should be http://www.test.com/myjsfile.js
Problem
If I use the code above uncommented it add an ending slash to all urls, including javascript files and css files.
I only want the rewritten urls to end with slash.
Question
Can it be done with htaccess? If so how?
The htaccess was almost correct. However the REQUEST_FILENAME needs to be before EVERY rewrite rule, not just before the first.
This works
RewriteEngine On
RewriteBase /folder/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .*[^/]$ $0/ [L,R=301]
RewriteCond $1 !^(index\.php)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php/$1 [L]
We are using an .htaccess in combination with anchor tags to serve files and conceal the server directory structure.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /_docu/clients/$1/$2/$3.pdf [NC,L]
For example, all files are stored under /public_html/_docu/clients/ and inside that folder are listed all the clients, and then under each client their projects. However, an anchor tag for a file would read only:
http://mydomain.com/client-name/proj-name/docname.pdf
(the /_docu/clients/ being omitted - there is a good reason for this). The above .htaccess grabs the client-name, proj-name and docname and serves it from the correct folder:
http://mydomain.com/_docu/clients/client-name/proj-name/docname.pdf
whilst preserving in the address bar the incorrect (concealed) directory structure.
I wish to handle the error condition of a document not existing. This should never happen, but it could. Can anyone suggest a way of dealing with this? Can something functionally akin to "if fileexist($1/$2/%3.pdf)" be somehow constructed in an .htaccess file?
EDIT:
Delayed response as JL's answer below required research and experimentation. Thanks, Jon, for the gentle push in the right direction but I haven't got it to work just yet. Here's what I tried:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# check if the requested file exists in the "_docu/clients" directory
RewriteCond %{DOCUMENT_ROOT}/_docu/clients/$1/$2/$3.pdf -f
RewriteRule ^([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$ /_docu/clients/$1/$2/$3.pdf [NC,L]
RewriteRule ^(.*)$ /errors/404.php [L]
I thought that what that should do is:
If http://mydomain.com/_docu/clients/$1/$2/$3.pdf does not exist,
GoTo page http://mydomain.com/errors/404.php
Actual outcome is an "internal server error" message.
EDIT TWO:
Latest changes:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$
RewriteCond %{DOCUMENT_ROOT}/_data/cli/%1/%2/%3.pdf -f
RewriteRule ^([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$ /_data/cli/$1/$2/$3.pdf [NC,L]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^(.*)$ /metshare/404.php [L]
The problem with this one is that legitimate pages also are directed to 404.php
MESSAGE TO FUTURE READERS:
All of the above concerns were addressed in Jon Lin's final answer. As issues were detected, he modified his answer until it was a perfect, working solution. I am leaving the above as it is because there are some good ULOs within (unscheduled learning opportunities) for those who want to compare versions.
You need to use a condition like this:
RewriteCond %{DOCUMENT_ROOT}/_docu/clients%{REQUEST_URI} -f
So that your rules looks ssomething like:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# check if the requested file exists in the "_docu/clients" directory
RewriteCond %{DOCUMENT_ROOT}/_docu/clients%{REQUEST_URI} -f
RewriteRule ^ /_docu/clients%{REQUEST_URI} [L]
EDIT: Response to edit in question
You can't do this:
RewriteCond %{DOCUMENT_ROOT}/_docu/clients/$1/$2/$3.pdf -f
Because the backreferences for $1/$2/$3 don't exist yet, they are matched in the groupings in your RewriteRule, which hasn't happened yet at this point. But you can try something like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# check if the requested file exists in the "_docu/clients" directory
RewriteCond %{REQUEST_URI} ^/([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$
RewriteCond %{DOCUMENT_ROOT}/_docu/clients/%1/%2/%3.pdf -f
RewriteRule ^([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$ /_docu/clients/$1/$2/$3.pdf [NC,L]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /errors/404.php [L]
Essentially creating a match against %{REQUEST_URI} in a previous RewriteCond then using the %N backreferences in the following RewriteCond.