Php foreach group items into a container - php

I can't figure out how to group my subcategories into a container after every fifth record.
for example I would like to output my subcats like this
<ul>
<li>
Main category
<div>
<div class="subcontainer">
sub1
sub2
sub3
sub4
sub5
</div>
<div class="subcontainer">
sub6
sub7
sub8
sub9
sub10
</div>
</div>
</li>
</ul>
I tried this:
<?php
$i=0;
foreach ($cat->sub as $child) {
if($i % 5 == 0){
echo '<div class="subcontainer"><div>'.$child->name.'</div></div>';
} $i++;
}
?>
But this will output only the 5th elements in the array.

You need to always print your $child->name variable and on every 5th item also print the </div><div> part. You almost have it.
$i=0;
echo '<div class="subcontainer">';
foreach($cat->sub as $child) {
$i++;
echo $child->name; // I'm assuming this is what contains your "sub1"-"sub10"
if ($i % 5 == 0) {
echo '</div><div class="subcontainer">';
}
}
echo '</div>';

You can also get $iwith foreach ($cat->sub as $i=>$child)

Related

Create a menu from database (mixed sub menus)

I created a database to store a menu informations with 3 level (2 sub menus level).
You can see it on the left here : https://volt-services.fr/sites/stge/index.php#
Here is the table in the database:
And the code to translate it to HTML:
<?php
$req = $DB->query("SELECT * FROM menu ORDER BY ordered");
foreach ($req as $r) {
if($r->level == 1) {
$tab[$r->ordered] = array($r->id,$r->name,$r->class,$r->icon);
} elseif ($r->level == 2) {
$tab[$r->parent][4][$r->ordered] = array($r->id,$r->name);
} elseif ($r->level == 3) {
$tab[$r->cat][4][$r->parent][2][$r->ordered] = array($r->id,$r->name);
}
}
foreach ($tab as $key => $value) {
?>
<li data-menu="<?= $value[0]; ?>" class="<?= $value[2]; ?> menu-item">
<span class="material-icons-outlined"><?= $value[3]; ?></span>
<span class="titre_menu"> <?= $value[1]; ?></span>
<ul id="sub_menu<?= $value[0]; ?>" class="box_sub_exp <?= $value[2]; ?>">
<?php foreach ($value[4] as $ke => $val) { // SUB MENU POSITION 4 ?>
<li class="<?= $value[2]; ?> submenu-item"><?= $val[1]; ?>
<?php if(!empty($val[2])) { // IS A MENU IN POSITION 2 ?>
<ul class="box_sub_sub_exp">
<?php foreach ($val[2] as $k => $v) { // SUB MENU POSITION 2 ?>
<li class="<?= $value[2]; ?> submenu-item"><?= $v[1]; ?></li>
<?php } ?>
</ul>
<?php } ?>
</li>
<?php } ?>
</ul>
</li>
<?php } ?>
</ul>
</nav>
</section>
On the first sub menu everything is OK. But on the second, the first line is missing, on the third 2 first lines are missing, etc...
I think there is a problem with my loop, could you please help me to find it ?
FIXED : the problem was in the request, not "ORDER BY ordered" but by "id"
Even if you set a numeric key with $r->ordered, you have to sort your table before your display loop !
Give a numeric key to a table line doesn't "auto-sort" it on loop.
Try using ksort() on $tab before your display foreach. So it's will use keys you've define and sort your table in order.

How to show 3 li in single div inside foreach loop?

I have data collection and getting detail by foreach loop, which is working fine.
But I want 3 in a single inside foreach loop.
For example:
<ol>
<div>
<li></li>
<li></li>
<li></li>
</div>
<div>
<li></li>
<li></li>
<li></li>
</div>
<div>
<li></li>
<li></li>
<li></li>
</div>
</ol>
I am using below code for displaying the data:
<ol class="product-items widget-viewed-grid">
<?php $iterator = 1; ?>
<div id="mp-list-items-<?php echo $block->getSliderId(); ?>" class="owl-carousel owl-theme">
<?php foreach ($items as $_item): ?>
<?php echo ($iterator++ == 1) ? '<li class="product-item product-slider"">' : '</li><li class="product-item product-slider"">' ?>
<div class="slider-product-item-info">
<div class="product details slider-product-item-details">
<strong class="product name product-item-name">
<a title="<?php echo $block->escapeHtml($_item->getName()) ?>" href="<?php echo $block->getProductUrl($_item) ?>">
<?php echo $block->escapeHtml($_item->getName()) ?>
</a>
</strong>
</div>
</div>
<?php echo ($iterator == count($items) + 1) ? '</li>' : '' ?>
<?php endforeach ?>
</div>
</ol>
echo "<ol>";
for( $i=0; $i<3; $i++ ) {
echo "<div>";
for($j=0; $j<3; $j++) {
echo "<li>";
echo "</li>";
}
echo "</div>";
}
echo "</ol>";
You have to use nested loops. Outer loop for product <div> and inner loop for product items <li>.
For Example
foreach($products as $product){
echo "<div class='product'>";
//Now you can call sql query to get items by product id
foreach($items as $item){
echo "<li class='list-item'>" . $item->name . "</li>"; //assuming $item has name property
} //end of inner loop
echo "<div class='product'>";
} //end of outer loop

How to make 2 columns in loop data

I do foreach loop to output my data so my data will be like this
Dog
Cat
Mouse
Bird
Egg
Eagle
Fish
using this code
<div class="col-md-6">
<?php foreach ($treefields as $key=>$item): ?>
<?php if($key==0);?>
<?php if($item['title'] == $estate_data_option_1057): ?>
<div class="additional-amenities">
<span class="available"><i class="fa fa-check-square"></i></span><strong> <?php echo $options_name_1057; ?>:</strong><?php echo $estate_data_option_1057;?></span>
</div>
<?php if (count($item['childs_4']) > 0) foreach ($item['childs_4'] as $child): ?>
<div class="additional-amenities">
<span class="available"><i class="fa fa-check-square"></i></span><strong><?php _che($child['description']); ?></strong><span><?php echo $child['title']; ?></span>
</div>
<?php endforeach; ?>
<?php else: ?>
<?php ?>
<?php endif;?>
<?php endforeach; ?> </div></div>
How can i make it 2 columns like this?
- Dog - Egg
- Cat - Eagle
- Mouse - Fish
- Bird
First count the number of items in your array, then figure out what half of that would be and ceil it, so it's not a float. Then use that value in a conditional to echo your markup to break it into multiple columns.
For example, here is the technique boiled down to put the array into two different ul elements.
<ul>
<?php
$animals = array('Dog','Cat','Mouse','Bird','Egg','Eagle','Fish');
$numAnimals = count($animals);
$maxAnimalsPerColumn = ceil($numAnimals/2);
for($i=0; $i < $numAnimals; $i++) {
echo "<li>".$animals[$i]."</li>";
if ($i+1 == $maxAnimalsPerColumn ) {
echo "</ul><ul>";
}
}
?>
</ul>
$numAnimals would be 7
$maxAnimalsPerColumn would be 4 ($numAnimals divided by 2, ceil'd)
When the loop value (plus 1 since it starts at zero) matches $maxAnimalsPerColumn, it will echo a closing ul tag and a new one to start the second.
The resulting markup would be roughly:
<ul>
<li>Dog</li>
<li>Cat</li>
<li>Mouse</li>
<li>Bird</li>
</ul>
<ul>
<li>Egg</li>
<li>Eagle</li>
<li>Fish</li>
</ul>
Use a counter. Example:
$nbrOfColumns = 2;
$rowsPerColumn = ceil(count($treefields)/$nbrOfColumns);
$counter = 1;
<div class="col-md-6">
foreach ($treefields as $key=>$item){
if($counter === $rowsPerColumn){
echo "</div><div class="col-md-6">";
$counter = 0;
}
(generate your HTML here)
$counter++;
}
</div>

How to dynamically open/close ul and li every x?

I am trying to build a php loop which generates a html navigation with years like this:
<ul>
<li>
1900
<ul>
<li>1901</li>
<li>1902</li>
</ul>
</li>
<li>
2000
<ul>
<li>2001</li>
<li>2002</li>
</ul>
</li>
</ul>
Php I am trying:
foreach (range(0, 1000, 100) as $number) { ?>
<ul>
// Here I should be checking
// if it is year 1942 or 2000 or 1080
// and place ti correctly
<?php echo $number; ?>
</ul>
<?php }
The above works, gives me a new ul every 100.
But I don't understand how I should set my php to open a new <ul> and <li> if we have "sub years" inside the century itself, also I should be checking what year is it that I am outputting in order to have it in its right <ul> or <li>
echo "<ul>";
for ($century=1900; $century <= 2000 ; $century =$century + 100) {
echo "<li>". $century;
echo "<ul>";
for ($year = $century; $year < $century + 100; $year++) {
echo "<li>". $year . "</li>";
}
echo "</ul>";
echo "</li>";
}
echo "</ul>";
I hope this is what you need:
<?php
$start_year=1900;
$end_year=2100;
for($year=$start_year;$year<=$end_year;$year++){
if($year%10==0) //Replace 10 (for decades) with 100 (for centuries)
{
if($year!=$start_year){
echo '</ul></li></ul>';
}
echo '<ul><li>'.$year.'<ul>';
}
else{
echo '<li>'.$year.'</li>';
}
}
?>

PHP loop split by 4

How would I achieve this PHP task?
I have an unordered html list and and array.
My code adds list tags to each item in the array to create one big unordered list
<ul>
<?php foreach ($rows as $id => $row): ?>
<li><?php print $row ?></li>
<?php endforeach; ?>
</ul>
current output below
<ul>
<li>01</li>
<li>02</li>
<li>.....</li>
<li>.....</li>
<li>15</li>
</ul>
What I want is to split the list items so that they are in groups of 4 as sub unordered lists. If the number is not divisible by 4 then the remainder should be a smaller list at the end, for example.
<ul>
<ul>
<li>01</li>
<li>02</li>
<li>.....</li>
<li>.....</li>
</ul>
<ul>
<li>05</li>
<li>06</li>
<li>.....</li>
<li>.....</li>
</ul>
<ul>
<li>09</li>
<li>10</li>
</ul>
</ul>
Thanks in advance.
<ul>
<?php foreach ($rows as $id => $row): ?>
<?php if ($id > 0 && $id % 4 === 0): ?>
</ul><ul>
<?php endif ;?>
<li><?php echo $row; ?></li>
<?php endforeach; ?>
</ul>
(Note that if the key of your $rows array is not simply an index number, you'll need to maintain your own counter variable.)
<?php
$id=0;
foreach ($rows as $id => $row)
{
$id+=1;
if ($id % 4 == 0)
{
echo "<ul>";
}
echo "<li>$i</li>";
if ($id % 4 == 0)
{
echo "</ul>";
}
}
if ($id % 4 != 0)
{
echo "</ul>";
}
?>
foreach ($rows as $id => $row) {
if ($id % 4 == 0) {
// do something
}
}
Try something like this :
<?php
$rows = array("2","3","5","6","8","9","0","3","5");
$i =0;
foreach ($rows as $id => $row):
if($i % 4 == 0)
{ echo "</ul><ul>";}
$i++;
?>
<li><?php print $row ?></li>
<?php endforeach; ?>
</ul>
In the end this is the solution I went for. This solution includes a statement to close the tags if there are a number of items not divisible by four, for example if there are five items in total. Thanks to everyone, I couldn't have done it without your input.
$count;
foreach ($rows as $id => $row)
{
if ($count % 4 == 0)
{
echo "<ul>";
}
echo '<li>' . $row . '</li>';
if ($count % 4 == 3 || $count == count($rows)-1)
{
echo "</ul>";
}
$count++;
}

Categories