I've one Array in PHP with limited data and static HTML view related to it which gives me tree view.
However; I need help to develop dynamic HTML code to view the same Data in Tree view.
Static Array code as follow
<?php
echo '<pre>';
$array = array(59336 => array(
array('parent_id' => 40503, 'child_id' => array()),
array('parent_id' => 20098, 'child_id' => array(array('parent_id' => 43849, 'child_id' => array(array('parent_id' => 43850, 'child_id' => array()), array('parent_id' => 43851, 'child_id' => array()))), array('parent_id' => 81542, 'child_id' => array()))),
array('parent_id' => 20099, 'child_id' => array(array('parent_id' => 43850, 'child_id' => array(array('parent_id' => 43851, 'child_id' => array()))), array('parent_id' => 81543, 'child_id' => array()))))
);
print_r($array);
?>
Static HTML
<ul id="tree-data" style="display:none">
<li id="root">
59336
<ul>
<li>
40503
</li>
<li>
20098
<ul>
<li>
43849
<ul>
<li>
43850
</li>
<li>
43851
</li>
</ul>
</li>
<li>
81542
</li>
</ul>
</li>
<li>
20099
<ul>
<li>
43850
<ul>
<li>
43851
</li>
</ul>
</li>
<li>
81543
</li>
</ul>
</li>
</ul>
</li>
</ul>
Need Dynamic HTML code to print the data using Static Array instead of my static HTML code. Kindly help me.
Try with below function which help to generate array as per your requirement.
<?php
function nested2ul($data) {
$result = array();
if (sizeof($data) > 0) {
$result[] = '<ul>';
foreach ($data as $entry) {
$result[] = sprintf(
'<li>%s %s</li>', $entry['parent_id'], nested2ul($entry['child_id'])
);
}
$result[] = '</ul>';
}
return implode($result);
}
?>
The html code as below :
<?php
$html = '<ul id="tree-data" style="display:none"><li id="root">59336';
$html .= nested2ul($array['59336']);
$html .= '</li></ul>';
echo $html;
?>
Related
Question in short: i want to output array: 0, 1 , 2 then break, echo something , output 3,4,5 and keep this in a loop.
Hello everyone i am working on a dynamic php website with bootstrap 4 and php to practice the language. Unfortunately i am now stuck since i dont know how to create something that kindoff looks like an algorith. Allright enough talking and lets get down to the code:
nav.php file
<ul class="navbar-nav">
<li class='nav-item dropdown'>
<a class='nav-link dropdown-toggle' data-toggle='dropdown' datatarget='dropdown_target' href='#'>
<span class='caret'></span>Dropdown
</a>
<div class="dropdown-divider"></div>
<div class="dropdown-menu" aria-labelledby="dropdown_target">
<!-- <a class="dropdown-item">Dropdown</a> -->
<?php
$i=0;
foreach ($dropItems as $item ) {
echo "<a class='dropdown-item' href=\"$item[slug]\">$item[title] </a>";
$i++;
if($i==1) break;
echo "<a class='dropdown-item'>Dropdown</a>";
}
?>
</div>
</li>
</li>
<?php
foreach ($navItems as $item ) {
echo "<li class='nav-item'> <a class='nav-link' href=\"$item[slug]\">$item[title]</a> </li>";
}
?>
</ul>
arrays.php
<?php
//Navigatie menu items
$navItems = array(
array(
"slug" => "index.php",
"title" => "home"
),
array(
"slug" => "contact.php",
"title" => "Contact"
),
array(
"slug" => "market.php",
"title" => "Marketplace"
),
);
$dropItems = array(
array(
"slug" => "#",
"title" => "Lps"
),
array(
"slug" => "#",
"title" => "Sps"
),
array(
"slug" => "market.php",
"title" => "Marketplace"
),
);
?>
You can use array_chunk to split the array in the chunks of three and foreach nested with echo "something";.
Can't see in your code where this echo of three is so I just made an example of how to do it.
$arr = range(1,12); //example array
$chunks = array_chunk($arr, 3);
Foreach($chunks as $chunk){
Foreach($chunk as $val){
Echo $val ." ";
}
Echo "\nsomething\n";
}
https://3v4l.org/0VlN0
Thanks to Andreas i got it working using his method
$chunks = array_chunk($dropItems, 2);
Foreach($chunks as $chunk){
Foreach($chunk as $item){
echo "<a class='dropdown-item' href=\"$item[slug]\">$item[title] </a>";
}
Echo "<div class='dropdown-divider'></div>";
}
I have to create a menu from a list with possible sub-lists.
From a simple I want to create a compatible bootstrap menu
So from a code like this:
<ul>
<li>Link 1</li>
<li>Link 2
<ul>
<li>Sublink A</li>
<li>Sublink B</li>
</ul>
</li>
<li>Link 3
<ul>
<li>Sublink C</li>
</ul>
</li>
</ul>
I'll have to create this:
array(
[0] => array(
[id] => 1,
[nome] => 'Link 1',
[parent] => NULL,
),
[1] => array(
[id] => 2,
[nome] => 'Link 2',
[parent] => NULL,
),
[2] => array(
[id] => 3,
[nome] => 'Sublink A',
[parent] => 2
),
[3] => array(
[id] => 4,
[nome] => 'Sublink B',
[parent] => 2
),
[4] => array(
[id] => 5,
[nome] => 'Link 3',
[parent] => NULL
),
[5] => array(
[id] => 6,
[nome] => 'Sublink C',
[parent] => 3
)
)
And finally, get back this one:
<ul class="nav navbar-nav">
<li><a class="primary" href="link_1.html">Link 1</a></li>
<li class="dropdown">
Link 2
<ul class="dropdown-menu">
<li>Sublink A</li>
<li>Sublink B</li>
</ul>
</li>
<li class="dropdown">
Link 3
<ul class="dropdown-menu">
<li>Sublink C</li>
</ul>
</li>
</ul>
Conditions are:
if has children has href="#", add class dropdown-toogle and data-toggle="dropdown";
child has class "dropdown-menu";
if hasn't parent add class "primary" to
I use this code, but it's only for a simple list, not nested lists.
<?php
$currentPage = "";
$contents = "<ul>
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
</ul>";
// remove width, height, style
$contents = preg_replace('/(width|height|style|target)="[^"]+"/i', "", $contents);
// remove spaces form li
$contents = str_replace(array('<li >',' <li >'),"<li>",$contents);
// remove ul/ol tag and tabs
$contents = str_replace(array('\t','<ul>','<ul >','</ul>','<ol>','<ol >','</ol>'),"",$contents);
$arrNavTopList = explode("\n",trim($contents));
echo "<h4>Array:</h4>\n";
print_r($arrNavTopList);
echo "<hr>\n<h4>List:</h4>\n";
$totNavTopList = count($arrNavTopList);
if($totNavTopList>0){
echo '<ul class="nav navbar-nav">'."\n";
$countNtL=1;
foreach($arrNavTopList as $pagename) {
$pagename = str_replace("\t","",$pagename);
preg_match_all("(<li>(.*?)</li>)", $pagename, $arrLinkList);
$linktopage = $arrLinkList[1][0];
if(
strtolower($linktopage)==strtolower(str_replace("_"," ",$currentPage)) ||
strtolower($linktopage)=="home" && !(strpos($currentPage,"^")===FALSE)
) {
$active=' class="active"';
} else {
$active='';
}
echo '<li'.$active.'>';
if (strstr($linktopage,"http") || strstr($linktopage,"target")) {
$linktopage = preg_replace('/(style|target)="[^"]+"/i', "", $linktopage);
$linktopage = str_replace('<a','<a rel="external nofollow" class="_blank"',$linktopage);
echo $linktopage;
} else {
if(strtolower($linktopage)=="home" || strtolower($linktopage)=="home page") {
echo ''.htmlentities($linktopage).'';
} else {
echo ''.htmlentities($linktopage).'';
}
}
echo '</li>'."\n";
$countNtL++;
}
echo '</ul>'."\n";
}
?>
<?php
/**
* Traverse an elements children and collect those nodes that
* have the tagname specified in $tagName. Non-recursive
*
* #param DOMElement $element
* #param string $tagName
* #return array
*/
//from: https://stackoverflow.com/a/3049677/1596547
function getImmediateChildrenByTagName(DOMElement $element, $tagName)
{
$result = array();
foreach($element->childNodes as $child)
{
if($child instanceof DOMElement && $child->tagName == $tagName)
{
$result[] = $child;
}
}
return $result;
}
$doc = new DOMDocument();
$doc->loadHTML("<ul>
<li>Link 1</li>
<li>Link 2
<ul>
<li>Sublink A</li>
<li>Sublink B</li>
</ul>
</li>
<li>Link 3
<ul>
<li>Sublink C</li>
</ul>
</li>
</ul>");
//from: https://stackoverflow.com/a/6953808/1596547
# remove <!DOCTYPE
$doc->removeChild($doc->firstChild);
# remove <html><body></body></html>
$doc->replaceChild($doc->firstChild->firstChild->firstChild, $doc->firstChild);
$elements = $doc->getElementsByTagName('ul');
$parentitems = getImmediateChildrenByTagName($elements->item(0),'li');
$elements->item(0)->setAttribute ('class' , 'nav navbar-nav');
foreach ($parentitems as $parentitem)
{
if($parentitem->childNodes->length > 1) {
$parentitem->setAttribute ('class' , 'dropdown' );
$link = $doc->createElement('a',$parentitem->childNodes->item(0)->nodeValue);
$link->setAttribute ('class' , 'primary dropdown-toggle' );
$link->setAttribute ('href' , '#');
$link->setAttribute ('data-toggle','dropdown');
//$parentitem->nodeValue = null;
$old = $parentitem->childNodes->item(0);
$parentitem->replaceChild($link,$old);
$parentitem->childNodes->item(1)->setAttribute ('class' , 'dropdown-menu' );
$submenuitems = getImmediateChildrenByTagName($parentitem->childNodes->item(1),'li');
foreach($submenuitems as $submenuitem)
{
$link = $doc->createElement('a',$submenuitem->nodeValue);
$link->setAttribute ('href' , $submenuitem->childNodes->item(0)->nodeValue.'.html');
$submenuitem->nodeValue = null;
$submenuitem->appendChild($link);
}
}
else
{
$link = $doc->createElement('a',$parentitem->nodeValue);
$link->setAttribute ('class' , 'primary' );
$link->setAttribute ('href' , $parentitem->childNodes->item(0)->nodeValue.'.html');
$parentitem->nodeValue = null;
$parentitem->appendChild($link);
}
}
echo $doc->saveHTML();
other answers used:
https://stackoverflow.com/a/6953808/1596547
https://stackoverflow.com/a/3049677/1596547
I am trying to put into a string the HTML after a h1 tag up until the next h1 tag, and then continue.
For example, here is the HTML:
<h1>Heading</h1>
<p>Paragraph</p>
<ul>
<li>List item</li>
<li>List item</li>
</ul>
<p>Paragraph</p>
<h1>Heading 2</h1>
<ul>
<li>List item</li>
<li>List item</li>
</ul>
<p>Paragraph<img /></p>
And from this I am trying to create this array:
array(
0 => '<p>Paragraph</p><ul><li>List item</li><li>List item</li></ul><p>Paragraph</p>',
1 => '<ul><li>List item</li><li>List item</li></ul><p>Paragraph<img /></p>'
)
What would be the XPath query to select all content after the h1 tag up until the next, and so on?
Any help or advice is appreciated.
UPDATE:
What I am ultimately trying to achieve is, using PHP, create this format of an array:
array(
'headings' => array(
1 => '<h1>Heading</h1>',
2 => '<h1>Heading 2</h1>'
),
'content' => array(
1 => '<p>Paragraph</p><ul><li>List item</li><li>List item</li></ul><p>Paragraph</p>',
2 => '<ul><li>List item</li><li>List item</li></ul><p>Paragraph<img /></p>'
)
)
Here is a quick way to do that.
Assuming your code is placed in $code:
$code = <<<'CODE'
<h1>Heading</h1>
<p>Paragraph</p>
<ul>
<li>List item</li>
<li>List item</li>
</ul>
<p>Paragraph</p>
<h1>Heading 2</h1>
<ul>
<li>List item</li>
<li>List item</li>
</ul>
<p>Paragraph<img /></p>
CODE;
Solution:
// Content array...
$content = array_map(
function ($element) {
return preg_replace('/\>\s+\</', '><', $element);
},
preg_split('/\<h1\>[^\<]*\<\/h1\>/', $code)
);
array_shift($content);
// Headings array...
preg_match_all('/\<h1\>[^\<]*\<\/h1\>/', $code, $matches);
$headings = $matches[0];
// Result
$result = array(
'headings' => $headings,
'content' => $content,
);
print_r($result);
Output:
Array
(
[headings] => Array
(
[0] => <h1>Heading</h1>
[1] => <h1>Heading 2</h1>
)
[content] => Array
(
[0] => <p>Paragraph</p><ul><li>List item</li><li>List item</li></ul><p>Paragraph</p>
[1] => <ul><li>List item</li><li>List item</li></ul><p>Paragraph<img /></p>
)
)
I did it like this :)
$html = '<h1>Heading</h1><p>Paragraph</p><ul><li>List item</li><li>List item</li></ul><p>Paragraph</p><h1>Heading 2</h1><ul><li>List item</li><li>List item</li></ul><p>Paragraph<img /></p>';
$dom_document = new DOMDocument();
$dom_document->loadHTML($html);
$dom_document->preserveWhiteSpace = false;
//use DOMXpath to navigate the html with the DOM
$dom_xpath = new DOMXpath($dom_document);
$elements = $dom_xpath->query("/html/body/*");
if (!is_null($elements)) {
$i = 0;
foreach ($elements as $element) {
if ($element->nodeName == 'h1') {
$i++;
$array['headings'][$i] = $dom_document->saveHtml($element);
continue;
} else {
$array['content'][$i] .= $dom_document->saveHtml($element);
}
}
}
var_dump($array);
NOTE: should you be using PHP 5.2 then replace:
$array['headings'][$i] = $dom_document->saveHtml($element);
and
$array['content'][$i] .= $dom_document->saveHtml($element);
with:
$array['headings'][$i] = $dom_document->saveXml($element);
$array['content'][$i] .= $dom_document->saveXml($element);
I'm using jsTree and I need to convert this HTML tag tree code <ul> <li> to a PHP array.
The jsTree HTML tag will be passed to PHP to be parsed and store in a structured tree PHP array(see below for the PHP array structure).
Additional question: Is my desired PHP array structure good or you can suggest a good structure? I'm open for suggestions.
Thanks in advance :)
Cheers,
Mark
jsTree Screenshot:
HTML Tree String:
<ul class="ltr">
<li id="phtml_1" class=" open">
<a style="" class=" " href="#"><ins> </ins>Folder 1</a>
<ul>
<li class="leaf" id="phtml_2">
<a style="" class=" " href="#"><ins> </ins>Child 1.1</a>
</li>
<li class="open" id="phtml_3">
<a style="" class=" " href="#"><ins> </ins>Folder 1.1</a>
<ul>
<li class="leaf last" rel="default">
<ins> </ins>Child 1.1.1
</li>
</ul>
</li>
<li class="last open" rel="default">
<ins> </ins>Folder 1.2
<ul>
<li class="leaf" rel="default">
<ins> </ins>Child 1.2.1
</li>
<li class="leaf last" rel="default">
<ins> </ins>Child 1.2.2
</li>
</ul>
</li>
</ul>
</li>
<li id="phtml_5" class="file open">
<a style="" class=" " href="#"><ins> </ins>Folder 2</a>
<ul>
<li class="leaf" rel="default">
<ins> </ins>Child 2.1
</li>
<li class="leaf last" rel="default">
<ins> </ins>Child 2.2
</li>
</ul>
</li>
<li class="leaf last" rel="default">
<ins> </ins>Outer Child
</li>
</ul>
PHP Array Structure:
<?php
$tree_array = array(
'Folder 1' => array(
'Child 1.1',
'Folder 1.1' => array(
'Child 1.1.1'
),
'Folder 1.2' => array(
'Child 1.2.1',
'Child 1.2.2'
),
),
'Folder 2' => array(
'Child 2.1',
'Child 2.2'
),
'Outer Child'
);
echo '<pre>',print_r($tree_array),'</pre>';
?>
PHP print_r Output:
Array
(
[Folder 1] => Array
(
[0] => Child 1.1
[Folder 1.1] => Array
(
[0] => Child 1.1.1
)
[Folder 1.2] => Array
(
[0] => Child 1.2.1
[1] => Child 1.2.2
)
)
[Folder 2] => Array
(
[0] => Child 2.1
[1] => Child 2.2
)
[0] => Outer Child
)
Regarding:
My problem I'm having a hard time parsing the string HTML tag and save it in a PHP array.
I suggest that you use an HTML parser, such as simplehtmldom. This will allow you to traverse over HTML DOM just the way you want.
Here is a quick and dirty UL walking script:
<?php
require_once( "simplehtmldom/simple_html_dom.php" );
$DOM = file_get_html( "test.htm" );
$ARR = array( );
function WalkUL( $ul, &$ar )
{
foreach( $ul->children as $li )
{
if ( $li->tag != "li" )
{
continue;
}
$arar = array( );
foreach( $li->children as $ulul )
{
if ( $ulul->tag != "ul" )
{
continue;
}
WalkUL( $ulul, $arar );
}
$ar[ $li->find( "a", 0 )->plaintext ] = $arar;
}
}
WalkUL( $DOM->find( "ul", 0 ), $ARR );
print_r( $ARR );
?>
Its output, not exactly as you wanted it but close:
Array
(
[Folder 1] => Array
(
[Child 1.1] => Array
(
)
[Folder 1.1] => Array
(
[Child 1.1.1] => Array
(
)
)
[Folder 1.2] => Array
(
[Child 1.2.1] => Array
(
)
[Child 1.2.2] => Array
(
)
)
)
[Folder 2] => Array
(
[Child 2.1] => Array
(
)
[Child 2.2] => Array
(
)
)
[Outer Child] => Array
(
)
)
Instead of messing with html you should submit the tree data in a more programmer-friendly format.
$('#saveButton').click(function() {
var treeData = $.tree.reference($('#sortableTree')).get(undefined, 'json');
var tmp = serializeTree(treeData, 0);
// now json-encode tmp and submit it
});
function serializeTree(nodes, parent)
{
var parents = {};
var childOrder = []
var childOrders = {};
for(var i = 0; i < nodes.length; i++)
{
var node = nodes[i];
var id = node.attributes.id.substr(5); // assuming the id looks like 'abcd-ID'
parents[id] = parent;
childOrder.push(id);
if(node.children)
{
var tmp = serializeTree(node.children, id);
for(var id in tmp[0])
parents[id] = tmp[0][id];
for(var id in tmp[1])
childOrders[id] = tmp[1][id]
}
}
childOrders[parent] = childOrder;
return [parents, childOrders];
}
Just for referecence: there's also a jQuery plugin for serializing a HTML DOM Tree of <ol> and <ul> lists:
http://www.drakedata.com/serializetree/sampleTree.html - it converts a nested structure of <ol> and <ul> lists to a string which can be used as an associated php array.
If you have a UL that does not contain any href elements (e.g. just plain text nexted ul).. I've adjusted Salman's simplehtmldom code to work with that:
$DOM = str_get_html( $catshtml );
$ARR = array( );
function WalkUL( $ul, &$ar )
{
foreach( $ul->children as $li )
{
if ( $li->tag != "li" )
{
continue;
}
$arar = array( );
foreach( $li->children as $ulul )
{
if ( $ulul->tag != "ul" )
{
continue;
}
WalkUL( $ulul, $arar );
}
$ar[ trim(preg_replace("#</?[a-z]+[^>]*>(.+</[a-z]+[^>]*>|)#is","",$li->innertext)) ] = $arar;
}
}
WalkUL( $DOM->find( "ul", 0 ), $ARR );
echo "<pre>"; print_r( $ARR );
i want to write a generalized function that can output something like this.
<span class="side_title">By Collection</span>
<ul class="menu">
<li class="top">
<a class="top_menu" href="#url">home</a>
</li>
<li class="sub">
collectionA
<ul>
<li>collectionA-1</li>
<li>collectionA-2</li>
</ul>
</li>
<li class="sub">
collectionB
<ul>
<li>collectionB-1</li>
</ul>
</li>
<li class="top">CollectionE</li>
</ul>
<span class="side_title">By Functions</span>
<ul class="menu">
<li class="top">
<a class="top_menu" href="#url">home</a>
</li>
<li class="sub">
functionA
<ul>
<li>functionA-1</li>
<li>functionA-2</li>
</ul>
</li>
<li class="sub">
functionB
<ul>
<li>functionB-1</li>
<li>functionB-2</li>
</ul>
</li>
<li class="top">functionE</li>
</ul>
but the problem is i can't find a data structure to represent this structure, i tried the follwoing(using array - where the key is link's content, value is the address. and recursion):
$a = array (
"By collection" => '',
'Base' => 'thisBase',
"expand" => array (
'Home' => 'home',
'collectionA' => 'collectionA',
'expand' => array (
'collectiona-1' => 'collectiona-1',
'collectiona-2' => 'collectiona-2'
),
'collectionB' => 'collectionb',
'expand' => array (
'collectionb-1' => 'collectionb-1',
'collectionb-2' => 'collectionb-2'
),
'collectionB' => 'collectionb',
'expand' => array (
'collectionc-1' => 'collectionc-1',
'collectionc-2' => 'collectionc-2'
),
),
"by Function" => ''
);
function expand($a=NULL)
{
foreach ($a as $key => $value)
{
if ($value == '')
{
echo '<span class="side_title">'.$key.'</span>';
echo '<ul class="menu">';
} elseif (is_array($value))
{
echo '<ul class="sub_menu">';
expand($value);
} else {
echo '<li><a href="'.$value.'>'.$key.'</a></li>';
}
}
echo '</ul>';
}
print_r($a);
expand($a);
i thought about using xml/tree to represent it, but the data structure is pass between different function, so i thought it will be to much effort, so i want to know what's wrong with this? or is there better way?
I don't know, if this solves your problem, but you forgot a closing " for the href attribute.
echo '<li>'.$key.'</li>';