php中菜单的层次关系


hierarchical relationship in php for menu

我们在这样的表中有层次关系

表名:类别

 id       parent_id    title
  1         0           main menu
  2         1           sub_menu1
  3         2           sub_sub_menu1

另一个表:域

id        cat_id        name
 1           1           main domain
 2           2           sub domain
 3           3           sub sub domain

我们正在尝试显示类别和子类别正如我的朋友所说,通过sql显示这种类型的关系太复杂,成本太高,所以我们改为通过php显示。

我们写了这个代码:-

function getSubCatCount($data,$parent){
    $count=0;
    $count =$count+ domainCatCount($parent);
    return $count;
}

function menuList($data, $parent = 0,$st )
{
    static $i = 0;
    $tab = str_repeat(" ",$i);
    if($data[$parent])
    {
    $html .= "";
    $i++;

    if($i==1)
                $html .= '<ul data-menu="main" class="menu__level">';
    else{
                $html .= '<ul data-menu="submenu-'.$parent.'" class="menu__level">';
    }
    $tmpLis="";
        foreach($data[$parent] as $v)
        {
            $html .= '<li class="menu__item"><a href="#" class="menu__link ';
            $child = menuList($data, $v['id'],"false");
            $html .= '" data-submenu="submenu-'.$v['id'].'" ';      
            //if(!$child)
            {
                $tmpLis.=domainHtmlList($v['id']);
            }
            $html .= '>';

            $html .= $v['title'].'<div style="float: right;"><table style="width: 145px;"><tr><td style="width: 30%;"><img src="https://cdn3.iconfinder.com/data/icons/metro-explorer/512/my_location-512.png"  style="width: 20px;height: 20px;" title="usages">'.getUsages($v['id']).'</td><td style="width: 30%;"><img src="http://www.clubs.uci.edu/cae/a/src/1432405005258.png"  style="width: 20px;height: 20px;" title="domains">'.getDomainCount($data,$v['id']).'</td><td style="width: 30%;"><img src="https://cdn2.iconfinder.com/data/icons/flat-ui-icons-24-px/24/eye-24-128.png"  style="width: 20px;height: 20px;" title="views">'.getViews($v['id']).'</td></tr></table></div></a></li>';
//if (preg_match_all('/<[a-z ''"]*data-menu=[''"]submenu-'.$v['id'].'[''"][^>]*>([^<]*)/i', $html, $matches)) {
    //print_r($matches);
    //$child = menuList($data, $v['id'],"true");
//$html .= $child;
//} 
        }
            if($st!="true")
            $html .= "</ul>";
            $html .=$tmpLis;
        foreach($data[$parent] as $v)
        {
            $child = menuList($data, $v['id'],"false");
            if($child)
            {
                $i–;
                $html .= $child;
            }
        }
        return $html;
    }
    else
    {
        return false;
    }
}

function domainHtmlList($i){
global $db; 
$domainCatRows = $db->getRows("SELECT * FROM  `url_domain` WHERE  `category` ='".$i."'");
if(count($domainCatRows)>0)
    $html = '<ul data-menu="submenu-'.$i.'" class="menu__level">';
foreach($domainCatRows as $ff) 
{
$dom=$ff['domain'];
$count=0;
if($ff['domain']=="[[[main_url]]]")
$dom="123.yt";
$html .= '<li class="menu__item"><a href="#" class="menu__link ';
    $html .=  'submenu-child" data-key="'.$ff['id'].'" data-domain="'.$dom.'" ';
$html .= '>';
$domainId=$ff['id'];
    //for usages
    $shortUrlRows = $db->getRows("SELECT count(*) as usages_count FROM `shorturl` WHERE `urlDomainId` in (".$domainId.") ");
    foreach($shortUrlRows as $val) 
    {
        $count=$count+$val['usages_count']; 
    }   
    //for views
    //$tmp= $db->getRows("SELECT count(*) as count FROM  `stats` WHERE  `url` like '%".$dom."%'");  
    //echo "SELECT * FROM  `stats` WHERE  `reffer` like '%".$dom."%'"."<br/>";
    //print_r($tmp);
    $tmp= $db->getRows("SELECT GROUP_CONCAT(id SEPARATOR ',') as shortUrlDomain FROM  `shorturl` WHERE  `urlDomainId` in (".$domainId.")");
    //echo "SELECT GROUP_CONCAT(id SEPARATOR ',') as shortUrlDomain FROM  `shorturl` WHERE  `urlDomainId` in (".$domainId.")"."<br/>";
    $tmpsts= $db->getRows("SELECT count(*) as count FROM  `stats` WHERE  `page_title` in (".$tmp[0]['shortUrlDomain'].")");
    //echo "SELECT count(*) as count FROM  `stats` WHERE  `page_title` in (".$tmp[0]['shortUrlDomain'].")"."<br/>";
    //$count=$count+$tmpsts[0]['count'];        
     $html .="<div style='float:right;'><table style='width: 140px;'><tr><td style='width: 30%;'><img src='https://cdn3.iconfinder.com/data/icons/metro-explorer/512/my_location-512.png'  style='width: 20px;height: 20px;' title='usages'>".$count."</td><td style='width: 30%;'><img src='https://cdn2.iconfinder.com/data/icons/flat-ui-icons-24-px/24/eye-24-128.png'  style='width: 20px;height: 20px;' title='views'>".$tmpsts[0]['count']."</td></tr></table></div>";
   $html .= $dom.'</a>';
            $html .='</li>';
    }
if(count($domainCatRows)>0)
$html .= "</ul>";
return $html;
} 

现在的问题是,当我们将子类别和域都放在一个类别中时,它不会同时显示这两个类别。它只显示子类别或域。我们尝试了所有的东西,但都没用。那么我们如何展示这种关系呢?

我建议所有有这个问题的人使用"嵌套树模型"。

在类别表中创建两个新的int列(lft和rgt),并用算法提供的值填充它们(只需阅读一些文档,这并不难理解)。完成后,您可以通过以下查询获得所有主要类别:

SELECT * FROM categories WHERE parent_id = 0 OR parent_id IS NULL

现在,对于每一个主要类别,都要得到她所有的孩子。

SELECT * FROM categories 
WHERE lft >= (
      SELECT lft FROM categories
      WHERE id = {$id}
) AND rgt <= (
      SELECT rat FROM categories
      WHERE id = {$id}
)
ORDER BY lft;

维基百科在算法方面帮了我很多忙:https://en.wikipedia.org/wiki/Nested_set_model

此外,还有一些php库,比如这个库。http://www.sideralis.org/baobab/

我希望它能帮助你,

谨致问候。