so I want to rewrite a URL. The default URL is http://example.com/m.php?i=random_string
Here's the rule
RewriteEngine On
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule !.*\.php$ %{REQUEST_FILENAME}.php [QSA,L]
RewriteRule ^m/([^/]+)/?$ m?i=$1 [L]
However, when I access http://example.com/m/random_string, the page comes up but my external css and js files don't load. Why does this happen? I thought that the directory does not change from the original rewritten URL.
The directory indeed does not change, but browser doesn't know that - what it gets looks like a directory, such as m/something, so it tries to load the CSS file relative to this directory.
To fix that, use absolute paths to your CSS and JS in the page, ie.:
/css/style.css
(the initial forward slash makes it absolute)
RewriteEngine On
RewriteRule ^m/([^/]+)/?$ m.php?i=$1 [L]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)(\?.*|)?$ %{REQUEST_FILENAME}.php$2 [QSA,L]
Have your rules like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^m/([^/]+)/?$ m.php?i=$1 [L,QSA,NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1\.php -f [NC]
RewriteRule ^(.+?)/?$ /$1.php [L]
RewriteCond %{REQUEST_FILENAME} !-d and RewriteCond %{REQUEST_FILENAME} !-f will prevent first rewrite rule to be applied for real files and directories.
Related
I'm trying to do a rewrite, where if the page doesnt exist, it rewrites to a category page. Its a bit different to the normal RewriteCond %{REQUEST_FILENAME} -f as the page name is dynamic based on the URL.
If somebody visits a dynamic path name such as "/contacts"
I first want it to check if the following folder/file exists based on the path name:
/[dynamicpath]/[dynamicpath].php
example:
/contacts/contacts.php
If that doesnt exist, rewrite to the following page
/categories/category/category.php?cat_url=[dynamicpath]
example:
/categories/category/category.php?cat_url=contacts
I've tried the below, but it fails with the first RewriteRule triggering when the file exists and goes straight to the category rewrite.
RewriteCond %{SCRIPT_URL} ^(.+)
RewriteCond %{DOCUMENT_ROOT}/%1/%1.php !-f
RewriteRule (.+)/?$ $1/$1.php [QSA,L]
RewriteRule ^([\w-]+)/?$ /categories/category/category.php?cat_url=$1 [QSA,L]
You may use these rules in your site root .htaccess:
RewriteEngine On
# attempt rewrite to /[dynamicpath]/[dynamicpath].php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1/$1.php -f
RewriteRule ^(.+?)/?$ $1/$1.php [L]
# else rewrite to categories/category/category.php?cat_url=...
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+?)/?$ categories/category/category.php?cat_url=$1 [QSA,L]
I found the answer by checking the server variables being passed and discovered %{REQUEST_FILENAME} included the full file path (document_root+filename).
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}%{REQUEST_URI}.php -f
RewriteRule ^(.+)/?$ $1/$1.php [L]
RewriteRule ^(.+)/?$ categories/category/category.php?cat_url=%{REQUEST_URI} [QSA,L]
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
I have the following rewrite in my .htaccess file which removes the .php extension from files, converting for example so.com/question.php to so.com/question.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
However this also breaks the default DirectoryIndex behaviour, in which just typing the directory will redirect to the index file in the folder, e.g. so.com/answer displays so.com/answer/index.php
Simply combining the above code with DirectoryIndex index.php does not achieve both results.
Can someone help me combine these two functions, or rewrite the code to exclude index.php files, which would achieve the same result?
I'm thinking you just need to verify that the file exists prior to doing the rewrite, that way you'll leave 404 and directoryindex behaviours intact:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
(not tested)
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php
I tested and it is working fine.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule !.*\.php$ %{REQUEST_FILENAME}.php [L, QSA]
verify files and folder and also, add RewriteBase /
I have the following in my .htaccess which is :
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ /index.php?type=cat&id=$1 [QSA,L]
RewriteRule ^page/([^/]+)$ /index.php?type=page&name=$1
This seems to work just fine but relative paths to pictures and css files inside of index.php become broken in the second case (Page). did not work. In second case, all images are pointing to page/images/ instead of image/
Other than hardcoding the actual path to images, is there any other way to fix this?
images, css, js folders are located in the root. This is how the root looks like
.htaccess
index.php
images/
css/
js/
RewriteCond directives only apply to the rule directly following them.Try the follwing
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ /index.php?type=cat&id=$1 [QSA,L]
RewriteCond %{REQUEST_URI} !\.(css|js|jpe?g|gif|png)$ [NC]
RewriteRule ^page/([^/]+)$ /index.php?type=page&name=$1 [L]
#rewrite requests for page/images to images
RewriteCond %{REQUEST_URI} ^/page(/images/.+)$ [NC]
RewriteRule . %1 [L]
EDIT.
Modified to rewrite page/images to images
I managed to solve this problem by the following code:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} ^GET\ /[^?\s]+\.php
RewriteRule (.*)\.php$ /$1/ [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)/$ $1.php [L]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule .*[^/]$ $0/ [L,R=301]
In other words, not to do anything if its a directory.
Yet, my current problem is that css and the images are not loaded until I change the path to the css file and to the images to the absolute path.
Is there any other way to solve it rather then changing all the paths in all the files in the website to absolute.
Thanks a lot.
Add RewriteCond %{REQUEST_FILENAME} !-f to the first two RewriteCond, then images and css won't hit the rewrite, but PHP files will, and things that are not folders will also hit the rewrite