PHP 301 Redirects

Hello all,

I’m building my first client website and I need to make redirects from the old URLs to the new ones.

Now I use this code in my .htaccess file:

[php]
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
[/php]

Which allows me to route requests through bootstrap.php like this:

[php]
if ($_SERVER[‘REQUEST_URI’] === BASE_URL) {
$model = new Model\Page($db);
$controller = new Controller\Page($view,$model);
$controller->home();
} elseif ($_SERVER[‘REQUEST_URI’] === BASE_URL . ‘about’) {
$model = new Model\Page($db);
$controller = new Controller\Page($view,$model);
$controller->about();
}
[/php]

Now let’s say I want to redirect the old search page to the new search page, the old URL looks like this:

/categories/43/all-categories.htm?keywords=&all_categories=43&gender=

It’s pretty messy in my opinion, in the new site I’ve made it like this:

/categories?name=&category=all&gender=

However the problem I have is I don’t know how I can redirect requests from the old URL to the new page? I’ve never had to do it before and I’m not sure with the code in the .htaccess file if you can use it for redirects?

The only file on the server is index.php which includes bootstrap.php and after all the routing is done the view for each page is just included in the code depending on the URL.

Can anyone give me some advice on what I can do?

Thanks,
Adam

Wow! I have not seen a MFC Controller/Page code in a long long time… It was designed, like, in the 70’s… LOL It was a nice flashback…

So, not really very good at URL rewriting, but, lets take a peek at your current code.
RewriteRule ^(.)$ index.php [QSA,L]
This says, as far as I know is something loosely like…
Condition#1: %{REQUEST_FILENAME} !-f WHICH is if the requested URL is NOT a regular file
Condition#2: %{REQUEST_FILENAME} !-d WHICH is if the requested URL is NOT a directory
IF condition’s pass, process URL using ^(.
)$ WHICH is URL with any extension.
THEN rewrite as index.php (appending, see next line)
[QSA, L] WHICH is Query String Append - Last Rule ( This ends the rewrite rules… )
Therefore, if I am correct, this rewrite does nothing more than make sure it is not a folder on the server nor a regular file and if not, it sends the URL to the index.php file.

Do you want to also just rewrite the displayed part of the URL? I mean do you just want this:
/categories/43/all-categories.htm?keywords=&all_categories=43&gender=
To show up as this:
/categories?name=&category=all&gender=
On the browser’s URL display area? Or do you want it to redirect to a different page in a different folder?
In a browser display area for the URL, you can have it show the full folder name with the filename or rewrite it to hide most of that data leaving just the arguments. Is that what you mean? Or just redirect to the new page? Not clear on what you are asking. Let us know and we can help you out…

As far as I know the .htaccess file redirects all requests to index.php unless the file actually exists on the server.

I basically want to know the best way to handle requests for URLs which have get variables in them, I mean lets say if the old URL was something like /old-page.htm I could do something like:

[php]
if ($_SERVER[‘REQUEST_URI’] === BASE_URL . ‘old-page.htm’) {
header("Location: " . BASE_URL . “new-page.htm”);
}
[/php]

But let’s say it’s a page like the search page which has parameters in the URL, is it possible to redirect the user to the correct page which contains the desired search results based on the parameters? For example:

[php]
if ($_SERVER[‘REQUEST_URI’] === BASE_URL . ‘/categories/43/all-categories.htm?keywords=test&all_categories=43&gender=’) {
header("Location: " . BASE_URL . “categories?name=test&category=all&gender=”);
}
[/php]

However if I do it that way, the parameters aren’t always going to be the same, I mean I could do something with preg_match and use the matches from that function to redirect the user so they see the correct search results but there must be a better way of redirecting than doing something like that.

Also the .htaccess code is from Flight which is a PHP framework however I was told to use it by another member of this forum a while ago.

Thanks,
Adam

Yes, and yes and no… LOL ANYTHING is possible in programming, just sometimes tricky to accomplish it…

Now, it is very easy to handle a rewrite rule to move a user from one place to another. Not a big issue to do that.
Therefore, yes, your first example can be done.

Now, the second example, yes, it can be done, but, you still need to send it to another file, not just some folder.
Unless you want it to pull the index file in that folder which also can be done.

No, normally you would not do the second one where you pull a URL to a FILE and then send it to nothing. It needs a file
at the other end, or perhaps an index file stuck in that folder. (Some place to end up with!)

To do the first example, you can read about it on Apache’s Mod-Rewrite page here:
https://httpd.apache.org/docs/2.4/rewrite/remapping.html
The very first example shows RewriteRule “^/foo.html$” “/bar.html” [PT]
This says all urls pointing to foo/anyfilename.html moves to bar.html. You would have to alter this to your two folder and file
names in your example.

The second needs more info to sort out. First, still confused with what you are asking. Do you mean that you want the
site to work as normal, but, just not show the exact URL in the browser’s URL line? OR, do you mean that you have a new
folder layout and want to send all of the multiple requests to folders into one place instead?

Okay, maybe I’m not understanding 301 redirects properly?

I only have an index.php and a bunch of view files in a view folder, all the routing is handled in index.php and there’s no other files on the site.

Because the old site uses actual files for each page e.g. Categories.php but the new site just has a route for categories which then has code in the controller to render the categories.php view.

I don’t think I can actually use the .htaccess file because there’s no actual file apart from index.php which the request can be routed to.

Maybe I am misunderstanding the actual purpose of a 301 redirect?

All I’m trying to do is ensure that if a user tries to visit the site through an old URL then they still get to see the correct view as how it would have been before the site got rebuilt.

Otherwise if there isn’t a route for the old URL it will just show a 404 page and surely that’s not good for search engines?

Hope that makes more sense.

Thanks,
Adam

Well, you have it mostly correct. Now that I understand what you want, let’s see… First, remember any URL that goes to your site will pass thru the mod-rewrite before ending up anywhere. And it sends everything to the index file, that is just fine for your needs. Then, in the index file, you just first see if it is a standard call , then just continue on. If not, just pull out the parts needed using PHP and continue on. Hmmm, did that make sense?

So, if we are talking about five different folder issues, no big deal… If you have a thousand folders all in the format of /categories/43/ or /categories/433/ or /categories/999/ then, no big deal. You can pull out the part after the categories folder name and place it into the new format. Since you listed the new format as: /categories?name=&category=all&gender= , it appears that you want the old versions mapped into the new versions with a possibility of adding arguments named “name”, “category” and “gender”. You can use the mod rewrite to pull the category number and look for arguments and if they are there add them at the end using the append option.

301 redirects are just permanent forwarding of a URL. Nothing more. The server will send a code (#301) to the browser and the browser knows how to handle it. Also, web crawlers, spiders, robots like Google’s use the 301 to save the new URL instead of the old one. But, you can do a limited amount of handling of the rewrite of the URL using the .htcaccess code. That is all there is to that.

So, how many URL might come to the new site that need to be rewritten to the new format? One as you showed or many?
If less than 10, post their layout and we will see if we can come up with a rewrite for you to fit them into the new version.
(PS: /categories/43/… is the same as /categories/88/… So that is one url layout!)

I was looking around for a simple example of rewriting a folder into an argument so you can get an idea how to do it.
Here is one I found. Might help explain how it’s done. In this case, it uses two folders that it keeps are two variables.
Then, it write to the new file with the arguments in place. We would have to change it to fit your layout. As I mentioned lastly,
it depends on how many layouts you have all together…

Url requested: http://domain.com/shoes/prada/
Page served: http://domain.com/shop.php?cid=shoes&bid=prada

RewriteEngine on
RewriteRule ^(.)/(.)/(.)/(.)?$ product.php?tid=$1&sid=$2&eid=$3 [L]
RewriteRule ^(.
)/(.)/(.)?$ brand.php?tid=$1&sid=$2 [L]
RewriteRule ^(.
)/(.)?$ shop.php?tid=$1 [L]

Now, there is a “Rule Tester” online that you can place this sampler into and then enter the requested URL for testing.
If you use that, you can figure out the correct combo to cover all of your possible changes you need. You can find it here:
http://martinmelin.se/rewrite-rule-tester/
Put in the above rules, change them for your site and test… Might help a lot…

Sorry, one last thing… You can do this simple rewrite that might work…

RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

Using this rule, if you enter: /categories/43/all-categories.htm?keywords=test&all_categories=43&gender=

It should return: index.php?q=/categories/43/all-categories.htm&keywords=test&all_categories=43&gender=
(Just need to add the folder at the beginning…)

That passes everything to the index page with little trouble. Then, inside the index page, just pull out the q= if needed and parse as you might need. If the q= is not there, then it did not come from the old URL’s…

I don’t think it works, it seems to just go straight to index.php regardless of what you put in the URL.

I don’t know if it’s best doing something like this:

[php]

<? if ($_SERVER['REQUEST_URI'] === BASE_URL . 'old-page.htm') { header( "HTTP/1.1 301 Moved Permanently" ); header( "Location: " . BASE_URL . 'new-page.htm' ); } ?>

[/php]

Ah, did you read my notes? I said you would have to rewrite it to pass the data in the way you wanted it to be.
It was not a total final code. You never answered any of my questions that can help us solve this for you.

  1. do you have just the one old URL that can be sent? All your samples talk about category #43. Is that the only one?
    If so, it is an easy fix…
  2. Area there hundreds of other category folders in the old layout? If so, the solution is trickier, but, not if the same exact
    folder structure is in place /categories/43/… /categories/99/… /categories/32/… This is an easy fix.

The last sampler I sent ( RewriteRule ^(.*)$ index.php?q=$1 [L,QSA] ) gives you back a $_GET[“q”]; value that is the full
folder and program layout for the old incoming URL. You would have to add a small parsing system in the index.php new
version to handle it and alter as needed.

Your forcing of the #301 is okay, but, the old arguments will be needed to be checked in the index file and would be harder
to grab the folder layout from that. Again, if it is always /categories/43/… Then, no need for that… Easier with a rewrite!

Categories is not a folder it’s just one file which is categories.php on the old site, I have no idea why it was coded in that way to use that URL.

I’ll see if the get variable is available in index.php but I’ll still have to do some parsing in the code to get the parameters from the URL for the new URLs right?

Thanks,
Adam

Okay, no! Now I understand. I was imagining that you had a ton of folders with different category numbers. It makes no sense to me either why they would do it that way. So, lets see what we can do with that information.

So, we need to still do the mod-rewrite because you want the 301 to be automatic for Google robots and others.
Therefore, you do not want to do it inside the index file. A quick recap for my own mind…

Input is: ( Never changes except maybe the ? sections… )
/categories/43/all-categories.htm?keywords=test&all_categories=43&gender=

Ouput is: ( ? sections carried over… )
categories?name=test&category=all&gender=

So, the obvious steps to do this alteration woud be;
acquire the ?keywords which is basically is gender as that is the only one in the first version that is needed in the second.
rewrite the list to match most of the first… Output being: categories?name=test&category=all&gender=####

This does not make sense to me either. If you have an index.php file, you would need to call it not the categories.php file…
I think that is where my mind has been stopping on this one… Anyway, this is what seems to work in my tests:

RewriteRule /categories/43/all-categories.htm(.*) categories?name=test&category=all$1 [R,QSA]

It does leave the arguments in place, but, just do not use them in the index.php file. Does that work for you?
I found a way to take out one argument, to remove any you don’t want, but, too tired to test now. Will check it out tomorrow…
Let me know if this version is good enough…

That would be okay but I’m not sure if it works?

My .htaccess file looks like this:

[php]
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.)$ index.php [QSA,L]
RewriteRule categories/43/all-categories.htm(.
) categories?name=test&category=all$1 [R,QSA]
[/php]

I think I need to take the L argument out of the first rewrite rule in order for the second one to be processed but even when I tried doing that it still seems to take you to index.php but it doesn’t actually do anything.

??? Well, the old part should be under the new rule. You want to check for old URL first and then do the rest.

[php]
RewriteEngine On
RewriteRule categories/43/all-categories.htm(.) categories?name=test&category=all$1 [R,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.
)$ index.php [QSA,L]
[/php]
Not sure how you test this. You would need to your browser and enter the domain and above…
www.yourdomain.com/categories/43/all-categories.htm?keywords=&all_categories=43&gender=
And, not sure if you need the started slash in the rewrite rule. I think it is not needed…

Sponsor our Newsletter | Privacy Policy | Terms of Service