【问题标题】:API RESTful Laravel 6.x Best Practice for Many to Many RelatioshipAPI RESTful Laravel 6.x 多对多关系最佳实践
【发布时间】:2020-05-22 15:21:43
【问题描述】:

我正在使用 Laravel 6 开发一个 API。

我有 2 个模型:

card -> 带有 card_id ecc 的表格卡片。

user -> 具有 user_id ecc 的表 users。

我已经在模型中定义了多对多关系

用户.php

public function cards()
{
    return $this->belongsToMany('App\Models\v1\Card');
}

卡片.php

public function users() {
    return $this->belongsToMany('App\Models\v1\User');
}

数据透视表称为 card_user 。

现在我已经为单个实体创建了路由:

Route::resource('v1/users', 'v1\UsersController');
Route::resource('v1/cards', 'v1\CardsController');

我需要开发用于从数据透视表中插入和删除行的路由和控制器。

解决此问题的最佳做法是什么?

我尝试使用响应特定端点的特殊控制器来解决这个问题:

Route::resource('v1/cards/{id}/users', 'v1\CardsUsersController')->only([
    'index', 'store', 'destroy'
]);

但是当我需要存储信息时,我需要将卡片和用户的 ID 传递到 URL 中,并作为帖子正文中的对象,如下所示:

[
    'user_id' => $userId,
    'card_id' => $cardId
]

有更好的方法吗?

非常感谢!

【问题讨论】:

  • 你需要分享UsersUsersControllerCardsUsersController

标签: laravel rest api


【解决方案1】:

您可以按照此处所述使用嵌套资源: https://laravel.com/docs/6.x/controllers#restful-nested-resources

“有时您可能需要定义到“嵌套”资源的路由。例如,一个照片资源可能有多个“cmets”可以附加到照片上。要“嵌套”资源控制器,请使用“点”表示法在您的路线声明中:

Route::resource('photos.comments', 'PhotoCommentController');

此路由将注册一个“嵌套”资源,可以使用以下 URL 访问该资源:photos/{photos}/cmets/{cmets}。”

【讨论】:

    【解决方案2】:

    如果您必须为它们设置单独的路由和控制器,那么最好这样做

    Route::resource('v1/card_user', 'v1\CardsUsersController')->only(['index', 'store','destroy']);
    

    保持路线整洁,不要过于复杂。您或将来查看代码的其他人应该能够理解它的用途。

    【讨论】:

    • 标准方式是使用resource/id/sub-resource/sub-resource-id
    • 谢谢!我可以从路线返回什么样的资源?我创建了一个 CardUser 资源并返回如下内容: {#1279 +"card_user": {#1216 +"card_id": 1 +"card_code": "95196" +"enabled": 1 +"users": array :1 [ 0 => {#1272 +“id”:1 +“last_name”:“Lubowitz”+“first_name”:“Beau”+“用户名”:“beau.lubowitz”}]}+“状态”:“成功" +"代码": 201 }
    • @RobertoBani 如果您按照我的示例进行操作,那么您的 CardUser 资源应该同时具有 card 和 user 作为 serate 实体。顺便说一句,这似乎不是标准方法,所以我认为你应该使用 Devons 的答案来获得最佳实践。我建议这种方法是因为我个人更喜欢保持 url 的简短。 This question将帮助您更好地理解
    【解决方案3】:

    我会结合这两个答案。作为一种关系,它在技术上是一种嵌套资源。此外,您确实有 2 个 RESTful 操作:存储和销毁(对应于 Laravel 中的附加和分离)。您可能还需要一个索引来查看所有关系。我相信“创建”操作是可选的,具体取决于您的 UI。

    // Ability_Role pivot routes
    Route::resource('v1/user.cards', 'UserCardController')
      ->only(['index', 'create', 'store','destroy']);
    

    这将给出以下路线:

    +--------+----------+------------------------------+--------------------+-------------------------------------------------+------------+
    | Domain | Method   | URI                          | Name               | Action                                          | Middleware |
    +--------+----------+------------------------------+--------------------+-------------------------------------------------+------------+
    |        | GET|HEAD | v1/user/{user}/cards         | user.cards.index   | App\Http\Controllers\UserCardController@index   | web        |
    |        | POST     | v1/user/{user}/cards         | user.cards.store   | App\Http\Controllers\UserCardController@store   | web        |
    |        | GET|HEAD | v1/user/{user}/cards/create  | user.cards.create  | App\Http\Controllers\UserCardController@create  | web        |
    |        | DELETE   | v1/user/{user}/cards/{card}  | user.cards.destroy | App\Http\Controllers\UserCardController@destroy | web        |
    +--------+----------+------------------------------+--------------------+-------------------------------------------------+------------+
    

    我选择将路线标记为 user.cards,因为我认为您更经常希望从用户模型开始并附加卡片。

    对于 store 方法,您可以发布一组卡片以附加给用户。

    如果您还想从卡片开始,并存储一组用户,您还可以定义反向关系(尽管它需要一个仅包含创建和存储路由的第二个控制器:

    // Inverse create and store routes
    Route::get('v1/cards/{card}/users/create', 'CardUserController@create')
      ->name('cards.users.create');
    Route::post('v1/cards/{card}/users', 'CardUserController@store')
      ->name('cards.users.store');
    

    现在您将获得另外 2 条路线:

    +--------+----------+------------------------------+--------------------+-------------------------------------------------+------------+
    | Domain | Method   | URI                          | Name               | Action                                          | Middleware |
    +--------+----------+------------------------------+--------------------+-------------------------------------------------+------------+
    |        | GET|HEAD | api/user                     | api.               | Closure                                         | api        |
    |        |          |                              |                    |                                                 | auth:api   |
    |        | POST     | v1/cards/{card}/users        | cards.users.store  | App\Http\Controllers\CardUserController@store   | web        |
    |        | GET|HEAD | v1/cards/{card}/users/create | cards.users.create | App\Http\Controllers\CardUserController@create  | web        |
    |        | GET|HEAD | v1/user/{user}/cards         | user.cards.index   | App\Http\Controllers\UserCardController@index   | web        |
    |        | POST     | v1/user/{user}/cards         | user.cards.store   | App\Http\Controllers\UserCardController@store   | web        |
    |        | GET|HEAD | v1/user/{user}/cards/create  | user.cards.create  | App\Http\Controllers\UserCardController@create  | web        |
    |        | DELETE   | v1/user/{user}/cards/{card}  | user.cards.destroy | App\Http\Controllers\UserCardController@destroy | web        |
    +--------+----------+------------------------------+--------------------+-------------------------------------------------+------------+
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-30
      • 1970-01-01
      • 2013-08-08
      相关资源
      最近更新 更多