-
Star
(122)
You must be signed in to star a gist -
Fork
(38)
You must be signed in to fork a gist
-
-
Save RuGa/5354e44883c7651fd15c to your computer and use it in GitHub Desktop.
/** | |
* Mass (bulk) insert or update on duplicate for Laravel 4/5 | |
* | |
* insertOrUpdate([ | |
* ['id'=>1,'value'=>10], | |
* ['id'=>2,'value'=>60] | |
* ]); | |
* | |
* | |
* @param array $rows | |
*/ | |
function insertOrUpdate(array $rows){ | |
$table = \DB::getTablePrefix().with(new self)->getTable(); | |
$first = reset($rows); | |
$columns = implode( ',', | |
array_map( function( $value ) { return "$value"; } , array_keys($first) ) | |
); | |
$values = implode( ',', array_map( function( $row ) { | |
return '('.implode( ',', | |
array_map( function( $value ) { return '"'.str_replace('"', '""', $value).'"'; } , $row ) | |
).')'; | |
} , $rows ) | |
); | |
$updates = implode( ',', | |
array_map( function( $value ) { return "$value = VALUES($value)"; } , array_keys($first) ) | |
); | |
$sql = "INSERT INTO {$table}({$columns}) VALUES {$values} ON DUPLICATE KEY UPDATE {$updates}"; | |
return \DB::statement( $sql ); | |
} |
Why is this not in Laravel as default?! 👍 💯
Works perfectly, love it. Saved me many queries!
🔥
+1 this should be in laravel by default
This still is working till today.. super thanks 👍 💯
Work fine, I used this to migrate millions rows.
I just add this to handle null value (which should not be replace by empty string) :
return ($value !== '' && $value !== null) ? '"'.str_replace('"', '""', $value).'"' : 'null';
This was really helpful. I'll add for anyone needing it - if you want to omit a "created_at" timestamp you can inject this right before the $updates variable:
if(isset($first['created_at'])) { unset($first['created_at']); }
This will keep the created date from being updated.
This is not firing model events. It's a bad code when using model events and observers.
It also doesn't protect against SQL injection
I need help creating something similar for a PHP form. I have tried a few ways but I am not getting it to work. Would appreciate it if anyone here would be willing to help me out.
It is better to use \DB::connection()->getPdo()->quote($value) instead of str_replace because of the problem when values contain slashes. Just replace the corresponding code with this:
...
$values = implode( ',', array_map( function( $row ) {
return '('.implode( ',',
array_map( function( $value ) { return \DB::connection()->getPdo()->quote($value); } , $row )
).')';
} , $rows )
);
...
where are you guys putting this code! In controller or method!
@rassemdev it would be in your specific model file. I would make it a trait to be able to reuse it on other models or implement it on Model.php (all models extends this one)
@rassemdev it would be in your specific model file. I would make it a trait to be able to reuse it on other models or implement it on Model.php (all models extends this one)
Yeah, but the class Model is part of a vendor package. Do not update dependencies that are not your own because they might change in the future. Create a trait and use it in the models that need it, it is quite possible that not all of them will use this functionality.
@rassemdev it would be in your specific model file. I would make it a trait to be able to reuse it on other models or implement it on Model.php (all models extends this one)
you can't create it as a trait to your models, because it can work only with single object. But must work with bunch of them. So in this case trait a good idea for repositories, but not for models.
This code is totally vulnerable to SQL injection attacks.
does this work without composite keys ? I want to mass update but it requires me 7 composite keys to detect duplicate due to extremely poor constructed data from amazon api.
👍 💯