Prepared Statement, Fails when re-used - php

I have this code, works fine when looped through once.
<!-- language: php -->
<?php
$query = "SELECT username FROM users WHERE user_id = ? LIMIT 1";
$stmt = $con->prepare($query) or die(mysqli_error($con));
$stmt->bind_param("s", $user_id);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($username);
?>
When I call it for the first time on the page, it loads fine and the data shows as it should.
<!-- language: php -->
<?php
// This one works fine.
while ($stmt->fetch()){
echo 'Welcome '.$username;
}
?>
If I want to re-use the same query somewhere else, it fails wihtout errors. Am I doing it wrong? What is the correct way to re-use the same query multiple time on the same page, Since the data is the same, I don't want to re-query the DB each time.
<!-- language: php -->
<?php
// When re-used somewhere else on the page, it fails. Nothing shows.
while ($stmt->fetch()){
echo 'Welcome '.$username;
}
?>

fetch returns one row after another. Once you fetch all rows, any further call to fetch() method will return false.
You need to re-execute() the query in order to get the same result again. This will go to call database again though. If you want to cache the result, you need to put it into some in-memory cache / global variable / whatever you prefer.
If you really want to get to the beginning of result set again, you can use mysqli_data_seek() for this:
mysqli_data_seek($stmt, 0);
while ($stmt->fetch()){
echo 'Welcome '.$username;
}

You could pull the query result into an array with fetchAll
$users = $stmt->fetchAll();
// this works
foreach($users as $user) {
echo 'Welcome ' . $username;
}
// this works again
foreach($users as $user) {
echo 'Welcome ' . $username;
}
More information here: http://php.net/manual/fr/pdostatement.fetchall.php

What you can do is get the result-set as an ASSOC Array and save the result in a variable. Now you can use this array as many times as you want.
Update your code like this,
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$results = $stmt->fetchAll();
foreach ($results as $r) {
//first time use
}
foreach ($results as $r) {
//second time use
}

I needed to split up the code to achieve what I needed with MySQL(i).
Thanks for your inputs.
<?php
// Preparing the statement
$query = "SELECT username FROM users WHERE user_id = ? LIMIT 1";
$stmt = $con->prepare($query) or die(mysqli_error($con));
$stmt->bind_param("s", $user_id);
$stmt->store_result();
?>
<?php
// Executing it when needed and creating some variables for later re-use
$stmt->execute();
$stmt->bind_result($username);
while ($stmt->fetch()) {
$new_username = $username;
echo 'Welcome '.$new_username;
}
?>
<?php
// It is possible now to re-use the same result set
echo 'Welcome '.$new_username;
?>

You can store the results:
<?
$query = "SELECT username FROM users WHERE user_id = ? LIMIT 1";
$stmt = $con->prepare($query) or die(mysqli_error($con));
$stmt->bind_param("s", $user_id);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($col['username']);
$result = array();
for ($i = 0; $i < $stmt->num_rows; $i++){
$stmt->data_seek($i);
$stmt->fetch();
foreach ($col as $key => $value){
$result[$i][$key] = $value;
}
}
?>

Related

how to query once and display multiple times with where clause?

I want to learn how to query once and display in multiple boxes with
where clause?
like :
if status 1 ? : display in <div class="1"> elseif status 2 ?: <div class="2"> etc. etc.
I know my answer is in my question and I need to do if statements, but I dont know how to display while loop or foreach a few times with same query.
Here is my query :
$stmt = $pdo->prepare("SELECT * FROM categories");
$stmt->execute();
while($row = $stmt->fetch()){
}
I have searched on google got a few examples like this with for loop but I didnt find any examples with where claus.
$i;
$stmt = $pdo->prepare("SELECT * FROM categories");
$stmt->execute();
while($row = $stmt->fetch()){
}
for($i=0; $i<5; $i++){
}
I tried if statment without foreach loop :
if($status == 1){
foreach(){
echo "Display box 1";
}
}
if($status == 2){
foreach(){
echo "Display box 2";
}
}
Displaying only one post need while loop or foreach to display all posts with status 1
Thanks
While you could buffer multiple streams, read the entire dataset into a PHP array and search it or run multiple queries, all are unnecessary and inefficient. Just sort the query. Consider:
$stmt = $pdo->prepare("SELECT * FROM categories ORDER BY status");
$stmt->execute();
$prevstatus=-1;
print "<div style='display:none'>";
while($row = $stmt->fetch()){
if ($row['status']!=$prevstatus) {
$prevstatus=$row['status'];
print "</div><div class='$prevstatus'>";
}
print ....
}
print "</div>";
I don't know if I understand your question but:
$stmt = $pdo->prepare("SELECT * FROM articles");
$stmt->execute();
while($row = $stmt->fetch()){
echo "<div class=\"class_". $row["status"] ."\">div content</div>\n";
}
And - CSS classes can not begin with numbers or have only numbers as a name! In my example I use .class_x (where X is your value from database)

Mysqli query with bind params using fetch_array

I know how to use fetch_array instead of printf() function when expressing rows from database using mysqli bind function.
How can I use $row->mysqli_fetch_array and then use $row[0],$row[1] instead of using the printf() function every time I want to print something from database?
Returning an associative array from a prepared statement you can follow up the procedure like this as follows.
<?php
$category = $_POST['category'];
$sql = "select id, name from items where category = ?";
$stmt = $connection->prepare($sql);
$stmt->bind_param('s', $category);
if($stmt->execute())
{
$result = $stmt->get_result();
$a = $result->fetch_array(MYSQLI_ASSOC); // this does work :)
}
else
{
error_log ("Didn't work");
}
?>
You can use while loop for printing up the value over from the associative array.
while($a = $result->fetch_array(MYSQLI_ASSOC))
{
echo 'Id: '. $a['id'];
echo '<br>';
echo 'Name: '.$a['name'];
}
Output:
Id: 1
Name: Example
If I got your question correctly you can try:
$row=mysqli_fetch_array($result,MYSQLI_NUM);
foreach($row as $cell) {
echo "$cell";
}

Fetch row with pdo and relational database

i have a little problem, i have a database with 2 tables, users and comments and i need to print the result with pdo.
if i try this code, everything works great:
$stmt = $dbConnection->prepare("SELECT comment_text, username FROM users, comments WHERE users.user_id = comments.user_id");
$stmt->execute();
$stmt->fetch(PDO::FETCH_ASSOC);
foreach ($stmt as $row) {
echo $row['comment_text'] . "<br>By " . $row['username'] . "<br>";
}
But if i try to add a variable which get the result of fetch i get a totally different result with only 2 rows and only the first letter of the value...
$stmt = $dbConnection->prepare("SELECT comment_text, username FROM users, comments WHERE users.user_id = comments.user_id");
$stmt->execute();
$comment = $stmt->fetch(PDO::FETCH_ASSOC);
foreach ($comment as $row) {
echo $row['comment_text'] . "<br>By " . $row['username'] . "<br>";
}
if i try this code, everything works great:
it is not.
this way you are losing the very first comment. So it should be just
$stmt->execute();
foreach($stmt as $row )
{
echo $row['comment_text']."<br>By ".$row['username']."<br>" ;
}
in case you want to save the result in array, you have to use the appropriate function for that:
$stmt->execute();
$comments = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($comments as $row )
{
echo $row['comment_text']."<br>By ".$row['username']."<br>" ;
}
while fetch() is getting you only one record, fetchAll() is doing what the name suggests
Both your samples aren't functionning properly :
In the first one you loop over every row except the first row, for which you did a fetch, and then did nothing with this first row.
In the second one you loop over every field of the first row, which produce some unexepected output.

How to get fetchall to only get one input per row and to get multiple results

I am using php and MySQL to retrieve and to print the output from the mysql database; however, when I run through the following code I get two results from the echo instead of one:
<?php require('includes/config.php');
$stmt = $db->prepare("select username From members where resetToken like 'yes';");
$stmt->execute();
$result = $stmt->fetchAll();
foreach ($result[0] as $value) {
echo "$value <br>";
}
?>
Also when I run the sql through phpmyadmin it returns multiple users but when I run it through the php page it only returns one. Also the config.php contains all of the database info so that is not the problem.
There's only one result because you're only checking the very first result (at index 0). Iterate first over the results, then over their values:
<?php
require('includes/config.php');
$stmt = $db->prepare("select username From members where resetToken like 'yes';");
$stmt->execute();
$results = $stmt->fetchAll();
foreach ($results as $values)
foreach($values as $value) {
echo "$value <br>";
}
}
?>

How to fetch 2 times in MYSQL PDO without FETCHALL

I have this sample query:
$STH = $DBH->query("SELECT id FROM table");
I want to get the first row and then loop and display all rows. So I use the following to get the first row:
$STH->setFetchMode(PDO::FETCH_ASSOC);
$first_row = $STH->fetch();
$first_row = $first_row['id'];
I use while loop to display all rows again:
while ($list = $STH->fetch()) {
$id = $list['id'];
echo $id;
}
Now the while skips the first row and I want it to be displayed. Is there an equivalent to mysql_data_seek to reset the pointer again to the first row? I know fetchall can be used but it's bad on memory and wasteful. I could also run the query and limit to 1 but this is not recommended as I have a query that joins multiple tables and would be very slow. Is there any other solution?
Thanks
I take that back looks like you can use the cursor orientation contants to select the result... sample code coming... I havent tried this so you may need to play a bit. This is also based on the assumption that a PDO::FETCH_ORI_FIRST acts like a data_seek and leaves the cursor on the first position as opposed to returning it to whatever it was before.
$stmt = $pdo->prepare('SELECT id FROM table', array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$stmt->execute();
$first = $pdo->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_FIRST);
$first_row = $first['id'];
// other stuff
// first iteration we rewind to the first record;
$cursor = PDO::FETCH_ORI_FIRST;
while (false !== ($row = $stmt->fetch(PDO::FETCH_ASSOC, $cursor))) {
$id = $row['id'];
// successive iterations we hit the "next" record
$cursor = PDO::FETCH_ORI_NEXT;
echo $id;
}
I dont think you can rewind a statement... Assuming these blocks arent seprated by a bunch of intermediary logic id just do it in the loop.
$STH->setFetchMode(PDO::FETCH_COLUMN); // no need to pull an array
$count = 0;
while ($id = $STH->fetch()) {
if($count === 0) {
$first_row = $id;
}
echo $id;
$count++;
}
Could you just use a do...while loop instead?
$STH->setFetchMode(PDO::FETCH_ASSOC);
$list = $STH->fetch();
$first_id = $list['id'];
do {
$id = $list['id'];
echo $id;
} while ($list = $STH->fetch());
You can fetch all the result, and then just act on it as an array. So, for instance, you could shift the first result off the front, and then loop over any additional rows:
<?php
$sql = "YOUR QUERY";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// get first row
$firstRow = array_shift($rows);
// loop over remaining rows
foreach ($rows as $row) {
// do something
}

Categories