How to build "ul li" list from this array? - php

I have data in an array with the following structure:
$persons = array(
array($id, $name, $parent),
array(2, 'John Smith', 0),
array(3, 'Steve Martin', 2),
array(4, 'Peter Griffin', 3),
array(5, 'Cinder Ella', 0)
);
and I would like to get a tree like this:
<ul>
<li>John Smith</li>
<ul>
<li>Steve Martin</li>
<ul>
<li>Peter Griffin</li>
</ul>
</ul>
<li>Cinder Ella</li>
</ul>
Probably this is just as easy as 1-2-3 but I have tried everything already without success...

heres a solution:
<?php
$persons = array(
array(2, 'John Smith', 0),
array(3, 'Steve Martin', 2),
array(4, 'Peter Griffin', 3),
array(5, 'Cinder Ella', 0)
);
echo "<ul>";
printChildren($persons,0);
echo '</ul>';
function printChildren($arr,$id){
foreach($arr as $subvalue)
if($subvalue[2] == $id){
echo '<li>'.$subvalue[1].'</li>';
if(countChildren($arr,$subvalue[0])>0){
echo '<ul>';
printChildren($arr,$subvalue[0]);
echo '</ul>';
}
}
}
function countChildren($arr,$id){
$i=0;
foreach($arr as $value){
if($value[2] == $id) $i++;
}
return $i;
}
?>

function getChild($searchkey,$arr,&$doneArr){
$doneArr[] = $searchkey;
foreach($arr as $valArr){
if($key = array_search($searchkey,$valArr)){
$id = $valArr[0];
$name = $valArr[1];
$parent = $valArr[2];
if(!in_array($id,$doneArr)){
$html = '<ul>';
$html .= '<li>'.$name.'</li>';
$html .= getChild($id,$arr,$doneArr); // used to get recursively all childs
$html .= '</ul>';
}
}
}
return $html;
}
$html = '<ul>';
$cnt = sizeof($persons);
$doneArr = Array(); // used to maintain processed items.
for($i=0;$i<$cnt;$i++){
$id = $persons[$i][0];
$name = $persons[$i][1];
$parent = $persons[$i][2];
if(empty($parent)){
$html .= '<li>'.$name.'</li>';
}
$html .= getChild($id,$persons,$doneArr);
}
$html .= '</ul>';
echo $html;
unset($doneArr);

Related

I want to add active class only on first child element php its a amp based code

I want to add active class only in first element of li
this is an amp code ...jquery is not working in this properly
how will I achieve this kind of logic please help
function custom_table_of_contents($content) {
global $tableOfContents;
global $checkvalue;
$tableOfContents = '';
$tableOfContents = "<ul class='toc-item-list'>";
$checkvalue = 0;
$index = 1;
$indexes = [2 => 1, 3 => 0, 4 => 0, 5 => 0, 6 => 0];
// Insert the IDs and create the TOC.
$content = preg_replace_callback('#<(h[1-6])(.*?)>(.*?)</\1>#si', function ($matches) use (&$index, &$tableOfContents, &$indexes, &$checkvalue) {
$tag = $matches[1];
$title = strip_tags($matches[3]);
$hasId = preg_match('/id=(["\'])(.*?)\1[\s>]/si', $matches[2], $matchedIds);
$id = $hasId ? $matchedIds[2] : sanitize_title($title);
// Generate the prefix based on the heading value.
//$prefix = '';
foreach (range(2, $tag[1]) as $i) {
if ($i == $tag[1]) {
$indexes[$i] += 1;
}
//$prefix .= $indexes[$i] . '.';
}
$title = "$title";
//Check the tag value
if($checkvalue<$tag)
{
//Condition where previous tag value is lesser than the current one
$tableOfContents .= '<ul>';
} else if ($checkvalue==$tag) {
//Condition where previous tag value is same as that of current one
} else if($checkvalue>$tag){
$tableOfContents .='</ul>';
}
$checkvalue=$tag;
$tableOfContents .= "<li class='$id active'><a href='#$id'>$title</a></li>";
if ($hasId) {
return $matches[0];
}
return sprintf('<%s%s id="%s">%s</%s>', $tag, $matches[2], $id, $matches[3], $tag);
}, $content);
$tableOfContents .= '</ul>';
echo $tableOfContents;
return $content;
}
If you want add active class for first <LI> tag replace below lines
$activeClass = ($checkvalue<$tag)?"active":"";
$tableOfContents .= "<li class='$id $activeClass'><a href='#$id'>$title</a></li>";
Full Code
function custom_table_of_contents($content) {
global $tableOfContents;
global $checkvalue;
$tableOfContents = '';
$tableOfContents = "<ul class='toc-item-list'>";
$checkvalue = 0;
$index = 1;
$indexes = [2 => 1, 3 => 0, 4 => 0, 5 => 0, 6 => 0];
// Insert the IDs and create the TOC.
$content = preg_replace_callback('#<(h[1-6])(.*?)>(.*?)</\1>#si', function ($matches) use (&$index, &$tableOfContents, &$indexes, &$checkvalue) {
$tag = $matches[1];
$title = strip_tags($matches[3]);
$hasId = preg_match('/id=(["\'])(.*?)\1[\s>]/si', $matches[2], $matchedIds);
$id = $hasId ? $matchedIds[2] : sanitize_title($title);
// Generate the prefix based on the heading value.
//$prefix = '';
foreach (range(2, $tag[1]) as $i) {
if ($i == $tag[1]) {
$indexes[$i] += 1;
}
//$prefix .= $indexes[$i] . '.';
}
$title = "$title";
//Check the tag value
if($checkvalue<$tag)
{
//Condition where previous tag value is lesser than the current one
$tableOfContents .= '<ul>';
}
else if ($checkvalue==$tag)
{
//Condition where previous tag value is same as that of current one
}
else if($checkvalue>$tag){
$tableOfContents .='</ul>';
}
$checkvalue=$tag;
$activeClass = ($checkvalue<$tag)?"active":"";
$tableOfContents .= "<li class='$id $activeClass'><a href='#$id'>$title</a></li>";
if ($hasId) {
return $matches[0];
}
return sprintf('<%s%s id="%s">%s</%s>', $tag, $matches[2], $id, $matches[3], $tag);
}, $content);
$tableOfContents .= '</ul>';
echo $tableOfContents;
return $content;
}

create div from each item in tags column

My tags column is like this:
first row: sky - earth - sea
second row: iron - silver - gold
third row: apple - fruit - food
...and so on
Want to create a div from each item, like this:
<div class='tagdown'>sky</div>
<div class='tagdown'>earth</div>
$st = $db->query("select tags from posts");
$arr = array();
$items = "";
while ($row = $st->fetch()) {
array_push($arr, explode(' - ', $row['tags']));
}
foreach($arr as $item) {
$items .= "<div class='tagdown'>" . $item . "</div>\n";
}
echo $items;
Notice: Array to string conversion...
Another Try:
for ($i = 0; $i < count($arr); ++$i) {
$items .= "<div class='tagdown'>" . $arr[$i] . "</div>\n";
}
echo $items;
Notice: Array to string conversion...
Any help?
Dont push and again traverse your array. just print out data in while loop. Try following code:
$items = "";
while ($row = $st->fetch()) {
$arr = explode(' - ', $row['tags']);
$items .= "<div class='tagdown'>".implode("</div>\n<div class='tagdown'>",$arr)."</div>\n";
}
echo $items;
Try like shown below
Example :
<?php
$items = "";
$str = "sky-earth-sea";
$arr = explode("-", $str);
$count = count($arr);
for($i = 0; $i < $count; $i++) {
$items .= "<div class='tagdown'>".$arr[$i]."</div></br>";
}
echo $items;
?>
explode() returns an array and you are pushing an array into an other array
its making 1 2D array you can check thar using print_r($arr);
use this
while ($row = $st->fetch()) {
$tag=explode('-', $row['tags'];
foreach($tag as $t){
array_push($arr,$t ));
}
}
You can also use fetch associative if using mysqli_connect
while ($row = $result->fetch_assoc()) {
array_push($arr, explode(' - ', $row['tags']));
}
foreach($arr as $a) {
foreach($a as $v){
$items .= "<div class='tagdown'>" . $v . "</div>\n";
}
}
echo $items;
-------------- OR -------------
$arr = array();
$items = "";
while ($row = $result->fetch_assoc()) {
$tag = explode(' - ', $row['tags']);
foreach($tag as $v){
$items .= "<div class='tagdown'>" . $v . "</div>\n";
}
}
echo $items;

stuck with simple php looping logic

I have an array which can have any no. of elements in it. Now i want to loop this array and create design such that each li can have 15 elements inside it , next set of li will be created based of multiples of 15's elements.
Now my array has exact 15 elements and the code i am trying creating 2 li , which it should create only 1 li.
May be my logic is too bad or I am missing anything.
Here is my code:-
<?php $result = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); ?>
<div class="slide">
<?php $design = '<ul class="slides"><li><div class="MainSlider">';
foreach($result as $key=>$row)
{
$design .= '<div class="MainSliderPic">'.$key.'</div>';
if(($key+1)% 15 == 0){
$design .= '</div></li><li><div class="MainSlider">';
}
if(count($result) == $key+1){
$design .= '</div></li></ul>';
}
}
echo $design;
?>
</div>
You can use array_chunk for to achieve it:
$result = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
$chunks = array_chunk($result, 15);
foreach ($chunks as $chunk) {
echo '<ul><li>';
echo implode('</li><li>', $chunk);
echo '</li></ul>';
}
Don't mix opening and closing of tags in your code. Do it separately where it belongs, e.g.
$design = '<ul class="slides">';
$n = 0;
foreach($result as $key=>$row) {
if ($n == 0)
$design .= '<li><div class="MainSlider">';
$design .= '<div class="MainSliderPic">' . $key . '</div>';
++$n;
if ($n == 15) {
$design .= '</div></li>';
$n = 0;
}
}
$design .= '</ul>';
echo $design;
Try following code:
<?php $result = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); ?>
<div class="slide">
<?php $design = '<ul class="slides"><li><div class="MainSlider">';
foreach($result as $key=>$row)
{
$design .= '<div class="MainSliderPic">'.$key.'</div>';
if((($key+1)% 15 == 0) && (count($result) != ($key+1))){
$design .= '</div></li><li><div class="MainSlider">';
}
if(count($result) == $key+1){
$design .= '</div></li></ul>';
}
}
echo $design;
?>
</div>

Group MySQL results into blocks of A-Z in PHP

I have a list of thousands of results and I want to group them alphanumerically for example, I need it to be like this:
<h1>0-9</h1>
<ul>
<li>011example</li>
<li>233example</li>
<li>65example</li>
</ul>
<h1>A</h1>
<ul>
<li>albert</li>
<li>alfred</li>
<li>annie</li>
</ul>
<h1>B</h1>
<ul>
<li>ben</li>
<li>bertie</li>
<li>burt</li>
</ul>
But I can't work out how to split or group my results into 0-9 and A-Z.
Currently I have:
<?php
$get_az = mysql_query("SELECT custom_22 FROM db_table1");
echo '<ul>';
while ($row = mysql_fetch_assoc($get_az)) {
$getfirstletter = substr($row['custom_22'], 0,1);
$name = $row['custom_22'];
echo '<h1>'.$getfirstletter.'</h1>';
echo '<li>'.$name.'</li>';
}
echo '</ul>';
?>
Order by the name and handle each letter one by one.
$get_az = mysql_query("SELECT custom_22 FROM db_table1 ORDER BY custom_22 ASC");
$current_first_letter = null;
while ($row = mysql_fetch_assoc($get_az)) {
$first_letter = strtolower(substr($row['custom_22'], 0, 1));
if (preg_match("/[0-9]/", $first_letter)) { // detect digits
$first_letter = "0-9";
}
if ($first_letter !== $current_first_letter) {
if ($current_first_letter !== null) {
echo '</ul>';
}
echo '<h1>' . $first_letter . '</h1>';
echo '<ul>';
}
$current_first_letter = $first_letter;
echo '<li>' . htmlentities($row['custom_22']) . '</li>';
}
if ($current_first_letter !== null) {
echo '</ul>';
}
I would do it this readable way:
$get_az = mysql_query('SELECT custom_22 FROM db_table1 ORDER BY custom_22');
$groups = array();
split results to groups
while ($row = mysql_fetch_assoc($get_az)) {
$firstLetter = strtolower(substr($row['custom_22'], 0, 1));
check for digits
if (is_numeric($firstLetter)) {
$firstLetter = '0-9';
}
if (isset($groups[$firstLetter]) === false) {
$groups[$firstLetter] = array();
}
$groups[$firstLetter][] = $row['custom_22'];
}
simply iterate over groups and echoes it
foreach ($groups as $h1 => $items) {
echo sprintf('<h1>%s</h1>', strtoupper(htmlspecialchars($h1)));
echo '<ul>';
foreach ($items as $item) {
echo sprintf('<li>%s</li>', htmlspecialchars($item));
}
echo '</ul>';
}

How to print list using hierarchical data structure?

When I run this code:
foreach ($tree as $node) {
echo str_repeat(' ', $node->tree_depth * 4) . $node->id . PHP_EOL;
}
I get well formatted text like:
Food
Fruit
Red
Cherry
Strawberry
Cool
Not cool
Yellow
Banana
Meat
Beef
Pork
But I want to create a list with <ul><li>...:
I tried with:
echo '<ul>';
$prev_depth = 0;
foreach($table->fetchTree() as $row) {
if ($row->tree_depth > $prev_depth) {
echo '<li><ul>';
} else if ($row->tree_depth < $prev_depth) {
echo '</li></ul>';
}
echo '<li>' . $row->name . '</li>';
$prev_depth = $row->tree_depth;
}
echo '</ul>';
But I have some extra ul tags and so on. I lost 2 days on this so if you can help me please post here...
Try this algorithm:
$tree = array(
array('Food', 0),
array('Fruit', 1),
array('Red', 2),
array('Cherry', 3),
array('Strawberry', 3),
array('Cool', 4),
array('Not cool', 4),
array('Yellow', 2),
array('Banana', 3),
array('Meat', 0),
array('Beef', 1),
array('Pork', 1),
);
$depth = -1;
$flag = false;
foreach ($tree as $row) {
while ($row[1] > $depth) {
echo "<ul>\n", "<li>";
$flag = false;
$depth++;
}
while ($row[1] < $depth) {
echo "</li>\n", "</ul>\n";
$depth--;
}
if ($flag) {
echo "</li>\n", "<li>";
$flag = false;
}
echo $row[0];
$flag = true;
}
while ($depth-- > -1) {
echo "</li>\n", "</ul>\n";
}
Here you just need to replace $tree by $table->fetchTree(), $row[0] by $row->name and $row[1] by $row->tree_depth.
Try this code instead:
<?php
echo "<ul>\n";
$tree = array(
array('Food', 0),
array('Fruit', 1),
array('Red', 5),
array('Cherry', 3),
array('Strawberry', 3),
array('Cool', 4),
array('Not cool', 4),
array('Yellow', 2),
array('Banana', 3),
array('Meat', 0),
array('Beef', 4),
array('Pork', 2),
);
$depth = 0;
foreach ($tree as $node) {
if ($node[1] > $depth)
echo str_repeat("<ul>\n", $node[1] - $depth);
if ($node[1] < $depth)
echo str_repeat("</ul>\n", $depth - $node[1]);
$depth = $node[1];
echo "<li>" . $node[0] . "\n";
}
echo str_repeat("</ul>\n", $depth+1);
?>
I've updated it to output fewer <li> tags, thereby reducing the number of bullets. But on the other hand, this will generate HTML that wont validate since a jump of more than one level will result in a <ul><ul> being generated.

Categories