首页 > 解决方案 > 在 Laravel 中更新模型关系

问题描述

在我的 Laravel 应用程序中,我在 aUser和 a之间有一个链接,Team其中表中的department字段与表中的字段users相关。nameteams

这由给定的关系表示:

/**
 * Specify that a user belongs to only one team
 *
 * @return void
 */
public function team()
{
    return $this->belongsTo(Team::class, 'department', 'name');
}

显然,这种方法的一个问题是,如果您更改团队名称,那么用户就会成为孤儿。

为了纠正这个问题,我尝试了以下方法:

/**
 * Update this team in the database
 * If the team name changes also update the associated users
 *
 * @param Team $team
 * @return void
 */
public function update(UpdateTeam $request, Team $team)
{
    $data = $request->validated();

    if ($data['name'] != $team->name) {
        foreach ($team->users as $user) {

            $user->fill([
                'department' => $data['name'],
            ])->save();
        }
    }

    $team->fill($data)->save();
}

但在User模型中我也有这个访问器:

/**
 * Get a direct link to this user's profile using the global route helper
 */
public function getProfilePageAttribute()
{
    return $this->department ? route('profile.show', [$this->team->slug, $this->username]) : null;
}

当我更新团队名称时,这会引发错误,因为在更改期间$this->team有效null

我有一个TeamObserver并试图将此行为与updating事件挂钩,但关系$team->users也会返回null,因为它将使用当前属性而不是旧属性。

如果不将团队名称映射到用户表中的 id,有什么办法可以解决这个问题吗?主要是因为提供的数据使用名称作为部门。

是否可以在更新时告诉关系使用旧属性?

标签: phpmysqllaravel

解决方案


在您的模式中,在两个表之间添加一个外键约束,使用ON UPDATE CASCADE(也许ON DELETE SET NULL是?),这样可以确保用户部门的名称始终与父部门的值相同(部门名称)。

对于用户表的架构(迁移),添加外键

$table->foreign('department')
      ->references('name')
      ->on('teams')
      ->onUpdate('cascade')
      // ->onDelete('set null');

请记住,引用的两个列 (users.departmentteams.name) 必须是完全相同的类型和长度。数据也不能不匹配(意味着用户不能是不存在于 中的部门的成员teams)。

如果您想将其添加到新的迁移中,您可以这样做!

public function up()
{
    Schema::table('users', function($table) {
        $table->foreign('department')
              ->references('name')
              ->on('teams')
              ->onUpdate('cascade')
              // ->onDelete('set null');
    });
}

推荐阅读