Loop not stops in condition - php

I was just trying to display a particular content in a loop in list and after a condition is met it should display in a div.This is what i have tried
function the_meta() {
if ( $keys = get_post_custom_keys() ) {
echo "<ul class='post-meta'>\n";
$i = 0;
foreach ( (array) $keys as $key ) {
$keyt = trim($key);
if ( is_protected_meta( $keyt, 'post' ) )
continue;
$values = array_map('trim', get_post_custom_values($key));
$value = implode($values,', ');
echo apply_filters('the_meta_key', "<li id='slots_".$key."'><span class='post-meta-key'>$key:</span> $value</li>\n", $key, $value);
if (++$i > 8)
echo apply_filters('the_meta_key', "<div><span class='post-meta-key'>$key:</span> $value</div>\n", $key, $value);
}
echo "</ul>\n";
}
}
what I am getting is as follows
<ul class='post-meta'>
<li id='slots_Numeri_estratti_1'><span class='post-meta-key'>Numeri_estratti_1:</span> 22</li>
<li id='slots_numeri_estratti_2'><span class='post-meta-key'>numeri_estratti_2:</span> 23</li>
<li id='slots_numeri_estratti_3'><span class='post-meta-key'>numeri_estratti_3:</span> 24</li>
<li id='slots_numeri_estratti_4'><span class='post-meta-key'>numeri_estratti_4:</span> 25</li>
<li id='slots_numeri_estratti_5'><span class='post-meta-key'>numeri_estratti_5:</span> 26</li>
<li id='slots_numeri_estratti_6'><span class='post-meta-key'>numeri_estratti_6:</span> 27</li>
<li id='slots_numeri_estratti_7'><span class='post-meta-key'>numeri_estratti_7:</span> 28</li>
<li id='slots_numeri_estratti_8'><span class='post-meta-key'>numeri_estratti_8:</span> Concorso Nr. 36 - Montepremi complessivo € 10.474.698,21</li>
<li id='slots_numeri_estratti_9'><span class='post-meta-key'>numeri_estratti_9:</span> 21</li>
<div id='slots_numeri_estratti_9'><span class='post-meta-key'>numeri_estratti_9:</span> 21</div>
<li id='slots_numeri_estratti_10'><span class='post-meta-key'>numeri_estratti_10:</span> 33</li>
<div id='slots_numeri_estratti_10'><span class='post-meta-key'>numeri_estratti_10:</span> 33</div>
</ul>
The values are displaying twice, one in list and other in div.I have been searching on Google for hours and couldn't get any results to solve it.Someone please help me .Thanks!!

It should be like this
if (++$i > 8)
echo apply_filters('the_meta_key', "<div><span class='post-meta-key'>$key:</span> $value</div>\n", $key, $value);
else
echo apply_filters('the_meta_key', "<li id='slots_".$key."'><span class='post-meta-key'>$key:</span> $value</li>\n", $key, $value);
rather than
echo apply_filters('the_meta_key', "<li id='slots_".$key."'><span class='post-meta-key'>$key:</span> $value</li>\n", $key, $value);
if (++$i > 8)
echo apply_filters('the_meta_key', "<div><span class='post-meta-key'>$key:</span> $value</div>\n", $key, $value);

Related

Create a multi-dimensional array with PHP from lineal array

TL;DR I'm looking for a function to create a nested <ol> list from a one-dimensional array in PHP.
1) Currently I have this simplified markup in my test page:
<h2>Spiders</h2>
<h2>Beetles</h2>
<h3>External morphology</h3>
<h4>Head</h4>
<h4>Thorax</h4>
<h4>Legs</h4>
<h3>Anatomy and physiology</h3>
<h2>Ants</h2>
2) Which then is captured by a pretty simple function into an one-dimensional array like this:
array
(
0 => "H2 Spiders",
1 => "H2 Beetles",
2 => "H3 External morphology",
3 => "H4 Head",
4 => "H4 Thorax",
5 => "H4 Legs",
6 => "H3 Anatomy and physiology"
7 => "H2 Ants"
);
3) This is the tricky part, because I use the next loop with these overly complicated if statements to populate a multi-dimensional array.
$toc = array ();
//
foreach ($array as $value) {
$value_arr = explode(' ', $value, 2);
$depth = str_replace("H", "", $value_arr[0]);
$content = $value_arr[1];
//
if ($depth == 1) $toc[$title] = null;
elseif ($depth == 2) {
if (empty (end ($toc))) $toc[array_key_last ($toc)] = array ($title => null);
else $toc[array_key_last ($toc)][$title] = null;
} elseif ($depth == 3) {
if (empty (end ($toc[array_key_last ($toc)]))) $toc[array_key_last ($toc)][array_key_last ($toc[array_key_last ($toc)])] = array ($title => null);
else $toc[array_key_last ($toc)][array_key_last ($toc[array_key_last ($toc)])][$title] = '';
}
}
Output:
Array (
[Spiders] =>
[Beetles] => Array
(
[External morphology] => Array
(
[Head] =>
[Thorax] =>
[Legs] =>
)
[Anatomy and physiology] =>
)
[Ants] =>
)
4) And finally be parsed with this function into an perfectly indented html list.
function table_of_contents ($toc, $output = '') {
foreach ($toc as $key => $value) {
$output = "$output <li><a href='##" . sanitize_title ($key) . "'>$key</a>" . (is_array ($value) ? table_of_contents ($value) : null) . '</li>';
}
//
return "<ol>$output</ol>";
}
//
table_of_contents ($toc);
-
Spiders Beetles External morphology Head Thorax Legs Anatomy and physiology Ants
Everything works fine in the 1st, 2nd and 4th steps, but my current approach has the drawback that only allows me up to three levels of depth from the first array in the 3rd step.
My question is whether there is a more efficient and cleaner way to create the multi-dimensional array with (maybe) a recursive function or something like that?
It might be easier to parse your input using preg_match_all; this can give you arrays of depths and associated values. You can then iterate through those arrays, opening an <ol> when the depth increases, and closing it when the depth decreases:
$html = '<h2>Spiders</h2>
<h2>Beetles</h2>
<h3>External morphology</h3>
<h4>Head</h4>
<h4>Thorax</h4>
<h4>Legs</h4>
<h3>Anatomy and physiology</h3>
<h2>Ants</h2>';
preg_match_all('/<h(\d)>([^<]+)/', $html, $matches);
$cdepth = $matches[1][0] - 1;
foreach ($matches[1] as $key => $depth) {
if ($depth > $cdepth) {
echo "\n" . str_repeat(' ', $cdepth * 4) . "<ol>\n";
}
elseif ($depth < $cdepth) {
echo "</li>\n" . str_repeat(' ', $depth * 4) . "</ol>\n" . str_repeat(' ', $depth * 4) . "</li>\n";
}
else {
echo "</li>\n";
}
$cdepth = $depth;
echo str_repeat(' ', $cdepth * 4) . "<li>{$matches[2][$key]}";
}
while ($cdepth-- >= $matches[1][0]) {
echo "</li>\n" . str_repeat(' ', $cdepth * 4) . "</ol>\n";
}
Output:
<ol>
<li>Spiders</li>
<li>Beetles
<ol>
<li>External morphology
<ol>
<li>Head</li>
<li>Thorax</li>
<li>Legs</li>
</ol>
</li>
<li>Anatomy and physiology</li>
</ol>
</li>
<li>Ants</li>
</ol>
Demo on 3v4l.org
Update
If you want the third stage array for other reasons than output, you can generate it with this recursive function (which still works from the output of preg_match_all):
$html = '<h2>Spiders</h2>
<h2>Beetles</h2>
<h3>External morphology</h3>
<h4>Head</h4>
<h4>Thorax</h4>
<h4>Legs</h4>
<h5>Feet</h5>
<h3>Anatomy and physiology</h3>
<h2>Ants</h2>';
function push_values(&$k, $depth, $content) {
$output = array();
$cdepth = $depth[$k];
while ($k < count($depth)) {
if ($depth[$k] == $cdepth) {
$output[$content[$k]] = '';
$k++;
}
elseif ($depth[$k] > $cdepth) {
$output[$content[$k-1]] = push_values($k, $depth, $content);
}
else {
return $output;
}
}
return $output;
}
preg_match_all('/<h(\d)>([^<]+)/', $html, $matches);
$key = 0;
print_r(push_values($key, $matches[1], $matches[2]));
Output:
Array
(
[Spiders] =>
[Beetles] => Array
(
[External morphology] => Array
(
[Head] =>
[Thorax] =>
[Legs] => Array
(
[Feet] =>
)
)
[Anatomy and physiology] =>
)
[Ants] =>
)
Demo on 3v4l.org
Lastly, I would suggest a minor fix for the first code posted by #Nick causing an undesirable HTML output in the next scenario, where a depth difference greater than two will change the most superficial siblings; for example, the <h3> after <h6> become <h5> and the next <h2> was parsed as <h4>:
$html = '<h2>Spiders</h2>
<h2>Beetles</h2>
<h3>External morphology</h3>
<h4>Head</h4>
<h4>Thorax</h4>
<h4>Legs</h4>
<h5>Feet</h5>
<h6>Toes</h6>
<h3>Anatomy and physiology</h3>
<h2>Ants</h2>';
foreach ($matches[1] as $key => $depth) {
if ($depth > $cdepth) {
echo "\n" . str_repeat(' ', $cdepth * 4) . "<ol>\n";
}
elseif ($depth < $cdepth) {
echo "</li>\n" . str_repeat(' ', $depth * 4) . "</ol>\n" . str_repeat(' ', $depth * 4) . "</li>\n";
}
else {
echo "</li>\n";
}
$cdepth = $depth;
echo str_repeat(' ', $cdepth * 4) . "<li>{$matches[2][$key]}";
}
while ($cdepth-- >= $matches[1][0]) {
echo "</li>\n" . str_repeat(' ', $cdepth * 4) . "</ol>\n";
}
Output:
<ol>
<li>Spiders</li>
<li>Beetles
<ol>
<li>External morphology
<ol>
<li>Head</li>
<li>Thorax</li>
<li>Legs
<ol>
<li>Feet
<ol>
<li>Toes</li>
</ol>
</li>
<li>Anatomy and physiology</li>
</ol>
</li>
<li>Ants</li>
</ol>
</li></ol></li></ol>
-
To address that I just added another while statement to put the correct amount of </li></ol> before adding the next <li> element, which now can correctly validate the W3C inspector.
foreach ($matches[1] as $key => $depth) {
if ($depth > $cdepth) {
echo "\n" . str_repeat(' ', $cdepth * 4) . "<ol>\n";
}
elseif ($depth < $cdepth) {
while ($cdepth -- > $depth) {
echo "</li>\n" . str_repeat(' ', $depth * 4) . "</ol>\n" . str_repeat(' ', $depth * 4) . "\n";
}
}
else {
echo "</li>\n";
}
$cdepth = $depth;
echo str_repeat(' ', $cdepth * 4) . "<li>{$matches[2][$key]}";
}
while ($cdepth-- >= $matches[1][0]) {
echo "</li>\n" . str_repeat(' ', $cdepth * 4) . "</ol>\n";
}
Output:
<ol>
<li>Spiders</li>
<li>Beetles
<ol>
<li>External morphology
<ol>
<li>Head</li>
<li>Thorax</li>
<li>Legs
<ol>
<li>Feet
<ol>
<li>Toes</li>
</ol>
</li>
</ol>
</li>
</ol>
<li>Anatomy and physiology</li>
</ol>
<li>Ants</li>
</ol>

Insert new item to wordpress array [PHP]

I want to insert new <li> element to my function output.
function gallery_nav() {
$i = 0;
foreach ($myArray as $key ) {
$i++;
echo '<li>'. $i .'</li>';
}
}
It printing this html
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
Can i insert custom <li> element into this array? Like this:
<li>1</li>
<li>2</li>
<li class="custom">3</li>
<li>4</li>
<li>5</li>
<li class="custom">6</li>
<li>7</li>
<li>8</li>
<li>9</li>
If your custom indexes are assigned in an array, you can do something like this:
<?php
$myArray = array(1,2,3,4,5,6,7); # Your original array
$customArray = array(3,6); # Your custom array
$VarCount = count($myArray); # Set the default loop count
function gallery_nav($myArray, $customArray=NULL, $VarCount) {
for($i=1; $i<=$VarCount; $i++) {
$Class = NULL;
if(in_array($i, $customArray)){
$VarCount++; # Increment extra <li>
$Class = "class=\"custom\"";
}
echo "<li {$Class}>{$i}</li>
";
}
}
gallery_nav($myArray,$customArray, $VarCount);
?>
Which results in:
<li >1</li>
<li >2</li>
<li class="custom">3</li>
<li >4</li>
<li >5</li>
<li class="custom">6</li>
<li >7</li>
<li >8</li>
<li >9</li>
See live demo.
You could simply modify your function to check for a specific iteration number and output something extra:
$i = 0;
foreach ($myArray as $item => $value) {
$i++;
if ($i % 3 === 0) {
echo '<li class="custom">' . $i . '</li>';
}
echo '<li>'. $i .'</li>';
}
This will add an extra li element every 3 iterations.
If you don't want it to add an extra li every third iteration, then modify it back to this:
$i = 0;
foreach ($myArray as $item => $value) {
$i++;
if ($i % 3 === 0) {
$class = 'custom';
} else {
$class = '';
}
echo '<li class="' . $class .'">' . $i . '</li>';
}
If you only need it on iterations 3 and 6 and no others, modify the condition to this:
if ($i === 3 || $i === 6) {
// code
}

Array explode has empty value for html tag <li> how to not include that value

I have a random id generator which could be anywhere from 1 to x number of ids
$ranGen = "IDENTIFIER | c0402347-8b93-49e4-991b-8213ea2921b1| e8087fc5-ded7-43ab-858d-127fe23f90bc|" ;
I'm trying to go through each value and present it as an un-ordered list
<?php
$ranGen = "IDENTIFIER | c0402347-8b93-49e4-991b-8213ea2921b1| e8087fc5-ded7-43ab-858d-127fe23f90bc|" ;
$array = explode("|", $ranGen);
echo '<ul>' ;
foreach ($array as $value) {
echo '<li>' . trim($value) . '</li>';
}
echo '</ul>';
?>
I get the following results
<ul>
<li>IDENTIFIER </li>
<li> c0402347-8b93-49e4-991b-8213ea2921b1 </li>
<li> e8087fc5-ded7-43ab-858d-127fe23f90bc </li>
<li></li>
I do not want the last blank list - is there a way to do this
Test the value before you echo:
foreach ($array as $value) {
if( trim($value) != '') {
echo '<li>' . trim($value) . '</li>';
}
}
You have two options:
Check if the value is empty within the loop
Ignore the last part (if all of your input strings have that superfluous part at the end)
See this example:
<?php
$ranGen = "IDENTIFIER | c0402347-8b93-49e4-991b-8213ea2921b1| e8087fc5-ded7-43ab-858d-127fe23f90bc|" ;
$array = explode("|", $ranGen);
echo '<ul>';
foreach ($array as $value) {
// Option 1
if (trim($value) !== "") {
echo '<li>' . trim($value) . '</li>';
}
}
echo '</ul>';
// Option 2
$array = explode("|", $ranGen, -1);
echo '<ul>';
foreach ($array as $value) {
echo '<li>' . trim($value) . '</li>';
}
echo '</ul>';
?>
Replace this line : echo '<li>' . trim($value) . '</li>';
with this: echo trim($value) ? '<li>' . trim($value) . '</li>' : null;
Just filter it out:
$array = array_filter(explode("|", $ranGen));

Error create multi columns in php not use table

I have a sample list 1,2,3,4,5,6,7,8
I want create 3 colums with format
1 4 7
2 5 8
3 6
This is my code
$columns = 3;
$rows = ceil(count($lists) / $columns);
foreach ($lists as $key => $value) {
if($key % $rows == 0) {
echo '<div class="col-md-4">';
}
echo $value;
if($key % $rows == 0) {
echo '</div>';
}
}
This is result error
<div class="col-md-4">1</div>
2
3
<div class="col-md-4">4</div>
5
6
<div class="col-md-4">7</div>
8
How to fix it for result:
<div class="col-md-4">1 2 3</div>
<div class="col-md-4">4 5 6</div>
<div class="col-md-4">7 8</div>
This solution works for your last edit:
<div class="col-md-4">1 2 3</div>
<div class="col-md-4">4 5 6</div>
<div class="col-md-4">7 8</div>
So, code is:
$lists = array(1,2,3,4,5,6,7,8);
$columns = 3;
$rows = ceil(count($lists) / $columns);
echo '<div class="col-md-4">';
foreach($lists as $key => $value) {
if ($key % $rows == 0 && $key != 0) {
echo '</div><div class="col-md-4">'.$value.' ';
} else {
echo $value.' ';
}
}
echo '</div>';
... because you're only adding the div to every third value. I think this is what you want
$columns = 3;
$rows = ceil(count($lists) / $columns);
foreach ($lists as $key => $value) {
if($key % $rows == 0) {
echo '<div class="row">';
}
echo '<div class="col-md-4">' . $value . '</div>';
if($key % $rows == 0) {
echo '</div>';
}
}
It's a lot simpler to achieve what you're after. Say you have the following list:
$list = '1,2,3,4,5,6,7,8';
All you'd have to do is explode your string (list) into an array and chunk that into groups of 3. Now that simplifies what you are required to do when printing out your rows:
$chunks = array_chunk(explode(',', $list), 3);
foreach($chunks as $row){
echo "<div class='row'>";
foreach($row as $value){
echo "<div class='col-md-4'>{$value}</div>";
}
echo "</div>";
}
Example/Demo
References
array_chunk()
explode()
Assuming you need fixed 3 columns, here the code (you may have to fix the code based on your column requirement)
$columns = 3;
$lists = array(1,2,3,4,5,6,7,8);
$rows = ceil(count($lists) / $columns);
$i = 0;
while($i < $rows)
{
echo "<div class=col-xs-4>".#$lists[$i]."</div>";
echo "<div class=col-xs-4>".#$lists[$i+$rows]."</div>";
echo "<div class=col-xs-4>".#$lists[$i+$rows+$rows]."</div>";
$i++;
}

Load menu and sub-menus from two MySQL queries PHP

$menu = mysql_query(" query 1");
$k = 1;
for ($s = 0; $s < mysql_num_rows($menu); $s++)
{
$menus= mysql_fetch_assoc($menu);
$mainmenu[]=$menus['name'];
$submenus=mysql_query("query 2");
for ($m = 0; $m < mysql_num_rows($submenus); $m++)
{
$submenu = mysql_fetch_assoc($submenus);
$subitem[]=$submenu['name'];
$url=$submenu['url'];
}
}
foreach($mainmenu as $mains)
{
echo '<li class="hasul"><a><span><b>' .$mains.'</b></span></a></li>';
foreach($subitem as $sub)
{
echo '<ul>';
echo '<li><span>' .$sub. '</span></li>';
echo '</ul>';
}
}
The code above show two queries which load a menu and submenus. Query2 uses some inputs from query1.
The menus do load correctly but they contain same menu items. Ideally each menu should have its own menu items.
You have a foreach inside your foreach, that means, that for every main menu you are outputing all the submenus.
Create some parameter for submenu, like:
$mainmenu = array(
1 => 'about',
2 => 'news',
3 => 'search',
);
$submenu = array(
1 => array( 'about my name', 'about my location' ),
3 => array( 'search me' ),
);
And now check only the submenu you need:
if ( is_array( $mainmenu ) )
{
echo '<ul>';
foreach( $mainmenu as $key=>$menu )
{
echo '<li>'.$menu.'</li>';
if ( is_array( $submenu[$key]) )
{
echo '<ul>';
foreach( $submenu[$key] as $sub )
{
echo '<li>'.$sub.'</li>';
}
echo '</ul>';
}
}
echo '</ul>';
}
This will produce:
<ul>
<li>about</li>
<ul>
<li>about my name</li>
<li>about my location</li>
</ul>
<li>news</li>
<li>search</li>
<ul>
<li>search me</li>
</ul>
</ul>
I hope you get the idea.
use this.. this could be easier to understand..
echo '<ul>';
$qry = mysql_query("query 1");
while ($row = mysql_fetch_array($qry))
{
echo "<li>";
echo "<a href='" . $row['url'] . "'>'" . $row['name'] . "'</a>";
$qry2 = mysql_query("query 2");
if (mysql_num_rows($query2) > 0)
{
echo "<ul>";
while ($row2 = mysql_fetch_array($query2))
{
echo "<li>";
echo "<a href='" . $row2['url2'] . "'>'" . $row2['name2'] . "'</a>";
echo "</li>";
}
echo "</ul>";
}
echo "</li>";
}
echo "</ul>";
let me know if you want any further help...

Categories