How is a pivot table created by Laravel?
LaravelPivot TableLaravel 4EloquentLaravel 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
- Create new migration:
php artisan make:migration create_alpha_beta_table --create=alpha_beta
- 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