0

0

Laravel 8 实现嵌套下拉菜单并获取选中ID

DDD

DDD

发布时间:2025-08-16 17:08:01

|

896人浏览过

|

来源于php中文网

原创

laravel 8 实现嵌套下拉菜单并获取选中id

本文将指导你如何在 Laravel 8 中实现一个嵌套下拉菜单,并获取用户选择的选项的ID。我们将通过模型关联和递归视图来实现动态生成下拉菜单,并提供获取选中ID的思路,以便于后续的数据处理和多选功能的实现。

模型准备

首先,我们需要一个能够表示层级关系的Model。以下是一个Menu模型的示例,它使用了parent_id来建立父子关系:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Menu extends Model
{
    use HasFactory;

    protected $fillable = ['functional_area','parent_id'];

    public function parent()
    {
        return $this->hasOne(Menu::class, 'id', 'parent_id')->orderBy('sort_order');
    }

    public function children()
    {
        return $this->hasMany(Menu::class, 'parent_id', 'id')->orderBy('sort_order');
    }

    public static function tree()
    {
        return static::with(implode('.', array_fill(0, 100, 'children')))->where('parent_id', '=', '0')->orderBy('sort_order')->get();
    }
}

关键点:

GentleAI
GentleAI

GentleAI是一个高效的AI工作平台,为普通人提供智能计算、简单易用的界面和专业技术支持。让人工智能服务每一个人。

下载
  • parent_id: 用于指定父级菜单的ID。
  • parent(): 定义一个关联到父级菜单的关系。
  • children(): 定义一个关联到子菜单的关系。
  • tree(): 获取所有顶级菜单及其子菜单的静态方法。 implode('.', array_fill(0, 100, 'children')) 保证了无限极的子菜单都被加载,但实际应用中需要考虑性能,限制层级深度。

控制器逻辑

接下来,在控制器中获取菜单数据并传递给视图:

<?php

namespace App\Http\Controllers;

use App\Models\Menu;
use Illuminate\Http\Request;

class MenuController extends Controller
{
    public function getMenu()
    {
        $menuList = Menu::tree();
        return view('index')->with('menulist', $menuList);
    }
}

Menu::tree() 方法用于获取所有顶级菜单及其子菜单,并将其传递给名为 index 的视图。

视图实现:递归渲染菜单

视图部分使用递归的方式来渲染嵌套的下拉菜单。首先创建index.blade.php,该文件包含基本的HTML结构和Bootstrap样式。

<body>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" integrity="sha512-1PKOgIY59xJ8Co8+NE6FZ+LOAZKjy+KY8iq0G4B3CyeY6wYHN3yt9PW0XpSriVlkMXe40PTKnXrLnZ9+fkDaog==" crossorigin="anonymous" />
    <style>
        .dropdown-menu .nav-item a { color: #000 !important; }
        .dropdown-toggle:after { content: none; }
        .dropdown-menu .dropdown-menu { margin-left: 0; margin-right: 0; }
        .dropdown-menu li { position: relative }
        .nav-item .submenu { display: none; position: absolute; left: 100%; top: -7px; }
        .dropdown-menu>li:hover { background-color: #f1f1f1; }
        .dropdown-menu>li:hover>.submenu { display: block; }
    </style>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <a class="navbar-brand"></a>
        <ul class="navbar-nav mr-auto">
            @each('submenu', $menulist, 'menu', 'empty')

        </ul>
    </nav>

    <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
    <script type="text/javascript">

        $(document).on('click', '.dropdown-menu', ($event) => $event.stopPropagation());
        if ($(window).width() < 992) {
            $('.dropdown-menu a').click(($event) => {
                $event.preventDefault();
                if ($(this).next('.submenu').length) {
                    $(this).next('.submenu').toggle();
                }
                $('.dropdown').on('hide.bs.dropdown', () => $(this).find('.submenu').hide());
            });
        }

    </script>
</body>

然后,创建submenu.blade.php,用于递归渲染菜单项:

@if ((count($menu->children) > 0) AND ($menu->parent_id > 0))
<li class="nav-item dropdown">
    <a href="" class="nav-link dropdown-toggle" role="button" data-toggle="dropdown">
        {{ $menu->functional_area }}
        @if(count($menu->children) > 0)
        <i class="fa fa-caret-right"></i>
        @endif
    </a>
    @else
<li class="nav-item @if($menu->parent_id === 0 && count($menu->children) > 0) dropdown @endif">
    <a href="" class="nav-link dropdown-toggle" data-toggle="dropdown">
        {{ $menu->functional_area }}
        @if(count($menu->children) > 0)
            <i class="fa fa-caret-down"></i>
        @endif
    </a>
    @endif
    @if (count($menu->children) > 0)
    <ul class="@if($menu->parent_id !== 0 && (count($menu->children) > 0)) submenu @endif dropdown-menu" aria-labelledby="dropdownBtn">
        @foreach($menu->children as $menu)
        @include('submenu', $menu)
        @endforeach
    </ul>
    @endif
</li>

关键点:

  • 使用 @include('submenu', $menu) 递归调用自身,渲染子菜单。
  • 根据菜单是否有子菜单,动态添加 dropdown 类,以启用 Bootstrap 的下拉菜单功能。
  • $menu->functional_area 显示菜单的名称。
  • 需要注意的是,这里的href=""只是占位符,需要修改为实际的链接。

获取选中ID

目前的代码只是展示了如何生成嵌套下拉菜单。要获取用户选择的菜单项的ID,需要进行以下修改:

  1. 修改链接: 将 submenu.blade.php 中的 <a> 标签的 href 属性修改为包含菜单ID的链接,例如:

    <a href="{{ route('menu.select', ['id' => $menu->id]) }}" class="nav-link">
        {{ $menu->functional_area }}
    </a>
  2. 定义路由: 在 routes/web.php 中定义一个路由来处理菜单选择:

    Route::get('/menu/select/{id}', [MenuController::class, 'select'])->name('menu.select');
  3. 控制器方法: 在 MenuController 中创建一个 select 方法来处理选择的菜单ID:

    public function select($id)
    {
        // 在这里处理选中的菜单ID
        dd($id); // 示例:打印选中的ID
    
        // 可以将ID存储在Session中,或者进行其他操作
        // return redirect()->back();
    }

实现多选

要实现多选功能,可以考虑以下方案:

  1. 使用复选框: 将下拉菜单中的链接改为复选框,用户可以选择多个菜单项。
  2. 使用JavaScript: 在用户点击菜单项时,使用 JavaScript 将选中的菜单ID添加到一个数组中。
  3. 提交表单: 将选中的菜单ID数组通过表单提交到服务器。

注意事项

  • 性能问题: 递归渲染深度嵌套的菜单可能会影响性能。可以考虑使用缓存或分页来优化。
  • 安全性: 确保对用户输入进行验证和转义,以防止跨站脚本攻击(XSS)。
  • 用户体验: 考虑使用户能够方便地浏览和选择菜单项。可以使用搜索、过滤等功能来提高用户体验。
  • 样式定制: 根据项目需求,自定义下拉菜单的样式。

总结

本文介绍了如何在 Laravel 8 中实现嵌套下拉菜单,并获取用户选择的菜单项的ID。通过模型关联和递归视图,可以动态生成下拉菜单。要实现多选功能,可以使用复选框或 JavaScript。在实际应用中,需要注意性能、安全性和用户体验等问题。 可以根据实际需求进行修改和优化,以满足项目的特定要求。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
laravel组件介绍
laravel组件介绍

laravel 提供了丰富的组件,包括身份验证、模板引擎、缓存、命令行工具、数据库交互、对象关系映射器、事件处理、文件操作、电子邮件发送、队列管理和数据验证。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

340

2024.04.09

laravel中间件介绍
laravel中间件介绍

laravel 中间件分为五种类型:全局、路由、组、终止和自定。想了解更多laravel中间件的相关内容,可以阅读本专题下面的文章。

293

2024.04.09

laravel使用的设计模式有哪些
laravel使用的设计模式有哪些

laravel使用的设计模式有:1、单例模式;2、工厂方法模式;3、建造者模式;4、适配器模式;5、装饰器模式;6、策略模式;7、观察者模式。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

773

2024.04.09

thinkphp和laravel哪个简单
thinkphp和laravel哪个简单

对于初学者来说,laravel 的入门门槛较低,更易上手,原因包括:1. 更简单的安装和配置;2. 丰富的文档和社区支持;3. 简洁易懂的语法和 api;4. 平缓的学习曲线。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

385

2024.04.10

laravel入门教程
laravel入门教程

本专题整合了laravel入门教程,想了解更多详细内容,请阅读专题下面的文章。

141

2025.08.05

laravel实战教程
laravel实战教程

本专题整合了laravel实战教程,阅读专题下面的文章了解更多详细内容。

85

2025.08.05

laravel面试题
laravel面试题

本专题整合了laravel面试题相关内容,阅读专题下面的文章了解更多详细内容。

80

2025.08.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

573

2026.03.04

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

CSS教程
CSS教程

共754课时 | 43万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号