PHP, adding a div wrap around a dynamic loop - php

I am working on a calendar script to output events that are grouped by month. Everything is working fine, except I can't figure out how to add a div wrapper around each month without some closing tag issues. Here is my loop code:
if ($posts) {
$month_titles = array();
$close = false;
foreach( $posts as $post ) {
setup_postdata( $post );
$month_title = date('F Y', strtotime(get_post_meta($post->ID,'_event_start_local', true)));
if(!in_array($month_title, $month_titles)) {
if($close) echo '</ul>';
echo '<h4>'.$month_title.'</h4>';
echo '<ul>';
$month_titles[] = $month_title;
$close = true;
}
echo '<li>'.get_the_title().'</li>';
}
if ($close) echo '</ul>';
}
Here is how this is current output:
<h4>Month Name 2018</ul>
<ul>
<li>Title of Event</li>
<li>Title of Event</li>
</ul>
I would like for it to be like this:
<div>
<h4>Month Name 2018</h4>
<ul>
<li>Title of Event</li>
<li>Title of Event</li>
</ul>
</div>
I have tried a few different ways to add the div wrap and it either closes too early or too late. I need a fresh set of eyes on this as I have been messing with it too long!

This logic should work for what you want:
// preset some vars
$oldMonth = null;
$firstItem = true;
foreach($posts as $post) {
setup_postdata($post);
$month_title = date('F Y', strtotime(get_post_meta($post->ID,'_event_start_local', true)));
// check if we have a new month coming up:
if($oldMonth != $month_title) {
// when it's the first one ever, just open the div
if($firstItem) {
echo "<div>";
$firstItem = false; //..and remember that the following aren't the first
} else { // else close the previous ones and open a new one
echo "</ul></div><div>";
}
// show the new month and open the list
echo '<h4>'.$month_title.'</h4>';
echo '<ul>';
}
echo '<li>'.get_the_title().'</li>';
$oldMonth = $month_title; // remember the last month
}
// at the end close the last ul and last div
echo '</ul></div>';

It seems just changing these lines:
if($close) echo '</ul>';
echo '<h4>'.$month_title.'</h4>';
to
if($close) echo '</ul></div>';
echo '<div><h4>'.$month_title.'</h4>';
should do what you want. Note you have to change the if on $close in both places in your code)

Related

PHP - Unable to get same number of </ul> as <ul>

I am unable to generate same number of </ul> as <ul> in the following code:
<?php
$array=array("item1","item2","item3");
for ($i=0;$i<count($array);$i++)
{
if($i<count($array)-1)
{
echo '<li><span>'.$array[$i].'</span><ul>';
}
else
{
echo '<li><span>'.$array[$i].'</span>';
}
}
for ($i=0;$i<count($array);$i++)
{
echo '</ul></li>';
}
?>
The code is generating uneven number of <li><ul> and </ul></li>. Please tell me where I am going wrong?
This is a minor error. In your second for statement change $i<count($array); to $i<count($array)-1;.
So your final code will be:
<?php
$array=array("item1","item2","item3");
for ($i=0;$i<count($array);$i++)
{
if($i<count($array)-1)
{
echo '<li><span>'.$array[$i].'</span><ul>';
}
else
{
echo '<li><span>'.$array[$i].'</span>';
}
}
for ($i=0;$i<count($array)-1;$i++)
{
echo '</ul></li>';
}
?>
With if($i<count($array)-1) you check if $i is smaller than the length - 1.
That check isn't performed in the second loop. So the first one actually performs as many steps as the second one but only writes in all but the last iteration.
Try This:
$array=array("item1","item2","item3");
echo '<ul>';
for ($i=0;$i<count($array);$i++)
{
echo '<li><span>'.$array[$i].'</span></li>';
}
echo '</ul>;

Generate closing divs in WP loop with php

I am new to php and Wordpress and what I am trying to accomplish is listing all my posts by month+year. The month+year is shown as a link, which when clicked, toggles the days. My css code looks like this and is working properly (toggle function done by jquery).
<div class="monat"> <!-- month div -->
Oktober 2014 <!-- Toggle Button -->
<div class="tage"> <!-- toggle div - shown when toggle button clicked -->
12 <!-- day of month -->
20 <!-- day of month -->
22 <!-- day of month -->
23 <!-- day of month -->
</div> <!-- end toggle div -->
</div> <!-- end month div -->
That´s what I have accomplished so far in php. The problem is, that i need 2 closing divs at the end (for class monat and class tage) and I am not sure how to implement them in the php code...
<?php
$prev_month = '';
$prev_year = '';
while(have_posts())
{
the_post();
if(get_the_time('F') != $prev_month || get_the_time('Y') != $prev_year)
{
echo '<div class="monat">'.get_the_time('F Y').'<div class="tage">';
}
?>
<?php the_time('j'); ?>
<?php
$prev_month = get_the_time('F');
$prev_year = get_the_time('Y');
}
?>
Thanks for your help,
Andreas
Thank you so much, hakre!
Works like a charm!
Here is the edited code:
<?php
$prev_month = '';
$prev_year = '';
$divs_opened = false;
query_posts( 'category_name=wurst' );
while(have_posts()) { ## Loop Start
the_post();
$month_changed = (get_the_time('F') != $prev_month) || (get_the_time('Y') != $prev_year);
if ($month_changed) {
if ($divs_opened) {
echo "</div></div>";
}
$divs_opened = true;
{
echo '<div class="monat">'.get_the_time('F Y').'<div class="tage">';
}
}
?>
<?php the_time('j'); ?>
<?php
$prev_month = get_the_time('F');
$prev_year = get_the_time('Y');
} ## Loop End
if ($divs_opened) {
echo "</div></div>";
}
?>
You've already found out how to detect the month change event:
$month_changed = (get_the_time('F') != $prev_month)
|| (get_the_time('Y') != $prev_year);
if ($month_changed) {
...
}
and you output (here I've placed ...) the opening of the divs already. But you're still missing when to place the close of those.
First of all you only need to place closing div tags when you have opened any. You can do this very similar like you do with the months check, just with another variable:
$prev_month = '';
$prev_year = '';
$divs_opened = false; ## third variable
while (have_posts()) {
...
So now when you for the first time open the divs, set that $divs_opened variable to true:
$month_changed = (get_the_time('F') != $prev_month)
|| (get_the_time('Y') != $prev_year);
if ($month_changed) {
$divs_opened = true;
...
}
And as you need to close the divs if they were already opened, you need to check for that, too:
$month_changed = (get_the_time('F') != $prev_month)
|| (get_the_time('Y') != $prev_year);
if ($month_changed) {
if ($divs_opened) {
echo "</div></div>";
}
$divs_opened = true;
...
}
so now this is nearly done, but there is one more place you need to close the divs (if opened), too: that is after the loop:
$prev_month = '';
$prev_year = '';
$divs_opened = false; ## third variable
while (have_posts()) {
...
}
if ($divs_opened) {
echo "</div></div>";
}
That should do it. And I hope it gives you the pointers that you can use a similar method how you detected the month change for the closing divs, too.

w3 validator gives my navigation errors

I've been doing some researching and discovered this nice website http://validator.w3.org/
After running a test i see that my navigation get loads of error.
The error i get is the ul in the coding. I don't close it off because i give it it styling if a condition is met else close it.
But this is not a valid solution according to w3 which gives me some errors.
Can you help me find a fix for my navigation so it gets valid?
With thanks Jim
<ul id="nav-container">
<?php
$select_category = mysql_query("SELECT * FROM menu WHERE hidden = 0 ORDER BY menu ASC");
while ($ln = mysql_fetch_array($select_category)) {
$idcat = $ln['nmr'];
$catname = $ln['menu'];
$catsname = str_replace(' ', '-', $ln['menu']);
echo '<li>';
if($catname == "carparts") {
echo '<span><strong>'.$catname.'</strong></span>';
} else {
echo '<span><strong>'.$catname.'</strong></span>';
}
This gives me the errors: (fixed)
echo '<ul';
if(isset($_GET['cats'])) {
if ($_GET['cats'] == $idcat) {
echo ' style="display:block;">';
} else {
echo '>';
}
The fix: also deleted the closing bracket at the end.
echo '<ul';
if(isset($_GET['cats']) && $_GET['cats'] == $idcat){
echo ' style="display:block;">';
} else {
echo '>';
}
/fix finish
//Error finish
$select_sub = mysql_query("SELECT * FROM submenu WHERE nmrmenu = '$idcat' AND hidden = 0");
while ($lsub = mysql_fetch_array($select_sub)) {
$subname = $lsub['submenu'];
$subsname = str_replace(' ', '-', $lsub['submenu']);
$pil = '»';
$brnr = $lsub['nmr'];
if(isset($_GET['cat'])) {
if ($_GET['cat'] == $brnr) {
$subname = '<u>'.$lsub['submenu'].'</u>';
} else {
$subname = $lsub['submenu'];
}
}
echo '<li><span><strong> '.$subname.' </strong></span></li>';
}
echo '</ul>';
echo '</li>'; // to this location
}
echo '</li>'; //relocated this up one line
} **//Deleted this one!**
?>
</ul>
Update
The output gets like this which is horrible: (fixed)
<ul</li><li><span><strong>name</strong></span>
<ul</li><li><span><strong>name</strong></span><ul</li>
New: now the ul problem is gone, but it's complaining about the li's. Any clue why?
Error: document type does not allow element "li" here; missing one of "ul", "ol", "menu", "dir" start-tag
<ul id="nav-container">
<li>
<span><strong>name</strong></span>
<ul>
<li>
<span><strong> name </strong></span>
</li>
</ul>
</li>
</ul>
/update
You have </ul> and then immediately follow it with a <li>. You can't have a list item outside of a list.

php add a css class to selected menu item

I have a menu generated in php this way.
<?php
while($rowMenu = mysql_fetch_array($rsMenu)){
$link="category.php?cat=".$rowMenu['MenuItemID'];
$name = utf8_encode($rowMenu['name']);
?>
<li><?php echo $name; ?></li>
<?php
}
?>
and now I want to add a background-color to the item of the present page.The background-color is defined in css ( .productActive )
I search for add a css class in php like I make with javascript but didnt find any solution, so I made this way
<?php
$cat=$_GET['cat']; /gets the id from the URL
while($rowMenu = mysql_fetch_array($rsMenu)){
$link="category.php?cat=".$rowMenu['MenuItemID'];
$name = utf8_encode($rowMenu['name']);
?>
<li><?php echo $name; ?></li>
<?php
if($cat == $rowMenu['MenuItemID']) {
echo"<li class='productActive'>".$nome."</li>";
}
}//end of while
?>
But this way add one more item to the menu. it repeats the present li item. Is there any other way??
Thanks
while($rowMenu = mysql_fetch_array($rsMenu)){
$link="category.php?cat=".$rowMenu['MenuItemID'];
$name = utf8_encode($rowMenu['name']);
if($cat == $rowMenu['MenuItemID']) {
echo"<li class='productActive'>".$name."</li>";
} else {
echo"<li>".$name."</li>";
}
}
That should work, I think
while($rowMenu = mysql_fetch_array($rsMenu)){
$link = "category.php?cat=".$rowMenu['MenuItemID'];
$name = utf8_encode($rowMenu['name']);
// add active class?
$class = $cat == $rowMenu['MenuItemID']
? ' class="productActive"'
: '';
?>
<li<?= $class; ?>><?= $name; ?></li>
<?php
}//end of while
Then if the item matches, it'll add the class to the tag, otherwise it won't add anything.
Although I would prefer this:
printf('<li%s>%s</li>', $class, $link, $name);
p.s. Anchors should always be inside the <li>, not outside.

php mysql vertical menu

I am trying to design a dynamic vertical menu :
my table is:
primary // primary key
pid //parent id 0 if none
cid //the actual category id
comment //some comment
the thing is that I want to design a php function where after reading the values from database it should output it into an html ordered list (like a multilevel nested unordered list)
I know that it would be easily achieved by using a recursion function
the problem is that i just can't do it.. I've tried many times but failed in vain
The main problem comes in nesting (where to give list items and where to start the list)
I would be very grateful if anyone of you could help me out...
well i've managed to write an ugly code:
{here i ve used two tables one for the parent and one for the child}
$query="SELECT * FROM parentCat";
$result=mysql_query($query);
echo "<ul id=\"suckertree1\">";
while($row=mysql_fetch_array($result))
{
$name=$row['comment'];
$pid=$row['catid'];
echo "<li> $name ";
$query="select * from childCat WHERE pid=$pid";
$subresult=mysql_query($query);
$af=mysql_num_rows($subresult);
if($af>0)
{
echo "<ul>";
while($subrow=mysql_fetch_array($subresult))
{
$name=$subrow['comment'];
echo "<li> $name </li>";
}
echo "</ul>";
}
echo "</li>";
}
echo "</ul>";
it will show only one sublevel...
wht should i do to make it work for infinite level
I thing a while script is best for you
$query = mysql_query("SELECT * FROM menu ORDER BY primary ASC");
$parent=0;
$sub=0
echo "<ul>";//start list
while($menu = mysql_fetch_array($query){
if($parent != $menu['pid']){//if not seen item before
if($sub != 0){echo "</ul>";}else{$sub++;}//if not first submenu, close submenu before. If first sub sub++.
echo "<ul>";}//open submenu
echo "<li>".$menu[cid]."</li>";//echo item
if($parent != $menu['pid']){//if not seen before
$parent = $menu['pid']; //set to seen before so next loop will be recognised
}
}
echo "</ul>"; //end list
I dont know if this is gonna work since I did not test it, but it should show you an option on how it could be done. Idea of lists:
<ul>
<li>Item1</li>
<ul>
<li>Subitem1</li>
<li>Subitem2</li>
</ul>
<li>Item 2</li>
<ul>
<li>Subitem1 of Item2</li>
</ul>
</ul>
Gives:
Item1
Subitem1
Subitem2
Item2
Subitem1 of Item2
Try this, it should do the trick.
<?php
$query = "SELECT a.comment parent
, b.comment child
FROM menu a
JOIN menu b
ON a.primary = b.pid
ORDER BY a.primary";
$result = mysql_query($query);
$parent = '';
echo "<ul>";
foreach ($result as $next) {
if ($next['parent'] != $parent) {
if (strlen($parent) > 0) {
echo " </ul>";
echo " </li>";
}
echo " <li>" . $next['parent'];
echo " <ul>";
}
echo " <li>" . $next['child'] . "</li>";
$parent = $next['parent'];
}
echo " </ul>";
echo " </li>";
echo "</ul>";
?>
To render a nested list for an assoc array try this:
<?php
$list = array(
'item-1' => 'test-1',
'item-2' => 'test-2',
'item-3' => array(
'item-3-1' => 'test-3',
'item-3-2' => array(
'item-3-2-1' => 'test-4',
'item-3-2-2' => 'test-5',
),
),
'item-4' => 'test-6',
);
function render_list($list) {
echo '<ul>';
foreach ($list as $key => $value) {
echo '<li>';
echo $key.':';
if (is_array($value)) render_list($value);
else echo $value;
echo '</li>';
}
echo '</ul>';
}
render_list($list);
Which will result in this:
<ul>
<li>item-1:test-1</li>
<li>item-2:test-2</li>
<li>
item-3:
<ul>
<li>item-3-1:test-3</li>
<li>
item-3-2:
<ul>
<li>item-3-2-1:test-4</li>
<li>item-3-2-2:test-5</li>
</ul>
</li>
</ul>
</li>
<li>item-4:test-6</li>
</ul>
item-1:test-1
item-2:test-2
item-3:
item-3-1:test-3
item-3-2:
item-3-2-1:test-4
item-3-2-2:test-5
item-4:test-6

Categories