Parent-child navigation generation from tree array in PHP - php

Following function arranges the array totally wrong. Have you noticed any wrong piece of code in following function?
function buildHtmlList($array)
{
$maxlevel = 0;
foreach ($array as $key => $value)
{
$previousparent = isset($array[$key - 1]['parent']) ? $array[$key - 1]['parent'] : null;
$nextparent = isset($array[$key + 1]['parent']) ? $array[$key + 1]['parent'] : null;
if ($value['parent'] != $previousparent)
{
echo "\n<ul>";
++$maxlevel;
}
echo "\n<li>" . $value['name'];
if ($nextparent == $value['parent'])
echo "</li>";
}
for ($i = 0; $i < $maxlevel; ++$i)
{
echo "\n</li>\n</ul>";
}
}

It arranges the array totally wrong. Have you noticed any wrong piece of code in following function?
The wrong piece is the whole logic of the function. You treat the array as a flat list (as it is!), however, you'd like to display a tree.
As a flat list can't be displayed as a tree, you need to change the flat list to a tree first and then write a function that displays a tree.
An example how to convert a flat array to a tree/multidimensional one is available in a previous answer.

Try something like this (where $array is formatted like your example):
$corrected_array = array();
// This loop groups all of your entries by their parent
foreach( $array as $row)
{
$corrected_array[ $row['parent'] ][] = $row['name'];
}
// This loop outputs the children of each parent
foreach( $corrected_array as $parent => $children)
{
echo '<ul>';
foreach( $children as $child)
{
echo '<li>' . $child . '</li>';
}
echo '</ul>';
}
Demo

Related

Multiple json in one foreach

Hey i have five json from all getting information now i encountered with problem like this -> from five different json i need to get latest videoId who newer shows first and all it need put to one function foreach for my too hard i try it do about 5hours and stay in same step
Json 1 json 2
All code need from this two json get latest(newest) videoId in one foreach echo
<?php
$videoList1 = json_decode(file_get_contents('https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId=UCKLObxxmmAN4bBXdRtdqEJA&maxResults=50&key=AIzaSyDVTF2abNVa5pRitb8MVz1ceJFhE-2y_qk'));
$videoList2 = json_decode(file_get_contents('https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId=UCynfZM0Edr9cA4pDymb2rEA&maxResults=50&key=AIzaSyDVTF2abNVa5pRitb8MVz1ceJFhE-2y_qk'));
$i = 0;
foreach($videoList1->items as $item){
if(isset($item->id->videoId)) {
echo $item->id->videoId;
if ( ++$i > 3) {
break;
}
}
}
Tray this:
$videoList1 = json_decode(file_get_contents('https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId=UCKLObxxmmAN4bBXdRtdqEJA&maxResults=50&key=AIzaSyDVTF2abNVa5pRitb8MVz1ceJFhE-2y_qk'),true);
$videoList2 = json_decode(file_get_contents('https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId=UCynfZM0Edr9cA4pDymb2rEA&maxResults=50&key=AIzaSyDVTF2abNVa5pRitb8MVz1ceJFhE-2y_qk'),true);
$videoList = array_merge($videoList1["items"],$videoList2["items"]);
/// sort lastet first
foreach ($videoList as $key => $part) {
$sort[$key] = strtotime($part['snippet']['publishedAt']);
}
array_multisort($sort, SORT_DESC, $videoList);
foreach ($videoList as $video) {
if(isset($video["id"]["videoId"])) {
echo 'publishedAt: '. $video['snippet']['publishedAt'] . ' VideoID: ' . $video["id"]["videoId"] . "\n </br>";
}
}

How to display multilevel one to many relationship tree

How to loop all records and display all the respective children using HTML <ul></ul>? I tried using PHP Do While but stuck at only 1 level.
MySQL (select * from user)
Desired output
Tree View
List View
The easy was is to do that with the help of array. Hope it helps.
$data = array();
foreach ($result as $item) {
$key = $item['name']; // or $item['info_id']
if (!isset($data[$key])) {
$data[$key] = array();
}
$data[$key][] = $item;
}
You can use this code:
$aResults; // it is your mysql result (array)
$resultSorted = array();
$resultSorted = recursiveList($aResults, '');
function recursiveList(&$aResults, $iKey)
{
$aChilds = '<ul>';
foreach ($aResults as $iLoopKey => $aResult) {
if ($aResult['parent'] == $iKey) {
unset($aResults[$iLoopKey]);
$aChilds .= '<li>' . $aResult['name'] . '</li>';
$aChilds .= recursiveList($aResults, $aResult['name']);
}
}
return $aChilds . '</ul>';
}
// Output example
echo '<pre>';
print_r($resultSorted);
As a result, I recived:
Also you'd better use 'parent_id' instead 'parent' in yours tables.

php split array of strings to <ul><li>

Hi I'm having the problem that I have an array list of strings which contains the path to .txt files on my server.
example:
// list all textfiles
$list = findFiles(dirname(__FILE__), array ("txt") );
// sort list
array_multisort($list["txt"], SORT_ASC, SORT_STRING );
// iterate through list and print out found files as ul-li list
foreach ($list["txt"] as $file_entry) {
echo '<li>$file_entry</li>\n';
}
This gets me something like that:
<li>path1\path\chek.txt</li>
<li>path1\path\test\check2.txt</li>
<li>path1\path1\test\check.txt</li>
<li>path2\test\pt\check1.txt</li>
<li>path2\test\pt\check2.txt</li>
<li>path2\test\check2.txt</li>
<li>path2\path2\check.txt</li>
<li>path2\path3\dir.txt</li>
<li>path2\path3\test\check.txt</li>
<li>path3\path3\test\check1.txt</li>
I want to "convert" that array to something which looks like an directory tree (to make later use of some jquery plugin [e.g. http://filamentgroup.com/examples/jquery-tree-control/] ):
<ul>
<li>path1
<ul>
<li>path</li>
<ul>
<li>check.txt</li>
</ul>
<li>path1</li>
...
So the question is how to make such a directory list from my array?
Here's what I got, by transforming the paths into nested arrays, then merging them recursively, then formatting using a recursive function to print it out as a list;
$list['txt'] = array(
'path1\path\chek.txt',
'path1\path\test\check2.txt',
'path1\path1\test\check.txt',
'path2\test\pt\check1.txt',
'path2\test\pt\check2.txt',
'path2\test\check2.txt',
'path2\path2\check.txt',
'path2\path3\dir.txt',
'path2\path3\test\check.txt',
'path3\path3\test\check1.txt'
);
$paths = array();
foreach ($list['txt'] as $file_entry) {
$path = explode('\\', $file_entry);
$pathArr = $file_entry;
for ($i = count($path) - 1; $i >= 0; $i--) {
$pathArr = array($path[$i] => $pathArr);
}
$paths = array_merge_recursive($paths, $pathArr);
}
function to_list($paths, $depth = 0) {
echo str_repeat("\t", $depth) . "<ul>\n";
foreach ($paths as $entry => $value) {
echo str_repeat("\t", $depth + 1) . '<li>';
if (is_array($value)) {
echo "$entry\n";
to_list($value, $depth + 2);
echo "\n" . str_repeat("\t", $depth + 1);
} else {
echo "$entry";
}
echo "</li>\n";
}
echo str_repeat("\t", $depth) . "</ul>\n";
}
to_list($paths);
I think that you should better "explode" every string to an array() using "\" as delimiter, than you merge all table ton one multi-array.
['path1']=>['path']=>"chek.txt"
=>['path']=>['test']=>"check2.txt"
=>['path']=>['test']=>"check.txt"
...
finaly for every new array you add an "<ul>" tag !

PHP Nested loops where values are the key to the next level of the array

I'm relatively new to PHP and I hope you can help me solve my problem. I am selecting out data from a database into an array for timekeeping. Ultimately, I would like to calculate the total number of hours spent on a project for a given customer.
Here is the code to populate a multi-dimensional array:
...
foreach ($record as $data) {
$mArray = array();
$name = $data['user'];
$customer = $data['customer'];
$project = $data['project'];
$hours = $data['hours'];
$mArray[$name][$customer][$project] += $hours;
}
...
I would now like to iterate over $mArray to generate an xml file like this:
...
foreach ($mArray as $username) {
foreach ($mArray[$username] as $customerName) {
foreach ($mArray[$username][$customerName] as $project ) {
echo '<'.$username.'><'.$customerName.'><'.$project.'><hours>'.
$mArray[$username][$customerName][$project].'</hours></'.$project.'>
</'.$customerName.'></'.$username.'>';
}
}
}
This nested foreach doesn't work. Can someone give me a couple of tips on how to traverse this structure? Thank you for reading!
UPDATE:
Based on the comments I've received so far (and THANK YOU TO ALL), I have:
foreach ($mArray as $userKey => $username) {
foreach ($mArray[$userKey] as $customerKey => $customerName) {
foreach ($mArray[$userKey][$customerKey] as $projectKey => $projectName) {
echo '<name>'.$userKey.'</name>';
echo "\n";
echo '<customerName>'.$customerKey.'</customerName>';
echo "\n";
echo '<projectName>'.$projectKey.'</projectName>';
echo "\n";
echo '<hours>'.$mArray[$userKey][$customerKey][$projectKey].'</hours>';
echo "\n";
}
}
}
This is now only providing a single iteration (one row of data).
Foreach syntax is foreach($array as $value). You're trying to use those values as array keys, but they're not values - they're the child arrays. What you want is either:
foreach($mArray as $username) {
foreach($username as ...)
or
foreach($mArray as $key => $user) {
foreach($mArray[$key] as ...)

PHP Multidimensional array to unordered list, building up url path

I have a multidimensional array in PHP produced by the great examples of icio and ftrotter (I am use ftrotterrs array in arrays variant):
Turn database result into array
I have made this into a unordered list width this method:
public function outputCategories($categories, $startingLevel = 0)
{
echo "<ul>\n";
foreach ($categories as $key => $category)
{
if (count($category['children']) > 0)
{
echo "<li>{$category['menu_nl']}\n";
$this->outputCategories($category['children'], $link
, $start, $startingLevel+1);
echo "</li>\n";
}
else
{
echo "<li>{$category['menu_nl']}</li>\n";
}
}
echo "</ul>\n";
}
So far so good.
Now I want to use the url_nl field to build up the url's used as links in the menu. The url has to reflect the dept of the link in de tree by adding up /url_nl for every step it go's down in the tree.
My goal:
- item 1 (has link: /item_1)
* subitem 1 (has link: /item_1/subitem_1)
* subitem 2 (has link: /item_1/subitem_1)
* subsubitem 1 (has link: /item_1/subitem_2/subsubitem_1)
- item 2 (has link: /item_2)
the table
id
id1 (parent id)
menu_nl
url_nl
title_nl
etc
What I have so far:
public function outputCategories($categories, $link, $start, $startingLevel = 0)
{
// if start not exists
if(!$start)
$start = $startingLevel;
echo "<ul>\n";
foreach ($categories as $key => $category)
{
$link.= "/".$category['url_nl'];
if($start != $startingLevel)
$link = strrchr($link, '/');
if (count($category['children']) > 0)
{
echo "<li>".$start." - ".$startingLevel.
"<a href='$link'>{$category['menu_nl']}</a> ($link)\n";
$this->outputCategories($category['children'], $link
, $start, $startingLevel+1);
echo "</li>\n";
}
else
{
$start = $startingLevel+1;
echo "<li>".$start." - ".$startingLevel.
"<a href='$link'>{$category['menu_nl']}</a> ($link)</li>\n";
}
}
echo "</ul>\n";
}
As you see in the example I have used a url_nl field which is recursively added so every level of the list has a link with a path which is used as a url.
Anyhow, I have problems with building up these links, as they are not properly reset while looping to the hierarchical list. After going down to the child in de list the first one is right but the second one not.
I'm stuck here...
It looks like you modify the $link variable inside the foreach loop, So you add item1 to $link, loop thru its subitems and return to the first iteration and add item2 to the variable...
replace this
$link .= "/".$category['url_nl'];
with
$insidelink = $link . "/".$category['url_nl'];
(and change remaining $link inside the loop to $insidelink)
Adding: This is also true for $startingLevel. Do not modify it, use +1 inline:
echo "<li>".$start." - ".$startingLevel +1.
"<a href='$link'>{$category['menu_nl']}</a> ($link)</li>\n";
Here is an easier way:
$inarray = your multi-dimensional array here. I used directory_map in codeigniter to get contents of directory including it's subdirectories.
$this->getList($filelist2, $filelist);
foreach ($filelist as $key => $val) {
echo $val;
}
function getList($inarray, &$filelist, $prefix='') {
foreach ($inarray as $inkey => $inval) {
if (is_array($inval)) {
$filelist = $this->getList($inval, $filelist, $inkey);
} else {
if ($prefix)
$filelist[] = $prefix . '--' . $inval;
else
$filelist[] = $inval;
}
}
return $filelist;
}

Categories