How is a pivot table created by Laravel?

LaravelPivot TableLaravel 4Eloquent

Laravel Problem Overview


In Laravel 4, when working with many-to-many relationships as described in the 4.2 docs, how can I actually get Laravel to create the pivot table for me?

Do I need to add something in my migrations for the two models that are involved? Do I need to manually create a migration for the pivot table? Or how does Laravel know to create the pivot table?

All I've done so far is add the belongsToMany information to the two respective models, i.e.

class User extends Eloquent 
{
    public function roles()
    {
         return $this->belongsToMany('Role');
     }
 }

However, that does not trigger creation of the pivot table. What step am I missing?

Laravel Solutions


Solution 1 - Laravel

It appears as though the pivot table does need to be created manually (i.e. Laravel does not do this automatically). Here's how to do it:

1.) Create a new migration, using singular table names in alphabetical order (default):

php artisan make:migration create_alpha_beta_table --create --table=alpha_beta

2.) Inside the newly created migration, change the up function to:

public function up()
{
	Schema::create('alpha_beta', function(Blueprint $table)
	{
		$table->increments('id');
		$table->integer('alpha_id');
		$table->integer('beta_id');
	});
}

3.) Add the foreign key constraints, if desired. (I haven't gotten to that bit, yet).


Now to seed, say, the alpha table, using keys from beta, you can do the following in your AlphaTableSeeder:

public function run()
{
	DB::table('alpha')->delete();

    Alpha::create( array( 
		'all'			=> 	'all',
		'your'			=> 	'your',
		'stuff'			=> 	'stuff',
    ) )->beta()->attach( $idOfYourBeta );
}

Solution 2 - Laravel

I use Jeffrey Way's Laravel-4-Generators or Laravel-5-Generators-Extended.

then you can just use this artisan command:

php artisan generate:pivot table_one table_two

Solution 3 - Laravel

To expand on Ben's answer (I tried to edit it but reviewers said it added too much):

To add the foreign key constraints, make sure if alpha id is unsigned, alpha_id is also unsigned in the pivot table. This migration would run after (2) in Ben's answer since it alters the table created then.

public function up()
{
    Schema::table('alpha_beta', function(Blueprint $table)
    {
        $table->foreign('alpha_id')->references('id')->on('alpha');
        $table->foreign('beta_id')->references('id')->on('beta');
    });
}

Solution 4 - Laravel

For Many to Many relationships you can create the Migration file of the Database manually like this:

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

class CreateAccountTagTable extends Migration
{

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('account_tag', function (Blueprint $table) {
            // $table->timestamps(); // not required
            // $table->softDeletes(); // not required

            $table->integer('account_id')->unsigned();
            $table->foreign('account_id')->references('id')->on('accounts');

            $table->integer('tag_id')->unsigned()->nullable();
            $table->foreign('tag_id')->references('id')->on('tags');
        });
    }

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

Note: in case you have timestamps on the pivot table you must set withTimestamps on the relationship of both ends like this:

return $this->belongsToMany(\Mega\Modules\Account\Models\Tag::class)->withTimestamps();

.

return $this->belongsToMany(\Mega\Modules\Account\Models\Account::class)->withTimestamps();

Solution 5 - Laravel

  1. Create new migration:

php artisan make:migration create_alpha_beta_table --create=alpha_beta

  1. Inside the newly created migration:

public function up() {
    Schema::create('alpha_beta', function(Blueprint $table) {
            $table->increments('id');
            $table->unsignedBigInteger('alpha_id');
            $table->unsignedBigInteger('beta_id');
            // foreign keys
            $table->foreign('alpha_id')->references('id')->on('alphas');
            $table->foreign('beta_id')->references('id')->on('betas');
     });
}

Solution 6 - Laravel

for the latest Laravel's versions:

composer require --dev laracasts/generators

php artisan make:migration:pivot table1 table2

Solution 7 - Laravel

In addition to all the above answers

  • There is no need to have an AI index for a pivot table. Its uniquely defined by its touple (key1,key2).
  • The primary key should be the composition (key1,key2). The benefits are that the touples are unique and all queries are best optimized.

So here comes a real life example:

Schema::create('bill_user', function (Blueprint $table) {
    // unsigned is needed for foreign key
    $table->integer('user_id')->unsigned();
    $table->integer('bill_id')->unsigned();

    $table->primary(['user_id', 'bill_id']);

    $table->foreign('user_id')
        ->references('id')->on('users')
        ->onDelete('cascade');

    $table->foreign(bill_id')
        ->references('id')->on('bills')
        ->onDelete('cascade');
});

Solution 8 - Laravel

following the latest laravel conventions, the up method should be

public function up() {
        Schema::create('country_timezone', function (Blueprint $table) {
            $table->foreignId('country_id')->references('id')->on('countries');
            $table->foreignId('timezone_id')->references('id')->on('timezones');
        });
    }

the simplest but modern way of writing pivot table migration, where the Country and Timezone are models with many-to-many relationship. And id and timestamps are not necessary to include but straightforward manner

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBenView Question on Stackoverflow
Solution 1 - LaravelBenView Answer on Stackoverflow
Solution 2 - Laraveluser3260759View Answer on Stackoverflow
Solution 3 - LaravelAfzal NView Answer on Stackoverflow
Solution 4 - LaravelMahmoud ZaltView Answer on Stackoverflow
Solution 5 - LaravelAdam PeryView Answer on Stackoverflow
Solution 6 - LaravelLyuba EvdokimovaView Answer on Stackoverflow
Solution 7 - LaravelAdamView Answer on Stackoverflow
Solution 8 - LaravelDanish MehmoodView Answer on Stackoverflow