Laravel Laravel Database Eloquent ORM

Creating a One to One Relation in Laravel 5

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.

How to create One-to-One Relation in Laravel 5

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 NULLSET 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.



Share your thoughts

You may use <pre> </pre> tag for writing multi lines code or <code> </code> tag for writing single line code in the comment section bellow.