Working on a Laravel project and trying to get a simple URL rewrite working. Here is the .htaccess file, located in the '/public' folder — you can see I have added one rule
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
# above is default, rule added by me:
RewriteRule ^articles/page/([a-zA-Z0-9-/]+)$ /articles?page=$1 [L]
</IfModule>
However, this just 404s. I suspect the default rule is breaking it somehow but don't know enough to fix it.
Can anyone help, please?
It would appear to me that your rule to convert articles/page/{slug} into articles?page={slug} is never hit. Because the rule is the bottom-most and your index.php rewrite rule says it's the "last" rule ([L]) and matches anything it wins every time (i.e. there's never any fall-through to your new rule).
Move your articles-specific rule between RewriteBase and RewriteCond and don't mark it as the last rule (get rid of [L]) and try again. That should transform articles/page/{slug} into articles?page=slug and then pass that on to the index.php rule.
You may also need the QSA rewrite rule option to make sure the query string you create works with any query string that exists already.
See:
http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule
http://httpd.apache.org/docs/current/rewrite/flags.html
Try changing order of your rules:
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteBase /
# above is default, rule added by me:
RewriteRule ^articles/page/([a-zA-Z0-9/-]+)/?$ /articles?page=$1 [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Or you can use Laravel's routes:
Route::get("/articles/page/{article}", "ArticleController#showArticle")
->where("article", "[a-zA-Z0-9/-]+");
And the controller:
class ArticleController extends Controller {
public function showArticle( $articleID ) {}
}
I think this is a better approach.
Related
I have recently moved to a new server for my website, and i activated mod_rewrite with success, but some files still not working !
Like this one:
RewriteRule ^activate\/(.*)\/(.*)$ activate.php?Email=$1&hash=$2
I have made all necessary changes on my VPS (Ubuntu) !
Any idea ?
Like this lines work well:
RewriteRule ^search\/(.*)\/([a-zA-Z0-9_-]+)$ search.php?view=$1&p=$2
RewriteRule ^search$ searchResults.php
RewriteRule ^term$ term.php
RewriteRule ^faq$ faq.php
# Non-working line...
RewriteRule ^activate\/(.*)\/(.*)$ activate.php?Email=$1&hash=$2
Note that mod_rewrite are enabled and all other lines work well only this one !
First thing, you must define a RewriteBase because of your two rules (first and last) that create both virtual directories.
Then, you should disable MultiViews option to make term or faq rule work without problem.
Finally, you can rewrite your patterns in a more generic way (or at least in a better way, more precise). Also, don't forget L flag ([L]) after each rule, otherwise mod_rewrite continues to evaluate next rules.
You can replace your current code in your htaccess by this one (assuming your htaccess is in root folder)
Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteRule ^search/([^/]+)/([^/]+)$ search.php?view=$1&p=$2 [L]
RewriteRule ^search$ searchResults.php [L]
RewriteRule ^term$ term.php [L]
RewriteRule ^faq$ faq.php [L]
RewriteRule ^activate/([^/]+)/([^/]+)$ activate.php?Email=$1&hash=$2 [L]
I have updated country code in the base path and I am attempting the redirect users that end up going to:
www.example.com/uk/etc1/etc2/etc..
www.example.com/gb/etc1/etc2/etc..
But also sometimes also www.example.com/uk#etc
I thought this would be fairly trivial in mod_rewrite I cant get anything to work.
The closest I feel I have come is the following rule, but nothing happens when I land on uk.
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine on
RewriteRule .* index.php [L] #this is active already on the page
RewriteRule ^/uk(.*) /gb(.*) [R]
</IfModule>
Edit:
This seems closer but I am getting stuck in an endless loop:
RewriteRule ^uk(.*) /gb$1 [R]
Edit 2 / (3) Answer:
This seems to redirect correctly(is correct):
RewriteRule ^uk(.*)$ /gb$1 [R=302,L]
RewriteRule .* index.php [L]
But the formatting is broken on the page, looks like some loop problem.
But the formatting is incorrect, If I swap the two RewriteRules the formatting is correct but the uk => gb conversion doesn't seem to get called at all.
Answer
Be careful of Rewriteconditions, I failed to notice the significance of them and I removed them for the original index.php rewrite which meant it could not locate any media.
I failed to take notice of the rewrite conditions which applied for the original index.php
This should do the trick:
Options +FollowSymLinks
DirectoryIndex index.php
RewriteEngine on
RewriteRule ^/uk(.*) /gb$1 [R=301,L]
Bellow is my basic .htaccess code
Options +FollowSymLinks
RewriteEngine on
RewriteBase /artist/
RewriteRule ^member/([^/]*)$ /artist/index.php?member=$1
Bellow is my static .htaccess code
Options +FollowSymLinks
RewriteEngine on
RewriteBase /artist/
#we module doing some action
RewriteRule ^member/([^/]*)/([^/]*)/action/([^/]*)/$ /artist/index.php?member=$1&module=$2&action=$3
#action operation e.g create
RewriteRule ^member/([^/]*)/([^/]*)/action/([^/]*)/opt/([^/]*)/$ /artist/index.php?member=$1&module=$2&action=$3&opt=$4
#if only module calls
RewriteRule ^member/([^/]*)/([^/]*)/$ /artist/index.php?member=$1&module=$2
RewriteRule ^member/([^/]*)/([^/]*)/opt/([^/]*)/$ /artist/index.php?member=$1&module=$2&opt=$3
RewriteRule ^member/([^/]*)$ /artist/index.php?member=$1
RewriteRule ^member/0/$ /artist/index.php?member=$1
RewriteRule ^member/([^/]*)/([^/]*)/opt/([^/]*)/$ /artist/index.php?member=$1&module=$2&opt=$3
RewriteRule ^member/([^/]*)/([^/]*)/opt/([^/]*)/topicId/([^/]*)/$ /artist/index.php?member=$1&module=$2&opt=$3&topicId=$4
can any one help me to write dynamic RewriteRule to add query sting in my RewiteRule so that i dont have to add manually RewriteRule and also it will reduce the line of my .htaccess code
some thing like:
RewriteRule ^member/([^/]*)[dynamic code]$ /artist/index.php?member=$1[dynamic code here]
At that point you rewrite all requests to /artist/index.php without constructing a query string, and index.php examines the request URI to populate its own variables.
i.e. have only one rule
RewriteRule ^member/.* /artist/index.php
index.php can look at $_SERVER['REQUEST_URI'], explode on slashes, etc.
mod_rewrite's job is not to implement complex logic. You put it in your application.
http://en.wikipedia.org/wiki/Front_Controller_pattern
TL;DR
How can I get .htaccess to rewrite http://domain.com/images to http://domain.com/images/ (i.e. add a trailing slash to URLs without one)? The URLs can be deeper than one level, for example http://domain.com/images/page/1.
More info
Say I have a URL like this:
http://jamwaffles2/wallpapers
This will redirect to this in the URL bar, with the rewrite rule working fine:
http://jamwaffles2/wallpapers/?page=wallpapers
However
http://jamwaffles2/wallpapers/ (note trailing slash)
Rewrites fine to
http://jamwaffles2/index.php?page=wallpapers (not visible to user)
With a nice http://jamwaffles2/wallpapers/ in the address bar.
The issue here is that when a trailing slash isn't given to the URL, the URL in the address bar changes to a not-so-pretty one. Can someone offer a solution to this?
Here's my .htaccess:
# turn rewriting on
RewriteEngine on
RedirectMatch permanent ^/$ http://jamwaffles2/home
Options +FollowSymLinks
RewriteRule ^([^/\.]+)/?$ /index.php?page=$1 [L,NC,QSA]
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ /index.php?page=$1&var1=$2 [L,NC,QSA]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ /index.php?page=$1&var1=$2&var2=$3 [L,NC,QSA]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ /index.php?page=$1&var1=$2&var2=$3&var3=$4 [L,NC,QSA]
As a side note, there are more levels to the URL; the .htaccess should make that apparent (e.g. http://jamwaffles2/home/page/2).
EDIT
Curiously, this only happens on /wallpapers. If I type in http://jamwaffles2/home it works as expected, but won't work with http://jamwaffles2/wallpapers.
1) Try this directive: Options +FollowSymLinks -MultiViews -- depending on Apache config it can be the deal breaker.
2) Use this code (one of possible variants) to add trailing slash for NON-EXISTING resources ONLY:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*[^/])$ /$1/ [R=301,L]
It will redirect (301 Permanent Redirect) so URL will change in browser (e.g. example.com/hello => example.com/hello/).
If it still does not work (for whatever the reason may be) -- if you can edit Apache config files -- please enable rewrite debugging (RewriteLogLevel 9) and check the rewrite log to see why some URL failing correct rewrite. Every server can be configured differently, so the same rule may work a bit differently in your case.
In my present project I've got several directories: application (my MVC files, which mustn't be accessed), images, css, and js. Effectively I want all requests to images/css/js to proceed unchanged, but all others I wish to call index.php/my/path.
My .htaccess currently looks like this, and is wreaking havoc with my routing.
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond $1 !^(index\.php|images|js|css|robots\.txt)
RewriteRule ^(.*)$ http://example.com/index.php/$1 [L]
</IfModule>
This isn't working as relative URLs start stacking up, such as: example.com/blog/view/1/blog/view/2.
When I attempt something like,--
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/(index\.php|images|js|css|robots\.txt)
RewriteRule ^ index.php%{REQUEST_URI} [PT]
</IfModule>
I get this error with any request: No input file specified.
How can I force all requests not to my whitelisted directories to call, not redirect to (redirection murders posting, I found), index.php/path? IE, when /blog/view/1 is requested by the browser, .htaccess calls index.php/blog/view/1. The reference files at Apache's site aren't too clear about how to do this sort of thing—that, or, I am just missing the point of what I'm reading about RewriteRule.
And, I really want to understand this. Why will your answer work? Why are my attempts failing?
This is what I have in my .htaccess for my framework:
<IfModule mod_rewrite.c>
RewriteEngine on
#This will stop processing if it's images
RewriteRule \.(css|jpe?g|gif|png|js)$ - [L]
#Redirect everything to apache
#If the requested filename isn’t a file….
RewriteCond %{REQUEST_FILENAME} !-f
#and it isn’t a folder…
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L,QSA]
#L = (last - stop processing rules)
#QSA = (append query string from requeste to substring URL)
</IfModule>
Hope this helps.
PS: Maybe you want to remove the lines to stop redirecting if it's a file or folder ;)
Antonio helped me get on the right track, so here's the resulting .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine on
# skip if whitelisted directory
RewriteRule ^(images|css|js|robots\.txt|index\.php) - [L]
# rewrite everything else to index.php/uri
RewriteRule . index.php%{ENV:REQUEST_URI} [NE,L]
</IfModule>
You're going to have to do that using PHP. For example, if you wanted to split your URI into something like domain.tld/controller/action/param, then you could use the following PHP code as a start:
<?php
// Filter URI data from full path
$uri_string = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['REQUEST_URI']);
$uri_string = trim($uri_string, '/'); // Make sure we don't get empty array elements
// Retrieve URI data
$uri_data = explode('/', $uri_string);
In that case, $uri_data[0] is the controller, $uri_data[1] is the action, and beyond that are parameters. Note that this isn't a foolproof method, and it's never a great idea to trust user-entered input like this, so you should whitelist those controllers and actions which can be used.
From here, knowing the controller and having a consistent directory structure, you can require_once the proper controller and call the action using variable variables.
This is what I use in my .htaccess file for my CMS:
Options -Indexes
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php/$1 [NC,L]
And then in my index.php file I have:
$path_info = '';
$path_info = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : $path_info;
$path_info = isset($_SERVER['ORIG_PATH_INFO']) ? $_SERVER['ORIG_PATH_INFO'] : $path_info;
$request = explode('/', trim($path_info, '/'));
// if $request[0] is set, it's the controller
// if $request[1] is set, it's the action
// all other $request indexes are parameters
Hope this helps.