2014-06-10 359 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); 
    } 
}