Как использовать два ForeignId в Laravel - PullRequest
1 голос
/ 09 апреля 2020

У меня есть две таблицы, такие как:

Пользователь:

Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('loginid')->unique();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });

IP:

Schema::create('i_p_s', function (Blueprint $table) {
        $table->id();
        $table->string('address')->unique();

        $table->foreignId('user_id')->nullable();
        $table->string('hostname');
        $table->string('description')->nullable();
        $table->timestamps();

        $table->index('user_id');
    });

IP Модель:

public function User() {
    return $this->belongsTo(User::class);
}

Пользователь Модель:

public function IPs() {
    return $this->hasMany(IP::class);
}

Столбец user_id означает, что данный IP-адрес используется данным пользователем.

А теперь я хочу добавить новый столбец last_modified, который означает, кто является последним редактором. этой строки.

Так что я думаю, last_modified тоже должно быть $table->foreignId('user_id')->nullable();.

Но как определить связь в модели IP?

Кроме того, я звоню user_id как сейчас.

$ips = IP::with('user')->get();

@foreach ($ips as $ip)
    {{ $ip->user }}
@endforeach

Так как же я могу назвать last_modified после определения?

Большое спасибо

1 Ответ

2 голосов
/ 09 апреля 2020

Как показано в документации (https://laravel.com/docs/7.x/migrations#foreign -key-constraints ),

$table->foreignId('user_id')->nullable();

- это всего лишь ярлык "старого" способа

Schema::table('i_p_s', function (Blueprint $table) {
    $table->unsignedBigInteger('user_id');

    $table->foreign('user_id')->references('id')->on('users');
});

Проблема с вашим кодом заключается в том, что вам нужен также constrained() -метод. Это приведет к растворению указанного имени столбца, например user_id, в "Laravel, используйте столбец id таблицы users здесь" .
Я не уверен, что nullable() -метод будет использоваться для этого ярлыка.

Точно так же ваши отношения будут растворяться в ваших моделях. Если вы не добавляете дополнительные значения к belongsTo() и haveMany() -методам, Laravel попытается найти свой путь в вашей базе данных, приняв стандартные соглашения об именах для первичных ключей и имен таблиц (если имена таблиц не установить в вашей модели).

  • Первичные ключи принимаются за id. Это также причина, по которой $table->ip() работает.
  • имена таблиц принимаются во множественном числе от названия модели. Это также означает, что вы должны обязательно задать имя вашей таблицы i_p_s в вашей IP-модели, так как она не соответствует соглашению. Лучше было бы подумать об адаптации к соглашению и назвать свою таблицу ips.
  • внешние ключи должны быть (чтобы можно было так все распускать) именоваться именем единственного числа таблицы, подчеркивание, первичное ключ. другими словами user_id.

Таким образом, ваше предположение должно быть правильным, помимо факта, что вы не можете добавить второй столбец с именем user_id. Для вашего второго внешнего ключа ваш код должен выглядеть как «обычный / традиционный» способ сделать это.

Schema::table('i_p_s', function (Blueprint $table) {
    $table->unsignedBigInteger('last_modified')->nullable();

    $table->foreign('last_modified')->references('id')->on('users');
});

Я почти уверен, что это будет работать, хотя я еще не проверял это. К сожалению, я не уверен, что вы можете предоставить имя столбца и таблицу также в ограниченном методе. Если это так, это было бы очень удобно. Попробуйте, в противном случае используйте традиционный способ.

Соотношение в модели должно выглядеть следующим образом:

public function hasChanged() {
    $this->hasMany(IP::class, 'last_modified', 'id');
}

last_modified - это внешний ключ в i_p_s -table, в то время как id является локальным столбцом вашей * * модели 1052 *.

Обратим это обратно для IP-модели:

public function wasChangedBy() {
    $this->belongsTo(User::class, 'last_modified', 'id');
}

В обоих случаях вы можете отказаться от установки столбца 'id' в качестве первичного ключа вашей users -таблицы, как это стандартно.

Отношения такие же, как в вашем примере, потому что строительство / архитектура. В 99% это всегда отношение «один ко многим».

И последнее, но не менее важное, было немного странно видеть эту конструкцию одного и того же внешнего ключа, дважды ссылающегося на одну и ту же таблицу. Но я нашел этот пост, в котором говорится, что в конечном итоге это совершенно нормально.
Mysql: использование двух внешних ключей для одной таблицы

Единственный способ, которым я мог подумайте о том, чтобы иметь промежуточную таблицу между i_p_s и users, но это привело бы к аль oop в вашей базе данных между этими двумя таблицами, чего также следует избегать. Так что я бы сказал, что это нормально.

Надеюсь, это поможет;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...