I'm trying to make a nested list with php by using a foreach loop but I'm kind of stuck now. My code uses a foreach loop and checks if the item is a heading, if it is it will start a nested list below it. The problem now is that if it's not a heading I want to put the corresponding list items into a single ul element below its heading. Now as you can see it puts every single list items that isn't a heading into a seperate ul element of its own because of the foreach loop. How can I fix this?
<ul>
<?php foreach($listitems as $listitem) : ?>
<?php if( $listitem['heading'] == 1) : ?>
<li><?php echo $listitem['listitem']; ?><!--begin nested list-->
<?php endif; ?>
<?php if( $listitem['heading'] == 0) : ?>
<ul><li><?php echo $listitem['listitem']; ?></li></ul>
<?php endif; ?>
<?php endforeach; ?>
</li><!--end nested list-->
</ul>
This is the desired html output:
<ul>
<li>Javascript Basics<!--begin nested list-->
<ul>
<li>Getting Started</li>
<li>Data and Variables</li>
<li>Functions</li>
<li>Scope</li>
<li>Working With Objects</li>
<li>Creating Objects</li>
<li>Arrays</li>
<li>Conditions And Decisions</li>
<li>Loops</li>
</ul>
</li><!--end nested list-->
</ul>
You need to set the inner lists start and end tags when the heading changes.
Something like this
<ul>
<?php
$NonHeadCount = 0;
$HeadingOpen = false;
foreach($listitems as $listitem)
{
if( $listitem['heading'] == 1)
{
$HeadingOpen = true;
if ($NonHeadCount != 0)
{
echo "</ul>";
}
echo "<li>".$listitem['listitem'];
$NonHeadCount = 0;
}
if( $listitem['heading'] == 0)
{
if ($NonHeadCount == 0)
{
echo "<ul>";
}
echo "<li>".$listitem['listitem']."</li>";
}
}
if ($NonHeadCount != 0)
{
echo "</ul>";
}
if ($HeadingOpen)
{
echo "</li>";
}
?>
</ul>
You have to change the $listitems format.
Some like this:
<?php
$listitems = array(
'item1' => array(
'item11',
'item12',
'item13'
),
'item2' => array(
'item21',
'item22',
),
'item3',
'item4'
);
?>
Then, do this:
<?php
echo "<ul>";
foreach($listitems as $item => $listitem):
echo "<li>$item</li>";
if(count($listitem) > 0):
echo "<ul>";
foreach($lisitem as $item):
echo "<li>$item</li>";
endforeach;
echo "</ul>";
endif;
endforeach;
echo "<ul>";
?>
Related
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.
I am display data from the database. Currently, I have 6 records in my database and I am getting my output like
<ul>
<li>Records1</li>
<li>Records2</li>
<li>Records3</li>
<li>Records4</li>
<li>Records5</li>
<li>Records6</li>
</ul>
Now what I am doing is, I have to close the </ul> tag after 4th li tag and then start new ul after 4th li.
My expected output is
<ul>
<li>Records1</li>
<li>Records2</li>
<li>Records3</li>
<li>Records4</li>
</ul>
<ul>
<li>Records5</li>
<li>Records6</li>
</ul>
is it possible?
I am using below code
<?php
if ($tyler_query->have_posts()) {
$index = 0;
$check=0;
$first4=0;
while ( $tyler_query->have_posts() ) {
$tyler_query->the_post();
if ($index < 4) {
if ($first4==0){?>
<ul>
<?php $first4=1;}?>
<li>
<!--output here-->
</li>
<?php if ($first4==4){?>
</ul>
<?php }?>
<?php }
else {
if ($check==0){?>
<ul>
<?php $check=1;}?>
<li>
<!--output here-->
</li>
<?php } $index++;}?>
</ul>
<?php }?>
You can just insert a closing tag followed by an opening tag, whenever it meets your condition. In the following after every third item:
<?php
$items = [
'Syd',
'Roger',
'Nick',
'David',
'Richard'
];
$i = 0;
echo '<ul>';
foreach($items as $item) {
if($i++%3 == 0)
echo '</ul><ul>';
echo '<li>' . $item . '</li>';
}
echo '</ul>';
Output:
<ul><li>Syd</li><li>Roger</li><li>Nick</li></ul><ul><li>David</li><li>Richard</li></ul>
It's quick example. Hope help you.
if ($tyler_query->have_posts()) {
$index = 0;
$check = 6;
?>
<ul>
<?php while ($tyler_query->have_posts()) {
$tyler_query->the_post(); ?>
<li><?php echo 'some_value' ?></li>
<?php if ($index % $check === 0 ) { ?>
</ul><ul>
<?php }
$index++;
} ?>
</ul>
<?php } ?>
your code would work if you echo the HTML tag/output you want to see in the browser.
<?php
if ($tyler_query->have_posts()) {
$index = 0;
$check = 0;
$first4 = 0;
while ($tyler_query->have_posts()) {
$tyler_query->the_post();
$output = "whatever the output object is";
if ($index < 4) {
if ($first4 == 0) {
echo '<ul>';
$first4 = 1; // increment so that the this if block wont trigger again
}
echo '<li>' . $output . '</li>';
// increment so that the next if block trigger once
if ($first4 == 4) {
echo '</ul>';
}
$first4++;
}
if ($index >= 4){
if ($check == 0) {
echo '<ul>';
$check = 1;
}
// assuming you want to have the rest of the data in this block.
// data 5 and above
else {
echo '<li>' . $output . '</li>';
}
}
$index++;
}
echo '</ul>';
}
?>
<?php
foreach ($navItems as $ni) {
?>
<li class="<?php echo $ni->classes ?><?php echo($ni->hasSubmenu)?" dropdown":""; ?>">
<?php
if ($ni->hasSubmenu) {
?>
<?php echo (isset($translate) && $translate == true) ? t($ni->date) : $ni->name; ?> <span class="caret"></span>
<?php
} else{
?>
<?php echo (isset($translate) && $translate == true) ? t($ni->name) : $ni->name; ?>
<?php
}
?>
<?php
if ($ni->hasSubmenu) {
echo '<ul class="dropdown-menu">'; //opens a dropdown sub-menu
} else {
echo '</li>'; //closes a nav item
echo str_repeat('</ul></li>', $ni->subDepth); //closes dropdown sub-menu(s) and their top-level nav item(s)
}
?>
</li>
<?php
}
I want that "Szelíd beszéd" on the top, that is the newest added to the page.
As Concrete5 returns a single array of objects rather than a nested array, you can't tell what is a child and what isn't until you loop through it.
As such, I would suggest you rebuild the nav items array, and when you get to those items, append a page list of them and then continue.
This may not work, as you would lose references on those pages for the likes of 'hasSubmenu' or 'subDepth' but give it a go.
<?php
$navItemsNew = array();
$addedOrderedList = false;
$parentID = 4; //replace 4 with the ID of the parent page
foreach ($navItems as $ni) {
if($ni->cObj->getCollectionParentId() == $parentID){
if($addedOrderedList){
continue;
}else{
$pl = new PageList();
$pl->filterByParentID($parentID); //Get all posts beneath that parent
$pl->sortByPublicDate(); // Sort by public date, newest first
$pl->setItemsPerPage(0); //return all items in 1 page
$posts = $pl->getPage(1);
$addedOrderedList = true;
array_merge($navItemsNew, $posts);
continue;
}
}
$navItemsNew[] = $ni;
}
foreach ($navItemsNew as $ni) {
?>
<li class="<?php echo $ni->classes ?><?php echo($ni->hasSubmenu)?" dropdown":""; ?>">
<?php
if ($ni->hasSubmenu) {
?>
<?php echo (isset($translate) && $translate == true) ? t($ni->date) : $ni->name; ?> <span class="caret"></span>
<?php
} else{
?>
<?php echo (isset($translate) && $translate == true) ? t($ni->name) : $ni->name; ?>
<?php
}
?>
<?php
if ($ni->hasSubmenu) {
echo '<ul class="dropdown-menu">'; //opens a dropdown sub-menu
} else {
echo '</li>'; //closes a nav item
echo str_repeat('</ul></li>', $ni->subDepth); //closes dropdown sub-menu(s) and their top-level nav item(s)
}
?>
</li>
<?php
}
The pages in submenu comes from xml, from another website, tomorow will be added 1 new page ..and will show us in in autonav last child...but we need first!
I'm listing related pages based on category. This is what I'm using to list all related categories. What I'm trying to do is hide the entire block if it doesn't return any categories. I'm not sure how to do that with the foreach.
<h3>Related Category</h3>
<ul>
<?php foreach((get_the_category()) as $catCS) {
if($catCS->parent == 4){ ?>
<li><?php echo $catCS->cat_name; ?></li>
<?php }
} ?>
</ul>
Not sure if you know, but WordPress have a command to get parent categories get_category_parents, so if you use that you could use it like this:
<?php
$result = get_category_parents($cat, true, '</li><li>');
$result = substr($result, 0, -4);
if(!is_wp_error($result))
{
?>
<h3>Related Category</h3>
<ul>
<li><?php echo $result; ?>
</ul>
<?php
}
?>
NOTE: substr is a small hack to remove the last empty <li> opening due to how I am using </li><li> as a separator.
This is untested, but you could filter the current array into a resulting array and test if that is empty or not.
<?php
# save the result
$categories = array();
# fill $categories if any match
foreach ((get_the_category()) as $cat)
{
if($cat->parent == 4)
{
$categories[] = $cat;
}
}
# print nothing if $categories is empty
if (!empty($categories))
{
?>
<h3>Related Category</h3>
<ul>
<?php
foreach($categories as $catCS)
{
?>
<li><?php echo $catCS->cat_name; ?></li>
<?php
}
?>
</ul>
<?php
}
?>
There might be a better way but this should work.
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++;
}