php - Come posso inserire le chiavi composite nei modelli in Laravel 5?




web composite-primary-key (6)

Ho nel mio DataBase una tabella con due chiavi primarie (id e language_id) e ho bisogno di metterlo nei miei modelli. La primaryKey predefinita in Models (Model.php in Laravel 5) è id, e voglio che primaryKeys sia id e id_language. Ho provato a metterlo con matrici o una stringa con ',' ma non funziona. Mi dice che l'array non può essere convertito in String.

Per favore aiuto.

Grazie!


Ecco il mio file di migrazione, ha risolto il mio problema di gestione delle chiavi durante la migrazione. Potresti aver bisogno di aggiornare la classe del modello in un secondo momento, se ottieni errore di tipo di offset illegale o qualcosa del genere. La soluzione è qui - here

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateAccountSessionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('account_sessions', function (Blueprint $table) {
            $table->string('session', 64);//creates a string column, that can use in primary key. don't let it exceeds 797 bytes
            $table->integer('account_id')->unsigned();//unsigned integer column
            $table->timestamps();

            $table->primary(['session', 'account_id']);//added the primary keys

            $table->foreign('account_id')->references('id')->on('accounts');//foreign key
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('account_sessions');
    }
}

Ho scritto questo semplice tratto PHP per adattare Eloquent alla gestione delle chiavi composite:

<?php

namespace App\Model\Traits; // *** Adjust this to match your model namespace! ***

use Illuminate\Database\Eloquent\Builder;

trait HasCompositePrimaryKey
{
    /**
     * Get the value indicating whether the IDs are incrementing.
     *
     * @return bool
     */
    public function getIncrementing()
    {
        return false;
    }

    /**
     * Set the keys for a save update query.
     *
     * @param  \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    protected function setKeysForSaveQuery(Builder $query)
    {
        foreach ($this->getKeyName() as $key) {
            // UPDATE: Added isset() per devflow's comment.
            if (isset($this->$key))
                $query->where($key, '=', $this->$key);
            else
                throw new Exception(__METHOD__ . 'Missing part of the primary key: ' . $key);
        }

        return $query;
    }

    // UPDATE: From jessedp. See his edit, below.
    /**
     * Execute a query for a single record by ID.
     *
     * @param  array  $ids Array of keys, like [column => value].
     * @param  array  $columns
     * @return mixed|static
     */
    public static function find($ids, $columns = ['*'])
    {
        $me = new self;
        $query = $me->newQuery();
        foreach ($me->getKeyName() as $key) {
            $query->where($key, '=', $ids[$key]);
        }
        return $query->first($columns);
    }
}

Collocalo in una directory di Traits directory del tuo modello principale, quindi puoi aggiungere una semplice copertina nella parte superiore di qualsiasi modello di chiave composta:

class MyModel extends Eloquent {
    use Traits\HasCompositePrimaryKey; // *** THIS!!! ***

    /**
     * The primary key of the table.
     * 
     * @var string
     */
    protected $primaryKey = array('key1', 'key2');

    ...

aggiunto da jessedp:
Questo ha funzionato meravigliosamente per me fino a quando non volevo usare Model :: find ... quindi il seguente è un codice (che potrebbe probabilmente essere migliore) che può essere aggiunto al tratto hasCompositePrimaryKey sopra:

protected static function find($id, $columns = ['*'])
{
    $me = new self;
    $query = $me->newQuery();
    $i=0;

    foreach ($me->getKeyName() as $key) {
        $query->where($key, '=', $id[$i]);
        $i++;
    }

    return $query->first($columns);
}

Aggiornamento 2016-11-17

Ora lo sto mantenendo come parte di un pacchetto open-source chiamato LaravelTreats .



Sembra che sia cambiato, dal momento che questo funziona con almeno Laravel 5.1:

$table->primary(['key1', 'key2']);

Ho appena eseguito la migrazione e quello che vedo nel database si adatta a ciò che ho inserito nel codice sopra (ovviamente i campi del nome sopra sono solo a scopo di presentazione).

Aggiornamento : questo vale per le migrazioni, ma non appena si desidera inserire tramite eloquente non funziona con le chiavi composite e non lo farà mai (ultima voce):

https://github.com/laravel/framework/issues/5517


https://laravel.com/docs/5.3/migrations#columns

Si Puoi.

condivido il mio codice di migrazione:

    <?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class RegistroEmpresa extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('registro_empresa', function(Blueprint $table)
        {
            $table->string('licencia',24);
            $table->string('rut',12);
            $table->string('nombre_empresa');
            $table->string('direccion');
            $table->string('comuna_Estado');
            $table->string('ciudad');
            $table->string('pais');
            $table->string('fono');
            $table->string('email');
            $table->string('paginaweb');
            $table->string('descripcion_tienda');
            $table->string('monedauso');
            $table->timestamps();
            $table->primary(['licencia', 'rut']);
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('registro_empresa');
    }

}

Nelle migrazioni puoi semplicemente definire le chiavi primarie composte per una tabella come @ erick-suarez e @sba hanno detto, nel tuo Schema::create o Schema::table scrittura $table->primary(['key1', 'key2']);

Nel modello Eloquent che rappresenta quella tabella non è possibile utilizzare direttamente quella chiave composita con metodi Eloquent, ad esempio find($key) o save($data) ma è comunque possibile recuperare l'istanza del modello per scopi di visualizzazione utilizzando

$modelObject = ModelName->where(['key1' => $key1, 'key2' => $key2])->first();

E se vuoi aggiornare un record in quella tabella puoi usare i metodi di QueryBuilder come questo:

ModelName->where(['key1' => $key1, 'key2' => $key2])->update($data);

Dove $data è l'array associativo dati che vuoi aggiornare con il tuo modello così ['attribute1' => 'value1', ..] .

Nota: è comunque possibile utilizzare le relazioni Eloquenti in modo sicuro per il recupero con tali modelli, in quanto vengono comunemente utilizzati come tabelle pivot che interrompono strutture di relazione molti-a-molti.







composite-primary-key