基于Laravel 5.6的多对多关联表Select2搜索栏实现咨询
嘿,我来帮你搞定这个Laravel 5.6的多对多关联+Select2搜索问题!先看看现有代码里的小问题,再一步步调整到符合需求~
Laravel 5.6 多对多关联+Select2搜索实现方案
你当前的项目有COIN(字段id、name)和EVENT(字段id、title、description)两张表,通过中间表coin_event实现多对多关联,需要实现一个带Select2的多选搜索栏,选中币种后返回其关联的所有状态为APROBADO的事件,下面是具体调整方案:
1. 修正模型与迁移的细节
Coin模型
关联方法可以明确指定中间表并开启时间戳维护(可选,但更规范):
// app/Coin.php public function events() { return $this->belongsToMany(Event::class, 'coin_event') ->withTimestamps(); // 自动维护中间表的created_at/updated_at }
Event模型
同理优化关联方法:
// app/Event.php public function coins() { return $this->belongsToMany(Coin::class, 'coin_event') ->withTimestamps(); }
中间表迁移
添加外键约束,保证数据关联的严谨性:
// database/migrations/xxxx_xx_xx_create_coin_event_table.php public function up() { Schema::create('coin_event', function (Blueprint $table) { $table->increments('id'); $table->unsignedInteger('coin_id'); $table->unsignedInteger('event_id'); $table->timestamps(); // 新增外键约束,删除主表记录时自动删除中间表关联数据 $table->foreign('coin_id')->references('id')->on('coins')->onDelete('cascade'); $table->foreign('event_id')->references('id')->on('events')->onDelete('cascade'); }); }
2. 重构PageController的search方法
你原来的方法存在逻辑错误:findMany返回的是集合,无法链式调用查询构造器的orderBy和where。我们直接从Event模型出发,通过关联筛选更高效:
// app/Http/Controllers/PageController.php use Illuminate\Http\Request; use App\Coin; use App\Event; public function search(Request $request) { // 验证请求参数,确保选中的币种ID存在于coins表 $request->validate([ 'coinSearch' => 'required|array|exists:coins,id' ]); // 筛选关联选中币种、状态为APROBADO的事件,按event_at倒序分页 $events = Event::whereHas('coins', function($query) use ($request) { $query->whereIn('coins.id', $request->coinSearch); }) ->where('status', 'APROBADO') ->orderBy('event_at', 'DESC') ->paginate(8); // 获取所有币种用于Select2下拉框 $coins = Coin::all(); return view('welcome', compact('events', 'coins')); }
3. 完善Welcome视图(添加Select2初始化)
你的视图已经有了Select2的HTML结构,但缺少JS初始化,同时修正一些动态数据的硬编码问题:
<form name="form" method="get" class="form" role="form" action="{{ route('search') }}"> {{ csrf_field() }} <div class="form-group"> <select class="select2 select-coin col-12 form-control" id="coinSearch" name="coinSearch[]" multiple="multiple" style="width: 260px;" required> @foreach ($coins as $coin) <!-- 提交后保留选中状态,注意字段名和数据库一致,若你的字段是coin_name则改回 --> <option value="{{ $coin->id }}" {{ in_array($coin->id, old('coinSearch', [])) ? 'selected' : '' }}> {{ $coin->name }} </option> @endforeach </select> <button class="btn btn-rounded btn-info">Buscar</button> </div> </form> <div class="row"> @foreach ($events as $event ) <div class="col-lg-3 col-md-4 col-sm-6 col-xs-12"> <div class="card text-center"> <div class="card-header"> <h5> <strong>{{ \Carbon\Carbon::parse($event->event_at)->toFormattedDateString() }}</strong> <!-- 修正模态框动态数据,替换硬编码内容 --> <a class="reminder" href="#alertReminder" data-toggle="modal" data-target="#alertReminder" data-idevent="{{ $event->id }}" data-date="{{ \Carbon\Carbon::parse($event->event_at)->toFormattedDateString() }}" data-coin="{{ $event->coins->pluck('name')->implode(', ') }}" data-title="{{ $event->title }}"> <i class="far fa-clock"></i> </a> </h5> @foreach ($event->coins as $coin) <h5 style="display: inline;"> <strong><span>{{ $coin->name }} ({{ $coin->coin_symbol }})</span></strong> </h5> @endforeach <h6>{{ $event->title }}</h6> </div> <div class="card-body"> <h5 class="card-title"> <small>(Publicado: {{ \Carbon\Carbon::parse($event->created_at)->toFormattedDateString() }})</small> </h5> <p class="card-text">{{ $event->description }}</p> <a class="btn btn-xs btn-outline-primary waves-effect waves-light proof_modal" href="{{ asset($event->proof) }}"> <span class="btn-label"><i class="fa fa-file-photo-o"></i></span> Prueba </a> <a class="btn btn-xs btn-outline-primary waves-effect waves-light" target="_blank" href="{{ $event->source }}"> <span class="btn-label"><i class="fa fa-external-link-square"></i></span> Fuente </a> </div> <div class="card-footer"> <h6 class="text-footer-card"><small>Publicado por: {{ $event->twitter_account }}</small></h6> @if(empty($event->wallet_address)) <h6 class="text-footer-card"><small>ETH: 0x6e4Cf4b17086cD4Aae40Dbe9cB998d8460F0FbC6</small></h6> @else <h6 class="text-footer-card"><small>{{ $event->wallet_type }}: {{ $event->wallet_address }}</small></h6> @endif </div> </div> <br> </div> @endforeach </div> <div class="text-center"> {{ $events->links() }} </div> <!-- 引入Select2的CSS和JS --> <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" /> <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script> <script> $(document).ready(function() { // 初始化Select2,添加占位提示 $('#coinSearch').select2({ placeholder: "Selecciona una o varias monedas", allowClear: true }); }); </script>
4. 路由配置
别忘了在routes/web.php中添加对应路由:
Route::get('/search', 'PageController@search')->name('search');
这样整个流程就通顺了:用户通过Select2多选币种,提交表单后控制器查询关联这些币种且状态为APROBADO的事件,分页返回给视图展示。
内容的提问来源于stack exchange,提问作者Felipe
相关产品推荐
相关产品推荐

