1

Following a question earlier about sanitising a string, I'm now attempting to use the principles seen at How can I prevent SQL injection in PHP?

$connection = mysqli_connect('localhost', 'user', 'xxxxx');
$database = mysqli_select_db($connection, 'xxxxx');

$param1 = $_GET['q'];

//prepared mysqli statement
$stmt = mysqli_stmt_init($connection);    
$stmt = $connection->prepare('SELECT * FROM CONTACTS WHERE SURNAME = ?');
$stmt->bind_param('s', $param1); // 's' specifies the variable type => 'string'

$stmt->execute();
$result = $stmt->get_result();
$num_rows = mysqli_num_rows($result);

echo "Records Found:".$num_rows."<br/><br/><hr/>";

while ($row = $result->fetch_assoc()) {
   echo $result['COMPANY']." ".$result['FORENAME']." ".$result['SURNAME'];
}

However, although $connection and $database are both processing correctly, I'm getting the following error:

Fatal error: Call to undefined method mysqli_stmt::get_result() in /my_first_mysqli.php on line xxxx

Am I not getting the syntax correct or does it have more to do with the php version 5.2.0 I'm rocking. (Yes, I'm upgrading code before upgrading server).

If it's the latter, is there a simpler MySQLi method I can use that will work before I upgrade the php version?

EDIT


I've updated this now which is a bit cleaner:

 $servername = "localhost"; $username = "xxxx"; $password = "xxxx"; $dbname = "xxxx";

 // Create connection
$conn = new mysqli($servername, $username, $password, $dbname);

 // Check connection
 if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}

$param1 = $_GET['q'];

$stmt = mysqli_prepare($conn, "SELECT CONTACTID, COMPANY, FORENAME, SURNAME FROM CONTACTS WHERE SURNAME = ?");

/* bind parameters for markers */
mysqli_stmt_bind_param($stmt, "s", $param1);

/* execute query */
mysqli_stmt_execute($stmt);

/* bind result variables */
mysqli_stmt_bind_result($stmt, $CONTACTID, $COMPANY, $FORENAME, $SURNAME);

/* fetch value */
mysqli_stmt_fetch($stmt);

$num_rows = mysqli_num_rows($stmt);
echo "Records Found:".$num_rows."<br/><br/><hr/>";


/* close statement */
mysqli_stmt_close($stmt);


mysqli_close ($conn);

I'm obviously not getting a recordset result to loop through and don't know how to... The rest appears to work without throwing an error.

Richard Owens
  • 155
  • 16
  • I guess this method is indeed not supportet in php 5.2 – Lars-Olof Kreim Jun 27 '18 at 13:03
  • Do I have to revert back to sanitising my strings again??? – Richard Owens Jun 27 '18 at 13:05
  • You shouldn't. The `prepare` and `execute` existed before 5.2. The `get_result` is the only issue. If you take that out what is the behavior? The examples in the manual don't use `get_result` http://php.net/manual/en/mysqli.prepare.php. – user3783243 Jun 27 '18 at 13:12
  • 3
    Possible duplicate of [mysqli\_stmt\_get\_result alternative for php 5.2.6](https://stackoverflow.com/questions/12996427/mysqli-stmt-get-result-alternative-for-php-5-2-6) – Lars-Olof Kreim Jun 27 '18 at 13:12
  • 1
    Great dupe link Lars. @Richard You will need to explicitly nominate your columns (versus `*`) in the SELECT clause. – mickmackusa Jun 27 '18 at 13:18
  • 1
    Do you actually need `$stmt = mysqli_stmt_init($connection);`? I never use it. But I never used php5.2 either. Beyond that, please use either procedural or oo but not a mixture of both. – mickmackusa Jun 27 '18 at 13:21
  • I am going through each of these comments and working through the knock-on effect of each. I'm just trying to understand the mysqlnd driver support mentioned in the post from @Lars – Richard Owens Jun 27 '18 at 14:18
  • 1
    That duplicate link is a really good page. Please read that advice a couple times, then refer to the manual to research the function, then try to update your code. If no success, show your updated code in your question body via an edit. – mickmackusa Jun 27 '18 at 14:43
  • @user3783243 - if I remove the get_result(), I get "Statement NOT prepared" & "Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, null given in /my_first_prepared_mysqli.php on line 29" + "Fatal error: Call to a member function fetch_assoc() on a non-object in /my_first_prepared_mysqli.php on line XX" I am trying to replicate the example given but the bindings are a real pain. – Richard Owens Jun 27 '18 at 14:43
  • @mickmackusa & Lars OK - I'm struggling with this as I don't have much OOP experience so I don't understand the structure. Procedural is great for to follow but I can't work out how to prepare a statement without using OOP prepare(). I have taken out the mysqli_stmt_init(); – Richard Owens Jun 27 '18 at 14:45
  • `Statement NOT prepared` sounds like a custom error. `mysqli_num_rows` needs a result object. Try http://php.net/manual/en/mysqli.store-result.php e.g. `$stmt->store_result(); $num = $stmt->num_rows;` I'm not a mysqli user though, I use PDO which is much more straight forward. If you are modifying I'd recommending heading down that path. – user3783243 Jun 27 '18 at 14:45
  • @user3783243 - the trouble is - there is no result so I can't store anything anyway. The "Statement NOT prepared is a custom error to check if the statement is prepared - which it isn't so can't even be executed!!! arrrgghh. – Richard Owens Jun 27 '18 at 14:49
  • @user3783243 PDO might be easier... I'll check that out if I exhaust my knowledge on mysqli. – Richard Owens Jun 27 '18 at 14:50
  • 1
    Please add the conditional that gives the `Statement NOT prepared` message. You should use error reporting on that return to see why it fails. You also don't need `$database = mysqli_select_db($connection, 'xxxxx');`, just set the DB as the 4th parameter of the connection. – user3783243 Jun 27 '18 at 14:54
  • @mickmackusa I've updated this now and shown as an edit as suggested. I think all I need to crack now is the syntax on how to get a result array and loop through them. – Richard Owens Jun 27 '18 at 15:54
  • What exactly you are wanting to achieve? I mean, do you want ur resulting webpage to show? – Sanu_012 Jun 27 '18 at 16:07
  • @Sanu_012 it's not just a dynamic webpage - it's an entire CRM so I'm using this in various ways. I think I've cracked it now with: while (mysqli_stmt_fetch($stmt)) { printf("%s %s %s %s", $CONTACTID, $COMPANY, $FORENAME, $SURNAME); echo "
    "; }
    – Richard Owens Jun 27 '18 at 17:06
  • Oh.. congrats if you have cracked it. Good luck. – Sanu_012 Jun 27 '18 at 17:08

1 Answers1

0

Thanks for all the contributions. I now have a working procedural solution that I thought I'd post for reference.

It's a bit cumbersome but it's fine and I believe it follows good modern practice.

$servername = "localhost"; $username = "xxxx"; $password = "xxxx"; $dbname = "xxxx";
$conn = new mysqli($servername, $username, $password, $dbname);// Create connection

// Check connection
if ($conn->connect_error) {
   die("Connection failed: " . $conn->connect_error);
}

$param1 = $_GET['q'];

$stmt = mysqli_prepare($conn, "SELECT CONTACTID, COMPANY, FORENAME, SURNAME FROM CONTACTS WHERE SURNAME = ?");
mysqli_stmt_bind_param($stmt, "s", $param1);// bind parameters for markers
mysqli_stmt_execute($stmt);// execute query
mysqli_stmt_bind_result($stmt, $CONTACTID, $COMPANY, $FORENAME, $SURNAME);// bind result variables

// fetch values
while (mysqli_stmt_fetch($stmt)) {
   echo $CONTACTID."<br>";
   echo $COMPANY."<br>";
   echo $FORENAME."<br>";
   echo $SURNAME."<br>";
   echo "<hr/>";
}

mysqli_stmt_close($stmt);// close statement

mysqli_close ($conn);

Feedback welcome if you can see any improvements.

Richard Owens
  • 155
  • 16