Как Laravel создает сводную таблицу?

В Laravel 4 при работе с отношениями "многие ко многим", как описано в документах 4.2, как я могу заставить Laravel создать для меня сводную таблицу?

Нужно ли мне что-то добавлять в мои миграции для двух задействованных моделей? Нужно ли мне вручную создавать миграцию для сводной таблицы? Или как Laravel знает, как создать сводную таблицу?

Все, что я сделал до сих пор, это добавил информацию belongsToMany к двум соответствующим моделям, т. Е.

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

Однако это не приводит к созданию сводной таблицы. Какой шаг мне не хватает?


person Ben    schedule 04.04.2013    source источник


Ответы (7)


Похоже, что сводную таблицу нужно создавать вручную (т.е. 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');
    });
}

3.) При желании добавьте ограничения внешнего ключа. (Я еще не дошел до этого момента).


Теперь, чтобы заполнить, скажем, альфа-таблицу, используя ключи из бета-версии, вы можете сделать следующее в своем AlphaTableSeeder:

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

    Alpha::create( array( 
        'all'           =>  'all',
        'your'          =>  'your',
        'stuff'         =>  'stuff',
    ) )->beta()->attach( $idOfYourBeta );
}
person Ben    schedule 05.04.2013
comment
Если вы получаете 'вызов неопределенного метода ... когда ваше семя пытается запустить этот метод {model} () - ›attach (/ ...), не забудьте создать модель для обеих таблиц с принадлежащими многим из них . Например, для этого примера: В models / Alpha.php вы должны включить: public function beta () {return $ this- ›ownToMany ('Beta');} - person sersun; 30.10.2014
comment
Я думаю, что шаг 1 должен быть: php artisan migrate:make create_alpha_beta_table --create=alpha_beta - person Adamski; 03.02.2015
comment
это первое поле id необходимо? - person Miguel Stevens; 25.11.2016
comment
для промежуточных сводных таблиц не должно быть первичного ключа. - person Tharaka Dilshan; 23.04.2019
comment
Отбросьте идентификатор, добавьте внешние ключи и в большинстве случаев вам также понадобится уникальный индекс, охватывающий оба FK. - person okdewit; 19.06.2019
comment
@TharakaDilshan Я согласен, первичный ключ AI не нужен. Однако элемент [alpha_id, beta_id] должен быть первичным ключом или, по крайней мере, проиндексирован! В противном случае запрос spped сильно замедлится - person Adam; 05.05.2021

Я использую Laravel-4-Generators Джеффри Уэя или Laravel-5-Generators-Extended.

тогда вы можете просто использовать эту команду ремесленника:

php artisan generate:pivot table_one table_two
person user3260759    schedule 15.02.2014
comment
Это также создает ограничения внешнего ключа. - person dan-klasson; 24.12.2014
comment
Для Laravel-5-Generators-Extended это команда make:migration:pivot, а не generate:pivot (как это было в Laravel-4-Generators). - person Jon; 15.02.2016

Чтобы расширить ответ Бена (я пытался отредактировать его, но рецензенты сказали, что он добавил слишком много):

Чтобы добавить ограничения внешнего ключа, убедитесь, что если alpha id не подписан, alpha_id также без знака в сводной таблице. Эта миграция будет выполняться после (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');
    });
}
person Afzal N    schedule 03.06.2013
comment
Кто бы ни проголосовал за ответ 1,5-летней давности. В следующий раз оставьте комментарий для исправления. - person Afzal N; 13.02.2015
comment
вы хотите добавить onDelete ('каскад'); ? - person Khan Shahrukh; 06.09.2017

Для отношений "многие ко многим" вы можете создать файл миграции базы данных вручную следующим образом:

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();
person Mahmoud Zalt    schedule 07.04.2016

  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');
     });
}
person Adam Pery    schedule 24.10.2019

В дополнение ко всем вышеперечисленным ответам

  • Для сводной таблицы нет необходимости иметь индекс AI. Его однозначно определяется его touple (key1, key2).
  • Первичный ключ должен быть составом (ключ1, ключ2). Преимущества заключаются в том, что элементы уникальны, а все запросы оптимизированы наилучшим образом.

Итак, вот пример из реальной жизни:

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');
});
person Adam    schedule 27.02.2021

использование имен таблиц в единственном числе в алфавитном порядке это ключ к жизни для этого лол

person Dany Aguilar    schedule 13.04.2021