Laravel如何创建数据透视表?

55
在Laravel 4中,当使用4.2文档中所述的多对多关系时,我应该如何让Laravel为我创建pivot表?我需要在涉及到的两个模型的迁移中添加一些内容吗?我需要手动创建一个用于pivot表的迁移吗?还是Laravel会自动创建pivot表?目前我只是将belongsToMany信息添加到了这两个相应的模型中。
class User extends Eloquent 
{
    public function roles()
    {
         return $this->belongsToMany('Role');
     }
 }

然而,这并不会触发数据透视表的创建。我错过了哪一步?

10个回答

74

似乎需要手动创建数据透视表(即Laravel不会自动创建)。以下是如何操作:

1)使用按照字母顺序排列的单数表名,创建一个新的迁移(默认):

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

2.) 在新创建的迁移中,将up函数更改为:

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

如有需要,可以添加外键约束(我还没涉及到这一部分)。


现在假设你想要使用来自 beta 表的键来填充 alpha 表,你可以在 AlphaTableSeeder 中执行以下操作:

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

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

如果在运行种子时出现“调用未定义的方法...”错误,而该{model}()->attach(/...)方法无法运行,请记得为两个表创建模型,并在其中一个表中使用belongsToMany。例如,在此示例中:在models/Alpha.php中,您将包括: public function beta() { return $this->belongsToMany('Beta'); } - sersun
1
我认为第一步应该是:php artisan migrate:make create_alpha_beta_table --create=alpha_beta - Adamski
1
第一个id字段是必需的吗? - Miguel Stevens
1
对于中级的数据透视表,不应该有主键。 - Tharaka Dilshan
3
取消ID字段,添加外键,并且在大多数情况下,您还需要添加一个覆盖两个外键的唯一索引。 - okdewit
@TharakaDilshan 我同意,不需要AI主键。但是元组[alpha_id,beta_id]应该是主键,或者至少建立索引!否则你的查询速度会慢很多。 - Adam

44

1
这也会创建外键约束。 - dan-klasson
5
对于 Laravel-5-Generators-Extended,命令是 make:migration:pivot,不再使用 generate:pivot(Laravel-4-Generators 中使用的命令)。 - Jon

29

为了详细说明Ben的回答(我试图编辑它,但评审人员说添加了太多内容):

要添加外键约束,请确保如果alpha id是无符号的,则枢轴表中的alpha_id也是无符号的。这个迁移将在Ben的回答中的(2)之后运行,因为它修改了那时创建的表。

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');
    });
}

8
谁给一个1.5年前的回答点了踩,请在下次评论中指出错误。请勿直接点踩。 - Afzal N
1
你想要添加一个 onDelete('cascade') 吗? - Khan Shahrukh
2
$table->foreignId('alpha_id')->constrained();$table->foreignId('alpha_id') 和相反的方式现在可能是更好的方法。 - Salman Malik

12

对于多对多关系,您可以手动创建数据库的迁移文件,像这样:

对于多对多关系,您可以手动创建数据库的迁移文件,像这样:

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');
    }
}

注意:如果您在中间表上有timestamps,您必须像这样在两端的关系上设置withTimestamps

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

.

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

11
  1. 创建新的迁移:
php artisan make:migration create_alpha_beta_table --create=alpha_beta
  1. 在新创建的迁移文件中:
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');
     });
}

6

对于最新版本的Laravel:

composer require --dev laracasts/generators

php artisan make:migration:pivot table1 table2

4

除了以上所有答案以外:

  • 在数据透视表中,不需要使用人工智能索引。它是由元组(key1,key2)唯一定义的。
  • 主键应该是组成(key1,key2)的结构。好处是元组是唯一的,并且所有查询都得到了最佳优化。

这里有一个现实生活中的例子:

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');
});

0

在旧版本中,您可以使用一些生成器或工匠来制作枢轴, 但在新版本中,这项工作变得太容易了。 您只需像下面的代码一样进行迁移即可。

php artisan make:migration category_post --create=category_post

运行代码后,使用以下参数进行迁移

 $table->foreignId('post_id')->constrained('post');
 $table->foreignId('category_id')->constrained('category');

0

遵循最新的Laravel惯例,up方法应该是这样的

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');
        });
    }

编写数据透视表迁移的最简单但现代化的方法,其中CountryTimezone是具有多对多关系的模型。而idtimestamps不是必须包含的内容,但可以以简单明了的方式进行。


0

1-通过在终端中运行以下命令来为枢轴表创建迁移:

php artisan make:migration create_table_name_table

2- 在迁移文件中,创建包含您关系所需的列的枢轴表。

<?php Schema::create('table_name', function (Blueprint $table) { $table->unsignedBigInteger('model1_id'); $table->unsignedBigInteger('model2_id'); // 添加关系需要的任何其他列 $table->timestamps(); // 设置组合键 $table->primary(['model1_id', 'model2_id']); // 设置外键 $table->foreign('model1_id')->references('id')->on('model1_table')->onDelete('cascade'); $table->foreign('model2_id')->references('id')->on('model2_table')->onDelete('cascade'); });

3- 在您的模型中,设置两个模型和枢轴表之间的关系。

<?php class Model1 extends Model { public function model2s() { return $this->belongsToMany(Model2::class, 'table_name', 'model1_id', 'model2_id'); } } class Model2 extends Model { public function model1s() { return $this->belongsToMany(Model1::class, 'table_name', 'model2_id', 'model1_id'); } }

4- 要在应用程序中以数据透视表格格式显示数据,您可以使用withPivot()方法从透视表中检索其他列。

<?php $model1 = Model1::find(1); foreach ($model1->model2s as $model2) { echo $model2->pivot->column_name; // 包括您需要的任何其他透视表列 }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接