For each loop to display separate results - php

I have a PHP code that takes an 'empfullname' from a drop down selection and displays a timecard based on the selection. However, I want to make it have the capability to allow a user to select 'All' and it just print all the employees available. I am thinking I have to do this with a foreach loop, but I can't seem to get it to work. Here is the if statement that I think I need.
if ($empfullname == 'All') {
$query = "select * from ".$db_prefix."employees order by empfullname asc";
$result = mysql_query($query);
$tmp_empfullname = stripslashes("".$row['empfullname']."");
foreach ($tmp_empfullname){
print timecard_html($empfullname,$local_timestamp_in_week);
}
} else {
print timecard_html($empfullname,$local_timestamp_in_week);
}
print '<script language="JavaScript" type=
"text/javascript" src="../scripts/jquery.totals3.js"></script>';
print <<<End_Of_HTML
<table align="center" border="0" cellpadding="0" cellspacing="3" class="buttons">
<tr><td><a href="timecardrpt.php"><img src=
"../images/buttons/done_button.png" border="0" /></a></td></tr>
</table>
End_Of_HTML;
include '../footer.php';

This is a huge mess and it's clear you aren't thinking through the logic or structure very well and you haven't looked at many examples of PHP MySQL functions. There are TONS of examples and tutorials you should be looking at. Regarding foreach, you need to understand how foreach works. Specifically, the syntax is foreach ($myArray as $value) and not just foreach ($myArray). There's a lot of other stuff as well.
You don't run any query in your "else" block.
You don't fetch rows from the result.
You use the deprecated and insecure mysql function instead of mysqli or PDO.
You are inconsistent in your variable names (you have $tmp_empfullname in your foreach but $empfullname in the statement block.
Strictly speaking, you don't need a foreach loop as a while works fine. You could use a foreach, but meh.
This should fix it:
//Do your mysqli connection here. it's different from the mysql connection.
if ($empfullname == 'All') {
$query = "select * from ".$db_prefix."employees order by empfullname asc";
} else {
$query = //put a SQL query here
}
if ($result = mysqli->query($query)){
while ($row = $result->fetch_assoc()){ //you could also do foreach ($result as $row)
print timecard_html(stripslashes($row['$empfullname']), $local_timestamp_in_week);
}
}

The poblem is that you are calling this $row without ever declaring it in a foreach so you should make the code after $result = mysql_query($query); look like:
foreach ($result as $row) {
$tmp_empfullname = stripslashes("".$row['empfullname']."");
}
Once that is done you should just need to do what Aleatoric to get each name that is in the $tmp_empfullname variable.

Related

I cannot find a way to display "No Results."

The code below works as written provided a name in the database is entered in the search box. If a name not in the data base is entered, the error 'Warning: Invalid argument supplied for foreach() ….. on line 201.' Rather than this generic error I want something like “No Results” to display. Any suggestions anyone? I am aware that this question has been asked before but none of the answers seem to match the type of output I am using here.
enter code here
<?php
include 'connect.php';
if (isset($_POST['submit-keyword'])) {
$keyword = $_POST['keyword'];
}
try {
//first pass just gets the column names
print "<table>";
$result = $con->query("SELECT * FROM Bath_Wells_NBR WHERE Founder LIKE '%$keyword%' ORDER BY DATE");
//return only the first row (we only need field names)
$row = $result->fetch(PDO::FETCH_ASSOC);
print " <tr>";
foreach ($row as $field => $value){
print " <th>$field</th>";
}
// end foreach
print " </tr>";
//second query gets the data
$data = $con->query("SELECT * FROM Bath_Wells_NBR WHERE Founder LIKE '%$keyword%' ORDER BY DATE");
$data->setFetchMode(PDO::FETCH_ASSOC);
foreach($data as $row){
print " <tr>";
foreach ($row as $name=>$value){
print " <td>$value</td>";
} // end field loop
print " </tr>";
} // end record loop
print "</table>";
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
} // end try
?>
the first thing you need to do is make use of the PDO object and actually use the prepared statement to avoid sql injection like this:
$keyword = '%' . $keyword . '%';
$q = $con->prepare("SELECT * FROM Bath_Wells_NBR WHERE Founder LIKE :keyword ORDER BY DATE");
$q->bindParam(':keyword',$keyword,PDO::PARAM_STR);
$q->execute();
//here we will use fetchAll to get the full dataset of results, or an empty array
$result = $q->fetchAll();
Now you have $result which is an array either of your data, or empty so you can solve your problem by saying:
if(count($result) < 1) {
//output an error message
} else {
//output your table
}
Now you have your solution, let's streamline the code a bit. Remember, programmers want DRY code, so we don't want to do the same query twice. Lets assume our result count was greater than 0 so we are inside our else block.
{
//get all the array keys from the first entry in the result. These are the column names from the database which we want to use for our headings
$headings = array_keys($result[0]);
//now we want to do the same thing to each element, i.e. wrap it in html tags so let's make use of array_walk. We use the & symbol to pass the values by reference so we can amend them
array_walk($headings, function(&$field, &$key) {
$field = <th>$field</th>
});
//so now we have an array of table headings, so lets quickly implode them, we don't want to write a whole loop for this
echo <tr> . implode('',$headings) . </tr>;
now you can do your original loop and just output the values hey presto, dryer simpler code! You could also try and experiment with array_walk_recursive and see if you can do the same to the values for your nested loop, after all you just want to wrap them in <td> tags!
Note, I've not tested this so code, but you should be able to use it pretty much as it is, just have a little play and experiment with it.
happy coding!

Check if PDO Query has Fetched all Rows Matching Where Conditions

I'm a novice PHP programmer in need of help. Is there a way to check if there are no remaining records within a PDO while loop? Within the while loop I'm adding up one of the fields and have an if statement to check if the total has eclipsed a variable.
Within the if statement I do all the data manipulations. My problem is if there aren't enough records to eclipse the variable I never get to the data manipulations.
Code:
$stmt = $db->query("SELECT * FROM table WHERE ... ");
while ($rows = $stmt->fetch(PDO::FETCH_ASSOC)) {
$add_column = $rows['number'];
$total_column = $total_column + $add_column;
//Other Stuff
if ($total_column > $variable_balance) {// Would like to also check here if there are no remaining records to fetch.
//Do Stuff
exit;
}
}
You can make sure that you fetch all records by using $stmt->fetchAll(PDO::FETCH_ASSOC) instead of $stmt->fetch(PDO::FETCH_ASSOC)
If you want to use fetchAll you can use a for-loop
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC)) {
foreach($rows as $row) {
$add_column = $row['number'];
//other stuff
}
}
This will automatically perform the actions for all records.

Nesting foreach loops with PDO statements

I'm trying to nest foreach loops with PDO statements (this previously worked for me in mysql,btw). The first example works and the second one doesn't. However I'd prefer not to run a SQL query every time (isn't that the point of PDO?) and would prefer to use something more like example 2. However, it doesn't 'nest' the loop inside the other, it seems, rather it runs the first then the next.
Example 1)
foreach($db->query('SELECT country FROM db GROUP BY `country`') as $row1) {
echo $row1['country']."<br/>";
foreach($db->query('SELECT * FROM db') as $row2) {
if ($row1['country']==$row2['country']){
echo $row2['name']."<br/>";
}
}
}
Example 2)
$cntry = $db->query('SELECT country FROM db GROUP BY `country` ');
$rslts = $db->query('SELECT * FROM db');
foreach ($cntry as $row1) {
echo "<div id='".$row1['country']."'>".$row1['country']."<br/>";
foreach($rslts as $row2) {
if ($row1['country']==$row2['country']){
echo $row2['name']."<br/>";
}
};
echo "</div>";
}
(isn't that the point of PDO?)
No. The point of PDO is to send your query to database server and to return the results back. But PDO cannot reduce the number of queries executed.
So, here goes the proper solution:
$stmt = $db->query('SELECT country, name FROM db ORDER BY country, name');
$data = $stm->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_GROUP);
foreach ($data as $country => $row)
{
echo $country."<br/>\n";
foreach ($row as $name)
{
echo $name."<br/>\n";
}
}
As a matter of fact, fetchAll() is just a syntax sugar for the code like this:
$data = array();
while ($row = $stmt->fetch())
{
$data[] = $row;
}
it just creates a regular PHP array out of query result. And of course you can loop over this array as many times as you wish. Means you an always replace fetchAll() with manual looping over results, and of course you may group the results whatever way you wish.
While using foreach on $stmt is just a syntax sugar again, intended to confuse PHP users. Because $stmt is not an array but a way more complex structure.
not sure, but as I remember it would be like this
$cntry = $db->query('SELECT country FROM db GROUP BY `country` ')->fetchAll (PDO::FETCH_COLUMN);
$rslts = $db->query('SELECT * FROM db')->fetchAll(PDO::FETCH_COLUMN);
foreach ($cntry as $row1) {
echo $row1['country']."<br/>";
foreach($rslts as $row2) {
if ($row1['country']==$row2['country']){
echo $row2['name']."<br/>";
}
}
}

Iterating over results of PDO query

I want to run a query using PDO, based on data in the URL paramater (yes, I know that this is prone to attacks, but its internal code for a utility).
$user = 'USER';
$pass = 'PASSWORD';
$dsn = 'mysql:dbname=PRODUCTS;host=HOST';
try {
$productDB = new PDO($dsn, $user, $pass);
$productDB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
$msg = 'PDO ERROR' . $e->getFile() . ' L.' . $e->getLine() . ' : ' . $e->getMessage();
die($msg);
}
if(isset($_GET['cat']))
{
$cat = $_GET['cat'];
print "cat = $cat <br>";
$products = $productDB->prepare('SELECT * FROM products WHERE cat_id LIKE ?');
$products->execute(array($cat));
$rows = $products->rowCount();
print "$rows rows returned";
?>
<table border="1">
<tr>
<td>product_id</td>
<td>product_name</td>
</tr>
<?php
foreach ($products->fetchAll() as $row) {
$id = $row['product_id'];
$product_name = $row['product_name'];
print "<tr>";
print "<th scope=\"row\"><b>$id</b></th>";
print "<td> $product_name </td>";
print "<tr>";
}
print "</table>";
}
?>
When I run this code, it prints the correct number of rows depending on the query, but does not populate the table.
I have also tried replacing the prepare and execute lines with:
$products = $productDB->query("SELECT * FROM products WHERE cat_id LIKE $cat");
Which returns the correct row count, but doesn't otherwise help.
And finally, I've tried replacing the foreach line with something like:
$rows = $products->fetchAll();
foreach ($rows as $row) {
My attempts to do the same with a fixed query all work fine, but I am having trouble working out how to place a variable element in a query, and then iterate over the results.
You're not doing anything to store the result:
$products->execute(array($cat));
needs to go in a variable:
$result = $products->execute(array($cat));
Then, instead of calling $products->fetchAll(), use $results->fetchAll():
foreach ($result->fetchAll() as $row)
I find it easier to use a $query variable (for prepare, etc) and then get the result into something like $result or $product. Makes the code a bit easier to read.
Try this (If I understood correctly) :
$products = $productDB->prepare("SELECT * FROM products WHERE cat_id LIKE :cat");
// Now, you can either do this :
$products->bindParam('cat', '%'.$cat.'%');
$products->execute();
// or you can call execute with an associative array of your parameterized query.
$products->execute(array('cat' => '%'.$cat.'%'));
// Then, get all the results like this :
$rows = $products->fetchAll();
foreach ($rows as $row) {
// Do work here ..
}
// Or, like this :
while ($row = $products->fetch(PDO::FETCH_ASSOC)) {
// Do work here ..
}
I personaly prefer the while, because you don't fetch the whole query in one var, reducing the amount of memory needed.
I also recommend you to use the FETCH_* parameter, to get only the kind of array you want.
By the way, you need to know that rowCount should not be used to count the rows returned by a SELECT. As said by php.net :
If the last SQL statement executed by the associated PDOStatement was a SELECT statement, some databases may return the number of rows returned by that statement. However, this behaviour is not guaranteed for all databases and should not be relied on for portable applications.

drilling down in PHP using hyperlinks

I am a novice at PHP and i have encountered a problem with the following code...
<?php
// Connects to Database
mysql_connect("localhost", "root") or die(mysql_error());
mysql_select_db("test") or die(mysql_error());
$data = mysql_query("SELECT country_id, country_name FROM country, channels WHERE channels.channel_id = country.channel_id AND channels.channel_id = '1'")
or die(mysql_error());
echo "<table border=0 cellpadding=15>";
echo "<tr align = center bgcolor=white>
<td><b>Country ID</b></td><td><b>Country Name</b></td>" ;
while (mysql_fetch_row($data)) {
$cid = mysql_result($data, 1);
$cname = mysql_result($data, 2);
# inserts value into table as a hyperlink
echo "<tr align = center bgcolor=white><td>$cid</td><td><a href=view_country_detail.php?cid=$cid>$cname</td>";
}
# displays table
print '</table>';
?>
to explain the problem i am getting, i am after generated hyperlinks to drill down to the companies which share the to be clicked country's id from the code above to then display a similar layout on the 'view_country_detail' page. i cant work out why the output for the table gives me a repeated row for the first two id's for the country column in the db. any help would be greatly appreciated as i am totally lost here. Thanks
I don't understand why you use mysql_fetch_row and then don't want to actually use the row you fetch.
You should not be using mysql_result here. What you are doing is fetching data from row 1 of the result set and then data from row 2 regardless of which row the pointer is on in your while loop.
Try this:
while ($row = mysql_fetch_assoc($data)) {
$cid = $row['country_id'];
$cname = $row['country_name'];
}
I personally find it much more readable in code to reference the fields by the associative keys used when using mysql_fetch_assoc or mysql_fetch_array.
Try structuring your while loop as follows:
while($row = mysql_fetch_array($data)){
$cid = $row[0]; //if you have the column names, replace 0 with 'column_name'
$cname = $row[1];
//then echo statement
}
Also, mysql_* functions have started the deprecation process and should no longer be used, even the php manual pages state the use of mysql_* is discouraged. Look into using the similar mysqli_* functions or PDO.
Try this:
while ($row = mysql_fetch_row($data)) {
$cid = $row[0];
$cname = $row[1];
...
}
mysql_fetch_row returns an array.
HOWEVER
You should look at stopping using the mysql_* functions - they're being deprecated. If you switch to PDO or mysqli, it helps make your code more secure, too.

Categories