Laravel 5.1 Create or Update on Duplicate

前端 未结 6 942
悲哀的现实
悲哀的现实 2020-12-03 01:29

In Laravel 5.1, for MySQL insert, I want to see if the record already exists and update on duplicate or create new if none exists.

I have already searched SO where t

相关标签:
6条回答
  • 2020-12-03 01:34

    Add the follow method insertUpdate to your Model

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

    You can use:

    App\User::insertUpdate([
        'name' => 'Marco Pedraza',
        'email' => 'mpdrza@gmail.com'
    ]);
    

    The next query it will be executed:

    insert into `users` (`name`, `email`, `updated_at`, `created_at`) values (?, ?, ?, ?) on duplicate key update `id` = LAST_INSERT_ID(id),`name` = 'Marco Pedraza',`email` = 'mpdrza@gmail.com',`updated_at` = '2016-11-02 01:30:05',`created_at` = '2016-11-02 01:30:05'
    

    The method automatically add/remove the Eloquent timestamps if you have enabled or disabled.

    0 讨论(0)
  • 2020-12-03 01:39

    In my case this was caused by a simple mismatch on the auto incrementing key in my model table.

    Getting the current max id:

    SELECT max(id) from companies
    

    Then setting the sequence value one higher:

    select setval('companies_id_seq', 164);
    

    eliminated the error.

    0 讨论(0)
  • 2020-12-03 01:41

    I created a package to work with MySQL insert on duplicate key.

    It may be useful for others:

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

    Example:

    /**
     * Class User.
     */
    class User extends Model
    {
        use Yadakhov\InsertOnDuplicateKey;
        ...
    }
    
    // associative array must match column names
    $users = [
        ['id' => 1, 'email' => 'user1@email.com', 'name' => 'User One'],
        ['id' => 2, 'email' => 'user2@email.com', 'name' => 'User Two'],
        ['id' => 3, 'email' => 'user3@email.com', 'name' => 'User Three'],
    ];
    
    User::insertOnDuplicateKey($users);
    
    0 讨论(0)
  • 2020-12-03 01:44

    To use laravel function updateOrCreate you need auto increment id in your table.

    what they are doing is

    select id from your_table where your_attributes

    after that get auto increment id

    then

    update your_table set your_values where field_id

    0 讨论(0)
  • 2020-12-03 01:52

    As per the Definition of the Eloquent Model Method "updateOrCreate()"

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

    it takes two argument ...

    1. one is the attributes using which you want to check in database if the record is present
    2. second is the new attribute values that you want to create or update

    AppInfo::updateOrCreate(['app_id' => $postData['appId']],
                            ['contact_email' => $postData['contactEmail']]);
    
    0 讨论(0)
  • 2020-12-03 01:53

    I am answering to this question cause I can't find any answer related to ON DUPLICATE KEY UPDATE, although I am using Laravel 5.4. If you look at the updateOrCreate method in the Laravel's core code, you will see after all Laravel is using 2 different queries: one for update and another one for create. Because of this, sometimes you can get duplicated data in the DB. So in some cases it can be useful to write this kind of raw query:

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

    Hope it can be useful for someone.

    0 讨论(0)
提交回复
热议问题