Ответ
Eloquent ORM позволяет определять отношения между моделями даже при отсутствии декларативных внешних ключей (FOREIGN KEY) на уровне базы данных. Для этого нужно явно указать имена полей, связывающих таблицы.
Сценарий: У нас есть таблицы users и posts. В таблице posts есть поле author_id, которое логически ссылается на users.id, но внешний ключ не создан.
1. Определение отношения hasMany (User -> Posts):
В модели User мы указываем, что локальным ключом является id, а внешним ключом в связанной таблице Post — поле author_id.
// app/Models/User.php
class User extends Model
{
public function posts()
{
// hasMany(RelatedModel, foreignKey, localKey)
return $this->hasMany(Post::class, 'author_id', 'id');
}
}
// Использование
$user = User::find(1);
foreach ($user->posts as $post) { // Eloquent выполнит запрос: SELECT * FROM posts WHERE author_id = 1
echo $post->title;
}
2. Определение обратного отношения belongsTo (Post -> Author):
В модели Post мы указываем, что внешним ключом в этой таблице является author_id, а он ссылается на локальный ключ id в модели User.
// app/Models/Post.php
class Post extends Model
{
public function author()
{
// belongsTo(RelatedModel, foreignKey, ownerKey)
return $this->belongsTo(User::class, 'author_id', 'id');
}
}
// Использование
$post = Post::find(10);
echo $post->author->name; // Запрос: SELECT * FROM users WHERE id = {value_of_author_id}
3. Создание миграции БЕЗ внешнего ключа:
// database/migrations/xxxx_create_posts_table.php
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('author_id'); // Просто целочисленное поле
// $table->foreign('author_id')->references('id')->on('users'); // ЭТУ СТРОКУ ПРОПУСКАЕМ
$table->string('title');
$table->timestamps();
});
Важные замечания:
- Целостность данных: Без FOREIGN KEY база данных не будет автоматически проверять существование связанной записи (
users.id) при вставке или обновленииposts.author_id. Ответственность за целостность ложится на приложение. - Каскадное удаление: Опции
onDelete('cascade')на уровне базы данных работать не будут. Для этого нужно использовать события модели или мягкое удаление (soft deletes). - Производительность: Отсутствие индекса на поле
author_idсильно замедлит выборки по отношению. Всегда добавляйте индекс вручную:$table->index('author_id');.