2014-06-10 362 views
6

我需要制作一个带有复合主键的表。我一直在寻找多个选项来解决这个问题,以创建一个AUTO_INCREMENT字段以及其他一些字段,并使它们成为一个复合主键,但最终我成功地做到了这一点;带复合主键的Laravel种子表

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

然后播种机看起来是这样的:

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组成的阵列与领域,而不是一个单一的主键。

而且,尽管给这个错误,第一个“种子”也得到添加到数据库中,但后无来者。

回答

1

雄辩不支持组合键。你可以使这项工作有以下两种方法之一:

1)使用架构生成器的播种机,并留下您的迁移,因为它是。

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)更改您的迁移,添加一个主键并定义一个唯一的键。将Seeder保持原样

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

Laravel 4不支持组合键。另外,最好也要正确设置主键,而不要使用foreign()语法。

如在该文档中指出:

$table->primary('specificationID');创建一个主键。但是,由于您使用的是increments('id');,因此您已经有一个主键作为ID。所以你的列规格ID是多余的,除非你实际上存储了一个预定义和恒定规格的ID。

$table->primary(array('specificationID', 'categoryID', 'name'));创建复合键

一般情况下,我会尽量保持你的综合指数尽可能短,只包括列,如果他们是绝对必要的。你真的需要为你的钥匙添加名字吗?我意识到对于较小的应用程序,这可能不是相关的,只是试图说出最佳实践。

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 
} 

如果您需要更新或删除您的模型,那么有必要overridesetKeysForSaveQuery方法:

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