3

Possible Duplicate:
mysql_fetch_array() expects parameter 1 to be resource, boolean given in select

i need some help here.

I have this query:

$order = isset($_GET['order']) ? mysql_real_escape_string($_GET['order']) : 'title';
$query = mysql_query("SELECT * FROM entry ORDER BY $order ASC");

You can either order by title, date or author.

But if someone gives $order something else it goes:

Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in C:\wamp\www\entries.php on line 20

How do I get rid of this error message?

Thanks

Community
  • 1
  • 1
Jolabero
  • 33
  • 2

9 Answers9

6

You cannot have something like colu\'nname in an order by clause -- which means mysql_real_escape_string is not the solution here.

Instead, you should check that $order actually contains the name of one of the columns of your table -- and not run the query if it doesn't.


For example, you could use something like this :

if (!in_array($_GET['order'], array('column1', 'title', 'id', 'other_column'))) {
    // deal with the problem
    // and don't run the query
    // because $_GET['order'] is not one of the allowed values
}
Pascal MARTIN
  • 385,748
  • 76
  • 642
  • 654
2

You shouldn't treat column identifiers the same as string literals. In your example, you could end up with SQL like this:

SELECT * FROM entry ORDER BY O\'Hare ASC

Which would result in a syntax error in any SQL parser.

I have a few tips:

  1. Put your SQL into a variable, don't try to build it inside the call to mysql_query(). If you use a variable, you can now inspect the SQL string, which makes errors like the above easier to catch.

    $sql = "SELECT * FROM entry ORDER BY $order ASC";
    // here you can log $sql, or output to Firebug, etc.
    $query = mysql_query($sql);
    
  2. Check that the return value does not indicate an error. You need to check for error states, because they can occur for many reasons.

    $query = mysql_query($sql);
    if ($query === false) {
      die(mysql_error());
    }
    
  3. Use mysql_real_escape_string() for strings -- not column names, table names, SQL keywords, etc. What I use instead is an associative array that maps the $_GET input to a valid column name, so I know it's safe. This also allows you to use different values in your app parameters than the names of columns.

    $ordercolumns = array(
      "t" => "title",
      "d" => "date"
    );
    $order = "title"; // the default
    if (isset($_GET["order"]) && isset($ordercolumns[$_GET["order"]])) {
      $order = $ordercolumns[$_GET["order"]];
    }
    // now we know $order can only be 'title' or 'date', 
    // so there's no need to escape it.
    $sql = "SELECT * FROM entry ORDER BY $order ASC";
    
Bill Karwin
  • 499,602
  • 82
  • 638
  • 795
1

Just not offer any order options to the user, that doesn't. If you are using a text input, replace it with a select. As long as the column exists, you shouldn't get an error.

You might hardcode each option in a switch-case:

switch($_GET['order']){
    case 'date' : 
         $order = 'date';
         break;
    case 'author' : 
         $order = 'author';
         break;
    default
         $order = 'title';
}

That will also prevent SQL-Injections.

2ndkauboy
  • 9,136
  • 2
  • 28
  • 62
0

It expects a column name in $order and if it isn't one it will fail. Try echoing the $query.

Jan
  • 2,239
  • 1
  • 17
  • 16
0

You should be checking the value of $_GET['order'] from a possible acceptable list of values.

You should also be checking if ($query) to determine if the query worked, before trying to fetch a row.

Fosco
  • 37,365
  • 6
  • 84
  • 100
0
$checker = array('title', 'date', 'author')

$order = isset($_GET['order']) ? mysql_real_escape_string($_GET['order']) : 'title';

if (in_array($_GET['order'], $checker) {
  $query = mysql_query("SELECT * FROM entry ORDER BY $order ASC");
}
karlw
  • 662
  • 4
  • 13
0

You should check for valid values and present an error to the user if something isn't as you expect.

A simple example,

$valid_values = array("title", "date", "author");

if (in_array($_GET['order'], $valid_values))
{
    // Your db stuff
}
else
{
    echo "The order value you gave wasn't valid. Please try another.";
}
Rich Adams
  • 25,210
  • 4
  • 38
  • 62
0

You also need to make sure $_GET["order"] contains a valid column.
Your problem comes from getting an invalid column name, that you put in the query. The mysql_query() function return false on error, and your error message tells you passed it to a mysql_fetch_assoc call.

Try something like

$columns = array("id", "name", "title");
if (false === ($key = array_search($_GET["column"], $columns))) {
  $column = "title";
} else {
  $column = $columns[$key];
}
$query = "SELECT * FROM entry ORDER BY {$column};";

I didn't use mysql_real_escape_string because this method also checks the input to be in the list of valid options.

Maerlyn
  • 33,032
  • 17
  • 94
  • 84
0

Check to see $order is a column name before you run the query

$order = isset($_GET['order']) ? mysql_real_escape_string($_GET['order']) : 'title';
//Run a check here, before the query
$query = mysql_query("SELECT * FROM entry ORDER BY $order ASC");

The mysql_real_escape_string also looks to be in an improper location. Just a heads up

Josh K
  • 562
  • 1
  • 4
  • 11