如何使用组合主键为 table 创建 CRUD API
How to create CRUD API for a table with compose primary keys
我有一个 Laravel 服务 CRUD API 的应用程序。有一个 table 组合主键,我在模型和迁移文件中引入了键:
protected $primaryKey = ['personel_id', 'valid_for_quarter'];
我也是这样定义它的路由的:
Route::middleware('auth:api')->group( function () {
Route::apiResources([
'peopleDatas' => 'API\PeopleDataController'
]);
});
和包含 show
方法的控制器 class 如下:
public function show(PeopleData $peopleData)
{
dd($peopleData);
}
现在的问题是:
1.当对象有多个主键时,访问show方法的url是什么?
请注意,我没有自己明确定义路由 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 |
另一方面,在这种情况下我应该明确定义 url 吗?例如 /api/peopleDatas/{key1}/{key2}
或者是否有适用于 Laravel 的任何标准方法?
2. 如果对象有多个主键,Eloquent
和 Laravel Route Model Binding 可以处理它并从数据库中获取项目,或者我需要从用户那里获取 ID 并在我的模型上应用 find
函数?
3. 如果它默认情况下不由 Laravel 本身处理,是否可以覆盖一些函数来告诉 Laravel 如何获取项目在 Route Model Binding
的情况下来自 DB?
有没有理由不能将一个唯一值(例如自增 ID)作为主键,然后将两个附加索引作为唯一复合索引?
这将解决您的路由参数问题,因为您只有一个主键:
/api/peopleDatas/{id}
您的迁移将包括唯一复合索引的规范:
$table->unique(['personel_id', 'valid_for_quarter']);
这样一来,您的组合列将保持唯一性,同时您的路线将简化为单个 ID,并且您的关系也可以使用单个 ID。这将提高性能并简化代码。
或者,如果您绝对必须有一个复合主键,您也可以这样做。您的迁移需要:
$table->primary(['personel_id', 'valid_for_quarter']);
您的模型需要为保存查询设置键(参见 link)
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;
}
路由绑定的最佳解决方案是使用显式路由模型绑定(参见 link 文档),您的参数是两个键的分隔组合:
/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);
});
}
我有一个 Laravel 服务 CRUD API 的应用程序。有一个 table 组合主键,我在模型和迁移文件中引入了键:
protected $primaryKey = ['personel_id', 'valid_for_quarter'];
我也是这样定义它的路由的:
Route::middleware('auth:api')->group( function () {
Route::apiResources([
'peopleDatas' => 'API\PeopleDataController'
]);
});
和包含 show
方法的控制器 class 如下:
public function show(PeopleData $peopleData)
{
dd($peopleData);
}
现在的问题是:
1.当对象有多个主键时,访问show方法的url是什么?
请注意,我没有自己明确定义路由 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 |
另一方面,在这种情况下我应该明确定义 url 吗?例如 /api/peopleDatas/{key1}/{key2}
或者是否有适用于 Laravel 的任何标准方法?
2. 如果对象有多个主键,Eloquent
和 Laravel Route Model Binding 可以处理它并从数据库中获取项目,或者我需要从用户那里获取 ID 并在我的模型上应用 find
函数?
3. 如果它默认情况下不由 Laravel 本身处理,是否可以覆盖一些函数来告诉 Laravel 如何获取项目在 Route Model Binding
的情况下来自 DB?
有没有理由不能将一个唯一值(例如自增 ID)作为主键,然后将两个附加索引作为唯一复合索引?
这将解决您的路由参数问题,因为您只有一个主键:
/api/peopleDatas/{id}
您的迁移将包括唯一复合索引的规范:
$table->unique(['personel_id', 'valid_for_quarter']);
这样一来,您的组合列将保持唯一性,同时您的路线将简化为单个 ID,并且您的关系也可以使用单个 ID。这将提高性能并简化代码。
或者,如果您绝对必须有一个复合主键,您也可以这样做。您的迁移需要:
$table->primary(['personel_id', 'valid_for_quarter']);
您的模型需要为保存查询设置键(参见 link) 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;
}
路由绑定的最佳解决方案是使用显式路由模型绑定(参见 link 文档),您的参数是两个键的分隔组合:
/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);
});
}