Laravel 5.2 - Verwenden Sie einen String als benutzerdefinierten Primärschlüssel für eloquente Tabellen und wird zu 0

81

Ich versuche, E-Mail als Primärschlüssel für meine Tabelle zu verwenden. Mein beredter Code lautet also:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class UserVerification extends Model
{
    protected $table = 'user_verification';
    protected $fillable =   [
                                'email',
                                'verification_token'
                            ];
    //$timestamps = false;
    protected $primaryKey = 'verification_token';
}

Und meine DB ist so-

Geben Sie hier die Bildbeschreibung ein

aber wenn ich das mache-

UserVerification::where('verification_token', $token)->first();

Ich bekomme das-

{
  "email": "[email protected]",
  "verification_token": 0,
  "created_at": "2016-01-03 22:27:44",
  "updated_at": "2016-01-03 22:27:44"
}

Das Bestätigungstoken / der Primärschlüssel wird also zu 0.

Kann mir bitte jemand helfen?

Abrar Jahin
quelle

Antworten:

180

Dies wurde am 29. Dezember 2015 zur Upgrade-Dokumentation hinzugefügt. Wenn Sie also zuvor ein Upgrade durchgeführt haben, haben Sie es wahrscheinlich verpasst.

Beim Abrufen eines Attributs aus dem Modell wird geprüft, ob diese Spalte als Ganzzahl, Zeichenfolge usw. umgewandelt werden soll.

Bei automatisch inkrementierenden Tabellen wird bei dieser Methode standardmäßig angenommen, dass die ID eine Ganzzahl ist:

https://github.com/laravel/framework/blob/5.2/src/Illuminate/Database/Eloquent/Model.php#L2790

Die Lösung lautet also:

class UserVerification extends Model
{
    protected $primaryKey = 'your_key_name'; // or null

    public $incrementing = false;

    // In Laravel 6.0+ make sure to also set $keyType
    protected $keyType = 'string';
}
andrewtweber
quelle
3
Gibt es einen Grund, warum das $incrementingFeld öffentlich statt geschützt ist?
Mubashar Abbas
5
@MubasharAbbas Nun, Ihr Modell muss mit Eloquent übereinstimmen. Warum macht Eloquent nun $incrementingöffentlich und $primaryKeygeschützt? Es ist ziemlich willkürlich. Ich vermute, dass $incrementinges in früheren Versionen von Eloquent keine Getter- oder Setter-Methoden gab (das tut es jetzt), und sie wollten einfach keine bahnbrechende Änderung vornehmen, nachdem sie sie hinzugefügt hatten
andrewtweber
1
Wenn Sie keinen Primärschlüssel (oder zusammengesetzte Schlüssel, die von Eloquent nicht unterstützt werden) haben und versuchen, eine solche Tabelle mit zu iterieren chunk, kann der folgende Fehler auftreten : SQLSTATE[42S22]: Column not found: 1054 Unknown column 'example.' in 'order clause'. In diesem Fall müssen Sie die orderByAnweisung explizit definieren , die Eloquent mit dem Primärschlüssel an Ihre Abfrage anhängen möchte.
Antongorodezkiy
Traurig, dass dies die Art von Dingen sind, die Laravel tut und die mich daran hindern, von ganzem Herzen zu lieben. Wäre es nicht sinnvoller, den Spaltentyp zu erkennen (wie bei so vielen anderen Spalten)?
Fräulein Amelia Sara
28

Auf dem Modell $incrementingauf false gesetzt

public $incrementing = false;

Dies verhindert, dass es sich um ein Auto-Inkrement-Feld handelt.

Laravel Docs - Eloquent - Modelle definieren

Lagbox
quelle
7

Es gibt zwei Eigenschaften für das Modell, die Sie festlegen müssen. Der erste $primaryKey, der dem Modell mitteilt, in welcher Spalte der Primärschlüssel zu erwarten ist. Der zweite, $incrementingdamit er weiß, dass der Primärschlüssel kein linearer Wert für die automatische Inkrementierung ist.

class MyModel extends Model
{
    protected $primaryKey = 'my_column';

    public $incrementing = false;
}

Weitere Informationen finden Sie im Primary KeysAbschnitt in der Dokumentation zu Eloquent .

Wader
quelle
1
Es muss mit public $incrementingder übergeordneten Klasse übereinstimmen.
Andrew Tweber
2

Ich habe Postman verwendet, um meine Laravel-API zu testen.

Ich habe einen Fehler erhalten, der besagt

"SQLSTATE [42S22]: Spalte nicht gefunden: 1054 Unbekannte Spalte", da Laravel versuchte, automatisch zwei Spalten "created_at" und "update_at" zu erstellen.

Ich musste public $timestamps = false;mein Modell eingeben . Dann habe ich nochmal mit Postman getestet und gesehen, dass ein"id" = 0 Variable in meiner Datenbank erstellt wurde.

Ich musste endlich hinzufügen public $incrementing false;, um meine API zu reparieren.

Erich Meissner
quelle
2

Verwenden Sie weiterhin die ID


<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class UserVerification extends Model
{
    protected $table = 'user_verification';
    protected $fillable =   [
                            'id',
                            'email',
                            'verification_token'
                            ];
    //$timestamps = false;
    protected $primaryKey = 'verification_token';
}

und erhalte die E-Mail:

$usr = User::find($id);
$token = $usr->verification_token;
$email = UserVerification::find($token);
Zμ 1
quelle