2014-06-10 11 views
6

Ho bisogno di creare una tabella con una chiave primaria composita. Ho esaminato più opzioni per risolvere il problema per creare un campo AUTO_INCREMENT insieme ad altri campi e trasformarle in una chiave primaria composta, ma alla fine ci sono riuscito in questo modo;Tabella semi di laravel con chiave primaria composita

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

Il modello per questa tabella è piuttosto semplice:

class Specification extends Eloquent { 

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

E poi la seminatrice si presenta così:

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

Tuttavia, quando si esegue il comando php artisan db:seed da CMD, ho ottenere il seguente errore:

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

La cosa strana è che ho già costruito molte altre tabelle in questa app, ma questa è la prima in cui lo protected $primaryKey nel modello è costituito da un array con campi, anziché avere un'unica chiave primaria.

Inoltre, nonostante questo errore, il primo 'seed' viene aggiunto nel database, ma nessuno dopo.

risposta

1

Eloquent non supporta chiavi composite. È possibile farlo funzionare con uno dei due metodi:

1) Utilizzare Schema Builder per la seminatrice e lasciare la migrazione come è.

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) Cambia la migrazione, aggiungere una chiave primaria e definire una chiave univoca. Lasciare la seminatrice come è

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 supporta chiavi composte. Inoltre, è meglio impostare correttamente anche la chiave primaria, senza utilizzare la sintassi foreign().

Come affermato nella documentazione:

$table->primary('specificationID'); crea una chiave primaria. Tuttavia dal momento che stai usando increments('id'); hai già una chiave primaria come id. Pertanto, l'ID della specifica della colonna è ridondante a meno che non si stia effettivamente memorizzando un ID di una specifica predefinita e costante.

$table->primary(array('specificationID', 'categoryID', 'name')); crea una chiave

In generale composito, vorrei cercare di mantenere il vostro indice composito più breve possibile e includere solo le colonne se sono assolutamente necessari. Hai davvero bisogno di aggiungere un nome alla tua chiave? Mi rendo conto che per le applicazioni più piccole questo potrebbe non essere rilevante, solo cercando di parlare delle migliori pratiche.

1

Il modo in cui sono riuscito a far funzionare Laravel 5.1 con le chiavi composite.In primo luogo definire lo schema come:

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

Il modello:

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 
} 

Se hai bisogno di aggiornare o cancellare il vostro modello, allora è necessario override il metodo 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); 
    } 
}