📜 ⬆️ ⬇️

Tree Navigation with Zend Framework

Large projects have a big problem - sooner or later, its contents turn into chaos (for the most part this refers to the backend, because on the front it's usually okay). As the project grows, its hierarchical structure becomes more complicated, which makes it difficult to control or work, so you should use a very obvious thing - the navigation output in the form of a tree. Pretty convenient when the entire contents of your project is displayed in a hierarchical form, don't you think so?

Task


Implement tree navigation. The nesting of the tree is unlimited.

Database



MySQL table

CREATE TABLE IF NOT EXISTS `navigation` (
`nav_id` smallint(5) unsigned NOT NULL auto_increment,
`nav_parent` smallint(5) unsigned NOT NULL default '1',
`nav_title` varchar(200) NOT NULL,
PRIMARY KEY (`nav_id`),
KEY `nav_parent` (`nav_parent`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `navigation`
ADD CONSTRAINT `navigation_ibfk_1` FOREIGN KEY (`nav_parent`) REFERENCES `navigation` (`nav_id`) ON DELETE CASCADE ON UPDATE CASCADE;

')
As many of you have already guessed, this table has a recursive foreign key. The content table is tied to the foreign key navigation table, but we will not consider it, because This thing is quite obvious.

Implementation



In most cases, you can extract html in php code and output it at the right moment. This is acceptable if our node has the form:

html:
<li>
<a href="#">Pangram</a>
</li>


php + html:
<?php
$node = "<li><a href=\"#\">Pangram</a></li>"
?>

All is well, but what if we need to enter an additional code?

html:
<li class="menulayer" id="navigation_item_46">
<a href="#" onclick="myFunction(); return false;">Pangram</a>
</li>


php + html:
<?php
$node = "<li class=\"menulayer\" id=\"navigation_item_46\"><a href=\"#\" onclick=\"myFunction(); return false;\">Pangram</a></li>"
?>

Anything else to add? I think that your coder will be frustrated for a long time , because very few people want to poke around in php code, especially not their own.

But the solution exists. Need to use a helper.

Helper class

<?php
class MY_View_Helper_NavigationTree{
private $tree;
public $view;

public function setView(Zend_View_Interface $view){
$this->view = $view;
}

public function scriptPath($script){
return $this->view->getScriptPath($script);
}

/**
* @access public
* @param array ,
* @param integer ,
* @param array
* @return mixed
*/
public function navigationTree($tree, $id, array $args){
$this->tree = $tree;
return $this->getTree($id, $args);
}

/**
* @access private
* @param integer ,
* @param array
* @return mixed
*/

private function getTree($id, array $args){
$nodes = array();
foreach ($this->tree as $node){
if($node['nav_id'] != 1){
if($node['nav_parent'] == $id){
$nodes[] = $node;
}
}
}

return $this->view->partial('navigation/_partial/item.phtml', array(
'nodes' => $nodes,
'tree' => $this->tree,
'baseUrl' => $args['baseUrl']
));
}
}
?>


Controller

public function indexAction(){
$menu = new navigation();
$this->view->tree = $menu->fetchAll();
}



For the corresponding action we will implement the view and call our helper.

Call the "root"

<?= $this->navigationTree($this->tree, 1, array('baseUrl' => $this->baseUrl))?>


Nested view

<? foreach($this->nodes as $item) : ?>
<li class="menulayer" id="navigation_item_<?= $item['nav_id'] ?>">
<a href="#" onlclick="myFunction(); return false;">
<?= $this->escape($item['nav_title']) ?>
</a>
<ul id="treeitem_<? echo $item['nav_id']?>">

<?= $this->navigationTree($this->tree, $item['nav_id'], array('baseUrl' => $this->baseUrl)) ?>
</ul>
</li>
<? endforeach ?>


As a result, we can modify our html code without problems.
I got about the following:
image

PS Special thanks to onthefly habraiser for preparing the material.

Source: https://habr.com/ru/post/50483/


All Articles