web-dev-qa-db-ja.com

Laravel 5.1複製時に作成または更新

Laravel 5.1、MySQL挿入の場合、レコードが既に存在するかどうかを確認し、重複がある場合は更新するか、存在しない場合は新規作成します。

私はすでにSOを検索しましたが、答えは古いlaravelバージョンです。古いトピックの1つでは、新しいupdateOrCreate()メソッドは昨年コアに追加されましたが、それを試してみると、エラーが発生しています:

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

これは私が使用するクエリです:

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

どこapp_idはそのテーブルの一意の外部キーです。存在する場合はレコードを更新するか、新しいレコードを作成します。 5.1ドキュメントを検索しようとしましたが、必要な情報が見つかりませんでした。誰かが私をここに案内してもらえますか...

23
Neel

Eloquentモデルメソッド「updateOrCreate()」の定義に従って

関数updateOrCreate(array $ attributes、array $ values = []){}

それは2つの引数を取ります...

  1. 1つは、レコードが存在する場合にデータベースでチェックインするために使用する属性です
  2. 2番目は、作成または更新する新しい属性値です

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

Laravel 5.4を使用していますが、ON DUPLICATE KEY UPDATEに関連する答えが見つからないため、この質問に答えています。 LaravelのコアコードでupdateOrCreateメソッドを見ると、Laravelが2つの異なるクエリを使用していることがわかります。1つは更新用、もう1つは作成用です。 DBで重複データを取得します。そのため、この種の生のクエリを作成すると便利な場合があります。

DB :: statement( "INSERT INTO table_namecol_1col_2)重複キーの更新時の値(?、?)col_1 = col_1 + 1 "、([val_1、val_2]));

それが誰かに役立つことを願っています。

14
Hayk

MySQLの重複キーへの挿入で動作するパッケージを作成しました。

他の人に役立つかもしれません:

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

例:

/**
 * 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);
7
Yada

次のメソッドinsertUpdateをモデルに追加します

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

次を使用できます。

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

次のクエリが実行されます:

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'

有効または無効にした場合、メソッドはEloquentタイムスタンプを自動的に追加/削除します。

3
Marco Pedraza

laravel function pdateOrCreateを使用するには、テーブルでauto increment idが必要です。

彼らがやっていることは

select id from your_table where your_attributes

その後、自動インクリメントIDを取得します

それから

update your_table set your_values where field_id

3
Shanka SMS

私の場合、これはモデルテーブルの自動インクリメントキーの単純な不一致が原因でした。

現在の最大IDの取得:

SELECT max(id) from companies

次に、シーケンス値を1つ高く設定します。

select setval('companies_id_seq', 164);

エラーを解消しました。

1
Ben Wilson