Skip to content
Greg Bowler edited this page Apr 19, 2026 · 2 revisions

Create a new Ulid() anywhere in your application, and you have a stringable object that can be used as the primary key in a database. Ulid strings look something like 01G2J6MYN0PGC5Q21W9C or can be prefixed with a type like CUSTOMER_01G2J6MYN0PGC5Q21W9C. They are cryptographically pseudo-random, and sort so that newer Ulids compare "greater than" older Ulids.

This solves the problems exposed with working with auto-incrementing integer primary keys, which are predictable and difficult to work with in distributed databases.

This library can be used when we want identifiers that:

  • do not expose sequential database IDs
  • can be created before a database insert happens
  • sort in creation order
  • carry a lightweight type prefix for readability

This library defaults to a compact 20-character identifier made from a 10-character timestamp section and a 10-character random section. If we need a different shape, both lengths can be configured.

What this library covers

  • Creating sortable IDs with new GT\Ulid\Ulid()
  • Adding uppercase prefixes such as INVOICE_
  • Reading timestamp and DateTime information back from an ID
  • Parsing existing ULID strings
  • Extracting prefixes, timestamps, and random sections explicitly
  • Converting to and from the library's Base32 alphabet

Recommended reading order

  1. Quick start guide
  2. Prefixes and typed identifiers
  3. Reading timestamp information
  4. Parsing existing ULIDs
  5. Custom lengths and timestamp sections
  6. Base32 encoding
  7. Examples

A small example

use GT\Ulid\Ulid;

$orderId = new Ulid("order");

echo $orderId, PHP_EOL;
echo $orderId->getTimestampString(), PHP_EOL;

Example output:

ORDER_01KPKT4PFTKVQ9P1E72F
01KPKT4PFT

The important thing to notice is that we do not have to manage any external state. We construct the object, use it as a string, and keep the helper methods nearby if we later want to inspect it.


Start with the Quick start guide to build the smallest useful setup from scratch.

Clone this wiki locally