views:

981

answers:

4

I have a website authored in PHP where anytime a user receives an error I will redirect them to a another page (using header(Location:...)) and put the error ID in the URL so that I know which error to display.

E.g. If the user tries to access a product page but that item is no longer available I will redirect back to the category of items they were previously looking at and display an error based on the error ID I have specified in the URL.

www.example.com/view_category.php?product_category_id=4&error_id=5

There are two things I don't like about this approach:

  1. It displays the error_id in the URL.
  2. if the page is refreshed, the error will still display.

Is there a way to cleanly remove a specific $_GET variable from a URL while leaving the rest of the variables intact AFTER the page is loaded?

I'm thinking maybe it's using modRewrite or a redirect back to the page itself but removing the error_id from the URL or using a $_SESSION variable and avoiding putting the error_id in the URL. Your thoughts?

I really am learning a lot from this community and thought if I posed the question I might be able to learn something new or to get some varied ideas as I'm fairly new to scripting.

+1  A: 

One way is to compare the HTTP_REFERER with the SCRIPT_NAME. They'll be the same if the user has hit Refresh.

Christopher Done
+5  A: 

No, there's no way to do that explicitly - at least not without a page refresh but then you'd lose the data anyway.

You're better off using a temporary session variable.

if ( /* error condition */ )
{
  $_SESSION['last_error_id'] = 5;
  header( 'Location: http://www.example.com/view_category.php?product_category_id=4' );
}

Then, in view_category.php

if ( isset( $_SESSION['last_error_id'] ) )
{
  $errorId = $_SESSION['last_error_id'];
  unset( $_SESSION['last_error_id'] );

  // show error #5
}
Peter Bailey
If a user opens several tabs at once then you have risk of unsetting the session variable before another page has had chance to load and thus show the error. This is why I suggest the referrer method.
Christopher Done
That would only be a problem if the other tab was in the middle of loading. And the only consequence would be that the error message would not display on the tab that loaded 2nd. right?
justinl
Referrer isn't a bad idea either, but it's not foolproof. Besides, he's talking about having the error_id not exist in the URL at all, which inspecting the referrer doesn't address.Also, this on reason is why MVC is so popular - requests that error are just forwarded to the error controller, and no page refresh actually occurs.
Peter Bailey
+1  A: 

First, log the error in your database :)

After that, set a cookie or session variable and then redirect the user to safe page. When that page is loaded, have it check for the variable, display the error, and then delete variable from the cookie or session array.

sirlancelot
So is it generally considered a good idea anytime a user encounters an error I should insert the error id and perhaps the URL and date into a mysql table? How would you sort/make sense of this data once it has been logged?
justinl
Users are generally unreliable. They rarely/won't tell you when there's an error so it's a good idea to log as much information as you can.
sirlancelot
I don't particularly agree with this. Database error logging is for when unexpected things happen. A user hitting a page with an item that's no longer available is *expected* behavior.
Peter Bailey
Would you also store the user id of the person who encountered the error?
justinl
@Peter, yes I agree. Some discretion is needed when logging errors so your server doesn't fill up with logged 404 errors :)
sirlancelot
@justinl Store anything useful that would help you fix the problem.
sirlancelot
A: 

Quick Hack: You could have also imploded()'d on "&" in the the $_SERVER['QUERY_STRING'] variable to manipulate that string and then explode()'d it back.

xentek
parse_str() and http_build_query() are better, more bespoke functions for working with query data.
Peter Bailey