Как показано в документации (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 в вашей базе данных между этими двумя таблицами, чего также следует избегать. Так что я бы сказал, что это нормально.
Надеюсь, это поможет;)