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?

Dharman
  • 30,962
  • 25
  • 85
  • 135
Jolabero
  • 33
  • 2

9 Answers9

7

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
  • 395,085
  • 80
  • 655
  • 663
2

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,302
  • 3
  • 31
  • 65
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
  • 538,548
  • 86
  • 673
  • 828
0

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

Jan
  • 2,295
  • 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
  • 38,138
  • 7
  • 87
  • 101
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
  • 668
  • 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
  • 26,096
  • 4
  • 39
  • 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,687
  • 18
  • 94
  • 85
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