How to create a MongoDB ObjectID from a timestamp using PHP

This is a useful tidbit of code to have until PHP adds this feature into their MongoDB extension. I stumbled on an example on Stack Overflow illustration showing how to do this and rewrote it in what I think is a slightly more modern way that does the same thing.

ObjectId’s are constructed using a 4-byte timestamp value, 3-byte machine identifier, 2-byte process id, and a 3-byte counter which create a 12-byte BSON type:


 --------------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|---------------|-----------|-------|--------------|
| time          | machine   | pid   | counter      |
 --------------------------------------------------

Knowing that makes this PHP code easy to understand:

MongoUtil:

/**
 * Class MongoUtil.
 */
class MongoUtil {

    /**
     * This is needed to keep documents unique that have the same timestamp.
     * @var integer
     * @see $timestamp
     */
    public static $_mongoIdFromTimestampCounter = 0;

    /**
     * Mongo Id From Timestamp
     * @param integer $timestamp
     * @return MongoID
     * @see http://docs.mongodb.org/manual/reference/object-id/
     */
    public static function mongoIdFromTimestamp( $timestamp ) {
        // Build Binary Id
        $binaryTimestamp = pack('N', $timestamp); // unsigned long
        $machineId = substr(md5(gethostname()), 0, 3); // 3 bit machine identifier
        $binaryPID = pack('n', posix_getpid()); // unsigned short
        $counter = substr(pack('N', self::$_mongoIdFromTimestampCounter++), 1, 3); // Counter
        $binaryId = "{$binTimestamp}{$machineId}{$machineId}{$counter}";

        // Convert to ASCII
        $id = '';
        for ($i = 0; $i < 12; $i++) {
            $id .= sprintf("%02X", ord($binaryId[$i]));
        }

        // Return Mongo ID
        return new MongoID($id);
    }

}

Example of usage:

$date = strtotime('today');
$mongoId = MongoUtil::mongoIdFromTimestamp( $date );

// Do more stuff.
Mar 31, 2014 Programming

Support this blog

Buy yourself ANYTHING!

That's right! Shop as you normally would using Amazon.com with my affiliate link and the commissions made go directly into keeping this blog healthy. It's that simple! The hardware and software costs used for this site comes out of my own pocket and it's expensive. Lets keep this site ad free :)

Start shopping on Amazon.com now!

Thank you!
Richard S.