The php manual seems to be a little light regarding the mysqli extension and I am not finding any information poking with Google.
When I create a mysqli prepared statement, should the order of calls be
mysqli::prepare()
mysqli::stmt::bind_param()
mysqli::stmt::execute()
mysqli::stmt::store_result()
mysqli::stmt::bind_result()
or
mysqli::prepare()
mysqli::stmt::bind_param()
mysqli::stmt::execute()
mysqli::stmt::bind_result()
mysqli::stmt::store_result()
Furthermore, if I then want to change the parameters and reexecute the statement, should I use
mysqli::free_result()
mysqli::stmt::execute()
mysqli::stmt::store_result()
mysqli::bind_result()
or can I simply use execute() again and then use free_result() once I am finished using the statement?
It is not PHP manual but mysqli extension itself being unclear and ambiguous.
However, to clear your confusion
You can call store_result() anywhere you wish between prepare() and fetch(). As a matter of fact, bind_result() is just a supplementary function for fetch().
In PHP you rarely need to free anything in general, and especially in cases like this, when result going to be overwritten in the next call. So - yes, you can simply call execute() again (with bind_param() first).
Also note that some installations will let you call get_result which makes all that process with fetching variables at least sensible. But is isn't always available
Also note that neither bind_param() nor bind_result() will let you easily bind an arbitrary number of variables, which will make code even more bloated.
So, looking at all that mess I'd still suggest you to use either PDO or manually implemented placeholders, like safeMysql does.
here is an example that works:
$query="SELECT service_ip,service_port FROM users WHERE username=? and password=?";
$conn=connection();
$stmt = $conn->prepare($query);
$stmt->bind_param('ss', $user,$pass);
$ans=$stmt->execute();
$service_ip=false;
$service_port=false;
$stmt->bind_result($service_ip,$service_port);
$stmt->fetch();
mysqli_free_result($ans);
$stmt->close();
$conn -> close();
Here is proper code:
$query="SELECT service_ip,service_port FROM users WHERE username=? and password=?";
$stmt = $conn->prepare($query);
$stmt->execute(array($user,$pass));
$data = $stmt->fetch()/fetchAll()/fetchColumn();
// whoops! that's all
// ...in case you want to execute again
$stmt->execute(array($user2,$pass2));
$data = $stmt->fetch()/fetchAll()/fetchColumn();
// and again...
$stmt->execute(array($user3,$pass3));
$data = $stmt->fetch()/fetchAll()/fetchColumn();
Note that you already have all required data. Feel the power of PDO
Related
I have 2 prepared statements in function. After I get result from first, I need one field's value from this result to be used in second statement as bind_param() function's parameter. But I was getting error, until I found out about store_result() function and used it after first statement. So can you tell or give some reference to read, why is there need to use store_result() function and why this problem arises, during using 2 prepared statements.
I don't know if I am right, but in my opinion this happens because I am not closing first statement before starting second and maybe because of both are open, some error arises.
EDIT:
I found out some information, that somehow helps me to solve this problem
Command out of sync:
This can happen, for example, if you are using mysql_use_result() and try to execute a new query before you have called mysql_free_result(). It can also happen if you try to execute two queries that return data without calling mysql_use_result() or mysql_store_result() in between.
store_result() it self for using Transfers a result set from the last query.
Example :
$stmt = $mysqli->prepare("SELECT col1,col2 FROM tabel WHERE col1= ?")
$stmt->bind_param('s', $test);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($col1,$col2);
$stmt->fetch();
You can read it in here how to use prepared-statement.
You can read this documentation how to use mysqli prepared-statement.
I have seen some tutorials on the web about using PHP Prepared Statements and MySQLi. some are using the mysqli_stmt mysqli::stmt_init() like:
$stmt = $mysqli->stmt_init();
to call prepare() and other properties and methods of prepared statement
and some are not initilaizing like
if ($stmt = $mysqli->prepare("INSERT INTO CodeCall (FirstName, LastName) values (?, ?)")) {}
now my question is , is it necessary to initialize an object to be used?
Thanks
No, it's not necessary. I use MySQLi all the time and have never used that method. You can simply use mysqli::prepare like you've seen in those examples.
The documentation says:
Allocates and initializes a statement object suitable for mysqli_stmt_prepare().
Any subsequent calls to any mysqli_stmt function will fail until mysqli_stmt_prepare() was called.
So it sounds like this is the "manual" way to create a prepared statement, because it requires more steps. The other mysqli::prepare method handles it in one step.
It might be necessary. I recently ran into an issue where I was doing it this way:
$stmt = $mysqli->prepare
And this worked on my local VM. It worked on our staging server. But it refused to work on the server we set up for the client to test. This server for the client was an exact clone of the staging server so it should have worked. After debugging I found that $stmt was never initialized so the application would always bomb out when $stmt->execute(); was called.
But doing it manually worked on all servers and locally:
$stmt = $mysqli->stmt_init();
$stmt->prepare($sql);
I have no idea why the first method did not work consistently. Felt like sharing though, seemed relevant.
I want to know if the use of bindParam is mandatory to prevent SQL injection using PDO and MYSQL.
Example:
$username=$_POST['username'];
$password=$_POST['password'];
$cryptpass=hashFunction($password);
$sth=$dbh->prepare("INSERT INTO users(username,password) VALUES(?,?)");
$sth->execute(array($username,$cryptpass));
Is it a safe and proper way to write this code? Omitting bindParam makes shorter code.
This is still binding the values to a prepared statement. You are doing the same thing as if you were using the bindParam function. So the answer is yes it is just as safe. bindParam just allows for more functionality than simply binding with the execute function for example:
$sth=$dbh->prepare("Select * from users where status=:v1");
$sth->bindParam(':v1',1,PDO::PARAM_INT);
$sth->execute();
This allows you to specify the data_type by default with execute everything is sent as a string. Also you can look at the answer to this similar question: PDO bindParam vs. execute
All that matters is that you use parameters rather than substituting directly into the query string. It doesn't matter whether you bind the parameters with bindParam or with an array argument to execute, they're equivalent.
I have a conventional query that works just fine that looks like this:
$result = $mysqli->query("SELECT value FROM activities WHERE name = 'Drywall'");
This succeeds in returning a row. However, for the purposes of diagnosing the problem I'm having with a prepared statement, I tried an identical query as a prepared statement like so:
$stmt = $mysqli->prepare("SELECT value FROM activities WHERE name = 'Drywall'");
$stmt->execute();
Despite the fact these are identical query strings, $stmt->num_rows is always 0. Why would the conventional query work, but the prepared statement not when they are the same exact query? Also, I realize including 'Drywall' in the prepared query string runs counter to the purpose of prepared statements, but I was just trying to eliminate the possibility that bind_param() was the culprit. So I was using bind_param() to fill in placeholders and that wasn't working either, despite my double-checking at runtime that the variable I was binding contained the correct value.
I think you want to use
$stmt->store_result();
before the call
$stmt->num_rows();
see last line of the descripton in the manual for $stmt->num_rows() (http://www.php.net/manual/en/mysqli-stmt.num-rows.php).
Check for proper use of the mysqli->prepare. The function depends on a parameter to be passed. It is different from passing the values directly in the query but can use with another way.
Verify the manual:
http://www.php.net/manual/pt_BR/mysqli.prepare.php
Did you try something like this:
$stmt = $mysqli->prepare("SELECT value FROM activities WHERE name = 'Drywall'");
$stmt->execute();
$res = $stmt->get_result();
$row = $res->fetch_assoc();
PS:
Prepared statements are Good. I would urge you to ALWAYS consider using them.
But in this case, a simple query would be much more efficient (would incur fewer round trips) than a prepared statement.
I've always used PDO statements, but for some reason I can't persuade the server guy to install PDO for php, but I do have MySQLi, I have no clue what I'm doing wrong, I do not get a connection error and I do not get a query error no matter how I try to output one. Here's what I'm doing.
include 'MySQLiConnect.php';
if($stmt = $mysqli->prepare("SELECT * FROM zipCodeTable WHERE zip_code = ?")){
$stmt->bind_param("s", '07110');
$stmt->execute();
$stmt->bind_result($resultsArray);
$stmt->fetch();
foreach($resultsArray as $columnData){
$matchingZipcode = $columnData['zip_code'];
$matchingTimezone = $columnData['time_zone'];
}
$stmt->close();
}
echo $matchingZipcode.', '.$matchingTimezone;
This is basically just to confirm a users zipcode, never used MySQLi prepared statements before, I tryed to do it straight from the manual, not sure what I'm doing wrong. Thank you for taking the time to read this.
You're trying to "bind" a literal string. You can't do this. You must bind a variable.
Change
$stmt->bind_param("s", '07110');
To
$string = '07110';
$stmt->bind_param("s", $string);
Also, when you bind a result you must provide a variable for each field returned.
For example:
$stmt->bind_result($zipCode, $timeZone);
This is slightly problematic when using SELECT *. You might be interested in checking out this comment for how you might want to go about it: http://www.php.net/manual/en/mysqli-stmt.bind-result.php#85470