As I now know, mysqli_real_escape_string is not as secure as prepared statements so I'm making the switch.
However I've run across a slight issue with the simplest bit of code.
The query I am expecting to be executed is SELECT * from forums WHERE id=1 and testing this against the database rows are found.
This is the prepared statement code I am using.
$con=mysqli_connect('a','b','c','d');
$forum = $_GET["forum"];
$stmt = mysqli_prepare($con, "SELECT * from forums WHERE id=?");
echo mysqli_stmt_bind_param($stmt, "i", $forum);
mysqli_stmt_execute($stmt);
mysqli_stmt_fetch($stmt);
mysqli_stmt_store_result($stmt);
if (mysqli_stmt_num_rows($stmt)<1){
echo "0";
}
This seems to return 10 which means the query binded successfully but no rows where found.
I'm sorry if this may seem trivial, but this doesn't make much sense to me.
I suppose you also need mysqli_stmt_bind_result, mysqli_stmt_store_result and mysqli_stmt_fetch to get some results out... At least this is what the manual says.
Unless you use mysqli_stmt_store_result, mysqli_stmt_num_rows will return 0 because mysqli hasn't yet fetched the data and doesn't know how many rows there are.
mysqli_stmt_store_result buffers all the resulting data from MySQL in memory for subsequent use by PHP but it can result in out-of-memory errors with large datasets or low memory limits.
Related
I'm trying to fetch the data from database using prepared statement. I'm new in PDO so I searched about it. Below are the two different pattern giving me same result.
Pattern 1
$pdo=new PDO("mysql:dbname=dummy_db;host=localhost","root","");
$statement=$pdo->prepare("SELECT * FROM mytable");
$statement->execute();
$results=$statement->fetchAll(PDO::FETCH_ASSOC);
print_r($results);
Pattern 2
$stmt = $conn->prepare("select * from mytable");
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_all(PDO::FETCH_ASSOC);
print_r($row);
Above both pattern giving me almost same result, so I wanted to know which one is good for fetching the data and what are the difference between them. I would like to appreciate if someone guide me.
This is interesting question.
Although you are probably unaware of the fact that the second code snippet has nothing to do with PDO and belongs to mysqli, still the question makes some sense.
Because PDO's fetchAll() is WAY more useful than simple fetch_all() from mysqli, thanks to PDO::FETCH constants, letting you fetch the data in dozens different formats.
This is one of the reasons why PDO is recommended over mysqli.
At the start of my application, I check for the account status. This is an internal check I control as I provide the application on a sub-domain.
I have been using this:
// Retrieve account status for application
$query = "SELECT `client_account_status` FROM `version_control` WHERE id = '1' ";
However, as I adapt to prepared statements, I am curious if this is absolutely necessary when there is no user input to check?
$stmt = mysqli_stmt_init($link);
if (mysqli_stmt_prepare($stmt, 'SELECT client_account_status FROM version_control WHERE id = 1')) {
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $client_account_status);
mysqli_stmt_fetch($stmt);
mysqli_stmt_close($stmt);
}
Necessary, no. Recommended, yes. However the way your query is currently written you get no benefit from the prepared statement. Instead it should be:
mysqli_stmt_prepare($stmt,
'SELECT client_account_status FROM version_control WHERE id = ?'));
mysqli_stmt_bind_param($stmt, 'i', 1);
mysqli_stmt_execute($stmt);
The problem with your initial version is that mysql has no way of knowing what part of your query is a parameter and what part is the SQL statement. The point of parameterized queries is to clearly separate the statement from the parameters.
See How can I prevent SQL injection in PHP? for more information on preventing SQL injection.
No, it is not necessary when there is no user input. It can sometimes still be useful to use a prepared statement when there is input though, even if it's not user input. This is because preparing a statement allows it to be executed more efficiently if it is run lots of times with different data each time.
This question is going to have a lot of opinions, I'll add mine to the list...
I personally always go with PDO, or Doctrine's DBAL library.
A query using something like the DBAL class would happen as so:
$result = $db->fetchColumn('SELECT client_account_status FROM version_control WHERE id = :id', [
'id' => $id
]);
In PDO it can be as easy as so:
$pdo->prepare('SELECT client_account_status FROM version_control WHERE id = :id');
$result = $pdo->execute(array(':id' => $id));
It's always easy to read and it doesn't require you to write 5 lines of code every single time you want to do something with the database.
You can have both security and efficiency, and it seems given how you asked your question that you only want to avoid mysqli prepared statements out of the complexity and annoyance of writing so much code for so little to happen.
I've read that if you used mysqli prepare instead of mysqli query it will be run on database only once even if you run the script 1000 times.
does that mean that if i ran a prepare statement like
select * from Table where user=?"
and then mysqli_stmt_bind_param($stmt, "s", "Harry");
and user "harry" doesn't exist in the database so num_rows will return 0.and then i insert immediately a new row in the database with user="harry" and ran the script again, will it return num_rows=1 or still return num_rows=0 because the result is cached?
The fact that you see the newly inserted row depends on other factors... transaction and transaction isolation. Preparing the statement just means that the server knows what is coming and has calculate a plan to optimize the statement. You can then run the query many times, with the same or with different parameters, and the server will not have to analyze it any more... just execute it.
So... to answer your question... the second time you should get num_rows=1. But in case you don't, the problem is not that you prepared a query with parameters... it's something else.
From what I know now about PDO statements and my own experiences on localhost and Google - there are some difficulties with using multiple PDO statements in one query. For instance this situation:
$stmt = $db_people->prepare("SELECT * FROM people WHERE online=1");
$stmt->execute();
$results_people = $stmt->fetch(PDO::FETCH_ASSOC);
On this query I can do simple PDO statement like fetch (in example). But when I want to use PDO statement like this:
$rows = $stmt->rowCount();
It is not possible and the statement will not return the right number of rows. When I do it in the other way around and filling one of the column name - rowCount works correctly like this:
$stmt = $db_people->prepare("SELECT name FROM people WHERE online=1");
$stmt->execute();
$rows = $stmt->rowCount();
And adding fetch after that like this:
$results_people = $stmt->fetch(PDO::FETCH_ASSOC);
Will not work corectly in this example. My question is - How to combine two different PDO statements in one single query? Thank you.
The answer probably depends on which operations you're trying to combine. For instance, if you're trying to combine PDOStatement::rowCount() with a SELECT SQL operation, then it's probably worthwhile to take notice of the warnings in the PDOStatement::rowCount() description which says that rowCount() is not 100% reliable for SELECT statements in all databases.
If the problem you're trying to solve is specifically limited to counting the result rows of a SELECT, then another approach would be to use PDOStatement::fetchAll() and count the rows in the returned array.
When to close prepared statements in PHP?
Example:
$query = "insert into web_reviews (title,added_date,reviewer_home_url,read_more_link,summary) values(?,?,?,?,?)";
$stmt = $this->db->prepare($query);
$stmt->bind_params($this->title,$this->added_date,$this->reviewer_home_url,$this->read_more,$this->summary);
$stmt->execute() or die("Cannot add the date to the database, please try again.");
$stmt->close();
$stmt = $this->db->prepare("select id from web_reviews where title = ? and read_more = ?");
$stmt->bind_params($this->title,$this->read_more);
$stmt->execute();
$stmt->bind_results($web_review_id);
$stmt->close();
Should I use $stmt->close(); here?
Edit:
What is written on the PHP Manual and also one comment from the manual says:
Closes a prepared statement.
mysqli_stmt_close() also deallocates
the statement handle. If the current
statement has pending or unread
results, this function cancels them so
that the next query can be executed.
Comment:
if you are repeating an statement in
an loop using bind_param and so on
inside it for a larger operation. i
thougt id would be good to clean it
with stmt->close. but it broke always
with an error after aprox. 250
operations . As i tried it with
stmt->reset it worked for me.
That is a good use of close, especially since you are planning on making another query. With both PDO statements and MySQLi statements, I find that erring on the side of cleanliness is almost always for the best -- it removes potential bugs down the line.
As to the gentlemen with 250 operations... I don't see what the real use case is. Why does he need to query the database 250 different times? Why can't he query the database once with 250 records? Or, more likely, why can't he query the database 25 times with 10 records?
I am unable to comment currently, so I am just providing an answer. When you run a prepared statement that queries the database for a result, it will not execute another query unless you remove the current result it is storing. $result = $stmt->get_result().
Secondly, If you will need the result from the first query to be saved so that you use it later, then I recommend using two result sets. The first stores the result from the first execution of $stmt and the second for the second execution. This might not answer the question directly, but it may help someone.