2015-07-25 15 views
11

In Laravel 5.1, für MySQL einfügen, möchte ich sehen, ob der Datensatz bereits existiert und auf doppelte aktualisieren oder neue erstellen, wenn keine existiert.Laravel 5.1 Erstellen oder Aktualisieren auf Duplizieren

Ich habe bereits SO gesucht, wo die Antworten für alte Laravel-Versionen waren. In einem der alten Themen hieß es, dass im letzten Jahr eine neue updateOrCreate() Methode hinzugefügt wurde. Aber wenn ich das versuche, erhalte ich die Fehlermeldung:

Integrity constraint violation: 1062 Duplicate entry '1' for key 'app_id' 

Dies ist die Abfrage, die ich verwende:

AppInfo::updateOrCreate(array(
    'app_id' => $postData['appId'], 
    'contact_email' => $postData['contactEmail'] 
)); 

Wo app_id ist der einzigartige Fremdschlüssel in dieser Tabelle und ich mag den Datensatz aktualisieren wenn vorhanden oder erstellen Sie eine neue. Ich habe versucht, die 5.1 Dokumente zu durchsuchen und konnte die Informationen nicht finden, die ich benötige. Kann mir jemand führen hier bitte ...

+2

https://github.com/yadakhov/insert-on-duplicate-key Ein Paket zu tun INSERT ON DUPLICATE KEY mit Laravel. – Yada

Antwort

22

Gemäß der Definition des Eloquent Modell Method "updateOrCreate()"

function updateOrCreate(array $attributes, array $values = []){}

es dauert zwei Argument ...

  1. ein das ist Attribute, mit denen Sie in die Datenbank einchecken möchten, wenn der Datensatz vorhanden ist
  2. Zweitens sind die neuen Attributwerte, die Sie erstellen oder aktualisieren möchten

AppInfo::updateOrCreate(['app_id' => $postData['appId']], 
         ['contact_email' => $postData['contactEmail']]); 
+0

Perfekt! Genau das habe ich falsch gemacht. Ich vermutete, dass das Setzen des eindeutigen Schlüssels in der Datenbank automatisch erfolgen sollte, aber ich lag falsch. Vielen Dank, dass Sie @MrPandav darauf hingewiesen haben. Es funktioniert jetzt gut, nachdem Sie 2 Argumente hinzugefügt haben. :) – Neel

+3

@Neel: Wann immer Sie keine Dokumentation online finden (normalerweise der Fall für innovative Beta-Frameworks) oder im Zweifel, öffnen Sie ihre Quellcode-Datei, sie haben immer sehr schöne Dokumentation und Szenario vor jeder Funktion erklärt defination – MrPandav

+0

Wenn ich noch nicht den Datensatz in der Datenbank erstellt habe, wie habe ich die ID? –

3

In der Folge Methode insertUpdate zu Ihrem Modell

<?php 

namespace App; 

use Illuminate\Auth\Authenticatable; 
use Illuminate\Database\Eloquent\Model; 
use Illuminate\Auth\Passwords\CanResetPassword; 
use Illuminate\Foundation\Auth\Access\Authorizable; 
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 

class User extends Model implements AuthenticatableContract, 
            AuthorizableContract, 
            CanResetPasswordContract 
{ 
    use Authenticatable, Authorizable, CanResetPassword; 

    /** 
    * The database table used by the model. 
    * 
    * @var string 
    */ 
    protected $table = 'users'; 

    /** 
    * The attributes that are mass assignable. 
    * 
    * @var array 
    */ 
    protected $fillable = ['name', 'email', 'password']; 

    /** 
    * The attributes excluded from the model's JSON form. 
    * 
    * @var array 
    */ 
    protected $hidden = ['password', 'remember_token']; 


    public static function insertUpdate(array $attributes = []) 
    { 
     $model = new static($attributes); 

     $model->fill($attributes); 

     if ($model->usesTimestamps()) { 
      $model->updateTimestamps(); 
     } 

     $attributes = $model->getAttributes(); 

     $query = $model->newBaseQueryBuilder(); 
     $processor = $query->getProcessor(); 
     $grammar = $query->getGrammar(); 

     $table = $grammar->wrapTable($model->getTable()); 
     $keyName = $model->getKeyName(); 
     $columns = $grammar->columnize(array_keys($attributes)); 
     $insertValues = $grammar->parameterize($attributes); 

     $updateValues = []; 

     if ($model->primaryKey !== null) { 
      $updateValues[] = "{$grammar->wrap($keyName)} = LAST_INSERT_ID({$keyName})"; 
     } 

     foreach ($attributes as $k => $v) { 
      $updateValues[] = sprintf("%s = '%s'", $grammar->wrap($k), $v); 
     } 

     $updateValues = join(',', $updateValues); 

     $sql = "insert into {$table} ({$columns}) values ({$insertValues}) on duplicate key update {$updateValues}"; 

     $id = $processor->processInsertGetId($query, $sql, array_values($attributes)); 

     $model->setAttribute($keyName, $id); 

     return $model; 
    } 
} 

können Sie verwenden:

App\User::insertUpdate([ 
    'name' => 'Marco Pedraza', 
    'email' => '[email protected]' 
]); 

Die nächste Abfrage es ausgeführt wird:

insert into `users` (`name`, `email`, `updated_at`, `created_at`) values (?, ?, ?, ?) on duplicate key update `id` = LAST_INSERT_ID(id),`name` = 'Marco Pedraza',`email` = '[email protected]',`updated_at` = '2016-11-02 01:30:05',`created_at` = '2016-11-02 01:30:05' 

Das traf hod fügt automatisch die Eloquent Zeitstempel hinzu oder entfernt sie, wenn Sie aktiviert oder deaktiviert haben.

+1

Hallo, willkommen in SO. Bitte decke nicht einfach Code ab, erkläre deinen Gedankengang, damit die Leute deine Antwort besser verstehen können. Vielen Dank. – Cthulhu

+0

Nützliche Funktion, die zu funktionieren scheint, im Gegensatz zur Funktion updateOrCreate aktualisiert diese auch die Zeitstempel. Warum aktualisiert es beide? Es sollte nur die updated_at aktualisieren, aktuell aktualisiert es auch die created_at. Und gibt es eine Möglichkeit, diese Funktion mit Masseneinsätzen zu verwenden? Deshalb habe ich nach dem gesucht, sonst funktionierte die Funktion updateOrCreate gut, abgesehen davon, dass die Zeitstempel nicht automatisch aktualisiert wurden. – vesperknight

2

Um Laravel Funktion updateOrCreate Sie benötigen Auto Zuwachs id in Ihrer Tabelle zu verwenden.

, was sie tun, ist

select id from your_table where your_attributes

nach diesem Autoinkrement-ID erhalten

dann

update your_table set your_values where field_id

+0

Nur wenn ich einen zusammengesetzten Schlüssel ohne Autoinkrement 'id' verwenden wollte. – Jonathan

+0

Sie benötigen primärer Feldname' id'. Sie nehmen geschütztes $ primaryKey = 'id'; vom Modell oder sonst können Sie in Ihrem Modell überschreiben. –

4

Ich habe ein Paket mit MySQL zu arbeiten, legen Sie auf doppelte Schlüssel .

https://packagist.org/packages/yadakhov/insert-on-duplicate-key

Beispiel:

Es kann für andere nützlich sein

/** 
* Class User. 
*/ 
class User extends Model 
{ 
    use Yadakhov\InsertOnDuplicateKey; 
    ... 
} 

// associative array must match column names 
$users = [ 
    ['id' => 1, 'email' => '[email protected]', 'name' => 'User One'], 
    ['id' => 2, 'email' => '[email protected]', 'name' => 'User Two'], 
    ['id' => 3, 'email' => '[email protected]', 'name' => 'User Three'], 
]; 

User::insertOnDuplicateKey($users); 
2

Ich antworte auf diese Frage, weil ich keine Antwort in Bezug auf ON DUPLICATE KEY UPDATE finden können, obwohl ich Laravel 5.4 benutze. Wenn Sie die updateOrCreate-Methode im Laravel-Kerncode betrachten, sehen Sie, dass Laravel zwei verschiedene Abfragen verwendet: eine für das Update und eine weitere für die Erstellung. Aus diesem Grund können Sie manchmal doppelte Daten in der DB erhalten. So in einigen Fällen kann es sinnvoll sein, diese Art von Roh-Abfrage zu schreiben:

DB::statement("INSERT INTO table_name (col_1 , col_2) VALUES (?, ?) ON DUPLICATE KEY UPDATE col_1 = col_1 + 1", ([val_1, val_2]));

Hoffen, dass es für jemanden nützlich sein kann.