views:

408

answers:

9

My url is something such as: "inventory.php?sorting=1" and so forth. Page loads fine but does not display the information properly.

mysql_connect("localhost","user","pass"); 
mysql_select_db("database"); 

if ($sorting == 1){
$result = mysql_query("select * from vehicles ORDER BY year DSC");
}
elseif ($sorting == 2){
$result = mysql_query("select * from vehicles ORDER BY make DSC");
}
elseif ($sorting == 3){
$result = mysql_query("select * from vehicles ORDER BY miles DSC");
}
elseif ($sorting == 4){
$result = mysql_query("select * from vehicles ORDER BY downpay DSC");
}
elseif ($sorting == 5){
$result = mysql_query("select * from vehicles ORDER BY pricepay DSC");
}
elseif ($sorting == 6){
$result = mysql_query("select * from vehicles ORDER BY pricecash DSC");
}
else {
$result = mysql_query("select * from vehicles");
}

while($r=mysql_fetch_array($result))
+4  A: 

Short answer: Replace $sorting with $_GET["sorting"], or add $sorting = $_GET['sorting']; to the top of your code.

Long answer: A long time ago, register_globals was used to automatically make URL parameters appear as variables. This lead to a lot of security problems (the above link contains an example), so it was eventually turned off by default (PHP 4.2.0). In PHP 6, this option no longer exists. Thus, you need to explicitly access URL GET parameters through $_GET or $_REQUEST.

As an alternative, you can explicitly import your URL parameters into local variables by using the import_request_variables command.

Heinzi
+5  A: 

You need to replace $sorting with $_GET["sorting"]

but, also:

Would it not be a better idea to use the switch statement?

switch($_GET["sorting"]{
    case 1:
 $result = mysql_query("select * from vehicles ORDER BY year DSC");
 break;
case 2:

etc.

Daniel May
+1, switch would make this soooo much easier :-)
ILMV
Other solutions explain the potential of using `$sorting = $_GET["sorting"];` - but you can save code space by simple switching on the `$_GET["sorting"];` - no need to waste another var name for something that is immutable.
Daniel May
+1 for finding the problem and suggesting switch (@Daniel - yep, variable names are a very limited resource. Save those variables! ;) )
Dominic Rodger
Must be my memory management woes kicking in there ;)
Daniel May
I find that using $_GET['...'] can get ugly sometimes, like when you're using get variables as indexes to arrays and have nested []'s.
Carson Myers
I can see your point, but I think it's alright here - I guess it depends on the situation and how many fields you're passing in.
Daniel May
This is the solution I went with, thanks so much for the suggestion. I've never used switch before but it's already very handy.
poxin
Definitely - it's quite fundamental and pretty much every language has its own version. Hope this helped and good luck with the rest of your project :-)
Daniel May
It would actually be better to put the column names in an array.
Justin Johnson
Agreed - that's obviously another choice. Incorporating the suggestions in the answers is a great idea, maybe you can improve your code more by including Simon's suggestions below.
Daniel May
+2  A: 

Is there some

$sorting = $_GET['sorting'];

somewhere in your code? It won't get it's value automatically.

Tamás Szelei
+2  A: 

Add this line at the start of your code.

$sorting = $_REQUEST['sorting'];
nullptr
+2  A: 

Why not use switch:

switch ($sorting) {
    case 1:
        $result = mysql_query("select * from vehicles ORDER BY year DSC");
        break;
    case 2:
        $result = mysql_query("select * from vehicles ORDER BY make DSC");
        break;
    // ...
    default:
        $result = mysql_query("select * from vehicles");
        break;
}

Also, make sure $sorting is assigned:

$sorting = $_GET['sorting']; // Place somewhere before the switch
Emil Ivanov
+2  A: 

You need to get the $sorting variable from the $_GET array. I would also rewrite it as a switch statement like this:

switch($_GET['sorting'])
{
  case 1:
    $result = mysql_query("select * from vehicles ORDER BY year DSC");
  brek;

  case 2:
    $result = mysql_query("select * from vehicles ORDER BY make DSC");
  break;

  ...

  default:
    $result = mysql_query("select * from vehicles");
  break;
}
Tjofras
+8  A: 

Why not just use the field name as the GET variable?

$sortField = $_GET['sorting'];
// Ensure we don't get any SQL injection:
$validFields = array('year', 'make', 'miles' ... 'pricecash');


$sql = "select * from vehicles";

if(in_array($sortField, $validFields)){
    $sql .= ' ORDER BY ' . $sortField .' DESC';
}

mysql_query($sql);

and then access the page using inventory.php?sorting=year etc.

This makes the URL more readable, predicatable and means you can support new fields by just adding them to the array without needing to write new switch cases.

Simon
Although this was not the question, +1 for a really useful answer.
Heinzi
+1 for a neat solution (and for finding the problem, which is that the OP was using `$sorting` instead of `$_GET["sorting"]`).
Dominic Rodger
-1 for SQL injection like "inventory.php?sorting=year;drop database;" See, for example, `mysql_real_escape_string` at http://php.net/manual/en/function.mysql-real-escape-string.php
Arjan
Doesn't this expose a hell of a lot of potential security issues?
Daniel May
sql injection won't work in this case, because he checks that the get variable exists in an array. Unless the OP put `year;drop database etc` into the array.
Carson Myers
Simon, it should be `$validFields[$sortField]` (otherwise, Arjan is right about the injection issue), `$validFields = array('year'` should be `$validFields = array(1=>'year'` to keep with the OP's original case, and it's always a good practice to sanitize user input `$sortField = (int)$_GET['sorting'];`
Justin Johnson
`in_array` tests if a array contains a specific value. I think you meant `array_key_exists`.
Gumbo
@Carson: Simon may have meant to, but that's not what he ended up doing. I'm sure it was a simple oversight.
Justin Johnson
You're totally right, I didn't read too well. Edited to revoke my downvote. (Though, in my opinion, secure and maintainable code should never make a reviewer raise one's eyebrows; rewriting to avoid seeing lines like `x = $_GET[..]` followed by `$sql = [..] . x` might avoid that.)
Arjan
Thanks @Carson, SQL Injection isn't a problem here because we're validating the field against a white list array of allowed values.Thanks @Arjan for being good enough to reevaluate your vote. @Gumbo and @Justin I'm using in_array and just $sortField rather than array_key_exists and $validFields[$sortField] as I suggested using the full field name as the GET parameter rather than a number representing the field as I feel that just obfuscates the URL. But yeah, your suggestions could be used to continue using the numerical parameter which is more inline with what the OP asked.
Simon
+3  A: 

And to make it nicer, you can do this:

$sortBy = '';
switch($_GET["sorting"]{
  case 1:
    $sortBy = 'year';
    break;
  case 2:
    $sortBy = 'make';
    break;
  //...
}  

if(!empty($sortBy)) {
  $result = mysql_query('select * from vehicles ORDER BY ' . $sortBy . ' DSC');
}
else {
  $result = mysql_query('select * from vehicles');
}

This way, you only have to change your query at one point if you have to change it someday.

Felix Kling
+2  A: 

you can use $_GET['sorting'] or $_REQUEST['sorting'] if it could come in by either get or post, but why not do this?

$query = "SELECT * FROM `vehicles`";

$sort_values = array( 1 => 'year', 'make', 'miles', 'downpay', 'pricepay', 'pricecash' );
$sort_number = $_GET['sorting'];
if( $sort_number <= count($sort_values) ) {
    $query .= " ORDER BY `{$sort_values[ $sort_number ]}` DESC";
}

$result = mysql_query($query);

note that the 1 => portion of the array is because you 1-indexed your list of queries.
the reason for the <= portion of the if statement is for that reason too -- if you 0-indexed it, you would just use <.

It may not seem like it yet, but you'll quickly find out that it's worth it to try and find ways to write less code. Using the array means you don't have to copy / paste any code (repeatedly writing $result = mysql_query(...);, etc) and it is virtually effortless to add new columns to your table, should you ever need to display more information.

One might even fetch the column names from the database directly and avoid ever touching this code again.

Carson Myers