簡體   English   中英

如何處理 laravel 中的同時保存 API 請求?

[英]How to handle simultaneous save API requests in laravel?

我正在嘗試通過 API 保存新預訂。 以下是保存預訂 function 的示例代碼。

public function save_booking(Request $request){
        $booking = new Booking;
        $booking->booking_number            = generate_booking_id();
        $booking->booking_type              = $request->input('bookingType');
        $booking->booking_date              = $request->input('bookingDate');
        $booking->booking_time              = $request->input('bookingTime');
        $booking->booking_status            = $request->input('bookingStatus');
        $booking->save();
}

注意 - generate_booking_id() 是一個幫助器 function 來生成像 BN-202105-0001 這樣的預訂(最后四位數字 0001 是通過從預訂表中添加總記錄數 + 1 來計算的)。

當兩個或多個同時保存 API 請求嘗試保存新預訂時,將為兩個請求分配相同的預訂號。 (例如請求 1 = BN-202105-0001,請求 2 = BN-202105-0001 等等。)

我想為每個同時的 API 請求分配不同的預訂號。 (例如,有 4 個同時請求嘗試保存新預訂,然后請求 1 = BN-202105-0001、請求 2 = BN-202105-0002、請求 3 = BN-202105-0003、請求 4 = BN-202105-0004)

如何解決 Laravel 中的這個並發請求問題?

提前致謝!

發生這種情況是因為您的generate_booking_id()正在同時從兩個不同的請求中讀取數據庫並為您生成預訂 ID。

您可以避免這種情況,方法是在數據庫級別創建一個ON INSERT觸發器,如下所示,為您更新booking_number ,而不是手動執行。 觸發器將確保在創建預訂之后而不是之前自動更新booking_number

假設您使用的是 MySQL:(盡管如此,您可以在其他數據庫管理系統中使用相同的方法)

CREATE TRIGGER 'bookings'.'update_booking_number'
AFTER INSERT ON 'bookings' FOR EACH ROW
BEGIN
    UPDATE bookings b
      SET booking_number = (SELECT CONCAT('BN-202105-000',COUNT(*) + 1) FROM bookings) 
      WHERE b.id = NEW.id;
END;

另一種解決方案是先將預訂記錄插入數據庫,然后調用generate_booking_id() function 以正確計算預訂號碼,然后將記錄更新到數據庫中:

 public function save_booking(Request $request){
            $booking = new Booking;
            $booking->booking_type              = $request->input('bookingType');
            $booking->booking_date              = $request->input('bookingDate');
            $booking->booking_time              = $request->input('bookingTime');
            $booking->booking_status            = $request->input('bookingStatus');
            $booking->save();

            $booking->booking_number            = generate_booking_id();
            $booking->save();
            
    }

為簡單起見,您可以嘗試將 booking_number 設為 model 的屬性。 然后,此屬性將給定前綴與預訂的實際 id 結合起來。 這樣您就不需要創建自己的增量 function,只需組裝您已有的。

屬性示例:

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Booking extends Model
{
    use HasFactory;

    function getBookingNumberAttribute() {
        $date = Carbon::createFromFormat('Y-m-d', $this->attributes['booking_date']);
        $year = $date->year;
        $month = $date->format('m');
        $fourDigitId = sprintf('%04d', $this->attributes['id']);
        return "BN$year$month-$fourDigitId";
   }

    static function findByBookingNumber($booking_number) {
        $splitBookingNumber = explode('-', $booking_number);
        return self::where('id', intval($splitBookingNumber[1]));
   }
}

function getBookingNumberAttribute 用作屬性的訪問器booking_number ,因此當您運行時:

$now = Carbon::now();
$booking = Booking::create([
    'booking_date' => $now->format('Y-m-d'),
    'booking_time' => $now->format('H:i:s'),
    'booking_status' => 'new',
]);
dump($booking->booking_number);

您應該始終獲得一個新 ID,因為創建唯一 ID 的邏輯由 mysql 數據庫處理。

我還添加了一種方法來顯示如何通過預訂編號查找預訂。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM