1

If this is a duplicate then I am really sorry, but I used google and also search here and could not find anything that would work for me. Maybe I just don't know what exactly to search for.

Anyway, back to my question:

I am trying to change old ugly URLs to nicer urls (wanted to have news/XXX/XY but relative links defeated me), so I wrote couple lines of code to my .htaccess and tested them (well, I actually used same code on my other page for redirect, so I know it does work). I get redirected from /news.php to /news, but the query string magic is not working at all...

RewriteRule ^news.php$ /news [L,NC,R=301]
RewriteRule ^news?$ /news.php [L,NC]

RewriteCond %{THE_REQUEST} /news\?rowstart=([^\s]+) [NC]
RewriteRule ^ news-row-%1? [R=302,L]

RewriteCond %{THE_REQUEST} /news\?readmore=([^\s]+)&rowstart=([^\s]+) [NC]
RewriteRule ^ news-%1-%2? [R=302,L]

RewriteCond %{THE_REQUEST} /news\?readmore=([^\s]+) [NC]
RewriteRule ^ news-%1? [R=302,L]

None of the RewriteRules after first one gets executed. But if I change my .htaccess like this:

RewriteRule ^news.php$ /news [L,NC,R=301]

RewriteCond %{THE_REQUEST} /news\?rowstart=([^\s]+) [NC]
RewriteRule ^ news-row-%1? [R=302,L]

RewriteCond %{THE_REQUEST} /news\?readmore=([^\s]+)&rowstart=([^\s]+) [NC]
RewriteRule ^ news-%1-%2? [R=302,L]

RewriteCond %{THE_REQUEST} /news\?readmore=([^\s]+) [NC]
RewriteRule ^ news-%1? [R=302,L]

RewriteRule ^news?$ /news.php [L,NC]

then it works. I tried using /\?bla - /news\?bla - /news\.php\?bla etc. Nothing actually worked.

Does somebody have any Idea why its behaving like this and how to fix it? It looks like it does not recognize the news after it starts loading from news.php file.

I am completly lost, as I don't work with .htaccess that often. Any ideas?

I actually ended up using this:

#########################
#   NICE URLS QUERIES   #
#########################

RewriteCond %{THE_REQUEST} /news(?:\.php|)\?rowstart=([^\s]+) [NC]
RewriteRule ^ news-page-%1? [R=302,L]

RewriteCond %{THE_REQUEST} /news\(?:\.php|)\?readmore=([^\s]+)&rowstart=([^\s]+) [NC]
RewriteRule ^ news-%1-%2? [R=302,L]

RewriteCond %{THE_REQUEST} /news(?:\.php|)\?readmore=([^\s]+) [NC]
RewriteRule ^ news-%1? [R=302,L]

RewriteRule ^news-([0-9]+)-([0-9]+)?$ news.php?readmore=$1&rowstart=$2 [L,QSA,NC]
RewriteRule ^news-([0-9]+)/?$ news.php?readmore=$1 [L,QSA,NC]
RewriteRule ^news-page-([0-9]+)/?$ news.php?rowstart=$1 [L,QSA,NC]


#######################
#   OTHER NICE URLS   #
#######################

RewriteRule ^news.php$ /news [L,NC,R=301]
RewriteRule ^news?$ /news.php [L,NC]
MiChAeLoKGB
  • 796
  • 14
  • 38

1 Answers1

3

The first thing you need to make sure you're doing is putting all the redirects first. That is, every rule that has the R flag needs to be before the rules that don't. But it looks like you're not matching the - style URLs to rewrite them BACK to the version with the query string. So I think you really want something like this (you can get rid of the .php extension while you get rid of the query string):

RewriteCond %{THE_REQUEST} \ /+news\.php(\ |$)
RewriteRule ^ /news [L,R=301]

RewriteCond %{THE_REQUEST} \ /+news(?:\.php|)\?rowstart=([\ &]+)
RewriteRule ^ /news-row-%1? [L,R=301]

RewriteCond %{THE_REQUEST} \ /+news(?:\.php|)\?readmore=([^&]+)&rowstart=([\ &]+)
RewriteRule ^ /news-%1-%2? [L,R=301]

RewriteCond %{THE_REQUEST} \ /+news(?:\.php|)\?readmore=([\ &]+)
RewriteRule ^ /news-%1? [L,R=301]

## Now, internally rewrite the request back to the query string and php extension

RewriteRule ^news$ /news.php [L]
RewriteRule ^news-row-(.*)$ /news.php?rowstart=$1 [L,QSA]
RewriteRule ^news-(.*)-(.*)$ /news.php?readmore=$1&rowstart=$2 [L,QSA]
RewriteRule ^news-(.*)$ /news.php?readmore=$1 [L,QSA]
Jon Lin
  • 142,182
  • 29
  • 220
  • 220
  • Hmm, this is really nice. I actually ended up using something similar (I put the code to my question), but as I don't work with .htaccess and apache, I just used OR flag for ``.PHP`` file version. Could you elaborate a bit on the ``(?:\.php|)`` ? As when I tried to use that (I actually did not use ``?:``, It just placed the ``.php`` to ``%1``... Thanks. – MiChAeLoKGB Jul 14 '15 at 08:54
  • 1
    @MiChAeLoKGB The `?:` makes the grouping made by the `()` un-captured, so it cant be backreferenced. See http://stackoverflow.com/questions/10804732/what-is-the-difference-between-and-in-regex It essentially means there can either be a `.php` or nothing, making the `.php` optional. If you remove the `?:`, the parentheses becomes a captured grouping and the `%1` will end up backreferencing it instead – Jon Lin Jul 14 '15 at 14:17
  • thanks for info, so I used part of your code and part of my code and now it works... Its so tedious to change URLs on CMS... .htaccess its nice, but you still have to change links like idiot in who knows how many files :D Anway, thanks for help. – MiChAeLoKGB Jul 14 '15 at 15:15