【问题标题】:updateExistingPivot using the primary key instead of the foreign keyupdateExistingPivot 使用主键而不是外键
【发布时间】:2019-11-07 16:52:38
【问题描述】:

我认为这个问题类似于this one,但我也认为我的用例略有不同。

当存在单个用户时,我可以使用updateExistingPivot 成功更新数据透视表;但是,我需要引用id,而不是引用数据透视表上的FK。

我有三个表:usersrolesrole_user

users
    id|name|email

roles
    id|title

role_user
    id|active|user_id|role_id

例如,如果我的应用程序中有两个用户,users 表将如下所示:

id: 1|name: foo|email: fooexample@email.com
id: 2|name: bar|email: barexample@email.com

我的roles 表如下所示:

id: 1|title: fizz
id: 2|title: buzz
id: 3|title: bang

默认情况下,每个用户都有 3 个角色。所以我的role_user 表是这样的:

id: 1|active: true|user_id: 1|role_id: 1
id: 2|active: true|user_id: 1|role_id: 2
id: 3|active: true|user_id: 1|role_id: 3
id: 4|active: true|user_id: 2|role_id: 1
id: 5|active: true|user_id: 2|role_id: 2
id: 6|active: true|user_id: 2|role_id: 3

因为updateExistingPivot 会查看 FK 来决定更新什么,所以对于单个用户来说一切都很好。然而,当我有重复的user_id 和/或role_id FK 的事情开始分崩离析。我需要能够查看数据透视表中的id,而不是查看 FK。

我正在将我的角色从我的控制器传递给一个 vue 组件,如下所示:

// Get the roles(s) that belong to the user.
$roles = $user->roles
    ->sortByDesc('title')
    ->toJson();

我正在屏幕上呈现列表,当用户点击一个角色时,他们可以更新它的状态:

...

async handleRoleClick(event, role) {
    console.log('updating role: ', role);
    try {
        let response = await axios.patch(`/my-path`, {
            active: !this.active,
            id: role.pivot.id,
        });

        // data getting passed is correct.
        // active: false
        // id: 5 <-- the id of the pivot table, not a FK value

        if (response.status === 200) {
            console.log('response.data', response.data);
            this.active = response.data.role.pivot.active;
            console.log('active: ', this.active);
        } else {
            console.error('Error: could not update role. ', response);
        }
    } catch (error) {
        console.error('Error: sending patch request. ', error);
    }
},
...

我的控制器中的更新方法如下所示:

$attributes = request()->validate([
    'active' => 'required',
    'id' => 'required',
]);

// Get the authenticated user.
$user = auth()->user();

// Update the roles' status in the pivot table.
$user->roles()->updateExistingPivot($attributes['id'], $attributes);

// Get the role that was just updated via the relationship.
$role_with_pivot = $user->roles()->where('role_user.id', $attributes['id'])->first();

return response()->json(['role' => $role_with_pivot], 200);

我在请求标头中发送的数据是正确的。我没有收到任何错误,但是我的数据透视表没有收到我传递给它的值。我认为这是因为我没有正确发送 id。在我上面的示例中,它将是id: 5。因为没有5user_id5role_id,Laravel 不确定该怎么做。

如何让 Laravel 查看数据透视表的 id,而不是外键?

【问题讨论】:

  • 为什么不直接发送角色ID,而不是数据透视表的主键?并在您的 vue 请求和响应中使用角色 ID?用户将在数据透视表中拥有唯一的角色行。
  • 如果您知道数据透视表中行的主键?为什么不直接查询数据透视表?

标签: laravel pivot-table laravel-6


【解决方案1】:

我的做法虽然似乎有点粗略。我真的很想看看是否有更多的“Laravel 方式”来做到这一点。上面的其他一切都是一样的,这就是我控制器上的update 方法的样子。

控制器

public function update(Request $request, Role $role)
{
    $attributes = request()->validate([
        'active' => 'required',
        'id' => 'required',
    ]);

    // Get the authenticated user.
    $user = auth()->user();

    // Get the requested role (row) from the pivot table.
    $role = $user->roles()->where('role_user.id', $attributes['id'])->first();

    // Update the requested role.
    $role->pivot->active = $attributes['active'];

    // Save the requested role.
    $role->pivot->save();

    // Get the role that was just updated via it's relationship.
    $role_with_pivot = $user->roles()->where('role_user.id', $attributes['id'])->first();

    return response()->json(['role' => $role_with_pivot], 200);
}

【讨论】:

    【解决方案2】:

    您应该在 View 中检索角色 id 而不是数据透视主键,并使用 role_id 更新数据透视表。

    如上所述,您的用户有多个角色,但只有一个角色和用户 ID 组合。

    async handleRoleClick(event, role) {
        console.log('updating role: ', role);
        try {
            let response = await axios.patch(`/my-path`, {
                active: !this.active,
                id: role.id, //change this
            });
    
            // data getting passed is correct.
            // active: false
            // id: 5 <-- the id of the pivot table, not a FK value
    
            if (response.status === 200) {
                console.log('response.data', response.data);
                this.active = response.data.role.pivot.active;
                console.log('active: ', this.active);
            } else {
                console.error('Error: could not update role. ', response);
            }
        } catch (error) {
            console.error('Error: sending patch request. ', error);
        }
    },
    

    【讨论】:

      猜你喜欢
      • 2010-09-17
      • 2017-02-09
      • 1970-01-01
      • 1970-01-01
      • 2012-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多