我想知道是否可以通过laravels路由模型绑定返回关系?
Say是一个拥有与其他用户“朋友”关系的用户模型,我想从路由或控制器返回用户信息和关系。
例如路线domain.tld/user/123
Route::model('user', 'User');
Route::get('/user/{user}', function(User $user) {
return Response::json($user);
});
这将返回用户信息,但我也想要关系,有没有简单/正确的方法来做到这一点?
我知道我可以做到这一点
Route::get('/user/{user}', function((User $user) {
return Response::json(User::find($user['id'])->with('friends')->get());
});
或
Route::get('/user/{id}', function(($id) {
return Response::json(User::find($id)->with('friends')->get());
});
但我怀疑可能有更好的方法。
答案 0 :(得分:13)
您不希望在每个查询上急切加载关系,例如Matt Burrow建议,只是为了让它在一个上下文中可用。这是低效的。
相反,在您的控制器操作中,您可以在需要时“按需”加载关系。因此,如果您使用路由模型绑定为控制器操作提供User
实例,但您还需要friends
关系,则可以执行以下操作:
class UserController extends Controller
{
public function show(User $user)
{
$user->load('friends');
return view('user.show', compact('user'));
}
}
答案 1 :(得分:12)
您可以在User模型中填充$with
属性。像这样;
protected $with = ['friends'];
这将自动为您自动加载关系数据。
请注意:这将针对每个用户模型查询执行此操作。
如果您不想一直加载朋友,那么您可以将其绑定到路线中的参数,就像这样;
Route::bind('user_id', function($id) {
return User::with('friends')->findOrFail($id);
});
Route::get('/user/{user_id}', 'BlogController@viewPost');
答案 2 :(得分:0)
马丁·宾恩(Martin Bean)的响应可能不是您要解决此问题的方式,仅是因为它为控制器引入了n + 1:
1)它必须通过路由模型绑定来加载User
,然后....
2)现在,它加载了friends
但是,他是正确的,您可能不想每次都加载该关系。
这就是为什么马特·伯罗(Matt Burrow)的解决方案可能更好的原因(他绑定了一个不同的值:可以使用{user}
之类的东西代替{user_with_friends}
并将其与{user}
分开绑定...
我个人认为,如果您只需要为该路由加载friends
,我只需传递$ userId(无绑定),然后以以下方式开始控制器方法:
$user = User::with('friends')->findOrFail($userId);
您可以让Laravel自动处理ModelNotFoundException(就像使用Route Model Binding一样),也可以将其包装在try / catch中