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

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 !

Related

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.

How to output Multidimensional Arrays PHP

I'm trying to create a multidimensional array which stores a website navigation. Currently my navigation consists of Main -> Level 1 -> Level 2. I am having issues accessing level 2 correctly.
My Array example array is...
$pages = array
(
array('page_name' => 'Home'),
array('page_name' => 'About us', 'level_one' => array('first1','first2', 'level_two' => array('second'), 'first3')),
array('page_name' => 'Gallery', 'level_one' => array('first1','first2','first3','first4')),
array('page_name' => 'Contact us')
);
My code to retrieve the navigation so far is...
$count = count($pages);
for ($x=0; $x<$count; $x++) {
# echo yes for active page
if ($filename == $pages[$x][1]) { echo 'yes'; }
# echo main navigation
echo $pages[$x]['page_name'];
# check if the item has a sub page
$firstcount = count($pages[$x]['level_one']);
# if the item has a sub page echo
if ($firstcount > 0) { for ($y=0; $y<$firstcount; $y++) {
echo "\r\n" . '.' . $pages[$x]['level_one'][$y];
# check if the page has a sub page
$secondcount = count($pages[$x]['level_one']['level_two']);
if ($secondcount > 0) { for ($z=0; $z<$secondcount; $z++) {
if($pages[$x]['level_one']['level_two'][$z] != '') { echo "\r\n" . '..' . $pages[$x]['level_one']['level_two'][$z]; }
}}
} }
echo "\r\n";
}
And the output I'm currently getting is...
Home
About us
.first1
..second
.first2
..second
.first3
..second
.
..second
Gallery
.first1
.first2
.first3
.first4
Contact us
I am trying to create a multi level navigation. My expected output would be...
<!-- Expected output
Home
About us
.first1
.first2
..second
.first3
Gallery
.first1
.first2
.first3
.first4
Contact us
-->
I think you should check out some php recursion examples:
function returnArrayAsString($ar, $level = 0){
$str = '<ul class="level' . $level . '">';
foreach($ar as $k => $v){
if(is_array($v)){
$str .= '<li>' . $k . returnArrayAsString($v, $level + 1) . '</li>';
} else {
$str .= '<li>' . $v . '</li>';
}
}
$str .= '</ul>';
return $str;
}
if you then have a simple array:
$ar = array(
'Home',
'About us' => array(
'sub1a',
'sub1b',
'sub1c' => array(
'sub2a',
'sub2b'
)
)
);
Put array in function:
echo returnArrayAsString($ar);
This would give you a nice ordered list no matter the depth of sub items in the array.
As you can see, the function calls itself if it finds an array value. the $level variable can be used as a indicator, you could also use it for breadcrumbs ( About us > sub1c > sub2a).
Hope it helps....
The problem is in your loop code. Using foreach to make things more clear, results in the following, which outputs your result as you want it.
foreach($pages as $page)
{
echo "{$page['page_name']}\n";
foreach($page['level_one'] as $key => $level_one)
{
if($key === 'level_two')
{
foreach($level_one as $level_two)
{
echo "..$level_two\n";
}
}
else
{
echo ".$level_one\n";
}
}
}
You can use a lot of functions/ways to do this:
1.By foreach(Reference)
2.use var_dump to view any arrayvar_dump()
But remember to use <pre></pre> for prettifying.

How to build a tree from a concatenated string in PHP?

I try to make a tree list in PHP from a hierarchy stored in a concatenated string in my mysql database
This my table :
and I'd like to reproduce something like this :
<ul>
<li>
<ul>
<li></li>
<li>
<ul>
<li></li>
<li></li>
</ul>
</li>
<li></li>
</ul>
</li>
<li></li>
<li></li>
</ul>
I know I have to use a recursive function I don't reach to do...
Maybe someone could help me
code without comments
see the usage and dataset section below to see what you need to pass and how to use these functions:
function items_to_tree( $items ){
$array = array();
foreach( $items as $item ) {
$parts = explode('.', $item['hierarchy']);
$last = array_pop( $parts );
$cursor = &$array;
foreach ( $parts as $part ) {
if ( !is_array($cursor[$part]) ) {
$cursor[$part] = array();
}
$cursor = &$cursor[$part];
}
$cursor[$last]['#item'] = $item;
}
return $array;
}
function tree_to_ul( $tree ){
$html = $children = '';
foreach( $tree as $key => $item ){
if ( substr($key,0,1) == '#' ) continue;
$children .= tree_to_ul( $item );
}
if ( isset($tree['#item']) ) {
$html .= '<li>' . PHP_EOL;
$html .= '<em>' . $tree['#item']['menu_text'] . '</em>' . PHP_EOL;
$html .= ( $children ? '<ul>' . $children . '</ul>' . PHP_EOL : '' );
$html .= '</li>' . PHP_EOL;
return $html;
}
else {
return $children;
}
}
code with comments and explanation
The code to convert your items to a tree structure:
function items_to_tree( $items ){
$array = array();
foreach( $items as $item ) {
/// split each hierarchy string into it's dot separated parts
$parts = explode('.', $item['hierarchy']);
/// pop off the last item of the array, we'll use this for assignment later
$last = array_pop( $parts );
/// create a reference to our position in the array we wish to fill out
$cursor = &$array;
/// step each hierarchy part and travel down the array structure,
/// just like you would if you typed an array path manually.
/// i.e. $array[$part][$part][...] and so on
foreach ( $parts as $part ) {
/// if at this point in the array, we don't have an array, make one.
if ( !is_array($cursor[$part]) ) {
$cursor[$part] = array();
}
/// ready for the next step, shift our reference to point to the next
/// $part in the array chain. e.g. if $cursor pointed to `$array[$part]`
/// before, after the next line of code the $cursor will point
/// to `$array[$oldpart][$part]`
$cursor = &$cursor[$part];
}
/// we popped the last item off the $parts array so we could easily
/// assign our final value to where the $cursor ends up pointing to.
/// starting with a hierarchy of '00001.00002.00003' would mean at this
/// point $cursor points to $array['00001']['00002'] and $last = '00003';
/// so finally we get $array['00001']['00002']['00003']['#item'] = $item;
$cursor[$last]['#item'] = $item;
/// use '#item' to keep our item's information separate from it's children.
}
/// return our built up array.
return $array;
}
The code to convert the tree structure to a UL:
function tree_to_ul( $tree ){
/// start with nothing
$html = $children = '';
/// step each item found in the current level of $tree
foreach( $tree as $key => $item ){
/// if the item's key starts with a # skip, these contain
/// our item's information and should not be treated as children
if ( substr($key,0,1) == '#' ) continue;
/// recurse this function so that we do the same for any child # any level.
$children .= tree_to_ul( $item );
}
/// if at this level a #item has been set, use this item information to
/// add a title to our level. You could change this to add whatever info
/// from your original database item that you'd like.
if ( isset($tree['#item']) ) {
$html .= '<li>' . PHP_EOL;
$html .= '<em>' . $tree['#item']['menu_text'] . '</em>' . PHP_EOL;
$html .= ( $children ? '<ul>' . $children . '</ul>' . PHP_EOL : '' );
$html .= '</li>' . PHP_EOL;
return $html;
}
/// if there wasn't an item, just return the traversed children.
else {
return $children;
}
}
dataset:
/// I simplified your dataset to an array, this could easily be generated
/// from a database query. You could also convert my code so that you
/// don't have to pre-generate an array, and instead could process after
/// each fetch from the database.
$items = array(
array('hierarchy' => '00001', 'menu_text' => 'One'),
array('hierarchy' => '00002', 'menu_text' => 'Two'),
array('hierarchy' => '00002.00001', 'menu_text' => 'Three'),
array('hierarchy' => '00002.00002', 'menu_text' => 'Four'),
array('hierarchy' => '00002.00003', 'menu_text' => 'Five'),
array('hierarchy' => '00002.00004', 'menu_text' => 'Six'),
array('hierarchy' => '00003', 'menu_text' => 'Seven'),
array('hierarchy' => '00003.00001', 'menu_text' => 'Eight'),
array('hierarchy' => '00003.00001.00001', 'menu_text' => 'Nine'),
array('hierarchy' => '00003.00001.00002', 'menu_text' => 'Ten'),
array('hierarchy' => '00003.00001.00003', 'menu_text' => 'Eleven'),
array('hierarchy' => '00003.00002', 'menu_text' => 'Twelve'),
);
usage:
/// Simple usage :) if a little complex explanation
$tree = items_to_tree( $items );
$html = tree_to_ul( $tree );
echo $html;
in the interests of codegolf ;)
The following could replace my items_to_tree function -- however it isn't advised.
$a = array();
foreach($items as $i){
eval('$a["'.str_replace('.','"]["',$i['hierarchy']).'"]=array("#item"=>$i);');
}
$refs = new stdClass();
//Assuming $data is the result array of your query to fetch the data.
foreach($data as $result)
{
$name = $result['hierarchy'];
$parent = substr($result['hierarchy'],0,strrpos($result['hierarchy'],'.'));
$thisref = &$refs->{$name};
foreach($result as $k => $v)
{
$thisref->{$k} = $v;
}
if ($parent == '') {
$tree->{$name} = &$thisref;
} else {
$refs->{$parent}->children->{$name} = &$thisref;
}
}
This will give you a nice object with every node's child in the property children.
function drawUL($level){
echo '<ul>';
foreach($level as $li){
echo '<li>'.$li->label;
if(isset($li->children))drawUl($li->children);
echo '</li>';
}
echo '</ul>';
}
drawUl($tree);

Parent-child navigation generation from tree array in 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

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