3

I am updating my current unprotected queries to parameterized ones to protect from SQL Injection.

I have spent a few hours trying to sort this however cant find the issue, any help much appreciated.

BEFORE (echo $row['storeID'];) works before

$storeName = mysqli_real_escape_string($conn,$_GET['store']); 
$query = "SELECT * FROM stores WHERE storeName = '$storeName'";
$results = mysqli_query($conn, $query);
$row = mysqli_fetch_assoc($results);

AFTER

$storeName = $_GET['store'];
$stmt = mysqli_prepare($conn, "SELECT * FROM stores WHERE storeName = ?");
mysqli_stmt_bind_param($stmt, "s", $storeName);
mysqli_stmt_execute($stmt);
$row = mysqli_stmt_fetch($stmt);

This echo should work but using statements it does not

 echo $row['storeID']; 
14
  • No need to mysqli_real_escape_string, prepare will take care of it. Commented Dec 26, 2018 at 22:03
  • @digijay I removed the mysqli_real_escape_string from the question, thanks - any ideas why this still wont work ? Commented Dec 26, 2018 at 22:09
  • Have a look at the examples here: php.net/manual/en/mysqli-stmt.fetch.php You have to iterate the results. Sorry that I didn't see it, I'm more the PDO guy ... Commented Dec 26, 2018 at 22:10
  • I have read though that, thanks anyway Commented Dec 26, 2018 at 22:15
  • 1
    @bradders: Gotta love PDO :-) Commented Dec 26, 2018 at 22:46

2 Answers 2

2

If you look at the documentation for mysqli_stmt_fetch you'll see this description:

Fetch results from a prepared statement into the bound variables

So if you want to go this route, you'll need to ue mysqli_stmt_bind_result as well:

$storeName = $_GET['store'];
$stmt = mysqli_prepare($conn, "SELECT * FROM stores WHERE storeName = ?");
mysqli_stmt_bind_param($stmt, "s", $storeName);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $col1, $col2, $col3,...);
while (mysqli_stmt_fetch($stmt)) {
    // do stuff with $col1, $col2, etc.
}

Now, with each iteration of the loop, the bound result variables are given the value from the result set.


However, I'd strongly suggest moving to PDO, which is far less verbose:

$storeName = $_GET['store'];
$stmt = $db->prepare("SELECT * FROM stores WHERE storeName = ?");
$stmt->execute([$storeName]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

// now you have a simple array with all your results
foreach ($rows as $row) {
    // do stuff with $row
}
Sign up to request clarification or add additional context in comments.

2 Comments

Really appreciate the answer, i will move forward with PDO... I have put together a query to select a single row, i have put this at the bottom of my question, would you consider this safe.. secure since its slightly different to yours?
Using named parameters is a good approach if you have a bunch of them; it can make it easier to keep track of them. For a single parameter like this, I feel that it's not worth the extra verbosity in your code, but it certainly doesn't hurt anything. It's a matter of personal opinion whether you want to use named or unnamed parameters.
1

You were missing a call to mysqli_stmt_get_result before fetching the row:

$storeName = $_GET['store'];
$stmt = mysqli_prepare($conn, "SELECT * FROM stores WHERE storeName = ?");
mysqli_stmt_bind_param($stmt, "s", $storeName);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$row = mysqli_fetch_assoc($result);

echo $row['id'];

1 Comment

Note that this function requires the mysqlnd driver.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.