导出PDF时出现Attempt to read property 'id' on bool错误的解决咨询
问题描述
点击导出PDF按钮时出现错误:Attempt to read property 'id' on bool,已调试控制器中的$data变量,确认能返回指定ID的记录。相关代码如下:
PDFController.php
<?php namespace App\Http\Controllers; use App\Models\Contract; use Illuminate\Http\Request; use Barryvdh\DomPDF\Facade\Pdf; use App\Models\User; use Filament\Infolists\Infolist; class PDFController extends Controller { public function downloadpdf($id) { $contract = Contract::with(['surveys', 'surveys.surveyors', 'surveys.assets']) ->where('id', $id) ->first(); $users = User::all(); $data = [ 'date' => $contract->selesai_kontrak, 'users' => $users, 'contract' => $contract ]; dd($data); $pdf = PDF::loadView('contractPDF', $data); return $pdf->download('ContractDetails.pdf'); } }
contractPDF.blade.php
<!DOCTYPE html> <html> <head> <title>Contract Details</title> </head> <body> <h1>Contract Details</h1> <p>Date: {{ $date }}</p> <div> <h2>Contract ID: {{ $contract->id }}</h2> <p>Pemberi Tugas: {{ $contract->pemberi_tugas }}</p> <p>Jenis Industri: {{ $contract->industries->type }}</p> <p>Tujuan Kontrak: {{ $contract->contract_types->type }}</p> <p>Lokasi Proyek: {{ $contract->lokasi_proyek }}</p> @foreach ($contract->surveys as $survey) <h3>Survey ID: {{ $survey->id }}</h3> <p>Surveyor: {{ $survey->surveyors->name }}</p> <p>Pemilik Aset: {{ $survey->pemilik_aset }}</p> <p>Tanggal Survey: {{ $survey->tanggal_survey }}</p> <p>Jenis Aset: {{ $survey->assets->type }}</p> <p>Keterangan Aset: {{ $survey->keterangan_aset }}</p> <img src="{{ asset('storage/' . $survey->gambar_aset) }}" alt="Gambar Aset"> <p>Harga Aset: Rp. {{ number_format($survey->harga_aset, 0, '.', '.') }}</p> @endforeach </div> </body> </html>
Contract.php
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\BelongsTo; class Contract extends Model { use HasFactory; protected $fillable = [ 'surveyors_id', 'surveys_id', 'pemberi_tugas', 'industries_id', 'contract_types_id', 'lokasi_proyek', 'tanggal_kontrak', 'selesai_kontrak', 'status_kontrak', 'durasi_kontrak', 'is_available', ]; public function surveys(): HasOne { return $this->hasOne(Survey::class); } public function surveyors(): BelongsTo { return $this->belongsTo(Surveyor::class); } public function contract_types(): BelongsTo { return $this->belongsTo(ContractType::class); } public function industries(): BelongsTo { return $this->belongsTo(Industry::class); } public function setStatusKontrakAttribute($value) { $this->attributes['status_kontrak'] = $value; if ($value === 'In Progress') { $this->attributes['is_available'] = 1; } elseif ($value === 'Selesai' || $value === 'Batal') { $this->attributes['is_available'] = 0; } } }
修复方案
1. 关联关系与视图遍历不匹配(核心错误)
Contract模型中surveys定义为HasOne(一对一),但视图里用@foreach遍历该关联。一对一关联返回的是单个模型对象,而非集合,遍历对象时会被当作布尔值处理,触发read property 'id' on bool错误。
分情况修复:
如果是真·一对一关系:
移除视图中的@foreach循环,直接访问关联属性,同时添加空判断:@if($contract->surveys) <h3>Survey ID: {{ $contract->surveys->id }}</h3> <p>Surveyor: {{ $contract->surveys->surveyors->name }}</p> <p>Pemilik Aset: {{ $contract->surveys->pemilik_aset }}</p> <!-- 其他属性同理 --> @endif如果实际是一对多关系:
修改Contract模型的关联定义:public function surveys(): HasMany { return $this->hasMany(Survey::class); }同时核对数据库:确保
surveys表存在contract_id外键(当前模型$fillable中的surveys_id可能是外键方向搞反了,需修正)。
2. 空关联的防御性处理
即使$contract存在,其关联的industries、contract_types等可能为空,直接访问属性会报错。
视图层处理:使用可选链式调用
?->和默认值:<p>Jenis Industri: {{ $contract->industries?->type ?? 'N/A' }}</p> <p>Tujuan Kontrak: {{ $contract->contract_types?->type ?? 'N/A' }}</p>模型层处理:给关联添加默认值,避免空对象报错:
public function industries(): BelongsTo { return $this->belongsTo(Industry::class)->withDefault(['type' => 'N/A']); } public function contract_types(): BelongsTo { return $this->belongsTo(ContractType::class)->withDefault(['type' => 'N/A']); }
3. 控制器优化
- 添加404异常处理,避免ID不存在时的错误:
$contract = Contract::with(['surveys', 'surveys.surveyors', 'surveys.assets', 'industries', 'contract_types']) ->where('id', $id) ->firstOrFail(); // 找不到记录直接返回404 - 预加载
industries和contract_types,避免N+1查询问题。 - 移除调试用的
dd($data),确保代码正常执行。
4. 数据库外键核对
- 一对一关系:确认
contracts表的surveys_id关联到surveys表的id。 - 一对多关系:确认
surveys表的contract_id关联到contracts表的id。
内容的提问来源于stack exchange,提问作者fajar sakti
相关产品推荐
相关产品推荐

