如何在Eloquent中获取模型及其一对一关联并返回单个对象
解决一对一关联查询并格式化Phone对象的方案
嘿,这事儿不难搞定!咱们分两步走:先把模型间的一对一关联定义清楚,再写查询逻辑就能得到你要的结构了。
第一步:定义模型的一对一关联
首先得在三个模型里分别配置关联关系,这样Eloquent才能正确关联三张表:
1. App\Phone 模型
namespace App; use Illuminate\Database\Eloquent\Model; class Phone extends Model { // 指定表名(如果模型名和表名不一致的话必须加) protected $table = 'phone_table'; // 关联到Model表,一对一关系 public function model() { return $this->belongsTo(Model::class, 'model_id'); } }
2. App\Model 模型
namespace App; use Illuminate\Database\Eloquent\Model; class Model extends Model { protected $table = 'model_table'; // 关联到Manufacturer表,一对一关系 public function manufacturer() { return $this->belongsTo(Manufacturer::class, 'manufacturer_id'); } }
3. App\Manufacturer 模型
namespace App; use Illuminate\Database\Eloquent\Model; class Manufacturer extends Model { protected $table = 'manufacturer_table'; }
第二步:查询并格式化结果
接下来就可以查询数据,并且组装成你需要的App\Phone对象结构了,这里给你两种常用方案:
方案一:直接查询并手动组装(适合简单场景)
用with()预加载关联,避免N+1查询问题,然后提取需要的字段:
// 替换$phoneId为你要查询的手机ID $phone = \App\Phone::with(['model.manufacturer']) ->select('id', 'imei', 'model_id') // 只查询需要的字段,提升性能 ->find($phoneId); // 组装成目标结构 $formattedPhone = (object) [ 'imei' => $phone->imei, 'model' => $phone->model->name, 'manufacturer' => $phone->model->manufacturer->name ];
如果担心关联数据可能不存在(比如某个手机没有绑定型号),可以用optional()避免报错:
$formattedPhone = (object) [ 'imei' => $phone->imei, 'model' => optional($phone->model)->name ?? '未知型号', 'manufacturer' => optional(optional($phone->model)->manufacturer)->name ?? '未知厂商' ];
方案二:使用API资源(推荐,适合重复使用/接口场景)
如果需要在多个地方复用这个格式化逻辑,Laravel的API资源是更优雅的选择:
- 先创建Phone资源:
php artisan make:resource PhoneResource
- 编辑
app/Http/Resources/PhoneResource.php:
namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class PhoneResource extends JsonResource { public function toArray($request) { return [ 'imei' => $this->imei, 'model' => optional($this->model)->name ?? '未知型号', 'manufacturer' => optional(optional($this->model)->manufacturer)->name ?? '未知厂商' ]; } }
- 查询并返回资源:
$phone = \App\Phone::with(['model.manufacturer'])->find($phoneId); return new \App\Http\Resources\PhoneResource($phone);
这样返回的结果就是你想要的结构啦!
内容的提问来源于stack exchange,提问作者Jijo Johny
相关产品推荐
相关产品推荐

