使用Laravel种子填充具有组合主键的表格

6

我需要制作一个含有复合主键的表格。我一直在寻找多种解决方案,通过创建一个AUTO_INCREMENT字段以及其它一些字段,并将它们组成一个复合主键来解决这个问题,但最终我是通过以下方式成功实现的:

class CreateSpecificationTable extends Migration {

    public function up()
    {
        Schema::create('specification', function(Blueprint $table){
            $table->increments('specificationID');
            $table->integer('categoryID', false, true);
            $table->string('name', 100);

            $table->dateTime('created_at');
            $table->dateTime('updated_at')->nullable()->default(null);
            $table->dateTime('deleted_at')->nullable()->default(null);

            $table->foreign('categoryID')->references('categoryID')->on('categories');
        });

        DB::unprepared('ALTER TABLE specification DROP PRIMARY KEY, ADD PRIMARY KEY(specificationID, categoryID, name)');
    }

这个表格的模型非常简单:
class Specification extends Eloquent {

    protected $table = 'specification';
    protected $primaryKey = array('specificationID', 'categoryID', 'name');
}

然后 Seeder 的样式如下:

class SpecificationSeeder extends Seeder {

    public function run()
    {
        Specification::create(array(
        'categoryID'=>1,
        'name'=>'size',
        ));

        Specification::create(array(
        'categoryID'=>2,
        'name'=>'resolution',
        ));

        Specification::create(array(
        'categoryID'=>1,
        'naam'=>'connection',
        ));
    }
}

然而,当我在CMD中运行php artisan db:seed命令时,我收到以下错误:

[ErrorException]
PDO::lastInsertId() expects parameter 1 to be string, array given

奇怪的是,我已经用同样的方法在这个应用程序中建立了很多其他表,但这是第一个模型中protected $primaryKey由字段数组组成而不是单个主键的表格。
此外,尽管出现了此错误,但第一个“种子”确实已被添加到数据库中,但之后没有更多的添加。
3个回答

1

我成功让 Laravel 5.1 与复合键一起工作的方法。首先,将架构定义为:

class CreateSpecificationTable extends Migration
{

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('specification', function(Blueprint $table){
            $table->primary(array('specificationID', 'categoryID', 'name'));
            $table->integer('categoryID', false, true);
            $table->string('name', 100);
            $table->dateTime('created_at');
            $table->dateTime('updated_at')->nullable()->default(null);
            $table->dateTime('deleted_at')->nullable()->default(null);
            $table->foreign('categoryID')->references('categoryID')->on('categories');
        });
    }

你的模型:

class Specification extends Eloquent {

    protected $table = 'specification';
    protected $primaryKey = array('specificationID', 'categoryID', 'name');
    public $incrementing = false; //important to avoid exception PDO::lastInsertId() expects parameter 1 to be string, array given
}

如果您需要更新或删除模型,则需要重写setKeysForSaveQuery方法:
protected function setKeysForSaveQuery(\Illuminate\Database\Eloquent\Builder $query)
{
    if(is_array($this->primaryKey)) {
        foreach($this->primaryKey as $pk) {
            $query->where($pk, '=', $this->original[$pk]);
        }
        return $query;
    } else {
        return parent::setKeysForSaveQuery($query);
    }
}

1
"Laravel 4 支持复合键。同时,最好正确设置主键,不要使用 foreign() 语法。
如文档所述: $table->primary('specificationID'); 创建一个主键。但是,如果您使用 increments('id'),则已经有了一个名为 id 的主键。因此,除非您实际上正在存储预定义和常量规格的 ID,否则您的 specificationID 列是多余的。 $table->primary(array('specificationID', 'categoryID', 'name')); 创建一个复合键。
总的来说,我会尽可能保持复合索引尽可能短,并仅在绝对必要时包括列。您真的需要将名称添加到您的键中吗?我意识到对于较小的应用程序来说,这可能并不那么相关,只是想提出最佳实践建议。"

1

Eloquent不支持复合键。您可以使用以下两种方法之一解决此问题:

1)对于数据填充器,使用Schema Builder,并保留现有的Migration。

class SpecificationSeeder extends Seeder {

    public function run()
    {
        $data = array(
            array(
                'categoryID'=>1,
                'name'=>'size',
            ),
            array(
                'categoryID'=>1,
                'name'=>'size',
            ),
            array(
                'categoryID'=>1,
                'naam'=>'connection',
            )
        );

        DB::table('specification')->insert($data);
    }
}

2) 更改您的迁移,添加主键并定义唯一键。将填充器保持不变。

class CreateSpecificationTable extends Migration {

    public function up()
    {
        Schema::create('specification', function(Blueprint $table){
            $table->increments('id');
            $table->integer('specificationID');
            $table->integer('categoryID', false, true);
            $table->string('name', 100);

            $table->dateTime('created_at');
            $table->dateTime('updated_at')->nullable()->default(null);
            $table->dateTime('deleted_at')->nullable()->default(null);

            $table->unique( array('specificationID', 'categoryID', 'name') );

            $table->foreign('categoryID')->references('categoryID')->on('categories');
        });
    }
}

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