Jak Mogę umieścić klucze kompozytowe w modelach w Laravel 5?

Mam w bazie danych tabelę z dwoma kluczami podstawowymi (id i language_id) i muszę umieścić ją w moich modelach. Domyślny klucz podstawowy w modelach (Model.php w Laravel 5) jest id, i chcę, aby primaryKeys były id i id_language. Próbowałem umieścić go z tablicami lub ciągiem znaków z',', ale to nie działa. Mówi mi, że tablica nie może być przekonwertowana w łańcuchu.

Proszę O Pomoc.

Dzięki!

Author: Sergioh Lonet, 2015-07-14

8 answers

Nie możesz. Eloquent nie obsługuje złożonych kluczy podstawowych.

Oto kwestia Github dotycząca tego.

 23
Author: lukasgeiter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-14 19:23:43

Napisałem ten prosty PHP aby przystosować się do obsługi kluczy złożonych:

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

Umieść go w katalogu Traits pod głównym katalogiem modelu, a następnie możesz dodać prostą jednowierszową do dowolnego modelu klucza kompozytowego:

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

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

    ...


dodany przez jessedp:
To działało wspaniale dla mnie, dopóki nie chciałem użyć Model:: find ... tak więc poniżej znajduje się jakiś kod (który prawdopodobnie byłby lepszy), który można dodać do Cechy hasCompositePrimaryKey powyżej:
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);
}

Aktualizacja 2016-11-17

Zachowuję to jako część pakietu open-source o nazwie LaravelTreats .

 57
Author: mopo922,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-10 17:41:15

Wygląda na to, że się zmieniło, ponieważ ten działa z co najmniej Laravel 5.1:

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

Właśnie uruchamiam migrację i to, co widzę w bazie danych, pasuje do tego, co umieściłem w powyższym kodzie (oczywiście pola nazwy powyżej są tylko dla celów prezentacji).

Update: dotyczy to migracji, ale jak tylko chcesz wstawić za pomocą eloquent, nie działa z kluczami kompozytowymi i nigdy nie będzie działać (last wpis): {]}

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

 8
Author: sba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-26 11:20:02

W migracjach możesz po prostu zdefiniować złożone klucze podstawowe dla tabeli jako @erick-suarez i @ SBA said, w Schema::create lub Schema::table zapis blokowy $table->primary(['key1', 'key2']);

W modelu elokwentnym reprezentującym tę tabelę nie można bezpośrednio użyć klucza złożonego za pomocą elokwentnych metod, np. find($key) ani save($data), ale nadal można pobrać instancję modelu do przeglądania za pomocą

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

I jeśli chcesz zaktualizować rekord w tej tabeli, możesz użyć metod QueryBuilder, takich jak to:

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

Gdzie $data jest tablicą asocjacyjną danych, którą chcesz zaktualizować swój model tak ['attribute1' => 'value1', ..].


Uwaga: możesz nadal bezpiecznie używać elokwentnych relacji do pobierania z takimi modelami, ponieważ są one powszechnie używane jako tabele przestawne, które przełamują wiele do wielu struktur relacji.

 5
Author: Mohyaddin Alaoddin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-04 22:47:57

Spróbuj spojrzeć na tę dokumentację, aby wstawić wiele do wielu relacji z CK

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

Edit: jakieś dodatkowe info
Jak widać w dokumentacji, funkcje dołączania i odłączania tworzą łącza potrzebne w tabeli pośredniej CK. Więc nie musisz ich tworzyć samodzielnie;)

W Twoim przypadku byłoby to model->languages()->attach(language_id)

 1
Author: Reyske,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-15 03:12:26

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

Tak, możesz.

Udostępniam mój kod migracji:

    <?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
Author: Erick Suarez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-22 18:29:51

Oto mój plik migracji, który rozwiązał mój problem zarządzania kluczami w migracji.. Może być konieczne zaktualizowanie klasy modelu później, jeśli uzyskasz nielegalny błąd typu offset lub coś w tym stylu. Rozwiązanie jest tutaj - Tutaj

<?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
Author: Sadidul Islam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-05 03:56:25

Proszę odwiedzić te dwa linki poniżej, te rozwiązanie rozwiązało mój klucz kompozytowy lub wielokolumnowy problem z kluczem podstawowym -

  1. Tworzenie bazy danych za pomocą kluczy złożonych

  2. Nielegalny błąd typu offsetu

 0
Author: Sadidul Islam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-05 04:00:32