The following code:
<?php
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
echo "Connection is successful!<br/>";
$sql = "SELECT * FROM users";
$users = $dbh->query($sql);
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
$dbh = null;
}
catch (PDOexception $e) {
echo "Error is: " . $e-> etmessage();
}
Output:
Connection is successful!
person A-male
person B-female
Running "foreach" twice is not my purpose, I'm just curious why TWO "foreach" statements only output the result once?
Following is the similar case:
<?php
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
echo "Connection is successful!<br/>";
$sql = "SELECT * FROM users";
$users = $dbh->query($sql);
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
echo "<br/>";
$result = $users->fetch(PDO::FETCH_ASSOC);
foreach($result as $key => $value) {
echo $key . "-" . $value . "<br/>";
}
$dbh = null;
}
catch (PDOexception $e) {
echo "Error is: " . $e-> etmessage();
}
Output:
Connection is successful!
person A-male
person B-female
SCREAM: Error suppression ignored for
Warning: Invalid argument supplied for foreach()
But when I delete the first "foreach" from the above codes, the output will become normal:
<?php
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
echo "Connection is successful!<br/>";
$sql = "SELECT * FROM users";
$users = $dbh->query($sql);
echo "<br/>";
$result = $users->fetch(PDO::FETCH_ASSOC);
foreach($result as $key => $value) {
echo $key . "-" . $value . "<br/>";
}
$dbh = null;
}
catch (PDOexception $e) {
echo "Error is: " . $e-> etmessage();
}
Output:
Connection is successful!
user_id-0000000001
name-person A
sex-male
Why does this happen?
A PDOStatement (which you have in $users) is a forward-cursor. That means, once consumed (the first foreach iteration), it won't rewind to the beginning of the resultset.
You can close the cursor after the foreach and execute the statement again:
$users = $dbh->query($sql);
foreach ($users as $row) {
print $row["name"] . " - " . $row["sex"] . "<br/>";
}
$users->execute();
foreach ($users as $row) {
print $row["name"] . " - " . $row["sex"] . "<br/>";
}
Or you could cache using tailored CachingIterator with a fullcache:
$users = $dbh->query($sql);
$usersCached = new CachedPDOStatement($users);
foreach ($usersCached as $row) {
print $row["name"] . " - " . $row["sex"] . "<br/>";
}
foreach ($usersCached as $row) {
print $row["name"] . " - " . $row["sex"] . "<br/>";
}
You find the CachedPDOStatement class as a gist. The caching iterator is probably more sane than storing the result set into an array because it still offers all properties and methods of the PDOStatement object it has wrapped.
Executing the same query again only to get the results you already had, as suggested in the accepted answer, is a madness. Adding some extra code to perform such a simple task also makes no sense. I have no idea why people would devise such complex and inefficient methods to complicate such primitive, most basic actions.
PDOStatement is not an array. Using foreach over a statement is just a syntax sugar that internally uses the familiar one-way while loop. If you want to loop over your data more than once, simply select it as a regular array first
$sql = "SELECT * FROM users";
$stm = $dbh->query($sql);
// here you go:
$users = $stm->fetchAll();
and then use this array as many times as you need:
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
echo "<br/>";
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
Also quit that try..catch thing. Don't use it, but set the proper error reporting for PHP and PDO
This is because you are reading a cursor, not an array. This means that you are reading sequentially through the results and when you get to the end you would need to reset the cursor to the beginning of the results to read them again.
If you did want to read over the results multiple times, you could use fetchAll to read the results into a true array and then it would work as you are expecting.
$users = $dbh->query($sql);
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
Here $users is a PDOStatement object over which you can iterate. The first iteration outputs all results, the second does nothing since you can only iterate over the result once. That's because the data is being streamed from the database and iterating over the result with foreach is essentially shorthand for:
while ($row = $users->fetch()) ...
Once you've completed that loop, you need to reset the cursor on the database side before you can loop over it again.
$users = $dbh->query($sql);
foreach ($users as $row) {
print $row["name"] . "-" . $row["sex"] ."<br/>";
}
echo "<br/>";
$result = $users->fetch(PDO::FETCH_ASSOC);
foreach($result as $key => $value) {
echo $key . "-" . $value . "<br/>";
}
Here all results are being output by the first loop. The call to fetch will return false, since you have already exhausted the result set (see above), so you get an error trying to loop over false.
In the last example you are simply fetching the first result row and are looping over it.
$row = $db->getAllRecords(DB_TBLPREFIX . '_payplans', '*', ' AND ppid = "' . $myid . '"');
foreach ($row as $value) {
$bpprow = array_merge($bpprow, $value);
}
This is based on PHP functions where you can globally use this data.
Related
I'm trying to get a data from db, I would to say welcome $row['name'];
then in a loop need to print the items
if I did the below code, I will get all items except the first item, but if I deleted the $row2 with the welcoming name, I will get all items why ?
is there a way to use this $row = $SQL->fetch() for both?
<?php
session_start();
include "connect.php";
$access = isset($_SESSION["userid"]);
if ($access) {
$SQL = $dbh->prepare("SELECT * from items, users where userid = ?");
$SQL->execute([$_SESSION["userid"]]);
$row2 = $SQL->fetch();
echo "Welcome " . $row2['name'] . "<br>";
while ($row = $SQL->fetch()) {
echo $row["itemname"] . "-" . $row["price"] . "-" . $row["itemqty"] . "<br>";
}
}else{
echo "<h1>Not Logged in. Access denied.</h1>";
}
?>
When you run fetch() you are moving forward the pointer in the result set. So your first call to fetch() gets the first row, second gets the second row, etc.
Probably the easiest approach would be to pull all results into an array and then work with that.
<?php
session_start();
include "connect.php";
$access = isset($_SESSION["userid"]);
if ($access) {
$SQL = $dbh->prepare("SELECT * from items, users where userid = ?");
$SQL->execute([$_SESSION["userid"]]);
$data = $SQL->fetchAll();
$row2 = $data[0];
echo "Welcome " . $row2['name'] . "<br>";
foreach ($data as $row) {
echo $row["itemname"] . "-" . $row["price"] . "-" . $row["itemqty"] . "<br>";
}
} else {
echo "<h1>Not Logged in. Access denied.</h1>";
}
I currently have a HTML search form which takes the users input (for example 123456) and using PHP searches a database to see if that number exists as an item number. It then returns information on that item in a table.
Is it possible to search for multiple items at once for example 123456, 654321, 000000 and have the results for each displayed in a table ? I currently have not been able to find any documentation on how I could achieve this. Any help would be greatly appreciated.
My current code which searches and brings back the data for one item is.
<div id="div1">
<!-- [SEARCH FORM] -->
<form method="post" action="nweb.php">
<h1>Product Information</h1>
<input type="text" name="search" required/>
<input type="submit" value="Search"/>
</form>
<?php
if (isset($_POST['search'])) {
require "2-search.php";
if (count($results) > 0) {
foreach ($results as $r) {
echo "<table>";
echo "<tr><td>Item number</td><td>" . $r['item_number'] . "</td></tr>";
echo "<tr><td>Stock available</td><td>" . $r['stock_available'] . "</td></tr>";
echo "<tr><td>Available Stock</td><td>" . $r['available_stock'] . "</td></tr>";
echo "<tr><td>Detailed Description</td><td>" . $r['detailed_desc'] . "</td></tr>";
echo "<tr><td>Gender</td><td>" . $r['gender'] . "</td></tr>";
echo "<tr><td>Group</td><td>" . $r['group'] . "</td></tr>";
echo "<tr><td>Subgroup</td><td>" . $r['sub_group'] . "</td></tr>";
}
echo "</table>";
} else {
echo "No results found";
}
}
?>
</div>
My search code is.
try {
$pdo = new PDO(
"sqlsrv:Server=$server;Database=$database", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
$stmt = $pdo->prepare ("SELECT * FROM dbo.[data] WHERE [item_number] LIKE ? OR [stock_available] LIKE ?");
$stmt->execute(["%" . $_POST['search'] . "%", "%" . $_POST['search'] . "%"]);
$results = $stmt->fetchAll();
if (isset($_POST['ajax'])) { echo json_encode($results); }
?>
One simple way, without too many drastic changes in your code, would be to choose a separator (maybe a comma) and write your items like that, then, you'd separate these items into an array of search items:
$searchFor = explode(',', $_POST['search']);
And search for them one by one:
$resultsArray = [];
foreach ($searchFor as $searchItem){
$stmt = $pdo->prepare ("SELECT * FROM dbo.[data] WHERE [item_number] LIKE ? OR [stock_available] LIKE ?");
$stmt->execute(["%" .$searchItem . "%", "%" . $searchItem . "%"]);
$results = $stmt->fetchAll();
array_push($resultsArray, $results);
}
Finally, you'd echo the tables almost the same way you did until now:
foreach ($resultsArray as $results) {
...
foreach ($results as $r) {
...
Assume I'm in need to loop twice with the result I got form PDO prepared statement.
First loop works fine, the next one does not work
The value of var_dump(q->fetch()) is empty array. Any ideas?
<?php
$q = $dbconnection->prepare("SELECT * from users WHERE role=?");
$q->execute(array('$id')); //Boolean true or false
// first loop
while ($row = $q->fetch(PDO::FETCH_ASSOC)) {
echo "<br/>" . $row['user_id'] . "--". $row['fname']. "</br>";
}
// second loop this loop will NOT echo any thing ?!
while ($row = $q->fetch(PDO::FETCH_ASSOC)) {
echo "<br/>" . $row['user_id'] . "--". $row['fname']. "</br>";
}
When you loop the row, you empty out the result set. If you want to loop over multiple times, you can use fetchAll(), store that in a variable and loop that where you need using a foreach loop.
$q = $dbconnection->prepare("SELECT * from users WHERE role=?");
$q->execute(array($id)); //Boolean true or false
$res = $q->fetchAll();
foreach ($res as $row) {
echo "<br/>" . $row['user_id'] . "--". $row['fname']. "</br>";
}
foreach ($res as $row) {
echo "<br/>" . $row['user_id'] . "--". $row['fname']. "</br>";
}
Alternatively, you can execute the query again, but if you do that, you make a double query to the database. So you query twice for the same data, which isn't very efficient.
Also you had execute(array('$id')), which would be the exact string $id, and not the variable representation. See the PHP manual on strings. So it should be execute(array($id)) instead.
PHP.net on PDOStatement::fetchAll()
Your are fecth a row time by time if you need two iteration you should perform a copy eg storing rows
while ($row = $q->fetch(PDO::FETCH_ASSOC)){
echo "<br/>" . $row['user_id'] . "--". $row['fname']. "</br>";
$my_rows[] = $row;
}
// second loop this loop will NOT echo any thing ?!
foreach($my_rows as $key=>$value){
echo "<br/>" . $value['user_id'] . "--". $value['fname']. "</br>";
}
I use a http://php.net/ page code for conecting with PDO. I Add the EXIST term. How to check if the EXISTS return false? If is not posible, how to check if select return an empty result?
try {
$conn = new PDO("mysql:host=$servername;dbname=xxxx", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
getUsers($conn,$po[0]);
$conn = null;
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
function getUsers($con,$po){
$sql = "SELECT * FROM usuarios WHERE EXISTS (SELECT id FROM webs WHERE name='$po')";
foreach ($con->query($sql) as $row) {
print $row['nombre'] . "\n";
print $row['id'] . "\n";
print $row['email'] . "\n";
}
}
The WHERE EXISTS returns a standard SELECT result (rows) based on the subquery after key EXISTS
So, to check if the EXISTS fails, you have to use rowCount, that return the number of rows returned by the query:
$result = $con->query($sql);
if( $result->rowCount() > 0 ) echo "EXISTS";
else echo "NOT EXISTS";
(Edit:)
Please note:
As noted in the comments below, the rowCount() works fine in this case and always with mySQL database structures, but «this behaviour is not guaranteed for all database» structures: with sqLite, i.e., it doesn't works.
if you will use like this then it will work and no require for check condition
$rows = $con->query($sql);
if($rows){
foreach ($rows as $row) {
print $row['nombre'] . "\n";
print $row['id'] . "\n";
print $row['email'] . "\n";
}
}
I am making a login page that checks for matching values in a database if the SELECT query returns a matching row with username and password then it will return a row count of 1. The way I have it coded right now when I echo the variable that stores the row count it will echo 26 for some reason and I'm not to sure why.
Would someone explain if I am doing something wrong or if this is normal behavior and where that value is coming from?
function checkLogin($conn,$myusername,$mypassword,$row,$row1){
try {
$sql = "SELECT COUNT(*) FROM CLL_users WHERE user_name = 'user' AND password = 'XXXX'";
if ($results = $conn->query($sql)) {
if($results->fetchColumn() > 0) {
$sql = "SELECT * FROM CLL_users WHERE user_name = 'user' AND password = 'XXXXX'";
foreach ($conn->query($sql) as $row)
{
$rowCount = count($row);
echo $rowCount;
print ("Username: " . $row['user_name'] . "<br>");
print ("Username: " . $row['password'] . "<br>");
}
echo $count;
}
else {
print "NO ROWS";
}
}
} catch (PDOException $e){
echo 'Connection failed: ' . $e->getMessage();
}
}
Your code, $rowCount = count($row);, is counting the columns in the current row - not the number of rows returned by the query.
On the same note, you are echoing a second count related variable, $count, but you neither declare-it nor increment it in your code. It looks like this one is the one that's supposed to be counting the number of rows you loop through. If this is true, you should set it as $count = 0; before the loop and use $count++; within it:
$count = 0;
foreach ($conn->query($sql) as $row) {
print ("Username: " . $row['user_name'] . "<br>");
print ("Username: " . $row['password'] . "<br>");
$count++;
}
echo $count;
Also, you're currently using PDO's rowCount prior to selecting a user, and you're using it properly. You could just store that result into a variable and use it to tell how many rows you are receiving:
$sql = "SELECT COUNT(*) FROM CLL_users WHERE user_name = 'user' AND password = 'XXXX'";
if ($results = $conn->query($sql)) {
$numRows = $results->fetchColumn();
if($numRows > 0) {
... rest of your code ....
function checkLogin($conn,$myusername,$mypassword,$row,$row1)
{
try
{
$sql = "SELECT COUNT(*) FROM CLL_users WHERE user_name = 'user' AND password = 'XXXX'";
if ($results = $conn->query($sql))
{
$count = $results->fetchColumn();
echo "$count\n";
if($count > 0)
{
$sql = "SELECT * FROM CLL_users WHERE user_name = 'user' AND password = 'XXXXX'";
foreach ($conn->query($sql) as $row)
{
print ("Username: " . $row['user_name'] . "<br>");
print ("Username: " . $row['password'] . "<br>");
}
}
else
{
print "NO ROWS";
}
}
}
catch (PDOException $e)
{
echo 'Connection failed: ' . $e->getMessage();
}
}