
本文介绍在 Laravel 中通过 Eloquent 关系与 with() 预加载,将 Roles.name 替代 role_id 直接注入用户列表 JSON 响应的标准化实现方式,避免手动数组转换,提升可维护性与性能。
本文介绍在 laravel 中通过 eloquent 关系与 `with()` 预加载,将 `roles.name` 替代 `role_id` 直接注入用户列表 json 响应的标准化实现方式,避免手动数组转换,提升可维护性与性能。
要在 API 响应中返回用户信息的同时展示其角色名称(role_name)而非 role_id,关键在于建立模型关系 + 预加载 + 智能序列化,而非手动 toArray() 或循环拼接。以下是完整、推荐的实践步骤:
✅ 第一步:定义 Eloquent 关系
在 User 模型中声明 belongsTo 关系(因用户属于一个角色):
// app/Models/User.php
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
public function role()
{
return $this->belongsTo(Role::class, 'role_id', 'id');
// 参数说明:关联模型类、外键字段、主键字段(可省略,因默认匹配)
}
}确保 Role 模型存在且结构正确(id, name):
// app/Models/Role.php
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
protected $fillable = ['name'];
}✅ 第二步:预加载关系并直接返回集合
修改控制器方法,使用 with('role') 预加载角色数据,并直接返回 Eloquent 集合 —— Laravel 会自动将其序列化为 JSON,且关系属性会被扁平化为嵌套对象:
// 在控制器中
use App\Models\User;
public function getUserList()
{
$users = User::with('role')->get();
// Laravel 自动调用 toJson(),无需 response()->json() 或 toArray()
return $users;
}此时响应结构为:
[
{
"id": 1,
"name": "Alice",
"role_id": 2,
"role": {
"id": 2,
"name": "Editor"
}
},
{
"id": 2,
"name": "Bob",
"role_id": 1,
"role": {
"id": 1,
"name": "Admin"
}
}
]✅ 进阶:扁平化字段(可选)
若需完全扁平结构(即 role_name 字段与 user_* 同级),可使用 select() + join(),但需谨慎权衡可读性与灵活性:
public function getUserList()
{
return User::select('users.id', 'users.name', 'roles.name as role_name')
->join('roles', 'users.role_id', '=', 'roles.id')
->get();
}⚠️ 注意:此方式失去 Eloquent 模型能力(如访问器、事件、延迟加载),仅适用于纯查询场景。
⚠️ 重要提醒
- ❌ 避免
User::all()->toArray():绕过 Eloquent 关系机制,导致 N+1 查询或手动处理; - ✅ 始终优先使用
with()预加载:防止 N+1 查询,提升性能; - ✅ 信任 Laravel 的 JSON 序列化:Eloquent 集合/模型可直接
return,框架自动处理; - ? 若敏感字段(如密码哈希)需隐藏,请在模型中定义
$hidden属性或使用资源类(ApiResource)进行精细化控制。
通过以上方式,你不仅实现了 user_id, user_name, role_name 的清晰响应,更遵循了 Laravel 的约定优于配置原则,代码简洁、性能可控、易于扩展。


















