1. 程式人生 > >Laravel一次更新多條記錄,批量更新的方法

Laravel一次更新多條記錄,批量更新的方法

在我們實際應用中,免不了這樣的情況——例如我們同時錄入多條資訊,可能三條五條還好說,但量一旦變大,就會增加讀寫資料庫的次數,會降低效率,那麼,我們該如何實現,做到一次讀寫資料庫,批量更新呢?

例如這種情況:


HTML程式碼:

<!doctype html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<form action="/enroll/complete_order_store" method='post'>
		{!!csrf_field()!!}
		@foreach($seats as $s) //多個座位資訊,每個都有他的ID
		<br>
		<br>
		<br>
		座位號:{{$s->id}}({{$s->rows.'排'.$s->cols.'座'}})
		<input type="hidden" name="id{{$s->id}}" value='{{$s->id}}'>
		<br>
		姓名:<input type="text" name="name{{$s->id}}" id="" value='{{$s->name}}'> //為了區別不同ID提交的不同name,所以在name後面加上了ID
		<br>
		手機:<input type="text" name="mobile{{$s->id}}" id="" value='{{$s->mobile}}'>
		<br>
		學校/單位:<input type="text" name="school{{$s->id}}" id="" value='{{$s->school}}'>
		<br>
		電子郵箱:<input type="text" name="email{{$s->id}}" id="" value='{{$s->email}}'>
		<br>
		是否需要發票: 是<input type="radio" name="is_bill{{$s->id}}" value='1' {{$s->is_bill == 1?'checked':''}}>否<input type="radio" name="is_bill{{$s->id}}" value='0' {{$s->is_bill == 0?'checked':''}}>
		<br>
		地址:<input type="text" name="address{{$s->id}}" id="" value='{{$s->address}}'>
		<br>
		郵編:<input type="text" name="post_code{{$s->id}}" id="" value='{{$s->post_code}}'>


		@endforeach
		<input type="hidden" name="ids" value='{{$ids}}'> //這裡ids是把所有id拼接成帶逗號的字串,例如 1,2,3
		<input type="submit" value="OK">
	</form>
</body>
</html>


處理思路,利用SQL WHEN THEN的方法,這個方法是我看 http://stackoverflow.com/questions/26133977/laravel-bulk-update裡的,提交的陣列應該是這種格式,主鍵放第一個

//test data
/*
$multipleData = array(
   array(
      'id' => 'My id' ,
      'name' => 'My Name 2' ,
      'date' => 'My date 2'
   ),
   array(
      'id' => 'Another id' ,
      'name' => 'Another Name 2' ,
      'date' => 'Another date 2'
   )
)
*/


    public function completeOrderStore(Request $request){
        $ids = Input::get('ids'); //拿到逗號分隔的字串,然後把他們變成陣列
        $arr = explode(',', $ids);
        $multipleData = []; 
        foreach($arr as $a){ //組成例子那樣的陣列
            $multipleData[] = ['id'=>$a, 
                               'name'=>Input::get('name'.$a),
                               'mobile'=>Input::get('mobile'.$a),
                               'school'=>Input::get('school'.$a),
                               'email'=>Input::get('email'.$a),
                               'is_bill'=>Input::get('is_bill'.$a),
                               'address'=>Input::get('address'.$a),
                               'post_code'=>Input::get('post_code'.$a)
                               ];
           
        }
        $res = $this->updateBatch('seats',$multipleData);
        return Redirect::to('/enroll/myorder');
    }

//同時更新多個記錄,引數,表名,陣列(別忘了在一開始use DB;)
    public function updateBatch($tableName = "", $multipleData = array()){

        if( $tableName && !empty($multipleData) ) {

            // column or fields to update
            $updateColumn = array_keys($multipleData[0]);
            $referenceColumn = $updateColumn[0]; //e.g id
            unset($updateColumn[0]);
            $whereIn = "";

            $q = "UPDATE ".$tableName." SET "; 
            foreach ( $updateColumn as $uColumn ) {
                $q .=  $uColumn." = CASE ";

                foreach( $multipleData as $data ) {
                    $q .= "WHEN ".$referenceColumn." = ".$data[$referenceColumn]." THEN '".$data[$uColumn]."' ";
                }
                $q .= "ELSE ".$uColumn." END, ";
            }
            foreach( $multipleData as $data ) {
                $whereIn .= "'".$data[$referenceColumn]."', ";
            }
            $q = rtrim($q, ", ")." WHERE ".$referenceColumn." IN (".  rtrim($whereIn, ', ').")";

            // Update  
            return DB::update(DB::raw($q));

        } else {
            return false;
        }

    }


大功告成,速度是不是提升了一大截~