我正在尝试优化多对多设计,这将返回树状结构。数据如下所示:
页面表:id,title,subtitle,class pages连接器表:id,page_id,parent_id,section
如果section = x,对于每个有子节点的父节点,section = x markup应该是这样的:
--- start parent 1 ---
-- if first parent echo *
<>* parent page id | parent title<>
--- parent 1 children ---
<>child page id | child title<>
<>child page id | child title<>
<><>child page id | child title<>
--- end parent 1 ---
--- start parent 2 ---
-- if first parent echo *
<>parent page id | parent title<>
--- parent 2 children ---
<>child page id | child title<>
<>child page id | child title<>
<>child page id | child title<>
--- end parent 2 ---
这个实现似乎运行良好,但我似乎无法弄清楚如何修改函数以返回上面的标记:
// Menu builder function, parentId 0 is the root
function buildMenu($parent, $menuData)
{
$html = "";
if (isset($menuData['parents'][$parent]))
{
$html .= "
<ul>\n";
foreach ($menuData['parents'][$parent] as $itemId)
{
if(!isset($menuData['parents'][$itemId]))
{
$html .= "<li>\n <a href='".$menuData['items'][$itemId]['link']."'>".$menuData['items'][$itemId]['label']."</a>\n</li> \n";
}
if(isset($menuData['parents'][$itemId]))
{
$html .= "
<li>\n <a href='".$menuData['items'][$itemId]['link']."'>".$menuData['items'][$itemId]['label']."</a> \n";
$html .= buildMenu($itemId, $menuData);
$html .= "</li> \n";
}
}
$html .= "</ul> \n";
}
return $html;
}
echo buildMenu(0, $menuData);
答案 0 :(得分:0)
您的数据结构似乎很奇怪。我可以说,你的$ menuData结构是这样的:
$menuData = array(
"parents" => array( ... ),
"items" => array(
0 => array( "link" => "...", "title" => "...", ... ),
1 => array( "link" => "...", "title" => "...", ... )
)
);
在我构建的层次结构中,它们看起来更像是这样:
$menuData = array(
array( "id" => 1, parent_id => 0, "link" => "...", "title" => "...", ... ),
array( "id" => 2, parent_id => 1, "link" => "...", "title" => "...", ... )
)
);
也许这是对你正在使用的上下文的约束,但只是说:更简单的结构使得代码更简单。
至于生成树的递归算法,如果它确实生成了你想要的东西(至少是无序列表结构),你只需要尝试添加你的“&lt;&gt;”和“ - ”在<li>
和</li>
串联之间所需的部分。但是,对于“第一个”父级,您的星号会有问题。如果要将星号添加到所有顶级菜单项,则应在buildMenu上建立可选参数,如下所示:
function buildMenu($parent, $menuData, $level = 0);
然后修改你的递归调用:
$html .= buildMenu($itemId, $menuData, ++$level);
添加条件以检测$ level == 0
$html .= "<li>\n " . ( $level == 0 ? "*" : "") . "<a href='".$menuData['items'][$itemId]['link']."'>".$menuData['items'][$itemId]['label']."</a>\n</li> \n";
如果您只想在第一个顶级父级上使用星号,那么最好只在函数范围之外建立一个全局变量,并将一次性标志条件设置为仅在第一次输出星号时代码被调用,而且永远不会再被调用。
希望这有帮助。