Laravel 9:隐藏无图片的Bootstrap 5空轮播组件
Laravel 9 项目轮播组件问题修复
问题背景
开发Laravel 9项目,使用Images和Projects两张表存储项目及图片数据,在实现页面展示每个项目的图片轮播时遇到两个问题:
- 点击任意轮播的左右控制按钮,页面中所有轮播会同时切换图片;
- 无对应图片的项目会显示空轮播,需要隐藏这类空容器。
数据库表结构
Images表
CREATE TABLE IF NOT EXISTS `images` ( `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, `name` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `path` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `project_id` bigint(20) UNSIGNED DEFAULT NULL, `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), KEY `images_project_id_foreign` (`project_id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;
Projects表
CREATE TABLE IF NOT EXISTS `projects` ( `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, `description` text COLLATE utf8mb4_unicode_ci NOT NULL, `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;
现有Blade视图代码
<div class="col-sm-8" style="background: rgba(204, 204, 204, 0.5);padding:5%;width:100%;"> <div class="row"> <h3 style="text-align: center">Galeries de nos réalisations</h3> <br> </div> @foreach ($projects as $project) <div class="row"> <!-- Carousel --> <div id="demo" class="carousel slide" data-bs-ride="carousel" style="width:70%;display: block; margin-left: auto; margin-right: auto;"> <!-- The slideshow/carousel --> <div class="carousel-inner"> @php($cpt = 0) @foreach($images as $image) @if ($image->project_id==$project->id) @if ($cpt == 0) <div class="carousel-item active"> <img src="<?php echo $image->path; ?>" alt="photo" class="d-block w-100"/> </div> @php($cpt++) @else <div class="carousel-item"> <img src="<?php echo $image->path; ?>" alt="photo" class="d-block w-100"/> </div> @php($cpt++) @endif @endif @endforeach </div> <!-- Left and right controls/icons --> <button class="carousel-control-prev" type="button" data-bs-target="#demo" data-bs-slide="prev"> <span class="carousel-control-prev-icon"></span> </button> <button class="carousel-control-next" type="button" data-bs-target="#demo" data-bs-slide="next"> <span class="carousel-control-next-icon"></span> </button> </div> </div> <div class="row"> <p><?php echo $project->description; ?></p> </div> @role('user')<!--Super-Admin--> <!-- Container (Contact Section) --> <div id="contact" class="row"> <h1 class="text-center" style="margin-top: 100px">Image Upload</h1> @if ($message = Session::get('success')) <div class="alert alert-success alert-block"> <strong>{{$message}}</strong> </div> @endif <form method="POST" action="{{ route('image.store') }}" enctype="multipart/form-data"> @csrf <input type="file" class="form-control" name="image" /> <input type="hidden" id="version" name="project_id" value="{{ $project->id }}" /> <button type="submit" class="btn btn-sm">Upload</button> </form> </div> @endrole <!--Create project --> @endforeach <div class="row"> <form method="POST" action="{{ route('projects.store') }}" enctype="multipart/form-data"> @csrf <label for="desc">Description:</label> <input type="text" id="desc" name="description"><br><br> <button type="submit" class="btn btn-sm">Upload</button> </form> </div> </div> @endsection
问题解决方案
1. 修复所有轮播同步切换的问题
问题根源:所有轮播容器的id均为demo,控制按钮的data-bs-target也指向#demo,导致点击时所有匹配该选择器的轮播都会响应。
修复方式:给每个轮播生成唯一标识,用项目ID作为后缀:
- 将轮播容器的
id="demo"改为id="carousel-{{ $project->id }}" - 将控制按钮的
data-bs-target="#demo"改为data-bs-target="#carousel-{{ $project->id }}"
2. 修复空轮播显示的问题
问题根源:无论项目是否有图片,都会渲染轮播容器。推荐结合Eloquent关联优化查询,同时在视图中判断是否显示轮播:
步骤1:定义模型关联
在Project模型中添加关联方法:
public function images() { return $this->hasMany(Image::class); }
步骤2:控制器预加载图片
查询项目时预加载关联的图片,避免视图中循环所有图片:
$projects = \App\Models\Project::with('images')->get();
步骤3:视图中判断渲染轮播
仅当项目存在图片时,才渲染轮播容器:
@foreach ($projects as $project) @if($project->images->isNotEmpty()) <div class="row"> <div id="carousel-{{ $project->id }}" class="carousel slide" data-bs-ride="carousel" style="width:70%;display: block; margin-left: auto; margin-right: auto;"> <div class="carousel-inner"> @foreach($project->images as $index => $image) <div class="carousel-item {{ $index === 0 ? 'active' : '' }}"> <img src="{{ $image->path }}" alt="photo" class="d-block w-100"/> </div> @endforeach </div> <button class="carousel-control-prev" type="button" data-bs-target="#carousel-{{ $project->id }}" data-bs-slide="prev"> <span class="carousel-control-prev-icon"></span> </button> <button class="carousel-control-next" type="button" data-bs-target="#carousel-{{ $project->id }}" data-bs-slide="next"> <span class="carousel-control-next-icon"></span> </button> </div> </div> @endif <!-- 项目描述、上传表单等代码保留 --> @endforeach
优化后的完整视图代码
<div class="col-sm-8" style="background: rgba(204, 204, 204, 0.5);padding:5%;width:100%;"> <div class="row"> <h3 style="text-align: center">Galeries de nos réalisations</h3> <br> </div> @foreach ($projects as $project) {{-- 仅渲染有图片的项目轮播 --}} @if($project->images->isNotEmpty()) <div class="row"> <div id="carousel-{{ $project->id }}" class="carousel slide" data-bs-ride="carousel" style="width:70%;display: block; margin-left: auto; margin-right: auto;"> <div class="carousel-inner"> @foreach($project->images as $index => $image) <div class="carousel-item {{ $index === 0 ? 'active' : '' }}"> <img src="{{ $image->path }}" alt="photo" class="d-block w-100"/> </div> @endforeach </div> <button class="carousel-control-prev" type="button" data-bs-target="#carousel-{{ $project->id }}" data-bs-slide="prev"> <span class="carousel-control-prev-icon"></span> </button> <button class="carousel-control-next" type="button" data-bs-target="#carousel-{{ $project->id }}" data-bs-slide="next"> <span class="carousel-control-next-icon"></span> </button> </div> </div> @endif <div class="row"> <p>{{ $project->description }}</p> </div> @role('user')<!--Super-Admin--> <div id="contact-{{ $project->id }}" class="row"> <h1 class="text-center" style="margin-top: 100px">Image Upload</h1> @if ($message = Session::get('success')) <div class="alert alert-success alert-block"> <strong>{{$message}}</strong> </div> @endif <form method="POST" action="{{ route('image.store') }}" enctype="multipart/form-data"> @csrf <input type="file" class="form-control" name="image" /> <input type="hidden" id="version" name="project_id" value="{{ $project->id }}" /> <button type="submit" class="btn btn-sm">Upload</button> </form> </div> @endrole @endforeach <div class="row"> <form method="POST" action="{{ route('projects.store') }}" enctype="multipart/form-data"> @csrf <label for="desc">Description:</label> <input type="text" id="desc" name="description"><br><br> <button type="submit" class="btn btn-sm">Upload</button> </form> </div> </div> @endsection
内容的提问来源于stack exchange,提问作者varius
相关产品推荐
相关产品推荐

