首页 > 解决方案 > 使用 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

也许有人明白我需要什么,因为我的英语不是最好的解释它。感谢您对此问题的任何帮助/解决方案。

标签: phpmysql

解决方案


$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);

推荐阅读