PHP Execute array multple times on the one page - php

I want to run two seperate foreach loops on the one page, but only write my SQL once. For example see the below code, only the ul with the id of first runs, the second ul is empty.
<?php
$mylist = 'SELECT * FROM myTable';
$showlist = $pdo->prepare($mylist);
$showlist->execute();
?>
<ul id="first">
<?php foreach ($showlist as $rowid):;?>
<li><?php echo $rowid['id'] ?></li>
<?php endforeach; ?>
</ul>
<ul id="second">
<?php foreach ($showlist as $rowname):;?>
<li><?php echo $rowname['name'] ?></li>
<?php endforeach; ?>
</ul>
I thought renaming the as would allow me to use it again but this doesn't seem to be the case? What is the best approach here?

try:
<?php
$mylist = 'SELECT * FROM myTable';
$showlist = $pdo->prepare($mylist);
$showlist->execute();
$result = $showlist->fetchAll();
foreach ($result as $rowid) {
// do stuff
}
foreach ($result as $rowname) {
// do stuff
}

You'd need to stack your elements in an extra array first:
$mylist = 'SELECT * FROM myTable';
$showlist = $pdo->prepare($mylist);
$showlist->execute();
$rows = array();
foreach($showlist as $row) {
array_push($rows, $row);
}
echo "<ul>";
foreach($rows as $row) {
echo "<li>".$row['id']."</li>";
}
echo "</ul><ul>";
foreach($rows as $row) {
echo "<li>".$row['name']."</li>";
}
echo "</ul>";

Related

How to convert resultset to nested unordered list and hide sublist items with a value of 0?

I am trying to display the below table value in list and sub-list.
and here is my for loop to display
$sql ="SELECT *FROM objectives";
$result = $conn->query($sql);
$categories = array();
foreach ($result as $result) {
$category = $result['content'];
$categories[$category][] = $result['sub_content'];
}
?>
<ul>
<?php foreach ($categories as $category => $subcategories): ?>
<li>
<?php echo $category; ?>
<ul>
<?php foreach ($subcategories as $subcategory):?>
<li><?php echo $subcategory; ?></li>
<?php endforeach; ?>
</ul>
</li>
<?php endforeach; ?>
</ul>
The data is displayed in list and with sub list. I don't want to display the 0 value in the sub-list.
Everything is fine except the display of 0 in sub-list. Please advise.
try this if you just don't want to display 0
<?php echo ($subcategory != '0')? '<li>'.$test.'</li>' : ''; ?>
and if you don't want to store in array then put this if condition
foreach ($result as $result) {
$category = $result['content'];
if($result['sub_content'] != '0'){
$categories[$category][] = $result['sub_content'];
}
}
Simply implementing echo ($subcategory != '0')? '<li>'.$test.'</li>' : ''; will result in needless markup in the dom. Specifically, you will have empty <ul></ul> tags as nested lists where only a single row containing $subcategory is 0. (Demonstration) These extra bits of markup may cause funky side-effects when css/styling is applied.
Further refinements are advisable as a matter of best practice:
When querying the database, only SELECT the columns that you specifically require for your task.
Add stability to your process by using an ORDER BY clause that will group the rows by content and possibly sort sub_content
Never use more loops than necessary. This task can be (and therefore, theoretically, should be) performed in a single loop.
Recommended Code: (Demo)
$result = $conn->query("SELECT content, sub_content FROM objectives");
$category = null;
$output = '';
foreach ($result as $row) {
if ($category !== $row['content']) { // new parent
if ($category !== null) { // not first iteration
$output .= "<li>$category"; // print parent
if ($sublist) {
$output .= "<ul>$sublist</ul>"; // print all children
}
$output .= "</li>";
}
$category = $row['content']; // overwrite $category
$sublist = ''; // reset sublist
}
if ($row['sub_content'] !== '0'){ // filter row
$sublist .= "<li>{$row['sub_content']}</li>";
}
}
if ($result) { // in case the resultset is empty
echo "<ul>";
echo $output; // print stored markup
echo "<li>$category"; // print last parent
if ($sublist) {
echo "<ul>$sublist</ul>"; // print all children from last parent
}
echo "</li>";
echo "</ul>";
}
Source Code Output:
<ul>
<li>Demonstrate where to find the following documentation:
<ul>
<li>Operating and Safety Strategy</li>
</ul>
</li>
<li>Explain the different turbine main operating states:
<ul>
<li>Power Production</li>
<li>Idle</li>
<li>Stop</li>
</ul>
</li>
<li>Explain how to recognise the current operating mode on the display of the operating panel</li>
<li>Explain the subsystem operating modes:
<ul>
<li>Stop</li>
<li>Manual</li>
</ul>
</li>
<li>Explain the difference between local and remote point of operation</li>
<li>Explain that only one point of operation can be active at a time</li>
</ul>
Rendered Output: (courtesy of phptester.net)

Possible to reduce complexity of fetching and displaying data?

What I'm doing with the following code is fetching data from a table via PHP in order to display the data on a website.
$stri = "SELECT a, b, c, d, e, f FROM table";
$stat = $conn->prepare($stri);
if ($stat->execute()) {
while ($resu = $stat->fetch(PDO::FETCH_ASSOC)) {
foreach ($resu as $key=>$value) {
echo $value . "<br>";
}
echo "<br><br>";
}
}
However, it seems redundant to use two loops. Is there not a more efficient way to accomplish the same thing while allowing each item of each row to be handled independently?
I plan to do something like the following with it which is why I need to be able to handle the items independently.
if ($stat->execute()) {
while ($row = $stat->fetch(PDO::FETCH_ASSOC)) {
echo '<div class="row">';
foreach ($row as $key=>$value) {
echo '<div class=' .$key. '>';
if (empty($value)) echo '---<br>';
else echo $value;
echo '</div>';
}
echo '</div>';
}
}
However, it seems redundant to use two loops.
I cannot get what does it mean, but in all it's quite possible to reduce the complexity. For this you need to use PDO in the full force, not as a just a substitution for mysql_query(). A separation of concerns would also help
Get your data first in the form of array
$sql = "SELECT a, b, c, d, e, f FROM table";
$stmt = $conn->prepare($sql);
$stmt->execute();
$data = $stmt->fetchAll();
and then display it, somewhere inside the HTML part of the page
<?php foreach ($data as $row): ?>
<div class="row">
<?php foreach ($row as $key=>$value): ?>
<div class="<?=$key?>">
<?php if (!$value): ?>
---<br>
<?php else ?>
<?=$value?>
<?php endif ?>
</div>
<?php endforeach ?>
</div>
<?php endforeach ?>
function checking($val)
{
if(empty($val))
{
echo "---<br>";
}
else
{
echo $val;
}
}
$stri = "SELECT a, b, c, d, e, f FROM t";
try
{
$stat = $conn->prepare($stri);
$stat->execute();
$results = $stat->fetchAll(PDO::FETCH_ASSOC);
foreach ($results as $key=>$value)
{
echo implode('',array_map("checking",$value));
echo "<br><br>";
}
}
catch(Exception $e)
{
error_log($e->getMessage());
}
I do a little bit changed of your code. Instead of use if to catch error, I prefer to use try catch method.

Foreach in foreach [PHP]

Actually I work with PHP framework Codeigniter and I want to compare value from first foreach to second one, but I'm getting an error. Example here:
<?php foreach($posts->result() as $post): ?>
(html content)
<?php foreach($tags->result() as $tag) {
if($tag->id_users == $post->id_users) echo $tag->tag_name;
} ?>
(html content)
<?php endforeach; ?>
When I compare $post->id_users inner second foreach I'm getting error, how can I get around this?
Its better to avoid loop inside a loop
$tag_ids = array();
foreach($tags->result() as $tag) {
$tag_ids[] = $tag->id_users;
}
foreach ($posts->result() as $key => $post) {
if(in_array($post->id_users, $tag_ids)) {
}
}
You don't close the second foreach. For eg
<?php foreach($posts->result() as $post): ?> foreach1
(...some html)
<?php foreach($tags->result() as $tag) { if($tag->id_users == $post->id_users) echo $tag->tag_name; } ?> //foreach2
(...some html)
<?php endforeach; ?>
<?php endforeach; ?>
You should not use $posts->result() and $tags->result() inside foreach loop. Because it will go to check for every time while foreach is live.
Overall it decrease the performance of script.
<?php
$posts = $posts->result();
$tags = $tags->result();
foreach($posts as $post) {
?>
<< Other HTML code goes here >>
<?php
foreach($tags as $tag) {
if($tag->id_users == $post->id_users) {
echo $tag->tag_name;
}
?>
<< Other HTML code >>
<?php
}
}

Getting last record value only

I am getting only the last element value, like in my case i am trying to get value of $dwnld_name
but don't know where i am missing, so only getting download name for the last record
<?php
global $cat_id;
$dwnld_sql = "SELECT * FROM wp_dm_downloads";
$dwnld_qry = mysql_query($dwnld_sql);
while($dwnld_row = mysql_fetch_array($dwnld_qry)){
echo $link = $dwnld_row['link'];
echo $dwnld_name = $dwnld_row['name'];
$cat_id = $dwnld_row['category'];
}
?>
<?php
$sql = "SELECT * FROM wp_dm_category";
$myquery = mysql_query($sql);
echo '<ul>';
while($row = mysql_fetch_array($myquery)){
$x = $row['name'];
echo $x_id = $row['id'];
?>
<li><a href="#"><?php echo $x; ?>
<?php if($x_id == $cat_id) { ?>
<ul>
<li><?php echo $dwnld_name; ?></li>
</ul>
<?php } ?>
</a></li>
<?php echo "<br/>";
}
echo '</ul>';
?>
It is because, you are taking the values from loop in strings.
Everytime loop runs, it overwrites the values by recent values.
You can create an array and append values to that and loop through that array using foreach
Corrected Code:
<?php
global $cat_id;
$dwnld_sql = "SELECT * FROM wp_dm_downloads";
$dwnld_qry = mysql_query($dwnld_sql);
$downloads = array();
while($dwnld_row = mysql_fetch_array($dwnld_qry)){
$downloads['link'] = $dwnld_row['link'];
$downloads['dwnld_name'] = $dwnld_row['name'];
$downloads['cat_id'] = $dwnld_row['category'];
}
?>
Now, loop through $downloads array.
Note: Do not use mysql_ functions are they are deprecated and will be removed in future versions of PHP.
You need to echo $dwnld_name in the loop, or save names into array.
With this solution you overwrite $dwnld_name variable in each loop and as a result after the loop you have the last record.

Matching up two foreach loops using array value

I have two foreach loops. The first grabs a load of questions from Wordpress, the second is supposed to grab the multiple answers. This is straight forward had it not involved some randomisation of the questions, which makes it confusing.
This is the two foreach loops without them being randomised.
<?php
$repeater = get_field('step_by_step_test');
foreach( $repeater as $repeater_row ){ ?>
<p><?php echo $repeater_row['question']; ?></p>
<?php $rows = $repeater_row['answer_options'];
foreach ($rows as $row){ ?>
<?php echo $row['answer']; ?><br />
<?php } ?>
<?php } ?>
This loops through each question and also grabs the multiple answers.
How can I incorporate it randomising the questions? This is my attempt, this works for getting a random set of questions but I'm getting an error for the answers part (invalid argument supplied for foreach).
<?php
$amount = get_field('select_number_of_questions');
$repeater = get_field('step_by_step_test');
$random_rows = array_rand( $repeater, $amount );
echo implode(', ', $random_rows);
foreach( $random_rows as $repeater_row ){ ?>
<p><?php echo $repeater[$repeater_row]['question']; ?></p>
<?php $rows = get_sub_field('answer_options');
foreach ($rows as $row){ ?>
<?php echo $row['answer']; ?><br />
<?php } ?>
<?php } ?>
I use this plugin for wordpress - http://www.advancedcustomfields.com/
First I'm going to rewrite your first code block to not look like chewed cud.
<?php
$repeater = get_field("step_by_step_test");
foreach($repeater as $repeater_row) {
echo "<p>".$repeater_row['question']."</p>";
$rows = $repeater_row['answer_options'];
foreach($rows as $row) {
echo $row['answer']."<br />";
}
}
?>
And now for the magic: Add shuffle($rows) immediately before the foreach($rows as $row) { line, and the answers will appear in random order.
EDIT in response to comments: Start your code like this:
$repeater = get_field("step_by_step_test");
shuffle($repeater);
$repeater_limit = array_slice($repeater,0,5);
foreach($repeater_limit as $repeater_row) {
....

Categories