如何为具有组合主键的表创建CRUD API

时间:2019-12-17 10:07:19

标签: php laravel eloquent crud

我有一个Laravel应用程序来提供CRUD API。有一个包含组合主键的表,我在模型以及迁移文件中介绍了这些键:

protected $primaryKey = ['personel_id', 'valid_for_quarter'];

我也这样定义它的路线:

Route::middleware('auth:api')->group( function () {
 Route::apiResources([
    'peopleDatas' => 'API\PeopleDataController'
 ]);
});

以及包含show这样的方法的控制器类:

public function show(PeopleData $peopleData)
{
    dd($peopleData);
}  

现在的问题是:

1。。在这种情况下,当对象具有多个主键时,用于访问show方法的URL是什么? 请注意,我没有自己明确定义路由网址,而是想使用Route::apiResources方法。可能吗?

这是路线列表:

|        | GET|HEAD  | api/peopleDatas                         | peopleDatas.index                 | App\Http\Controllers\API\PeopleDataController@index                       | api,auth:api |
|        | POST      | api/peopleDatas                         | peopleDatas.store                 | App\Http\Controllers\API\PeopleDataController@store                       | api,auth:api |
|        | GET|HEAD  | api/peopleDatas/{peopleData}            | peopleDatas.show                  | App\Http\Controllers\API\PeopleDataController@show                        | api,auth:api |
|        | DELETE    | api/peopleDatas/{peopleData}            | peopleDatas.destroy               | App\Http\Controllers\API\PeopleDataController@destroy                     | api,auth:api |
|        | PUT|PATCH | api/peopleDatas/{peopleData}            | peopleDatas.update                | App\Http\Controllers\API\PeopleDataController@update                      | api,auth:api |

在这种情况下,我应该明确定义网址吗?例如/api/peopleDatas/{key1}/{key2}还是Laravel是否有适用的标准方法?

2。。如果对象具有多个主键,EloquentLaravel Route Model Binding可以处理它并从数据库中获取项目,或者我需要从中获取ID用户并在模型上应用find函数?

3。。如果默认情况下,Laravel本身不处理它,是否可以重写某些函数来告诉Laravel在Route Model Binding的情况下如何从数据库中获取项目?

1 个答案:

答案 0 :(得分:1)

是否有一个原因,您不能将一个单一的唯一值(例如自动增量ID)作为主键,然后将两个附加索引作为一个唯一的复合索引?

这将解决您的路由参数问题,因为您只有一个主键:

/api/peopleDatas/{id}

您的迁移将包括唯一复合索引的说明:

$table->unique(['personel_id', 'valid_for_quarter']);

这样,您的组合列将保持唯一性,同时将路由简化为单个ID,并且您的关系也可以使用单个ID。这样可以提高性能并简化代码。

或者,如果您绝对必须具有复合主键,则可以这样做。您的迁移需要:

$table->primary(['personel_id', 'valid_for_quarter']);

您的模型需要为保存查询设置键(请参阅链接) https://blog.maqe.com/solved-eloquent-doesnt-support-composite-primary-keys-62b740120f

protected function setKeysForSaveQuery(Builder $query)
{
    $query
        ->where('personel_id', '=', $this->getAttribute('personel_id'))
        ->where('valid_for_quarter', '=', $this->getAttribute('valid_for_quarter'));

    return $query;
}

路由绑定的最佳解决方案是采用显式路由模型绑定(请参阅docs链接),并且您的参数是两个键的定界组合:

/api/peopleDatas/{people_data},其中人员数据= 1_3

https://laravel.com/docs/5.8/routing#explicit-binding

在您的路线服务提供商中,您需要指定解析逻辑,例如:

public function boot()
{
    parent::boot();

    Route::bind('people_data', function ($value) {
        return App\PeopleData::where('personal_id', explode('_', $value)[0])
            ->where('valid_for_quarter',  explode('_', $value)[1])
            ->first() ?? abort(404);
    });
}
相关问题