Database One to one relationships occurs when there is exactly one row in a parent db table that corresponds to one raw in a child db table . In my opinion there are generally few use cases for a one-to-one relationship because the very nature of the relationship indicates the data could be consolidated within a single record. However, for the sake of demonstration let's suppose your application offered user authentication and profile management, and you wanted to separate the user's authentication (e-mail address, password) and profile (name, phone number, gender) data into two separate tables. This relationship is depicted in the below diagram.
To manage this relationship in Laravel you'll associate the User
model (created automatically with every new Laravel 5 project) with the model responsible for managing the profiles, which we'll call Profile
. To create the model you can use the Artisan generator as:
$ php artisan make:model Profile
You'll find the newly generated model inside app/Profile.php
:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Profile extends Model { // }
Next, open up the newly created migration and modify the up
method to look like this:
public function up() { Schema::create('profiles', function(Blueprint $table) { $table->integer('user_id')->unsigned()->nullable(); $table->foreign('user_id')->references('id')->on('users'); //$table->foreign('user_id')->references('id')->on('users')->onUpdate('CASCADE')->onDelete('CASCADE'); $table->string('name'); $table->string('telephone'); $table->timestamps(); }); }
The bolded lines are the only two you'll need to add. The first line results in the addition of an integer-based column named user_id
. The second line identifies this column as being a foreign key which references the users
table's id
column. Third line which is commented, is identical to second line , but I have added further foreign key constraints by onDelete
, onUpdate
methods, you can pass four possible values NO ACTION
, SET NULL
, SET DEFAULT
, CASCADE
depending on what should happen to related record when the parent record updated or deleted.
You must specify an integer column as unsigned when it's intended to be used as a foreign key, otherwise the migration will fail. Next run the migration command to create the table.
$ php artisan migrate Migrated: 2015_01_20_201647_create_profiles_table
With the tables in place it's time to define the relations within the Laravel.
Defining the One-to-One Relation
You'll define a one-to-one relation by creating a public method typically having the same name as the related model. The method will return the value of the hasOne method, as demonstrated below:
class User extends Model { public function profile() { return $this->hasOne('App\Profile'); } }
and then we can define the inverse of the relation in the Profile model like below.
class Profile extends Model { public function user() { return $this->belongsTo('App\User'); } }
Once defined, you can retrieve a user's profile information by calling the user's profile method. Because the relations can be chained, you could for instance retrieve a user's telephone number like this:
User::find(212)->profile->telephone;
To retrieve the telephone number, Laravel will look for a foreign key in the profiles
table named user_id
, matching the ID stored in that column with the user's ID.
The above example demonstrates how to traverse a relation, but how is a relation created in the first place? I'll show you how to do this next.
Creating a One-to-One Relation
You can easily create a One-to-One relation by creating the child object and then saving it through the parent object, as demonstrated in the below example:
$profile = new Profile;
$profile->telephone = '614-867-5309';
$user = User::find(212);
$user->profile()->save($profile);
Deleting a One-to-One Relation
Because a profile should not exist without a corresponding user, you'll just delete the associated profile record in the case you want to end the relationship:
$user = User::find(212);
$user->profile()->delete();
However, if a user record were to be deleted from the database you wouldn't want its corresponding profile record to be orphaned. One way to avoid this is by deleting the related profile record after deleting the user record (via Eloquent's delete
method), but chances are this two step process will eventually be neglected, leaving orphaned records strewn about the database. Instead, you'll probably want to automate this process by taking advantage of the underlying database's ability to delete child tables when the parent table is deleted. You can specify this requirement when defining the foreign key in your table migration. I've modified the relevant lines of the earlier migration used to create the profiles
table, attaching the onDelete
option to the foreign key:
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')
->on('users')->onDelete('cascade');
With the cascading delete option in place, deleting a user from the database will automatically result in the deletion of the user's corresponding profile.
Be the first one to write a response :(
{{ reply.member.name }} - {{ reply.created_at_human_readable }}