Handle Table Relationships by Eloquent in Laravel 4

I summarize the things written in Laravel Docs so it almost the same things.

# One to One

In table below, every user has one phone. Column phone_id represent the data in phones and all phone_id stored in users table is unique and no repeat.

スクリーンショット 2014-08-21 午後7.48.58

In app/models/User.php, it should looks like this. In default, there is no User.php and you have to create by yourself.

class User extends Eloquent {

    public function phone()
    {
        // 1st parameter is eloquent class name
        // 2nd parameter is foreign key
        // 3rd parameter is local key in "users" table
        return $this->hasOne('User','user_id','id');
    }

}

For phones table

class Phone extends Eloquent {

    public function user()
    {
    	// 1st parameter is eloquent class name
        // 2nd parameter is foreign key
        // 3rd parameter is local key in "users" table
        return $this->belongsTo('User','user_id','id');
    }

}

In migrations file, it should looks like this.


use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePhonesAndUsersTable extends Migration {

	/**
	 * Run the migrations.
	 *
	 * @return void
	 */
	public function up()
	{
		Schema::create('users',function($table)
		{
			$table->increments('id');
			$table->string('name');
        	$table->timestamps();
		});
		//
		Schema::create('phones', function(Blueprint $table)
		{
			$table->increments('id');
            $table->string('name');
            $table->integer('user_id')->unsigned();
        	$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->timestamps();
   		});
	}	

	/**
	 * Reverse the migrations.
	 *
	 * @return void
	 */
	public function down()
	{
		//
		Schema::dropIfExists('users');
		Schema::dropIfExists('phones');
	}

}

To retrieve the results of user, you can use belongsTo(“User”)->getResults() as the code below.

$phone = Phone::find(1);
// because of one to one relationship, you will get single object instead of array
$user = $phone->user()->getResults(); 

To save the results, you can use save() method.

$phone = new Phone;
$phone->name = "iPhone 4s"

$user = new User;
$user->name = "Tanaka"
$user->save();

$user->phone()->save($phone);

# One to Many

One-to-Many is almost same as One-to-One. First let’s take a look on tables below, you will found out that same tables, same columns as One-to-One. In One-to-Many relationships, one user has many phones. It means that phones table, user_id column is not a unique column, it will contains multiple same user id. This is the only different between One-to-One and One-to-Many.

スクリーンショット 2014-08-21 午後7.48.58

In app/models/Phone.php, it should looks like this.

class Phone extends Eloquent {

    public function user()
    {
    	// 1st parameter is eloquent class name
        // 2nd parameter is foreign key
        // 3rd parameter is local key in "users" table
        return $this->belongsTo('User','user_id','id');
    }

}

In User.php, you should change hasOne to hasMany.

class User extends Eloquent {

    public function phones()
    {
        // 1st parameter is eloquent class name
        // 2nd parameter is foreign key
        // 3rd parameter is local key in "users" table
        return $this->hasMany('Phone','user_id','id');
    }

}

About the migrations, we are using exactly same One-to-One relationship tables, so migration code is exactly same as One-to-One.

You can do the saving as One-to-One.

$phone1 = new Phone;
$phone1->name = "iPhone 4s";

$user = new User;
$user->name = "Tanaka";
$user->save();

$user->phones()->save($phone1);

If you are going to save multiple data, you have to call save method multipe times.

$user->phones()->save($phone1);
$user->phones()->save($phone2);

You can retrieve the records as One-to-One, you are getting records in term of array not object

$phones = User::find(2)->phones()->getResults();
foreach($phones as $phone){
    # something here ...
}

# Many to Many

Many-to-Many is quite complex compare to One-to-One and One-to-Many. It required a pivot table in between two tables. In below, it shows the relationship between roles table, users table and pivot table user_role.

スクリーンショット 2014-08-21 午後9.36.07

Even though there are three tables in SQL but you just needs two models, there are User and Role.

In app/models/User.php

class User extends Eloquent {

    public function roles()
    {
        // 1st parameter is eloquent class name
        // 2nd parameter is pivot table name
        // 3rd parameter is associated key
        // 4th parameter is associated key
        return $this->belongsToMany('Role','user_role','role_id','user_id');
    }

}

In app/models/Role.php, same method belongsToMany as User.php but different parameter.

class Role extends Eloquent {

    public function users()
    {
    	// 1st parameter is eloquent class name
        // 2nd parameter is pivot table name
        // 3rd parameter is associated key
        // 4th parameter is associated key
        return $this->belongsToMany('User','user_role','user_id','role_id');
    }

}

For migrations, it should looks like this.

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateRolesAndUsersTable extends Migration {

	/**
	 * Run the migrations.
	 *
	 * @return void
	 */
	public function up()
	{
		Schema::create('users',function($table)
		{
			$table->increments('id');
			$table->string('name');
        	$table->timestamps();
		});
		//
		Schema::create('roles', function(Blueprint $table)
		{
			$table->increments('id');
            $table->string('name');
            $table->timestamps();
   		});
   		Schema::create('user_role', function(Blueprint $table) {
            $table->increments('id');
            $table->integer('role_id')->unsigned()->index();
            $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
            $table->integer('user_id')->unsigned()->index();
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->timestamps();
        });
	}	

	/**
	 * Reverse the migrations.
	 *
	 * @return void
	 */
	public function down()
	{
		//
		Schema::dropIfExists('user_role');
		Schema::dropIfExists('users');
		Schema::dropIfExists('roles');
	}

}

Saving and show records are not very big different from One-to-One and One-to-Many. Below show the sample code of retrieve the records and output the records.

You can save the data by using save() method.

$role = new Role;
$role->name = "Admin";

$user = new User;
$user->name = "Tanaka";
$user->save();

$user->roles()->save($role);

You can retrieve the records by using getResults() method. It is same as One-to-Many, you will received results in array not object.

$user = Role::find(4)->users()->getResults();

# Conclusions

It is very easy to figure out either the results return in object or array. One-to-One and of course you will get both single results and One-toMany you will get single in one and many in many (Not typo).

Advertisements

2 thoughts on “Handle Table Relationships by Eloquent in Laravel 4

  1. hi! great post but i don’t understand if is correctly that in on-to-one Phone->user have a belongsTo Phone and not User

    Class Phone extends Eloquent {
    public function user()
    {
    return $this->belongsTo(‘Phone’,’user_id’,’id’);
    }
    }

    Thanks

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s