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

Laravel中如何基于work type的foreignId二次筛选关联表内容?

问题描述

现有pekerjaan(工作)与jeniskerja(工作类型)两张表,Eloquent关联关系为:jeniskerja hasMany pekerjaan、pekerjaan belongsTo jeniskerja。目前已通过penyedia(供应商)的外键展示对应工作列表,需实现点击工作类型卡片标题时,展开并展示该类型下的工作列表。

当前代码如下:

控制器代码(AdminController)

public function showpenyedia(Penyedia $penyedia){
        $pekerjaan = $penyedia->pekerjaans; // 根据供应商展示对应工作

        $jeniskerja = Jeniskerja::all();
        
        return view('admin.showpenyedia', compact('penyedia','pekerjaan','jeniskerja'));
    }

视图代码(detailpenyedia.php)

@foreach ($jeniskerja as $jeniskerjas)
<section class="content">
  <div class="container-fluid">
    <div class="card card-default collapsed-card">
      <div class="card-header collapsed-card">
        <h3 class="card-title">
          <b>{{$jeniskerjas->nama_jenis}}</b> <!-- 显示工作类型名称 -->
        </h3>
    
        <div class="card-tools">
          <button type="button" class="btn btn-tool" data-card-widget="collapse">
            <i class="fas fa-plus"></i>
          </button>
        </div>
      </div>
      <div class="card-body table-responsive">
        <table id="tabelpekerjaan" class="table table-bordered">
          <thead>
            <tr>
              <th style="width: 10px" rowspan="2">年度预算</th>
              <th rowspan="2">合同日期</th>
              <th rowspan="2">工作包</th>
              <th rowspan="2">公司名称</th>
              <th rowspan="2">工作地点</th>
              <th rowspan="2">工作类型</th>
              <th rowspan="2">HPS</th>
              <th rowspan="2">金额</th>
              <th rowspan="2">文档</th>
              <th colspan="2">日期</th>
            </tr>

            <tr>
              <td>创建日期</td>
              <td>更新日期</td>
            </tr>
          </thead>
          <tbody>
            @php $no = 1; /*$totalNilai = 0.0;*/ @endphp
            @foreach ($pekerjaan as $pekerjaans)
            <tr>
              <td>{{$pekerjaans->tanggal->format('Y')}}</td>
              <td>{{$pekerjaans->tanggal->format('d/m/Y')}}</td>
              <td>{{$pekerjaans->pekerjaan}}</td>
              <td>{{$pekerjaans->penyedia->nama}}</td>
              <td>{{$pekerjaans->lokasi}}</td>
              <td>{{$pekerjaans->jeniskerja->nama_jenis}}</td>
              <td>Rp. {{number_format($pekerjaans->hps,0,',',',')}}</td>
              @php
              $pekerjaans->nilai_total = $pekerjaans->nilai_1 + $pekerjaans->nilai_2 + $pekerjaans->nilai_3 + $pekerjaans->nilai_4;
              @endphp
              <td>{{$pekerjaans->nilai_total}}</td>
              <td><a href="{{ route('pekerjaans.download', $pekerjaans->id) }}"><u>{{$pekerjaans->status}}</u></a></td>
              <td></td>
              <td></td>
            </tr>
            @endforeach
          </tbody>
        </table>
      </div>
    </div>
  </div>
</section>
@endforeach  
解决方法

1. 优化控制器查询逻辑

修改控制器,预加载每个工作类型下属于当前供应商的工作,避免N+1查询,同时减少不必要的数据传递:

public function showpenyedia(Penyedia $penyedia){
    // 预加载工作类型,并筛选出当前供应商的对应工作
    $jeniskerja = Jeniskerja::with(['pekerjaans' => function($query) use ($penyedia) {
        $query->where('penyedia_id', $penyedia->id);
    }])->get();
    
    return view('admin.showpenyedia', compact('penyedia','jeniskerja'));
}

2. 调整视图展示逻辑

修改视图,让每个工作类型卡片只展示该类型下的工作,同时优化折叠组件行为:

@foreach ($jeniskerja as $jeniskerjaItem)
<section class="content">
  <div class="container-fluid">
    {{-- 只显示有对应工作的类型卡片 --}}
    @if($jeniskerjaItem->pekerjaans->isNotEmpty())
    <div class="card card-default collapsed-card">
      <div class="card-header" data-card-widget="collapse">
        <h3 class="card-title">
          <b>{{$jeniskerjaItem->nama_jenis}}</b>
          {{-- 添加工作数量徽章 --}}
          <span class="badge bg-primary ml-2">{{$jeniskerjaItem->pekerjaans->count()}}</span>
        </h3>
    
        <div class="card-tools">
          <button type="button" class="btn btn-tool">
            <i class="fas fa-plus"></i>
          </button>
        </div>
      </div>
      <div class="card-body table-responsive">
        <table class="table table-bordered">
          <thead>
            <tr>
              <th style="width: 10px" rowspan="2">年度预算</th>
              <th rowspan="2">合同日期</th>
              <th rowspan="2">工作包</th>
              <th rowspan="2">公司名称</th>
              <th rowspan="2">工作地点</th>
              <th rowspan="2">工作类型</th>
              <th rowspan="2">HPS</th>
              <th rowspan="2">总金额</th>
              <th rowspan="2">文档</th>
              <th colspan="2">日期</th>
            </tr>
            <tr>
              <td>创建日期</td>
              <td>更新日期</td>
            </tr>
          </thead>
          <tbody>
            @php $no = 1; @endphp
            @foreach ($jeniskerjaItem->pekerjaans as $pekerjaan)
            <tr>
              <td>{{$pekerjaan->tanggal->format('Y')}}</td>
              <td>{{$pekerjaan->tanggal->format('d/m/Y')}}</td>
              <td>{{$pekerjaan->pekerjaan}}</td>
              <td>{{$pekerjaan->penyedia->nama}}</td>
              <td>{{$pekerjaan->lokasi}}</td>
              <td>{{$pekerjaan->jeniskerja->nama_jenis}}</td>
              <td>Rp. {{number_format($pekerjaan->hps,0,',',',')}}</td>
              @php
              $totalNilai = $pekerjaan->nilai_1 + $pekerjaan->nilai_2 + $pekerjaan->nilai_3 + $pekerjaan->nilai_4;
              @endphp
              <td>{{$totalNilai}}</td>
              <td><a href="{{ route('pekerjaans.download', $pekerjaan->id) }}"><u>{{$pekerjaan->status}}</u></a></td>
              <td>{{$pekerjaan->created_at->format('d/m/Y')}}</td>
              <td>{{$pekerjaan->updated_at->format('d/m/Y')}}</td>
            </tr>
            @endforeach
          </tbody>
        </table>
      </div>
    </div>
    @endif
  </div>
</section>
@endforeach

关键调整说明

  • 移除card-header上重复的collapsed-card类,确保Bootstrap折叠组件正常触发
  • 添加工作数量徽章,提升用户体验
  • 过滤无对应工作的类型卡片,避免空卡片占用空间
  • 补全创建/更新日期的显示逻辑
  • 优化变量命名,提升代码可读性

内容的提问来源于stack exchange,提问作者YuPi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 11:45:29