MYSQLi Multiple Records Outputs Duplicates - php

Issue:
I've continuously looked over my code and cannot find why the array is duplicating the data. A single entry into the database has a correct output, however if there is more than one it will duplicate those before it as well as the next one.
My Code:
global $connection;
//Query database & retrieve results.
$search = $connection->query('SELECT * FROM users WHERE country= "'.$country.'"');
echo '<table><tr><th>Username</th><th>Email</th><th>Country</th></tr>';
while ($result = $search->fetch_assoc())
{
$total[] = $result;
foreach ($total as $rows)
{
echo '<tr>';
echo '<td>'.stripslashes($rows['username']).'</td>';
echo '<td>'.stripslashes($rows['email']).'</td>';
echo '<td>'.stripslashes($rows['country']).'</td>';
echo '</tr>';
}
}
echo '</table>';
Output:
This will return the following form -
Username Email Country
exampleUser1 exampleEmail1#example.com United States
exampleUser1 exampleEmail1#example.com United States
exampleUser2 exampleEmail2#example.com United States
You can see the first line is repeated then the new entry is there, it will continue on from this the more it goes on.
Additional Info:
This is placed inside of a function and is executed when $_POST['country'] is submitted - $country is just $_POST['country'] with a real_escape_string.
$connection is just a new mysqli(localhost, user, pass, database) referenced in the script - it is globalised because this is wrapped inside a function.
Any help would be appreciated.

<?php
//... Your code
while ($rows = $search->fetch_assoc()) {
$rows = array_map('stripslashes', $rows);
echo '<tr>';
echo '<td>'.$rows['username'].'</td>';
echo '<td>'.$rows['email'].'</td>';
echo '<td>'.$rows['country'].'</td>';
echo '</tr>';
}
//... Your code
if you need to save and return from function this rows just create array $total and add $total[] = $rows; after echo '</tr>';

As mentioned in my comment, put the foreach outside your while loop like this:
echo '<table><tr><th>Username</th><th>Email</th><th>Country</th></tr>';
while ($result = $search->fetch_assoc()) {
$total[] = $result;
}
foreach ($total as $rows) {
echo '<tr>';
echo '<td>'.stripslashes($rows['username']).'</td>';
echo '<td>'.stripslashes($rows['email']).'</td>';
echo '<td>'.stripslashes($rows['country']).'</td>';
echo '</tr>';
}
echo '</table>';
Another solution is to just redeclare your $total all the time.. Just keep your code then and do:
$total = $result;

Related

Filtering an array with foreach and for loop

I'm pulling data from mssql database into an array called
$results2
I need to echo out each 'Item' only one time, so this example should only echo out:
"52PTC84C25" and "0118SGUANN-R"
I can do this easily with:
$uniqueItems = array_unique(array_map(function ($i) { return $i['ITEM']; }, $results2));
The issue is when i try to echo out the other items associated with those values. I'm not sure how to even begin on echoing this data. I've tried:
foreach($uniquePids as $items)
{
echo $items."<br />";
foreach($results2 as $row)
{
echo $row['STK_ROOM']."-".$row['BIN']."<br />";
}
}
This returns close to what I need, but not exactly:
This is what I need:
Assuming your resultset is ordered by ITEM...
$item = null; // set non-matching default value
foreach ($results2 as $row) {
if($row['ITEM'] != $item) {
echo "{$row['ITEM']}<br>"; // only echo first occurrence
}
echo "{$row['STK_ROOM']}-{$row['BIN']}<br>";
$item = $row['ITEM']; // update temp variable
}
The if condition in the code will check if the ITEM has already been printed or not.
$ary = array();
foreach($results2 as $row)
{
if(!in_array($row['ITEM'], $ary))
{
echo $row['STK_ROOM']."-".$row['BIN']."<br />";
$ary[] = $row['ITEM'];
}
}

echo database data to html php pdo

i have a database select on load of html on the select statement i select the last five in descending or here is the code
loadevent.php
<?php
function LoadEvent(){
global $dbh;
$stmt = $dbh->prepare("SELECT * FROM events ORDER by event_id DESC LIMIT 5") ;
//$stmt->bindValue(1,$eventwhat);
$stmt->execute();
while($selected_row = $stmt->fetch(PDO::FETCH_ASSOC)){
$_SESSION['searchresultwhat'] = $selected_row['event_what'];
$_SESSION['searchresultwhere'] = $selected_row['event_where'];
$_SESSION['searchresultwhen'] = $selected_row['event_when'];
$_SESSION['searchresultwho'] = $selected_row['event_who'];
$event = array($_SESSION['searchresultwhat'] => $selected_row['event_what'], $_SESSION['searchresultwhere'] =>$selected_row['event_where'], $_SESSION['searchresultwhen'] =>$selected_row['event_when'],$_SESSION['searchresultwho'] =>$selected_row['event_who']);
$_SESSION['arr'] = $event;
foreach ($_SESSION['arr'] as $_SESSION['searchresultwhat'] => $selected_row['event_what']){
echo $_SESSION['searchresultwhat'];
echo "<br/>\n";
}
}
}
?>
and in my html at top page i write
index.php
<?php include_once("include/loadevent.php");
LoadEvent();?>
in html my code is
<?php
foreach ($_SESSION['arr'] as $_SESSION['searchresultwhat'] => $selected_row['event_what']){
echo $_SESSION['searchresultwhat'];
echo "<br/>\n";
}
?>
when i do echo from loadevent.php i get the last five in descending order but in index all i get is the first event and nothing more why is it that way can anyone see where my mistake is?
You are doing some very odd things with the $_SESSION var, and as far as I can see there is no reason at all. Try this:
<?php
function LoadEvent()
{
global $dbh;
$stmt = $dbh->prepare("SELECT * FROM events ORDER by event_id DESC LIMIT 5") ;
$stmt->execute();
$events = array();
while ($selected_row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$events[] = array(
'searchresultwhat' => $selected_row['event_what'],
'searchresultwhere' => $selected_row['event_where'],
'searchresultwhen' => $selected_row['event_when'],
'searchresultwho' => $selected_row['event_who']
);
}
// Is this just for testing? Or should it be echoing stuff all the time?
// foreach ($events as $key => $value)
// {
// echo $value['searchresultwhat'];
// echo "<br/>\n";
// }
// This is completely optional and should be removed if you don't
// use the $_SESSION method later on in your HTML
$_SESSION['arr'] = $events;
return $events;
}
?>
...and then in your HTML, do this:
<?php
foreach ($_SESSION['arr'] as $value)
{
echo $value['searchresultwhat'];
echo "<br/>\n";
}
?>
Or, even better in your index.php do this:
<?php
include_once("include/loadevent.php");
?>
Then in your HTML, you can avoid the $_SESSION all together:
<?php
foreach (LoadEvent() as $value)
{
echo $value['searchresultwhat'];
echo "<br/>\n";
}
?>
The simple solution would be to replace $_SESSION['arr'] = $event; with $_SESSION['arr'][] = $event; AND
foreach ($_SESSION['arr'] as $_SESSION['searchresultwhat'] => $selected_row['event_what']){
echo $_SESSION['searchresultwhat'];
echo "<br/>\n";
}
with
foreach ($_SESSION['arr'] as $value){
echo $value[$_SESSION['searchresultwhat']];
echo "<br/>\n";
}
in your 'while' loop you overwrite values in $_SESSION superglobal:
while($selected_row = $stmt->fetch(PDO::FETCH_ASSOC)){
//it is overwritten each time you are in while loop
$_SESSION['searchresultwhat'] = $selected_row['event_what'];
(...)
foreach ($_SESSION['arr'] as $_SESSION['searchresultwhat'] => $selected_row['event_what']){
//in this place when you echo it, it echoes current loop iteration so it is executed 5 times
echo $_SESSION['searchresultwhat'];
echo "<br/>\n";
}
}
being at index.php you do echo of last value only from while loop.

Use PHP to Display MySQL Results in HTML Table

Update for CodingBiz:
I'm putting this in my code:
for($i=1;$i<=$numRows;$i++) {
$output .= '<tr>';
$row = $this->fetchAssoc($result);
$colRow = $this->fetchAssoc($colResult);
foreach($colRow as $colName) {
$output .= "<td>".$row[$colName]."</td>";
}
$output .= '</tr>';
}
in place of
for($i=1;$i<=$numRows;$i++) {
$output .= '<tr>';
$row = $this->fetchAssoc($result);
for($j=1;$j<=$colNumRows;$j++) {
$colRow = $this->fetchAssoc($colResult);
$output .= "<td>".$row[$colRow["COLUMN_NAME"]]."</td>";
}
$output .= '</tr>';
}
Is there anything wrong with this?
Original Post:
I'm writing a function in a PHP class to display the results of a query in a table. I'm not structuring any of the table myself, I want it everything to be done using PHP. Here is my code so far:
function allResults($table,$cols) {
if(isset($cols)) {
$query = "SELECT $cols FROM $table";
}
else {
$query = "SELECT * FROM $table";
}
$result = $this->query($query);
$numRows = $this->numRows($result);
$colQuery ="SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='shareride' AND TABLE_NAME='$table'";
$colResult = $this->query($colQuery);
$colNumRows = $this->numRows($colResult);
$output = '<table class="allResults">';
$output .= '<tr>';
for($i=1;$i<=$colNumRows;$i++) {
$colRow = $this->fetchAssoc($colResult);
$output .= "<td>".$colRow["COLUMN_NAME"]."</td>";
}
$output .= '</tr>';
for($i=1;$i<=$numRows;$i++) {
$output .= '<tr>';
$row = $this->fetchAssoc($result);
for($j=1;$j<=$colNumRows;$j++) {
$colRow = $this->fetchAssoc($colResult);
$output .= "<td>".$row[$colRow["COLUMN_NAME"]]."</td>";
}
$output .= '</tr>';
}
$output .= '</table>';
return $output;
}
In case it is unclear, query refers to mysqli_query, numRows refers to mysqli_num_rows, and fetchAssoc refers to mysqli_fetch_assoc. The database name is "shareride."
I know I am missing something in this line:
$output .= "<td>".$row[$colRow["COLUMN_NAME"]]."</td>";
but I just don't know what it is. Right now, I get all the table column titles displayed correctly, and I get the correct number of content rows, but I just can't populate those rows with the actual data from the database.
What am I missing? Any help would be GREATLY appreciated!
Get the data and column names from the same result set
<?php
$i = 0;
$colNames = array();
$data = array();
while($row = ***_fetch_assoc($res)) //where $res is from the main query result not schema information
{
//get the column names into an array $colNames
if($i == 0) //make sure this is done once
{
foreach($row as $colname => $val)
$colNames[] = $colname;
}
//get the data into an array
$data[] = $row;
$i++;
}
?>
UPDATE: Suggested by #YourCommonSense to replace the above code and it worked, simple and shorter - A WAY TO GET THE COLUMN NAMES/ARRAY KEYS WITHOUT LOOPING THROUGH LIKE I DID
$data = array();
while($row = mysql_fetch_assoc($res))
{
$data[] = $row;
}
$colNames = array_keys(reset($data))
Continued as before: Print the table
<table border="1">
<tr>
<?php
//print the header
foreach($colNames as $colName)
{
echo "<th>$colName</th>";
}
?>
</tr>
<?php
//print the rows
foreach($data as $row)
{
echo "<tr>";
foreach($colNames as $colName)
{
echo "<td>".$row[$colName]."</td>";
}
echo "</tr>";
}
?>
</table>
Test Result
You can see how I separated the data retrieval from table generation. They are dependent of each other now and you can test your table generation without the database by populating the arrays with static data
You can also make them into separate functions.
Never mix your database handling code with HTML output code. These are 2 totally different matters. Make your allResults function only return array with data, and then you can make another function to print in fancy way (and not in the database handler class).
You don't need information schema to get column name - you already have it in the returned array keys.
You don't need numRows either - use while() and foreach()
NEVER insert anything into query directly like you do with $cols - eventually it will lead to errors and injections.
Such a function, without accepting some parameters for the query, makes absolutely no sense especially in the context of migrating from mysql to mysqli - you are going yo use it as an old school mysql query inserting variables, not placeholders. So, it makes migration totally useless.
To know "Is there anything wrong with code", one have to run it, not watch. Run and debug your code, outputting key variables and making sure you can see errors occurred.
i'd try replacing the data part with something like:
while($row = $this->fetchAssoc($colResult))
{
echo "<tr>";
foreach($row as $value)
{
echo sprintf("<td>%s</td>",$value)
}
echo "</tr>";
}
i know it's not a proper answer, but it's really hard to read that code imho

How to iterate over an array of arrays

I'm hoping someone can help.
I'm sure its just a simple one that I just can't work out for some reason.
Basically I have up a class that handles all my database functions (connect, select, insert, update).
In the select function I am returning an array.
public function getAll($table, $cols, $where, $limit, $order) {
// Set the query variables
if($cols == '') {
$cols = '*';
}
if($where!='') {
$where = ' WHERE '.$where;
}
if($limit!= '') {
$limit = ' LIMIT '.$limit;
}
if($order!='') {
$order = ' ORDER BY '.$order;
}
// Make the query string
$sql = 'SELECT '.$cols.' FROM '.$table.$where.$order.$limit;
//echo $sql;
// Set the query
$news_qry = mysql_query($sql);
// Set the array
$rows = array();
// Run a loop through the results
while($item = mysql_fetch_object($news_qry))
{
// Add each row to an array.
$rows[] = $item;
}
return $rows;
}
This function is working as I can print an array. See below:
Array ( [Gallery_id] => 1 [Gallery_Name] => Test [Gallery_FolderName] => Test Folder )
But when I go to use the object -
$arr_GalleryInfo = $dataObj->getAll('tbl_Gallery', '', '', '', '');
Within the for each loop (see below) I only get the first letter of the result from the database.
<?php
foreach ($arr_GalleryInfo[0] as $arrGallery)
{
?>
<tr>
<td>
<?php echo $arrGallery['Gallery_Name']; ?>
</td>
<td>
<?php echo $arrGallery; ?>
</td>
<td>
<?php echo $arrGallery; ?>
</td>
</tr>
<?php
}
?>
Any help would be great.
Thanks.
Replace:
foreach ($arr_GalleryInfo[0] as $arrGallery)
{
etc...
with:
foreach ($arr_GalleryInfo as $arrGallery)
{
etc...
Well, your big issue is that you're trying to iterate over the 0-index of an array.
foreach ($arr_GalleryInfo[0] as $arrGallery) // get rid of the `[0]`.
That will make it so that you actually get some legit iteraction, but there are some other things which are gotchas that you're about to hit.
// this will output `Array`. You want $artGallery['Gallery_FolderName']
// or $artGallery['Gallery_id']
echo $arrGallery;
Of course, you could avoid that whole second issue with a nested loop:
foreach ($arr_GalleryInfo as $arrGallery) {
echo '<tr>';
foreach($arrGallery as $val ) echo "<td>$val</td>";
echo '</tr>';
}
If $news_qry = mysql_query($sql); fails, you'll have nothing to warn you if something breaks. You should make it: $news_qry = mysql_query($sql) or die(mysql_error());
And, of course, you should use mysql_real_escape_string on all of your db inputs.

Displaying an associative array in PHP

I am trying to build a function that extracts information from a database and inserts it into an associative array in PHP using mysql_fetch_assoc, and return the array so another function can display it. I need a way to display the returned assoc array. This should be a different function from the first one
print_r($array) will give nicely formatted (textually, not html) output.
If you just want information about what is in the array (for debugging purposes), you can use print_r($array) or var_dump($array), or var_export($array) to print it in PHP's array format.
If you want nicely formatted output, you might want to do something like:
<table border="1">
<?php
foreach($array as $name => $value) {
echo "<tr><th>".htmlspecialchars($name).
"</th><td>".htmlspecialchars($value)."</th></tr>";
}
?>
</table>
This will, as you might already see, print a nicely formatted table with the names in the left column and the values in the right column.
while ($row = mysql_fetch_assoc($result)) {
foreach ($row as $column => $value) {
//Column name is in $column, value in $value
//do displaying here
}
}
If this is a new program, consider using the mysqli extension instead.
Assuming you've made the call, and got $result back:
$array = new array();
while($row = mysql_fetch_assoc($result)){
$array[] = $row;
}
return $array;
This should get you going:
$rows = mysql_query("select * from whatever");
if ($rows) {
while ($record = mysql_fetch_array($rows)) {
echo $record["column1"];
echo $record["column2"];
// or you could just var_dump($record); to see what came back...
}
}
The following should work:
$rows = mysql_query("select * from whatever");
if ($rows) {
$header = true;
while ($record = mysql_fetch_assoc($rows)) {
if ($header) {
echo '<tr>';
foreach (array_keys($record) AS $col) {
echo '<td>'.htmlspecialchars($col).'</td>';
}
echo '</tr>';
$header = false;
}
echo '<tr>';
foreach (array_values($record) AS $col) {
echo '<td>'.htmlspecialchars($col).'</td>';
}
echo '</tr>';
}
}
(Yes, blatant mod of Fosco's code)
This should print the column headers once, then the contents after that. This would print just whatever columns were retrieved from the DB, regardless of the query.

Categories