Php laravel中的嵌套资源

Php laravel中的嵌套资源,php,laravel,eloquent,Php,Laravel,Eloquent,我正在构建我的API(make和models),我希望有嵌套的资源(不确定从RESTfull的角度来说这是否正确) /品牌/法拉利/车型 /品牌/法拉利/车型/f40 我定义了以下路线 Route::resource('makes.models', 'ModelsController'); 以及ModelsController.php /** * Display a listing of the resource. * * @return \Illuminate\Http\Respons

我正在构建我的API(make和models),我希望有嵌套的资源(不确定从RESTfull的角度来说这是否正确)

/品牌/法拉利/车型 /品牌/法拉利/车型/f40

我定义了以下路线

Route::resource('makes.models', 'ModelsController');
以及ModelsController.php

/**
 * Display a listing of the resource.
 *
 * @return \Illuminate\Http\Response
 */
public function index()
{
    $data = Models::all();
    return response()->json($data);
}

/**
 * Display the specified resource.
 *
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function show($id)
{
    $data = Models::find($id);
    return response()->json($data);
}
还有模型(是的,我需要更改名称)

我的问题是,即使路线有效,它也会返回db中的所有模型(不仅仅是法拉利),我应该在哪里定义这种关系?这不是自动的吗? 我有两个表make(id,name),models(id,name,make\u id)


谢谢大家!

使用嵌套资源时,所有控制器操作都将收到附加的第一个参数(父资源标识符)。因此,您需要相应地更新控制器操作:

public index($make) {
    $make = Make::with('models')->where('name', $make)->firstOrFail();

    return view('models.index', compact('make'));
}

public show($make, $model) {
    $make = Make::with('models')
        ->where('name', $make)
        ->firstOrFail();
    $model = $make->models()
        ->where('name', $make)
        ->firstOrFail();

    return view('models.show', compact('make', 'model'));
}
它应该与其他控制器操作相同


请注意,我对数据库的结构进行了假设。

资源路由将定义以下路由:

Method  Path                               Action 
GET     /makes/{make}/models               index   
GET     /makes/{make}/models/create        create  
POST    /makes/{make}/models               store 
GET     /makes/{make}/models/{id}          show   
GET     /makes/{make}/models/{id}/edit     edit    
PUT     /makes/{make}/models/{id}          update  
DELETE  /makes/{make}/models/{id}          destroy 
您的请求/品牌/法拉利/车型将与这些路线中的任何路线都不匹配(因为您的show参数只接受一个参数)。您可以请求/makes/models/1调用show,但实际上您缺少该调用的路由,因为嵌套路由不提供它

如果你说你总是得到所有的项目,你很可能会点击索引操作而不是显示

如果您想使用/makes/ferari/models/f40查询您的车型,您需要如下路线:

Route::get('/makes/{make}/model/{model}', 'ModelsController@show');
这已经是为您创建的资源路由的一部分。 现在,在show controller中,使用make和model参数查找正确的数据集:

public function show($make, $model)
{
    $data = Model::with('makes')
               ->whereName($model)
               ->whereHas('makes', function ($query) use ($make) {
                                      $query->where('name', '=', $make); 
                                   })->get();

    return response()->json($data);
}
拉威尔不会自动为你这么做

更新:路由模型绑定 您可能想查看一种更复杂的方法来实现这一点。您可以在两个模型中设置路由密钥名称,在本例中覆盖
getRouteKeyName()
方法并返回“name”,告诉Laravel使用name列而不是id

还可以通过执行以下操作将路由中的参数专门绑定到自定义解析逻辑

$router->bind('model', function ($value) {
    return Model::where('name', $value)->first();
});
然后每次在路由中使用
{model}
时,它都会使用名称而不是id

用鼻涕虫 但是,请注意,您必须绝对确保存储在数据库中的model和make的名称是sluggified的,以便它们适合在URL中使用。如有必要,您可以在绑定中执行上述操作,返回

return str_slug(Model::where('name', $value)->first());
然而,这是未经测试的,因此它可能有效,也可能无效

希望有帮助:-)

return str_slug(Model::where('name', $value)->first());