Одним из основных элементов фреймворка Laravel является Eloquent ORM — система объектно-реляционного отображения. Laravel Eloquent предоставляет очень удобный способ создания отношений между моделями.
В этой статье мы рассмотрим, как мы можем создать отношение «Один-к-Одному» (One To One) в Laravel.
Это отношение связывает одну запись в таблице с одной записью в другой таблице базы данных. «Один-к-Одному» является фундаментальным и очень простым в использовании.
Например, у нас есть модель User, используемая для аутентификации. И мы хотим добавить раздел управления профилем для хранения социальных ссылок на аккаунты пользователя, даты рождения и тому подобных данных. Мы можем добавить столбцы, связанные с профилем, прямо в таблицу пользователя, но это её усложнит.
Чтобы поддерживать нашу базу данных в чистоте и порядке, данные, относящиеся к аутентификации пользователей, такие как адрес электронной почты, имя пользователя и пароль мы храним в таблице пользователей. А данные, относящиеся к профилям, такие как социальные ссылки, дата рождения — в таблице профилей.
У одного пользователя может быть только один профиль, а профиль принадлежит только одному пользователю, поэтому здесь мы создаем отношения «Один-к-одному». Эта взаимосвязь изображена на диаграмме ниже.
Для реализации отношения «Один-к-одному» в Laravel, нам понадобятся две модели: User и Profile.
Примечание: я надеюсь вы уже установили Laravel и настроили базу данных в файле .env.
Как мы знаем, Laravel уже поставляется с моделью User, поэтому нам нужно создать модель Profile, которая будет сопоставлена с таблицей profiles в базе данных.
Чтобы создать модель Profile, используйте команду artisan:
php artisan make:model Profile -m
Эта команда создаст новую модель App\Profile с файлом миграции:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
//
}
и миграционный файл:
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateProfilesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('profiles');
}
}
Сначала мы обновим метод up в файле миграции:
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->date('dob');
$table->text('bio');
$table->string('facebook');
$table->string('twitter');
$table->string('github');
$table->timestamps();
});
}
Теперь обновим модель Profile:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
protected $table = 'profiles';
protected $fillable = ['dob', 'bio', 'facebook', 'twitter', 'github'];
}
Выполните следующую команду, для создания таблиц:
php artisan migrate
Как только вы создали таблицы, пришло время определить отношение «Один-к-Одному». Откройте файл User.php расположенный в папке app и добавьте новый публичный метод с именем profile в модель User.
public function profile()
{
return $this->hasOne(Profile::class);
}
Обычно дается такое же имя, как и у привязываемой модели, в данном случае — profile. Эта функция возвращает отношение hasOne.
Мы также можем добавить обратное отношение один к одному, добавив метод user в модель Profile
namespace App;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
protected $table = 'profiles';
protected $fillable = ['dob', 'bio', 'facebook', 'twitter', 'github'];
public function user()
{
return $this->belongsTo(User::class);
}
}
Мы добавили метод user, который возвращает отношение belongsTo, поскольку профиль принадлежит пользователю.
Получение данных «Один-к-Одному»
После того, как определили данные отношения, вы можете получить доступ к профилю пользователя, вызвав метод profile для объекта пользователя, как показано ниже
$user = User::find(1);
$userDob = $user->profile->dob;
$userBio = $user->profile->bio;
Чтобы получить профиль пользователя, Laravel будет искать внешний ключ в таблице profile под названием user_id, соответствующий идентификатору пользователя.
Создание отношений «Один-к-Одному»
Чтобы создать отношение «Один-к-Одному», мы сначала должны создать дочерний объект, являющийся объектом Profile
$profile = new Profile();
$profile->dob = '20-03-1999';
$profile->bio = 'A professional programmer.';
Теперь мы сохраним дочерний объект через родительский
$profile = new Profile();
$profile->dob = '20-03-1999';
$profile->bio = 'A professional programmer.';
$user = User::find(1);
$user->profile()->save($profile);
Удаление — это то же самое, что и создание. Сначала мы берем родительский объект $user, а затем вызываем метод delete для метода profile()
$user = User::find(1);
$user->profile()->delete();
А если мы удалим $user перед удалением профиля, то в базе останется потерянный профиль.
Один из подходов — сначала удалить профиль, а затем вызвать метод delete для объекта $user. Иногда вы можете пренебречь этой двухшаговой процедурой и оставить осиротевший профиль в базе данных.
Laravel предоставляет элегантный способ удаления дочерних записей при удалении родительской записи. Вы можете использовать метод onDelete() в своей миграции при определении ключа foriegn
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->date('dob');
$table->text('bio');
$table->string('facebook');
$table->string('twitter');
$table->string('github');
$table->timestamps();
});
}
При установке опции каскадного удаления, удаление пользователя из базы данных автоматически удалит и соответствующий профиль.
Автор: Larashout
Перевод: Demiurge Ash