RSS
 

Generate UUID in PHP

23 Feb

I posted this last year to PHP.net and thought I’d just share it here as well. It’s a short write-up and demonstration of a PHP class you can use to generate various versions of a Universally-Unique Identifier, or UUID.

The php5-uuid functions could definitely use some documentation to clarify how they should be used, but here’s what I’ve gleaned by examining the OSSP source code (found here: http://ossp-uuid.sourcearchive.com/documentation/1.5.1-1ubuntu1/php_2uuid_8c-source.html).

The uuid_make() function takes two arguments when generating v1 or v4, but four arguments are required when generating v3 or v5. The first two arguments have been thoroughly demonstrated and are straightforward, so I’ll skip to the as-yet non-described arguments.

The third argument to uuid_make() is: $namespace
– this is a secondary resource created with uuid_create(); it is apparently used to generate an internal UUID, which is used as the namespace of the output UUID

The fourth argument to uuid_make() is: $url
– this is the value that is to be hashed (MD5 for v3, SHA-1 for v5); it may be any string or even null

Here’s a simple class illustrating the proper usage (note that if php5-uuid is not installed on your system, each function call will just return false):

class UUID {
  /**
   * Generates version 1: MAC address
   */
  public static function v1() {
    if (!function_exists('uuid_create'))
      return false;

    $context = $uuid = null;
    uuid_create($context);
    uuid_make($context, UUID_MAKE_V1);
    uuid_export($context, UUID_FMT_STR, $uuid);
    return trim($uuid);
  }

  /**
   * Generates version 3 UUID: MD5 hash of URL
   */
  public static function v3($i_url) {
    if (!function_exists('uuid_create'))
      return false;

    if (!strlen($i_url))
      $i_url = self::v1();

    $context = $namespace = $uuid = null;
    uuid_create($context);
    uuid_create($namespace);

    uuid_make($context, UUID_MAKE_V3, $namespace, $i_url);
    uuid_export($context, UUID_FMT_STR, $uuid);
    return trim($uuid);
  }

  /**
   * Generates version 4 UUID: random
   */
  public static function v4() {
    if (!function_exists('uuid_create'))
      return false;

    $context = $uuid = null;
    uuid_create($context);

    uuid_make($context, UUID_MAKE_V4);
    uuid_export($context, UUID_FMT_STR, $uuid);
    return trim($uuid);
  }

  /**
   * Generates version 5 UUID: SHA-1 hash of URL
   */
  public static function v5($i_url) {
    if (!function_exists('uuid_create'))
      return false;

    if (!strlen($i_url))
      $i_url = self::v1();

    $context = $namespace = $uuid = null;
    uuid_create($context);
    uuid_create($namespace);

    uuid_make($context, UUID_MAKE_V5, $namespace, $i_url);
    uuid_export($context, UUID_FMT_STR, $uuid);
    return trim($uuid);
  }
}

And here’s a demonstration:

for ($i = 1; $i <= 3; ++$i) {
  echo 'microtime = ' . microtime(true) . '
'; echo "V1 UUID: " . UUID::v1() . '
'; echo "V3 UUID of URL='abc': " . UUID::v3('abc') . '
'; echo "V4 UUID: " . UUID::v4() . '
'; echo "V5 UUID of URL=null: " . UUID::v5(null) . '
'; echo '
'; }

And the output:

microtime = 1306620716.0457
V1 UUID: 7fddae8e-8977-11e0-bc11-003048c3b1f2
V3 UUID of URL='abc': 522ec739-ca63-3ec5-b082-08ce08ad65e2
V4 UUID: b3851ec7-4871-4527-92b5-ef5616bae1e6
V5 UUID of URL=null: e129f27c-5103-5c5c-844b-cdf0a15e160d
-------------------
microtime = 1306620716.0465
V1 UUID: 7fddb83e-8977-11e0-9e6e-003048c3b1f2
V3 UUID of URL='abc': 522ec739-ca63-3ec5-b082-08ce08ad65e2
V4 UUID: 7e78fe0d-59b8-4637-af7f-e88d221a7d1e
V5 UUID of URL=null: e129f27c-5103-5c5c-844b-cdf0a15e160d
-------------------
microtime = 1306620716.0467
V1 UUID: 7fddbfb4-8977-11e0-a2bc-003048c3b1f2
V3 UUID of URL='abc': 522ec739-ca63-3ec5-b082-08ce08ad65e2
V4 UUID: 12a940c7-0f3f-46a1-bb5f-bdd602e10654
V5 UUID of URL=null: e129f27c-5103-5c5c-844b-cdf0a15e160d

As you can see, the calls to v3() always return the same UUID because the same URL parameter, “abc”, is always supplied. The same goes for the v5() function which is always supplied a null URL.

The v4() UUIDs are always entirely different because they are (pseudo)random. And the v1() calls are very similar but just slightly different because it’s based on the computer’s MAC address and the current time.

 
3 Comments

Posted in PHP

 

49,988 views

Tags:

Leave a Reply

 

 
  1. mary

    August 22, 2012 at 10:55 pm

    UUID is not working in windows machine. please help.

     
  2. Vincent

    February 24, 2014 at 4:53 am

    The above code is no longer working. I received the following error

    Call-time pass-by-reference has been deprecated

     
  3. rommel

    February 24, 2014 at 6:09 am

    Hi Vincent-

    I have updated the code to include variable declarations and to remove the pass-by-reference ampersands from the function arguments, and that will resolve the “deprecated” warning in PHP 5.3 (which is an error in PHP 5.4).

    Thanks!