1

I'm trying to create reference numbers for customers and orders based on this answer with the following requirements:

  • All numbers
  • Unique (as possible without checking the database)
  • Same length
  • Customers start with 10
  • Orders start with 20

Here is my current code for a customer ref:

$ref = uniqid();
$decimalRef = hexdec($ref);
$finalRef = 10 . $decimalRef;

Is this a good solution? I'm worried about uniqueness and not sure if they will always be the same length.

Update

I don't want to use a database auto increment value because I don't want to write to the database beforehand, and I don't want my customers knowing they are my customer number 2. For obvious reasons.

Update 2

If I was to use a database auto-increment value, how do I then convert this into a more appropriate customer facing number as per the requirements (same length, starting with 10). If I only have 4 orders in the system, I don't want to announcing that to my users.

Community
  • 1
  • 1
paul
  • 731
  • 2
  • 9
  • 13
  • 1
    If you're using a database, what's wrong with a simple incremental id? – Mark Baker Nov 19 '13 at 10:56
  • I need to generate the reference first to send it to a payment gateway, if the payment is successful then I will store it in the DB. Also, it is a customer facing reference, I don't want my customers thinking they are customer number 4. – paul Nov 19 '13 at 11:00
  • 1
    You can always create a record in a database, and if the payment fails then delete it again; but uniqid() isn't a good way of generating unique values - you'd need to do a database read to see if the value had already been allocated to a customer, and regenerate the id if necessary – Mark Baker Nov 19 '13 at 11:08
  • It won't be acceptable to slow down my application with a database write beforehand. And as mentioned there would be implications if customers realise they are customer number 2. Perhaps i'll update my question, but uniqid will unique enough. – paul Nov 19 '13 at 11:16
  • `It won't be acceptable to slow down my application with a database write beforehand.` ?? We are talking about usecs! – hek2mgl Nov 19 '13 at 11:23
  • So if I was to perform a database write, how do I take row ID '4' and convert it into something similar to my requirements. – paul Nov 19 '13 at 11:30

3 Answers3

0

You can try this.I am not sure about the uniqueness of this but is working form me.

// Generate a random character string
    function rand_str1($length = 8, $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890',$type)
    {
        // Length of character list
        $chars_length = (strlen($chars) - 1);

        // Start our string
        $string = $chars{rand(0, $chars_length)};

        // Generate random string
        for ($i = 1; $i < $length; $i = strlen($string))
        {
            // Grab a random character from our list
            $r = $chars{rand(0, $chars_length)};

            // Make sure the same two characters don't appear next to each other
            if ($r != $string{$i - 1}) $string .=  $r;
        }

        // Return the string
        if($type=="Customers")
        {
        return "10".$string."";
        }
        else if($type=="Orders")
        {
        return "20".$string."";
        }
    }
Vikas Umrao
  • 2,800
  • 1
  • 15
  • 23
0

Ok so to ensure the reference number is unique I should use an auto-increment database ID, not create my own.

paul
  • 731
  • 2
  • 9
  • 13
0

The uniqid() function generates a unique ID based on the microtime

This means if you can make sure no concurrent request for uniqid generation, it will be fine on that one server (because it bases on the system's time).

My suggestion is to combine it with any user session id or user id if they are available, as it is safe to assume that no one user can make two concurrent requests at the same time.

"10". hexdec(uniqid()).$userId ;//or hexdec(session_id()) instead of $userId

Updated: I am afraid that the hexdec function will return a value too big for the Int type. This is really an overkill. If the only concern is the order number, one can prefix the order number with a timestamp or similar or make the autoincreament start from 2000 instead of 0.

David Lin
  • 13,168
  • 5
  • 46
  • 46
  • will this always be the same length? If not how can I always make the id number the same length? – paul Nov 19 '13 at 16:45