Laravel - 生成唯一订单号

6

我现在正在尝试在用户到达创建方法时生成唯一的订单号。订单号是在种子中生成的,需要像这样看起来:

种子

foreach(range(1,25) as $index)
    {
        DB::table('orders')->insert([

            'user_id' => rand(1,25),
            'order_nr' => '#' . sprintf("%08d", $index),
            'price_sum' => $faker->randomNumber($nbDigits = 4, $strict = false) . '.' . $faker->randomNumber($nbDigits = 2, $strict = false),
            'status' => $faker->randomElement(['paid', 'pending', 'failed']),
            'created_at' => Carbon::now(),
            'updated_at' => Carbon::now(),

        ]);
    }

订单号看起来像这样#00000001#00000002。当用户到达控制器中的创建方法时,需要创建一个新的唯一订单号。如何实现?控制器当前如下所示:
 public function create()
{
    $order = new Order;

    $order->user_id = Auth()->id();
    $order->order_nr = 


    dd($order);


    return view('steps.order');
}

需要检查最新的订单号并在该订单号上+1创建一个新的。例如,有25个订单,最后一个是#00000025,下一个需要创建的订单应该是#00000026。我该如何实现这一点?

6个回答

15

尝试按照以下步骤操作

$order = new Order;

$order->user_id = Auth()->id();
$latestOrder = App\Order::orderBy('created_at','DESC')->first();
$order->order_nr = '#'.str_pad($latestOrder->id + 1, 8, "0", STR_PAD_LEFT);
$order->save();

在这里,我假设ID是自增的。详细了解请参阅str_pad方法。


2
这对我来说解决了问题。谢谢! - user5838715
1
我不确定这个解决方案是否可行。假设我有以下订单:[1 => order1, 2 => order2, 3 => order3, ];您的订单将作为电子邮件发送给下单的客户或其他人。订单链接将是www.blah/order3。但是,如果我删除了第三个订单,并且它在客户的邮箱中,然后我创建一个新订单并使用相同的名称,则新订单也将具有相同的链接。这样链接就会变得不正确。我不知道这是否符合您的用例,但最好记住这一点。@RainierLaan - Epsilon47
也许我误解了,但为什么不使用MySQL,在所需的ID列上使用INT(8)ZEROFILL来实现自动增量或外键引用? - HelloSpeakman
@Epsilon47 当用户到达一个屏幕,查看他们订单的总金额时,他们会有两个选项。要么不付款,这意味着删除整个订单,或者选择付款,填写余下的数值并使其成为永久订单。一旦用户付款,就没有办法从系统中删除订单。因为首先为什么他们要这样做呢?只有在用户决定删除他/她的账户之后,订单才会被删除。在此之前,订单将保留。这是正确的思考方式,甚至处理方式吗? - user5838715
@RainierLaan 我认为你根本不应该删除订单,或者考虑使用软删除(我不确定在这种情况下id的行为如何)。因为你可能会遇到我所写的问题。所以如果你想要删除它们,我会使用随机数而不是有序数,或者干脆不删除它们。或者在存储之前,我会检查是否已经存在具有此id的订单。 - Epsilon47
@RainierLaan 或者你可以在表格中使用另一列,如 is_active,它将是布尔类型,默认为真。如果有人删除了他们的帐户,你可以将其设为假。只是一个想法。 - KalyanLahkar

5
使用行的自动列id值生成订单号。但是,不要为订单号创建额外的列,因为这将给您一个非规范化的数据库,因为订单列完全依赖于id列。
相反,将此方法添加到您的order模型中。
public function get_order_number()
{
    return '#' . str_pad($this->id, 8, "0", STR_PAD_LEFT);
}

如果您的最后一个订单ID是5,并且您要删除它,那么下一个订单的ID将为6
唯一的例外情况是如果您在事务中创建订单。如果事务回滚,则相关联的订单ID将被跳过。

5
你可以使用Laravel ID生成器
首先安装它: composer require haruncpi/laravel-id-generator 在你的控制器中导入这个类。
use Haruncpi\LaravelIdGenerator\IdGenerator;

现在只需使用它即可。

$prefix = "#";  
$id = IdGenerator::generate(['table' => 'your_table_name', 'length' => 9, 'prefix' =>$prefix]);

输出

#00000001
#00000002
#00000003
...

只是评论一下,至少在 Laravel 8 中,如果要填充的字段不是数据库中的 id 字段而是自定义字段,则此包似乎存在错误。该包不使用 ID 字段的实际 ID 号码,而是从 1 开始。然后一旦达到 10,它就会再次从 1 开始生成非唯一的 ID。 - m33ts4k0z

2

在读取最大值并增加它的过程中存在问题。在高负载服务器或并发请求时,两个请求可能会从MySQL中读取相同的max(id)。

创建唯一序列号的最佳方法是使用一个只有一个自动增量字段的序列表。

  1. 首先,在序列表中插入新记录。
  2. 然后通过LAST_INSERT_ID() MySQL函数从数据库中读取最后插入的id。
  3. 最后,您可以删除低于您的id的旧记录。

Laravel方式:

$id = DB::table('seq_foo')->insertGetId(['id' => null]);
DB::table('seq_foo')->where('id', '<', $id)->delete();

$id is your unique sequence number.


1
你可以试试这个:

public function generateOrderNR()
{
    $orderObj = \DB::table('orders')->select('order_nr')->latest('id')->first();
    if ($orderObj) {
        $orderNr = $orderObj->order_nr;
        $removed1char = substr($orderNr, 1);
        $generateOrder_nr = $stpad = '#' . str_pad($removed1char + 1, 8, "0", STR_PAD_LEFT);
    } else {
        $generateOrder_nr = '#' . str_pad(1, 8, "0", STR_PAD_LEFT);
    }
    return $generateOrder_nr;
}

您可以通过在create()函数中使用$this->generateOrderNR();来生成order_nr
此外,mt_rand()rand()快4倍,您可以使用它来提高用户体验。

0

我找到了一个更好的解决方案:

$paynowbillprefix1="ADDON-";
$paynowbillprefix1=strlen($paynowbillprefix1);
$query2 = "select gen_id from user_cart_addon order by id desc limit 0, 1";
$exec2 = mysqli_query($conn,$query2) or die ("Error in Query2".mysqli_error());
$res2 = mysqli_fetch_array($exec2);
$num2 = mysqli_num_rows($exec2);
$billnumber = $res2["gen_id"];
$billdigit=strlen($billnumber);
if ($billnumber == '')
{
    $billnumbercode ='ADDON-'.'1';
}
else
{
    $billnumber = $res2["gen_id"];
    $billnumbercode = substr($billnumber,$paynowbillprefix1, $billdigit);
    $billnumbercode = intval($billnumbercode);
    $billnumbercode = $billnumbercode + 1;
    $maxanum = $billnumbercode;   
    $billnumbercode = 'ADDON-'.$maxanum;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接