php - 使用 MySQL 数据库进行 PHP 导航
问题描述
我在需要 MySQL 数据库的地方做了一个导航。这是我与数据库的连接以获取所有信息。
$stmt = $pdo->prepare("SELECT * FROM navigation");
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_OBJ);
if($stmt->rowCount() > 0){
$primary_nav = [];
foreach ($results as $result){
if($result->sub == 0){
$primary_nav[] = array(
'name' => $result->name,
'url' => $result->url,
'icon' => $result->icon,
);
}elseif($result->sub == 1){
$primary_nav[] = array(
'name' => $result->name,
'icon' => $result->icon,
'sub' => array(
array(
'name' => $result->name_sub,
'url' => $result->url_sub
)
)
);
}
}
}
这很好用,如果我将导航添加到数据库中,一切看起来都很完美并且效果很好。现在我遇到的问题是当我想要一个新的子菜单而不是每次我得到一个只有一个子菜单的新顶部菜单条目时。
所以我的问题是,如何在不破坏代码的情况下让这部分工作。通常代码如下所示:
// first sub
array(
'name' => 'Test1',
'icon' => 'fa fa-bullhorn',
'sub' => array(
array(
'name' => 'First Sub 1',
'url' => 'sub1.php'
),
array(
'name' => 'First Sub 2',
'url' => 'sub2.php'
)
)
),
// second sub
array(
'name' => 'Test3',
'icon' => 'fa fa-bullhorn',
'sub' => array(
array(
'name' => 'Second Sub',
'url' => 'sub1_1.php'
)
)
)
数据库结构:
|-----name-----|----url----|----icon----|----sub----|----name_sub----|----url_sub----|----category----|
| Dashboard | index.php | icon | 0 | | | |
------------------------------------------------------------------------------------------------------
| Test | test.php | icon | 0 | | | |
------------------------------------------------------------------------------------------------------
| Test1 | | icon | 1 | First Sub 1 | sub1.php | 1 |
------------------------------------------------------------------------------------------------------
| | | icon | 1 | First Sub 2 | sub2.php | 1 |
------------------------------------------------------------------------------------------------------
| Test3 | | icon | 1 | Second Sub | sub1_1.php | 2 |
------------------------------------------------------------------------------------------------------**
因此,如果类别与另一个类别相同,则应该这样做:
Test1
-- First Sub 1
-- First Sub 2
Test3
-- Second Sub
但使用我的代码,它看起来像这样:
Test1
-- First Sub 1
Test2 (it would be empty because in the database it is empty just for example I puted Test2)
-- First Sub 2
Test3
-- Second Sub
也许有人明白我需要什么,因为我的英语不是最好的解释它。感谢您对此问题的任何帮助/解决方案。
解决方案
$stmt = $pdo->prepare("SELECT * FROM navigation");
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_OBJ);
if($stmt->rowCount() > 0){
$categories = [];
$primary_nav = [];
foreach ($results as $result){
if ($result->name) {
if ($result->category) {
$categories[$result->category] = sizeof($primary_nav);
}
$primary_nav[] = array(
'name' => $result->name,
'url' => $result->url,
'icon' => $result->icon,
);
}
if ($result->name_sub) {
$primary_nav[$categories[$result->category]]['sub'][] = array(
'name' => $result->name_sub,
'url' => $result->url_sub
);
}
}
}
我添加了一个额外的$categories
数组。
对于每个具有类别的“父”条目,$categories
数组存储数据库中的类别值和$primary_nav
数组中“父”条目的键。然后,该$categories
数组可用于使用其类别值将后续子类别添加到正确的父条目。
但是,在您当前的设置中,数据库允许您拥有没有父类别的子类别和没有名称的(子)类别。所以我建议使用这样的表设置:
id name url icon parent
1 Dashboard index.php icon null
2 Test test.php icon null
3 Test1 null icon null
4 First sub 1 sub1.php null 3
5 First sub 2 sub2.php null 3
6 Test3 null icon null
7 Second sub Sub1_1.php null 6
父类别的“父”列设置为空,子类别的“父”列设置为其父条目的 id。这也允许您拥有子子(等等)类别。
您需要递归查询它:
function buildNav($pdo, $id = null) {
$array = [];
if ($id) {
$stmt = $pdo->prepare("SELECT * FROM navigation WHERE parent = :id");
$stmt->bindValue('id', $id);
} else {
$stmt = $pdo->prepare("SELECT * FROM navigation WHERE parent IS NULL");
}
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_OBJ);
if ($stmt->rowCount() > 0){
foreach ($results as $result){
$array[] = array(
'name' => $result->name,
'url' => $result->url,
'icon' => $result->icon,
'sub' => buildNav($pdo, $result->id)
);
}
}
return $array;
}
$primary_nav = buildNav($pdo);
推荐阅读
- c# - 无法以全局管理员身份使用 Microsoft Graph 查询用户的 OneDrive For Business 文件
- html - 悬停后元素更改宽度(?)
- swift - 当我不想时,SKShapeNodes 与我的 SKPhysics 身体发生碰撞
- asp.net-core - 带有 Azure AD B2C 受众验证的 Angular 失败
- angular - 有效过滤数据
- c# - EF Core 导航属性循环
- bash - Bash将heredoc内容直接插入输出文件中的特定位置而没有临时文件?
- python - 使用 pd.series.str.extractall 与 re.findall 从 Pandas DataFrame 的列中提取数字
- css - 带背景的 css 网格 - 当网格大于背景时滚动
- sprite-kit - 从 SKView 获取 SpriteKit 纹理在 104 次调用后返回 nil