
本文教你如何在 laravel blade 模板中正确显示外键关联的原始数据(如 city_id 对应的 city_name),避免原生 sql 查询,推荐使用 eloquent 预加载关系,并安全访问关联模型属性。
本文教你如何在 laravel blade 模板中正确显示外键关联的原始数据(如 city_id 对应的 city_name),避免原生 sql 查询,推荐使用 eloquent 预加载关系,并安全访问关联模型属性。
在 Laravel 开发中,直接使用 DB::select() 查询原始数据虽可行,但会丢失模型关系能力,无法自然访问外键所指向的关联记录(如 city_id 对应的 City 名称)。正确做法是完全切换至 Eloquent ORM,利用其关系定义与预加载机制,实现清晰、高效、可维护的前后端数据绑定。
✅ 正确做法:用 Eloquent 替代原生查询
首先修正 Villa 模型中的关系定义。当前代码中 hasOne() 的参数顺序有误 —— hasOne(RelatedModel, foreignKey, localKey) 的标准用法应为:
// ✅ 正确写法(city_id 是 villa 表中的外键,指向 cities.id)
public function city()
{
return $this->belongsTo(City::class, 'city_id', 'id');
}
public function seller()
{
return $this->belongsTo(Seller::class, 'seller_id', 'id');
}
public function payment()
{
return $this->belongsTo(Payment::class, 'payment_id', 'id');
}
⚠️ 注意:
Villa属于City(一个 villa 属于一个 city),因此应使用belongsTo(),而非hasOne();同时方法名建议小驼峰(如city),符合 Laravel 命名惯例,便于后续调用。
接着更新控制器,弃用 DB::select(),改用 Eloquent 预加载(with()),一次性获取主数据及关联数据,避免 N+1 查询:
// App\Http\Controllers\WebsiteController.php
public function index()
{
// 预加载 city、seller、payment 关系,提升性能
$villas = Villa::with(['city', 'seller', 'payment'])->get();
return view('website', ['villas' => $villas]);
}
✅ 在 Blade 中安全访问关联字段
在 website.blade.php 中,即可通过点语法访问关联模型的属性。但务必添加空值检查,防止因关联记录缺失导致报错:
@foreach ($villas as $villa)
<div class="villa-block">
<a href="single-villa.html" id="villaname">{{ old('name', $villa->title) }}</a>
<a href="#" id="villaLocation">
{{ $villa->city?->name ?? '未知城市' }}
</a>
<span>卖家:{{ $villa->seller?->name ?? '未指定' }}</span>
<span>付款方式:{{ $villa->payment?->method ?? '未设置' }}</span>
</div>
@endforeach
-
?->是 PHP 空合并安全调用操作符(PHP 8.0+),若$villa->city为null,则跳过->name调用; -
??提供默认回退值,增强页面健壮性。
? 补充说明与最佳实践
-
不要在
fillable中包含id和时间戳字段:Laravel 默认已处理主键和created_at/updated_at,显式声明id可能引发意外批量赋值风险; -
数据库外键约束建议启用:在迁移文件中添加
foreignId('city_id')->constrained()->onDelete('set null'),确保数据一致性; -
如需分页,直接链式调用:
Villa::with([...])->paginate(12),Blade 中用{{ $villas->links() }}渲染分页控件; -
调试技巧:开发时可用
dd($villas->first())查看实际加载的关联结构,确认city,seller等是否为App\Models\City实例。
通过以上重构,你不仅解决了“显示城市名”的具体问题,更建立了符合 Laravel 设计哲学的数据访问模式:语义清晰、性能可控、错误可防。这才是面向模型(而非表)开发的真正起点。











