BatchUpdateService.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. <?php
  2. namespace App\Services\common;
  3. use App\Components\ErrorPush;
  4. use Illuminate\Support\Facades\DB;
  5. use App\Traits\ServiceAppAop;
  6. class
  7. BatchUpdateService
  8. {
  9. use ServiceAppAop,ErrorPush;
  10. public function batchUpdate($tableName = '', $multipleData = array(), $connection = 'mysql')
  11. {
  12. if (count($multipleData) == 1) {
  13. return false;
  14. }
  15. if ($tableName ?? false && !empty($multipleData)) {
  16. // column of fields to update
  17. $updateColumns = $multipleData[0];
  18. // table primary key
  19. $referenceColumn = $updateColumns[0];
  20. unset($multipleData[0]);
  21. if (count($multipleData) <= 200) {
  22. return $this->batchHandle($tableName, $updateColumns, $referenceColumn, $multipleData, $connection);
  23. } else {
  24. $chunk_datas = array_chunk($multipleData, 200, true);
  25. $bool = true;
  26. foreach ($chunk_datas as $chunk_data) {
  27. $is_successful = $this->batchHandle($tableName, $updateColumns, $referenceColumn, $chunk_data, $connection);
  28. $bool = $is_successful && $bool;
  29. }
  30. return $bool;
  31. }
  32. } else {
  33. return false;
  34. }
  35. }
  36. private function batchHandle($tableName, $updateColumns, $referenceColumn, $multipleData, $connection = 'mysql')
  37. {
  38. $updateSql = "UPDATE " . $tableName . " SET ";
  39. $sets = [];
  40. $bindings = [];
  41. foreach ($updateColumns as $updateColumn) {
  42. $setSql = ' `' . $updateColumn . '` = CASE';
  43. foreach ($multipleData as $multipleDatum) {
  44. $setSql .= ' WHEN ' . $referenceColumn . ' = ? THEN ? ';
  45. $bindings[] = $multipleDatum[$referenceColumn];
  46. $bindings[] = $multipleDatum[$updateColumn];
  47. }
  48. $setSql .= ' ELSE `' . $updateColumn . "` END";
  49. $sets[] = $setSql;
  50. }
  51. $updateSql .= implode(',', $sets);
  52. $whereIn = data_get($multipleData, '*.' . $referenceColumn);
  53. $bindings = array_merge($bindings, $whereIn);
  54. $whereIn = rtrim(str_repeat('?,', count($whereIn)), ',');
  55. $updateSql = rtrim($updateSql, ", ") . " WHERE `" . $referenceColumn . "` IN (" . $whereIn . ")";
  56. $debug = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT ,1)[0];
  57. unset($debug["object"]);
  58. unset($debug["args"]);
  59. try {
  60. // DB::update
  61. $bool = DB::connection($connection)->update($updateSql, $bindings);
  62. app('LogService')->log(__METHOD__, __FUNCTION__, '批量更新:' . $tableName . ' | '.json_encode($multipleData).' | 溯源:'.json_encode($debug));
  63. if (($tableName == 'authorities' || $tableName == 'menus') && env('APP_ENV')=='production'){
  64. $myfile = fopen(base_path()."\\database\\data\\{$tableName}.data", "a+");
  65. fwrite($myfile, vsprintf(str_replace('?',"'%s'",$updateSql), $bindings).";\r\n");
  66. fclose($myfile);
  67. }
  68. return $bool;
  69. } catch (\Exception $e) {
  70. $this->push(__METHOD__."->".__LINE__,"批量更新失败",$tableName . ' | '.json_encode($multipleData).' | 溯源:'.json_encode($debug) . $e->getMessage() . $e->getTraceAsString());
  71. return false;
  72. }
  73. }
  74. public function batchUpdateItself($tableName, $column, array $params, $connection = 'mysql')
  75. {
  76. $sql = "UPDATE ".$tableName;
  77. $sql .= " SET ".$column." = CASE ".$column;
  78. foreach ($params as $key => $value){
  79. $sql .= " WHEN ".$key." THEN ".$value;
  80. }
  81. $sql .= " END WHERE ".$column." IN (".implode(',',array_keys($params)).")";
  82. try {
  83. $bool = DB::connection($connection)->update($sql);
  84. app('LogService')->log(__METHOD__, __FUNCTION__, '批量更新本身' .$sql);
  85. return $bool;
  86. }catch (\Exception $e){
  87. $this->push(__METHOD__."->".__LINE__,"批量更新失败",'SQL:(' . $sql .") 堆栈:". $e->getMessage() . $e->getTraceAsString() . $e->getMessage() . $e->getTraceAsString());
  88. return false;
  89. }
  90. }
  91. }