0

This question has been edited for clarification:

I am trying to create "pretty URLs" that should disguise themselves as follows:

mysite.com/index.php?p=1 ==> mysite.com/site_one/index.php

mysite.com/aboutus.php?p=2 ==> mysite.com/site_two/aboutus.php

mysite.com/anypage.php?p=3 ==> mysite.com/site_three/anypage.php

As you can see, mod_rewrite should simply convert the "p" variable into a predetermined pseudo-directory (this directory does not exists...this is just an aesthetic rewrite).

Obviously, this creates a complication. When a user visits mysite.com/site_one/index.php, there should be a background transfer to mysite.com/index.php?p=1. This background transfer results in a loop that causes a server error.

I have attempted to prevent this loop by using the following code:

RewriteCond %{QUERY_STRING} !NON=
RewriteCond %{QUERY_STRING} ^(.*[&?])?p=1([&].*)?$
RewriteRule ^/?(.*)  /site_one/$1 [PT,L]


RewriteCond %{QUERY_STRING} !NON=
RewriteRule ^/?site_one/?(.*)  /$1?NON=1&p=1 [PT,L]

Unfortunately, this still causes a server error. Can anyone see where the code has gone wrong?

Community
  • 1
  • 1
inveni0
  • 25
  • 6
  • While I'm pretty confident that I could hack together some RewriteCond-based rules to help you with that specific case, it would probably be unhelpful. More information about the number of pages you need to handle, and how you maintain the mapping between values of "p" and the friendly URLs would be a helpful addition to your question. – timdev Apr 19 '12 at 20:45
  • Certainly, let me explain in more detail: The value of "p" may change, and so I'll add rules for each value of "p". For instance, if "p=1", the site would show "mysite.com/site_one". If "p=2", the site would show "mysite.com/site_two". If "p=3" and the user is calling a page named "about.php", the site should show "mysite.com/site_three/about.php. Basically, the "p" variable just gets disguised as a directory. I hope that makes sense. – inveni0 Apr 19 '12 at 20:58
  • 1
    Why don't you just name the pages in the $p variable, so that you can do something like www.mysite.com/about/ --> www.mysite.com/page.php?p=about . That would only require 1 rule, instead of you having to set rules for each page – Tom Apr 19 '12 at 21:00
  • Because then I'd have to convert the value of "p" to an integer in my PHP code, and I'd have to make sure that every page I upload (which is aplenty) includes this conversion. It would be easier to just have a global rule at the main level, and it will make the php code a little easier to manage. – inveni0 Apr 19 '12 at 21:06
  • add another column to your database named "URL" and you'll be able to retrieve the pages using that instead of having to use the ID – Tom Apr 19 '12 at 21:21
  • That also seems like more complication than is necessary. If this can be done easily and concisely in .htaccess, I'd much prefer that to manipulating an already incredibly complicated database around yet another arbitrary column. Specifically because the value of "p" will only be one of three options. – inveni0 Apr 19 '12 at 21:27
  • possible duplicate of [mod_rewrite {QUERY_STRING}](http://stackoverflow.com/q/3942054/), [mod_rewrite Problem - Routing pages to query string](http://stackoverflow.com/q/5397846/), [Rewriting query string using mod_rewrite](http://stackoverflow.com/q/1179868/), [mod_rewrite RewriteCond and query string](http://stackoverflow.com/q/3173271/) – outis Apr 19 '12 at 22:09
  • Not a duplicate. Those questions do not address my looping issue. – inveni0 Apr 19 '12 at 22:36
  • @outis I agree that it's not a dupe of those problems. There is a page in the foreground that gets forwarded internally to another page, if that page is called, then the page is routed to the foreground page and then internally written back to the page. /a/ -> [b.php] AND b.php -> /a/ -> [b.php] (where the brackets are in the background) – craniumonempty Apr 19 '12 at 23:06
  • @inveni0: as it stands, this question doesn't make sense precisely because you're asking for a redirect loop. Those other questions cover rewrites in each direction (query string to path, or path to query string). Also, this question is underspecified & unclear. There are quite a few other questions about rewrites & query strings; run some searches and look over them to both see if exactly what you want has already been asked, and to help clarify what exactly you want. – outis Apr 20 '12 at 01:14
  • @outis I've updated the question for clarification, and with the current status of my code (which seems right to me, but still throws an error). – inveni0 Apr 20 '12 at 02:22
  • @inveni0: when you say "background transfer", do you mean an "internal rewrite" (one not reflected in the user agent, as opposed an external redirect, which is)? [Why](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) are you rewriting to a URL with the "p" parameter? That's what's causing the loop, and has no apparent utility. – outis Apr 20 '12 at 05:37
  • Yes, I mean an internal rewrite. The "p" parameter is read by the PHP scripts that are hosted on the site. My scripts need to know the value of "p", regardless of whether the URL shows "p=1" or the "site_one" rewrite. – inveni0 Apr 20 '12 at 05:45
  • @inveni0: the first rewrite rule doesn't touch the query string, so the "p" parameter is still present. Do directories for each "site_*" exist, or is that only present in the public URL and not the filesystem? In general, respond to requests for clarifications by updating your post, rather than replying with a comment. For one thing, a question should be understandable without reading comments. For another, SO is a Q&A site, not a forum, and comments aren't intended (nor are they well suited) for discussions. – outis Apr 20 '12 at 05:55
  • ... Since the original question was unclear, you don't need to worry about preserving anything from the original. The edit history will to that. The original question and edit notice only clutter up the question. – outis Apr 20 '12 at 05:55
  • @outis I apologize that you are having trouble reading the revised question. I can not, however, add content that is already present in the question if you have simply overlooked it. Please refer to the line that reads "mod_rewrite should simply convert the "p" variable into a predetermined pseudo-directory (this directory does not exists...this is just an aesthetic rewrite)". That being said, I'll stop responding to you here, as you seem unable to answer my question. – inveni0 Apr 20 '12 at 06:02
  • Possible dup of [Is it possible to use mod_rewrite htaccess to rewrite a url from name to id](http://stackoverflow.com/q/7142093/90527) – outis Apr 20 '12 at 06:04
  • You're right about the "pseudo-directory" text; I re-read the re-write too quickly. However, keeping the original text doesn't help matters; parts of it are redundant (which simply means more text to read through) or poorly stated. Think of the original question as a rough draft; it doesn't need (indeed, shouldn't) to appear in the final draft. When I wrote that clarifications should go into the question, I was referring in particular to specifying which URLs you want to be internal rewrites and which external rewrites. As for ability, no-one can properly answer a bad question. – outis Apr 20 '12 at 06:11
  • Possible dup of [url rewriting an id with a string variable](http://stackoverflow.com/q/992185/), [Rewrite URL, replacing ID with title in query string](http://stackoverflow.com/q/6993963/), [mod rewrite, title slugs and htaccess](http://stackoverflow.com/q/2690742/), [htaccess mod_rewrite](http://stackoverflow.com/q/2188225/). – outis Apr 20 '12 at 06:38

2 Answers2

0

If you want, you could set a dummy query var behind the scenes. Try something like this:

RewriteEngine On

RewriteCond %{QUERY_STRING} !NON=
RewriteCond %{QUERY_STRING} ^(.*[&?])?p=1([&].*)?$
RewriteRule ^/?page.php  /main_site/ [R,QSA]

RewriteCond %{QUERY_STRING} !NON=
RewriteRule ^/?main_site/?(.*)  /page.php?NON=1&p=1&extra=$1 [QSA,L]

And just ignore NON from get/request in php.

craniumonempty
  • 3,525
  • 2
  • 20
  • 18
  • I've tested this here, and it fails. I'm not familiar enough to know if it's an error in the syntax or an error with the tool. http://martinmelin.se/rewrite-rule-tester/ – inveni0 Apr 19 '12 at 22:11
  • @inveni0 then try http://htaccess.madewithlove.be/ (or test on xampp on a local machine first), because the NOT (`!`) doesn't seem to be programmed into the site you gave – craniumonempty Apr 19 '12 at 23:00
  • Much better. I modified your answer to this: `RewriteCond %{QUERY_STRING} !NON= RewriteCond %{QUERY_STRING} ^(.*[&?])?p=1([&].*)?$ RewriteRule ^/?(.*) /main_site/$1 [PT,L] RewriteCond %{QUERY_STRING} !NON= RewriteRule ^/?main_site/?(.*) /$1?NON=1&p=1 [PT,L] ` It shows as okay on the test site, but doesn't work on my server (internal server error). Any idea as to what might cause that? – inveni0 Apr 19 '12 at 23:39
  • @inveni0 I'm not sure what you are doing with that. In the first rule it basically says everything in the directory send to /main_site (this includes if calling /main_site) as long as it has `p=1` and not `NON=1` in the query string. The second says if no `NON=1` in query then take everything in `/mainsite/` and send it to `/?NON=1&p=1`. And because the first has an [L] flag, it rolls to next. You end up never putting NON=1 on it and every time it goes down a folder it adds more so you end up endlessly `http://host.com/mainsite/mainsite/mainsite/mainsite/...` until crash – craniumonempty Apr 20 '12 at 10:31
0

I wound up having to work around this, as no htaccess method was helping me. I basically forwarded all values of "p" to the appropriate page and changing the variable "p" to the variable "s". I then told my web app that the value of "p" is equal to the value of "s" where "s" exists. I put this code in a file that communicates with the server, so it is present on all of my site's pages.

It's ugly and sloppy, but so is the reason I have to do it in the first place.

inveni0
  • 25
  • 6