3

I've taken over a former site/domain, and set up a new site using Wordpress. The WP installation rewrites URL's to static ones, as you'd expect it to.

At the same time I want to preserve the former pages, as they have incoming links. I'm not interested in 301'ing them to "new" pages.

The old URL structure is /index.php?id=123, which I suspect is causing the problem with the WP .htaccess file. For reference, this is what it looks like:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

I've tried adding the following:

RewriteRule ^([0-9]+).html index.php?id=$1 [R,L]

Doesn't work. Just redirects to site.com/?id=123 and shows the front page.

I should add that I plan on just adding these new pages as regular static HTML files in the format of 123.html, 321.html etc.

How do I use .htaccess to make this work together with the WP installation and what WP puts into the .htaccess file?

To clarify:

I want to have my 123.html static HTML page be index.php?id=123. When you access index.php?id=123 it should bring up 123.html, but show index.php?id=123 in the address bar. If you access 123.html it should 301 to index.php?id=123.

Trace DeCoy
  • 649
  • 6
  • 16
  • If you're adding actual static HTML pages they should just work anyway shouldn't they? The rules basically state *if it's index.php, pass it on unmodified* then *if it's neither a file nor directory, pass it to index.php* ... nothing there should affect an actual file called *123.html* – CD001 Apr 30 '15 at 15:08
  • Thanks, but I think you're misunderstanding. I want to preserve the dynamic URL's. I want the 123.html file to read index.php?id=123 in the browser URL field. – Trace DeCoy Apr 30 '15 at 15:11
  • So you want to effectively point `/index.php?id=123` to `/123.html`? You may have a problem there - rewrites only match on paths, not on query strings so you'll need to use a RewriteCond, see: http://stackoverflow.com/questions/13073253/how-to-redirect-urls-based-on-query-string – CD001 Apr 30 '15 at 15:24
  • Yes, I want to have my `123.html` static HTML page be `index.php?id=123`. When you access `index.php?id=123` it should bring up `123.html`, but show `index.php?id=123` in the address bar. If you access `123.html` it should 301 to `index.php?id=123`. I've taken a look at your URL, but I can't see how I can adapt it to my situation. Please advise if you don't mind. Thank you – Trace DeCoy Apr 30 '15 at 15:41
  • You don't want to 301 redirect it... this is gonna take an actual answer so, one minute. – CD001 Apr 30 '15 at 15:45

1 Answers1

1

To map an URL with a querystring up to an actual file you'll need to use a RewriteCond to match the querystring itself (as RewriteRule doesn't):

Something along these lines ought to do it:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# retrieve X.html when index.php?id=X is requested
RewriteCond %{REQUEST_FILENAME} index\.php
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
RewriteCond %1.html -F
RewriteRule .* %1.html? [L]

# standard WordPress routing
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

This will first check to see if you've got a request for index.php with a querystring like id=X.

Then it'll check to see if a file called X.html actually exists; I'm not 100% happy about having to use the more system hungry subrequest file check -F rather than the standard -f but I can't see a way around it in .htaccess in this case.

If X.html actually exists, it'll fetch that file whilst leaving the URL as index.php?id=X.

However if that file doesn't exist it'll fall back to standard WordPress no file, no directory routing to index.php

I'm not a WordPress expert but that should work; I guess the main WordPress controller uses $_SERVER['REQUEST_URI'] to determine the action.


Note: This won't, however, prevent people from accessing 123.html directly by going to the URL www.site.com/123.html - I kept falling into infinite loops and Apache 500 errors trying to prevent that :|

CD001
  • 8,332
  • 3
  • 24
  • 28
  • Thanks for the effort. The code is now: `# BEGIN WordPress RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] RewriteCond %{QUERY_STRING} ^id=([0-9]+)$ RewriteRule (.*) $1.html [L] # END WordPress` It redirects to site.com/?=123 and returns a 404. – Trace DeCoy Apr 30 '15 at 15:58
  • I see what you're saying regarding not redirecting index.php?id=123 to the file 123.html. I need it the other way around, but that is secondary, because no one would know to look for 123.html, as index.php?id=123 is the original URL that has the external links pointing to it. OT: I just tried your latest edit in its entirety, and it still just redirects to `/?id=123` and reports 404. I've both cleared cache and tried in another browser. – Trace DeCoy Apr 30 '15 at 16:06
  • @TraceDeCoy - sorry, I had to go pick the other half up from the supermarket and then forgot to check back in after... updated – CD001 May 01 '15 at 10:51
  • I'm stoked you're taking your time trying to help out CD001, really. However, even with your updated code, it does the same thing. I've uploaded a "test" file named 123.html to the root. I've then uploaded your htaccess code, cleared cache and tried the path site.com/index.php?id=123. It immediately redirectings to site.com/?id=123 and just shows the front page, as it would look like if you went to site.com. It doesn't show the 123.html page. Any other ideas? I should note that I'm on shared hosting, if that makes any difference. Thanks again. – Trace DeCoy May 04 '15 at 17:34
  • Hmmm ... it's working on my dev box; if you have all the files (index.php, .htaccess and 123.html) in the same (root) directory then it should be fine - shared hosting shouldn't make any difference. It could be that there's something else in your .htaccess file that's breaking it ...maybe... – CD001 May 05 '15 at 14:46
  • The .htaccess should be altering the resource on the fly before Wordpress can get its claws into it... you know there might be a really simple workaround for this. Instead of trying to get clever with .htaccess you could just put a simple kludge into *index.php* - something like `if($_GET['id'] == 123) include_once '123.html'; die();` – CD001 May 05 '15 at 15:49
  • That's true, however we are talking maybe 50 pages, so it's not a one-off. Would rather do a nifty htaccess snip. – Trace DeCoy May 05 '15 at 17:46
  • Hmm I guess that's that then. In any event, I appreciate your time and effort. Too kind. – Trace DeCoy May 05 '15 at 17:47
  • Yeah - sorry, I'm a bit stumped now, I've tested this on Apache 2.2 and 2.4; if mod_rewrite is enabled it *should* work :| – CD001 May 06 '15 at 08:11
  • Tested your code on another site, that's hosted elsewhere, and it works flawlessly. That must mean what you did is correct and the issue must be on my side of things. Accepting your answer, and once again thanks for your help. – Trace DeCoy May 07 '15 at 14:42
  • *phew* that was bugging me - I'm not often utterly stumped on SO! :D – CD001 May 07 '15 at 14:57
  • Sorry CD001, I spoke too soon it seems. Even though the problem now is no longer getting index.php?id=123 to work, now every one-word-URL reports a 404. E.g. site.com/sitemap/, site.com/category1/, site.com/post1/ etc., while site.com/post-number-2/ works just fine. – Trace DeCoy May 07 '15 at 17:05
  • Ah - sorry, looks like I broke the standard WordPress routing when I was tinkering with it... I've put it back as it should be now so it *should* work; though I'm no WordPress expert admittedly. – CD001 May 08 '15 at 08:54
  • Hah! No worries. It does seem to work, albeit not on the site I want it on. Wonder what's causing the issue. I've reached out to support, and they seem clueless. I'll keep at it, thanks again (again)! – Trace DeCoy May 08 '15 at 10:18
  • Update: I've gotten word back from my hosting, and apparently it's because of how Litespeed handles rewrites as opposed to Apache. Do you have any suggestion on how to combat this? – Trace DeCoy May 08 '15 at 12:16
  • Sorry - I've never used a litespeed server; Apache mod_rewrite I'm ok - Litespeed, no clue :| – CD001 May 08 '15 at 15:18
  • Thought I'd update you: Turns out, there was an error with the Litespeed software, and after updating it works like intended. Thanks again. – Trace DeCoy May 09 '15 at 14:02
  • Well that's a turn up for the books... I'm right and the software is wrong :D Glad it's sorted now anyway. – CD001 May 11 '15 at 15:13
  • CD001: Quick question, if you don't mind. Say I want to return a file inside a folder, e.g. pages/123.html, instead of root. How does that look? – Trace DeCoy Jun 10 '15 at 16:37
  • Assuming you want `index.php?id=123` to redirect to `/pages/123.html` you'd need to take that into account in the `RewriteCond` and `RewriteRule` conditions - e.g. `RewriteCond pages/%1.html -F` to check that the file exists and `RewriteRule .* pages/%1.html? [L]` to do the rewrite... off the top of my head, I've not checked it. – CD001 Jun 11 '15 at 09:18
  • Cool, thanks. Was unsure if I needed any special ^'s or .*'s before or after pages/ – Trace DeCoy Jun 12 '15 at 08:51
  • Hey CD001 -- Reviving this: do you happen to know how to do this on Nginx? For the life of me, I can't get it to work :/ Feel like I've tried EVERYTHING... https://stackoverflow.com/questions/71752246/nginx-rewrite-how-do-i-rewite-this – Trace DeCoy Apr 06 '22 at 09:53