繁体   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