Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

satz's avatar
Level 1

Custom Sequence Number Generation for Order

Hello,

I have planned a custom sequence number generation for Order Id using MYSQL stored procedures.

Eg, Order id : ORD000001

Any other suggestion and tips.

And let me know if you have already did this in any other method.

Best Regards, Satz

0 likes
12 replies
helgesverre's avatar

@mstnorris This is a 6 year old answer, but for others that wonder the same thing and finds this thread via google, in some countries (Ex: Most of Scandinavia), orders and invoices by law have to have sequential numbers (within the company).

1 like
bobbybouwmann's avatar

I think the best way would be writing your own function which checks for the last number or something

public function getNextOrderNumber()
{
    // Get the last created order
    $lastOrder = Order::orderBy('created_at', 'desc')->first();

    if ( ! $lastOrder )
        // We get here if there is no order at all
        // If there is no number set it to 0, which will be 1 at the end.

        $number = 0;
    else 
        $number = substr($lastOrder->order_id, 3);

    // If we have ORD000001 in the database then we only want the number
    // So the substr returns this 000001

    // Add the string in front and higher up the number.
    // the %05d part makes sure that there are always 6 numbers in the string.
    // so it adds the missing zero's when needed.
 
    return 'ORD' . sprintf('%06d', intval($number) + 1);
}
6 likes
vanderb's avatar

@bobbybouwmann Even if this post is 7 Years old, this snippet is very usefull. In order to add a prefix - e.g. the current year - and to reset incrementation on year-change here is a update for that snippet:


public function getNextOrderNumber()
{
  // Get the last created order
  $lastOrder = Order::orderBy('created_at', 'desc')->first();

  // Set Prefix
  $prefix = date('Y');

  // Set db-field
  $field = 'order_id';

  // Set length of incrementing number
  $length = 6;

  if (!$lastOrder) {
    // We get here if there is no order at all
    // If there is no number set it to 0, which will be 1 at the end.

    $number = 0;
  } else {
    // If we have ORD2023000001 in the database then we only want the number
    // So the substr returns this 000001
    $number = substr($lastOrder->{$field}, strlen($prefix));
  }

  // Reset incrementing no if prefix has changed (e.g. in new year)
  if (substr($lastOrder->order_no, 0, strlen($prefix)) !== $prefix) {
    $number = 0;
  }

  // Add the string in front and higher up the number.
  // the %05d part makes sure that there are always 6 numbers in the string.
  // so it adds the missing zero's when needed.

  return sprintf('%s%0' . $length . 'd', $prefix, intval($number) + 1);
}
1 like
Snapey's avatar

@vanderb by the time you have got half way through your function, some other thread is running and preparing the same number and prefix - ie, your code is not atomic and therefore NOT recommended.

vanderb's avatar

@Snapey Thanks for response. You're totally right and could end in bad conflicts on bigger projects.

This is only an updated version of the code by @bobbybouwmann that helped me out in smaller projects, without high traffic or multiple threads at same time. For bigger projects with high traffic/expected multiple threads I am using complete shopping solutions like aimeos etc.

bobbybouwmann's avatar

@mstnorris You clearly don't know anything about administration stuff. It's more useful to use a sequence here for administration purposes. It's also really easy to see which order you have in front. If you use a hashed id you will only see random characters...

1 like
satz's avatar
Level 1

@mstnorris & @bobbybouwmann : your both points are valid one.

I am going with the below approach.

  1. Order Id as normal Auto Generate Key
  2. Gonna create new column OrderNumber and use the hasids for Order ID

so user will see the order Number and admin will use the order id How about this.

Best Regards, Satz

mstnorris's avatar
Level 55

@satz that is what I would do personally, then depending on who needs to see the Order ID you can show the appropriate one.

Some use cases/examples:

It is far easier to keep the auto incrementing IDs as the primary key for the purpose of setting up model relationships. But you add the HashIds field for let's say, external users, where you might want a constant length of 7 characters, so that it can be easily identified without confusion.

On your site/app you can use the HashId to find and search for orders, and as there is no apparent sequence to them they won't be able to be guessed (not easily anyway).

I have set up HashIds for timesheet management, user management. With regards to the timesheet, I use it so employees can call in and quote their 5-character alphanumeric timesheet ID. It is much easier to understand 5 distinct characters instead of potentially 5 numbers.

AKmahato's avatar

@BOBBYBOUWMANN - I tried this way it's happening for the first time but when I insert the second record it should be incremented but it is not incrementing can you please help me resolve this

Please or to participate in this conversation.