Vue+Laravel中如何正确展示存在关联关系的两个模型数据
问题修复方案
核心错误梳理
你当前代码有4个直接导致效果不符合预期的问题:
- Book模型关联定义错误:原本写的是关联
Project模型的project()方法,和你要调用的with('author')预加载完全不匹配,关联根本不会生效 - 前端取值路径错误:Eloquent预加载的关联数据会挂载在和关联方法同名的属性上,你写的
item.author_id.name逻辑完全错误——author_id是存储作者ID的数字型字段,不是对象,无法读取name、mobile属性 - 数据维度错误:你直接遍历所有单本书籍数据,自然每本书都会渲染一个独立的作者工具栏,要实现同作者书籍归到同一卡片的效果,必须先按作者维度对数据分组
- 初始代码逻辑错误:原控制器写了两次return,第一次返回作者列表后,后续查询书籍的代码属于永远不会执行的死代码
分步修复
1. 修正Laravel后端代码
首先修正Book模型的关联定义,替换掉原来错误的project方法:
// app/Models/Book.php public function author() { // 外键字段为author_id,符合Laravel命名约定,第二个参数可省略 return $this->belongsTo(Author::class); }
然后修正控制器代码,去掉死代码,查询时预加载作者关联,同时直接按作者分组返回数据,减少前端处理逻辑:
// 控制器方法 public function index() { $books = Book::with('author')->get(); // 按作者ID分组,聚合同作者的所有书籍 $groupedData = $books->groupBy(fn($book) => $book->author->id) ->map(fn($items) => [ 'author' => $items->first()->author, 'book_list' => $items ])->values(); return response()->json([ 'grouped_books' => $groupedData ], 200); }
2. 修正Vuetify前端代码
调整遍历逻辑,外层遍历作者分组,每个分组渲染一个作者标题栏,内层遍历当前作者下的所有书籍渲染标签:
<v-row dense> <v-col cols="4" md="4" sm="12" v-for="group in grouped_books" :key="group.author.id" > <v-toolbar color="#1565C0" dark dense> <v-toolbar-title>{{ group.author.name }}|{{ group.author.mobile }}</v-toolbar-title> </v-toolbar> <v-card class="mb-5"> <v-card-text> <v-chip class="ma-2" outlined label color="#1565C0" v-for="book in group.book_list" :key="book.id" > {{ book.title }} </v-chip> </v-card-text> </v-card> </v-col> </v-row>
如果不想在后端做分组,也可以前端拿到带author关联的书籍列表后,用
reduce方法按author.id做分组,逻辑和后端处理完全一致。
内容的提问来源于stack exchange,提问作者Edson
相关产品推荐
相关产品推荐

