Comment puis-je mettre des clés en composite dans les Modèles de Laravel 5?

j'ai dans ma base de données une table avec deux clés primaires (id et language_id) et j'ai besoin de la mettre dans mes modèles. La valeur par défaut primaryKey dans les Modèles (Model.php dans Laravel 5) est id, et je veux que les primaryKeys soient id et id_language. J'ai essayé de le mettre avec des tableaux ou une chaîne avec", " mais ça ne marche pas. Il me dit que le tableau ne pouvait pas être converti en chaîne.

Aidez-Moi.

Merci!

26
demandé sur Sergioh Lonet 2015-07-14 22:05:24

8 réponses

vous ne pouvez pas. Eloquent ne supporte pas les clés primaires composites.

voici un problème de Github à ce sujet.

23
répondu lukasgeiter 2015-07-14 19:23:43

j'ai écrit ce simple PHP trait pour adapter éloquent pour manipuler des clés composites:

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

Placez que dans un répertoire Traits sous votre répertoire principal de modèle, alors vous pouvez ajouter un simple one-liner au sommet de n'importe quel modèle composite-clé:

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

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

    ...


ajouté par jessedp:

Cela a fonctionné merveilleusement pour moi jusqu'à ce que je voulais utiliser Model:: find ... donc, ce qui suit est un code (qui pourrait probablement être mieux) qui peut être ajouté au trait hascomositeprimarykey ci-dessus:
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);
}

mise à jour 2016-11-17

je maintiens ceci comme faisant partie d'un paquet open-source appelé LaravelTreats .

57
répondu mopo922 2018-05-10 17:41:15

il semble qu'Il a changé, puisque celui-ci fonctionne avec au moins Laravel 5.1:

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

je viens d'exécuter la migration et ce que je vois dans la base de données correspond à ce que j'ai mis dans le code ci-dessus (bien sûr, les champs de nom ci-dessus sont juste pour la présentation).

mise à jour : ceci est vrai pour les migrations, mais dès que vous voulez insérer via eloquent il ne fonctionne pas avec des clés composites et ne le fera jamais (dernière entrée):

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

8
répondu sba 2016-01-26 11:20:02

dans migrations vous pouvez simplement définir des clés primaires composites pour une table comme @erick-suarez et @sba dit, dans votre Schema::create ou Schema::table bloc écrire $table->primary(['key1', 'key2']);

dans le modèle éloquent qui représente cette table, vous ne pouvez pas directement utiliser cette clé composite avec des méthodes éloquentes par exemple find($key) ou save($data) , mais vous pouvez toujours récupérer l'instance du modèle à des fins de visualisation en utilisant

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

et si vous voulez mettre à jour un enregistrement dans cette table vous pouvez utiliser QueryBuilder méthodes comme ceci:

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

$data est le tableau associatif de données que vous voulez mettre à jour votre modèle avec comme ['attribute1' => 'value1', ..] .


Note: vous pouvez toujours utiliser des relations éloquentes en toute sécurité pour la récupération avec de tels modèles, car ils sont couramment utilisés comme pivot des tableaux qui brisent la structure des relations de plusieurs à plusieurs.

5
répondu Mohyaddin Alaoddin 2017-05-04 22:47:57

essayez de regarder cette documentation pour insérer beaucoup de relations avec CK

https://laravel.com/docs/5.2/eloquent-relationships#inserting-many-to-many-relationships

Edit: quelques informations supplémentaires

Comme vous pouvez le voir dans la documentation, les fonctions attach et detach créent les liens nécessaires dans la table intermédiaire CK. Si yo ne pas avoir à les créer vous-même;)

dans votre cas, ce serait model->languages()->attach(language_id)

1
répondu Reyske 2016-03-15 03:12:26

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

Oui, vous pouvez.

je partage mon code de migration:

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

}
1
répondu Erick Suarez 2016-09-22 18:29:51

Voici mon fichier de migration, il a résolu mon problème de gestion des clés dans la migration.. Vous pourriez avoir besoin de mettre à jour la classe model plus tard, si vous obtenez une erreur de type de décalage illégal ou quelque chose comme ça. La solution est ici - ici

<?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');
    }
}
0
répondu Sadidul Islam 2018-08-05 03:56:25

, Veuillez consulter ces deux liens ci-dessous, ces solution a résolu mon clé composite ou multi-colonne de clé primaire de problème

  1. création d'une base de données avec des clés composites

  2. Illégal type de décalage d'erreur

0
répondu Sadidul Islam 2018-08-05 04:00:32