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

导出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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 13:43:27