Обновление модельного отношения в Laravel - PullRequest
2 голосов
/ 03 июля 2019

В моем приложении Laravel у меня есть связь между User и Team, где поле department в таблице users связано с полем name в таблице teams.

Это представлено данным отношением:

/**
 * 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, так как при этом использовался бы текущий атрибут, а не старый атрибут.

Есть ли способ обойти это без сопоставления названий команд с идентификаторами в таблице пользователей? Главным образом из-за того, что предоставленные данные использовали названия как отдел.

Можно ли указать отношение для использования старых атрибутов при обновлении?

1 Ответ

1 голос
/ 03 июля 2019

В вашей схеме добавьте ограничение внешнего ключа между двумя таблицами, добавив ON UPDATE CASCADE (и, возможно, ON DELETE SET NULL?), Таким образом - вы гарантируете, что имя отдела пользователей всегда будет иметь одинаковое значение в качестве родителя (название отдела).

Для схемы (миграции) для таблицы пользователя добавьте внешний ключ

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

Имейте в виду, что оба столбца, на которые ссылаются (users.department и teams.name), должны быть точно одинакового типа и длины. Также не должно быть несоответствия данных (это означает, что пользователь не может быть членом отдела, которого нет в teams).

Если вы хотите добавить его в новую миграцию, вы можете сделать это!

public function up()
{
    Schema::table('users', function($table) {
        $table->foreign('department')
              ->references('name')
              ->on('teams')
              ->onUpdate('cascade')
              // ->onDelete('set null');
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...