[英]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.