UUID / GUID in native PHP…

In the course of my development efforts it has become fairly clear that I need to make use of a more cross platform and cross server identifier for certain content objects. The common tactic of using a database column that automatically increments has fallen pretty flat for this – it is almost guaranteed to collide if you try and merge tables or data in the future. The code is below the fold!

Microsoft databases have the concept of a [[wp;GUID]]  that they implement in a nice simple manner and that is supported well in .NET.Nothing similar exists in MySQL and PHP at the moment, though some tantalizing hints existed. Long and short of it, I solved the problem, or at least I have an early attempt at solving the problem. Compare it to the numbers you can get at this online UUID generator.

This code is a combination of…

So enjoy it, and please [[let me know]] if I missed anything! BOh, and a CHAR(32) in MySQL is a good place to store these.

// -_-_–_-_–_-_–_-_—

// build a UUID or GUID via PHP
// may or may not be Microsoft GUID compatible
// thanks to all the internet code examples!
//
// contact me with corrections and changes please,
// [email protected]
//
// 10/29/2004 – v1.0
//
// Do whatever you want with this code, it’s in the public domain

$rawid = strtoupper(md5(uniqid(rand(), true)));
$workid = $rawid;

// hopefully conform to the spec, mark this as a “random” type
// lets handle the version byte as a number
$byte = hexdec( substr($workid,12,2) );
$byte = $byte & hexdec(“0f”);
$byte = $byte | hexdec(“40”);
$workid = substr_replace($workid, strtoupper(dechex($byte)), 12, 2);

// hopefully conform to the spec, mark this common variant
// lets handle the “variant”
$byte = hexdec( substr($workid,16,2) );
$byte = $byte & hexdec(“3f”);
$byte = $byte | hexdec(“80”);
$workid = substr_replace($workid, strtoupper(dechex($byte)), 16, 2);

// build a human readable version
$rid = substr($rawid, 0, 8).’-‘
    .substr($rawid, 8, 4).’-‘
    .substr($rawid,12, 4).’-‘
    .substr($rawid,16, 4).’-‘
    .substr($rawid,20,12);

// build a human readable version
$wid = substr($workid, 0, 8).’-‘
    .substr($workid, 8, 4).’-‘
    .substr($workid,12, 4).’-‘
    .substr($workid,16, 4).’-‘
    .substr($workid,20,12);

// -_-_–_-_–_-_–_-_—

An example of the output….

A2C2817A-F2CE-49B1-BF4C-DB0961998E2A
9BCF2CD8-A5E5-4331-BD71-491804CE6ED6
575D3B15-19ED-4A50-A773-0FFD3631F391
AF457D46-7BF6-4F7F-B718-47EAD9FCD47E
8138B63D-0CC1-4E35-8641-A67FF0D3486D
6F4AD196-45FD-4B4D-88F7-68F9C009365C
930ED1AB-4335-4DF2-AB05-DFFC3E349295
B6097E8A-3CAD-492B-9DB9-59697AE97BA6
7944D65B-82DB-4946-81F5-D6527227D422
15BC5F60-B731-4C0B-9F88-8C71F1196FE1

5 Responses

  1. Thanks for putting this together. I was looking for some GUID support for php. Its a shame that its not part of the core. You think something like this would be needed by enough people to consider it

  2. The sites referred to a http://kruithof.xs4all.nl/uuid/uuidgen and http://kruithof.xs4all.nl/guid-uuid-random.html have been moved to
    http://www.famkruithof.net/uuid/uuidgen (and http://www.famkruithof.net/guid-uuid-random.html)

    While the old version of the page was written as a Java Servlet the new version has completely been rewritten in PHP. I have chosen a somewhat different approach for the generation of the random positions, by plainly generating multiple random numbers, each responsible for part of the string.

  3. Hello,

    I used your code as a basis for a UUID class in the framework I’m writing.

    http://coreforge.org/snippet/detail.php?type=snippet&id=3

    I actually use them as both session ids, and encryption keys for the session handler:

    http://coreforge.org/snippet/detail.php?type=snippet&id=1

    As for storing them, I use a postgres domain to hold them:

    CREATE DOMAIN “UUID” AS character(38) DEFAULT ‘{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}’::bpchar
    CONSTRAINT “UUID_check” CHECK ((VALUE ~ ‘^{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}}$’::text));

    They are stored in between brackets, similar to how Windows does it.

  4. Martijn,

    How easy would it be to make a “Time-based UUID” following your example shown above? I believe they are version 1 uuid’s?

Comments are closed.