Skip to content

Instantly share code, notes, and snippets.

@KerryJones
Created January 7, 2017 02:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KerryJones/b2c1361eaf40b29ed71370b418eea198 to your computer and use it in GitHub Desktop.
Save KerryJones/b2c1361eaf40b29ed71370b418eea198 to your computer and use it in GitHub Desktop.
Laravel 5.3 MySQL Upsert Trait
<?php
namespace App\Traits;
use Illuminate\Support\Facades\DB;
trait MySQLUpsert
{
/**
* Single call to insert/update based on any duplicate key (primary, unique, etc.)
*
* User::upsert(['email' => 'johndoe@gmail.com', 'name' => 'Johnny', 'phone' => '818-555-1234'], ['name', 'phone']);
*
* This will create the data with the initial values, if there is a duplicate,
* it will override the keys provided in the second optional array.
*
* @param array $array
* @param array $override (optional)
* @return mixed
*/
public static function upsert(array $array, $override = []) {
$class = get_called_class();
$object = new $class();
$table = $object->getTable();
$fillable = $object->getFillable();
$upsert_values = [];
$key_values = collect(array_keys($array))->reduce(function($previous, $key) use(&$array, $override, $fillable, &$upsert_values) {
if(!in_array($key, $fillable)) {
unset($array[$key]);
return $previous;
}
$previous['set'][] = '`' . $key . '` = ?';
if(in_array($key, $override)) {
$previous['upsert'][] = '`' . $key . '` = ?';
$upsert_values[] = $array[$key];
} else {
$previous['upsert'][] = '`' . $key . '` = VALUES(`' . $key . '`)';
}
return $previous;
}, ['set' =>[],'upsert' => []]);
$values = array_values($array);
DB::insert("INSERT INTO `$table` SET " . implode(',', $key_values['set']) . " ON DUPLICATE KEY UPDATE " . implode(',', $key_values['upsert']),
array_merge($values, $upsert_values)
);
foreach($array as $key => $value) {
$object->$key = $value;
}
return $object;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment