Одним из основных элементов фреймворка 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->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->unsignedBigInteger('user_id')->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->id(); $table->unsignedBigInteger('user_id')->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
Перевод: Алексей Широков
Наш Телеграм-канал — следите за новостями о Laravel.