You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 14:17:36