Laravel关联3张表实现借阅视图报错排查与解决
图书借阅关联数据展示问题排查与实现
问题背景
数据库包含三张表:
users:id、name(string)、email(string)、username(string)、password(string)bukus:id、nama_buku(string)、cover(string)、author(string)、barcode(string)bukus_users(多对多中间表):id、bukus_id(bigint)、users_id(bigint)、tgl_pinjam(datetime)、tgl_tenggat(datetime)、status(boolean)
需求:在视图中展示借阅数据,将bukus_id替换为图书名称nama_buku,users_id替换为用户的name/email/username,生成包含序号、用户信息、图书名称、借阅日期、到期日期、状态的表格。
遇到的错误:
- SQL错误:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'bukus.bukus_users_id' in 'field list' - 属性读取错误:
Attempt to read property "user" on int
错误原因分析
- 第一个SQL错误:Eloquent多对多关联定义时未指定正确外键,Laravel默认按模型名生成外键(如
bukus_users_id),但实际中间表字段为bukus_id和users_id,导致关联查询找错字段。 - 第二个属性错误:直接将
users_id这类int类型的字段值当作关联对象调用(如$item->user),但字段值并非关联模型实例。
修正后的代码实现
1. Eloquent模型定义
User.php(用户模型)
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class User extends Model { protected $table = 'users'; // 与图书的多对多关联 public function bukues(): BelongsToMany { return $this->belongsToMany(Buku::class, 'bukus_users', 'users_id', 'bukus_id') ->withPivot('tgl_pinjam', 'tgl_tenggat', 'status', 'id'); // 包含中间表额外字段 } }
Buku.php(图书模型)
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class Buku extends Model { protected $table = 'bukus'; protected $primaryKey = 'id'; // 与用户的多对多关联 public function users(): BelongsToMany { return $this->belongsToMany(User::class, 'bukus_users', 'bukus_id', 'users_id') ->withPivot('tgl_pinjam', 'tgl_tenggat', 'status', 'id'); } }
BukuUser.php(中间表模型,用于直接操作借阅记录)
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; class BukuUser extends Model { protected $table = 'bukus_users'; protected $fillable = ['bukus_id', 'users_id', 'tgl_pinjam', 'tgl_tenggat', 'status']; // 关联用户模型 public function user(): BelongsTo { return $this->belongsTo(User::class, 'users_id'); } // 关联图书模型 public function buku(): BelongsTo { return $this->belongsTo(Buku::class, 'bukus_id'); } }
2. PinjamController控制器代码
namespace App\Http\Controllers; use App\Models\BukuUser; use Illuminate\Http\Request; class PinjamController extends Controller { public function index() { // 预加载用户和图书关联,避免N+1查询问题 $pinjams = BukuUser::with(['user', 'buku'])->get(); return view('admin.pinjam.index', compact('pinjams')); } }
3. 视图文件(admin/pinjam/index.blade.php)
<div class="container"> <h1>Daftar Peminjaman Buku</h1> <table class="table table-bordered"> <thead> <tr> <th>No</th> <th>Informasi Pengguna</th> <th>Nama Buku</th> <th>Tanggal Pinjam</th> <th>Tanggal Tenggat</th> <th>Status</th> </tr> </thead> <tbody> @foreach($pinjams as $item) <tr> <td>{{ $loop->iteration }}</td> <td> Nama: {{ $item->user->name }}<br> Email: {{ $item->user->email }}<br> Username: {{ $item->user->username }} </td> <td>{{ $item->buku->nama_buku }}</td> <td>{{ $item->tgl_pinjam->format('d-m-Y H:i') }}</td> <td>{{ $item->tgl_tenggat->format('d-m-Y H:i') }}</td> <td> @if($item->status) <span class="badge bg-success">Sudah Kembali</span> @else <span class="badge bg-danger">Belum Kembali</span> @endif </td> </tr> @endforeach </tbody> </table> </div>
关键说明
- 中间表模型
BukuUser使用belongsTo关联用户和图书,而非多对多的belongsToMany,可直接查询中间表所有字段并关联对应模型。 - 控制器中用
with(['user', 'buku'])预加载关联,避免循环查询时产生大量SQL请求。 - 视图中通过
$item->user和$item->buku访问关联模型属性,而非直接操作users_id或bukus_id字段。
内容的提问来源于stack exchange,提问作者Kholid Syaifullah
相关产品推荐
相关产品推荐

