PHPackages                             slime-systems/eloquent-object-id - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. slime-systems/eloquent-object-id

ActiveLibrary[Database &amp; ORM](/categories/database)

slime-systems/eloquent-object-id
================================

MongoDB-style BSON's ObjectId for Eloquent and Laravel. Provides unique, chronologically ordered IDs.

1.0.0(7mo ago)10BSD-2-ClausePHPPHP &gt;=8.1CI passing

Since Nov 21Pushed 7mo agoCompare

[ Source](https://github.com/slime-systems/eloquent-object-id)[ Packagist](https://packagist.org/packages/slime-systems/eloquent-object-id)[ RSS](/packages/slime-systems-eloquent-object-id/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (6)Versions (2)Used By (0)

Eloquent Object ID
==================

[](#eloquent-object-id)

MongoDB-style BSON's ObjectId for Eloquent and Laravel.

[![PHP Composer](https://github.com/slime-systems/eloquent-object-id/actions/workflows/php.yml/badge.svg)](https://github.com/slime-systems/eloquent-object-id/actions/workflows/php.yml)[![Packagist Version](https://camo.githubusercontent.com/503e6b9469042497520b1ac08c60b1cae49bde603f7a0303d3ba04f89b413208/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f736c696d652d73797374656d732f656c6f7175656e742d6f626a6563742d6964)](https://packagist.org/packages/slime-systems/eloquent-object-id)

 [![Your Project Logo](./assets/logo.webp)](./assets/logo.webp)

✨ Features
----------

[](#-features)

- **Decentralized Generation**: Create IDs on the fly without hitting the database.
- **No Collisions**: Statistically unique IDs for distributed systems.
- **Chronological Sorting**: IDs are naturally ordered.
- **High Performance**: Storage-efficient binary-packed format results in better indexing and faster queries.
- **Batteries Included**: Integrated with Laravel’s Eloquent ORM.

📦 Installation
--------------

[](#-installation)

Install the package via Composer:

```
composer require slime-systems/eloquent-object-id
```

🤔 Why ObjectIDs?
----------------

[](#-why-objectids)

Before diving into how to use ObjectIDs, it's important to understand **why they are so useful**. The ObjectID is a remarkable invention, offering significant benefits beyond a simple unique identifier.

### The Basic

[](#the-basic)

An ObjectID is a type of identifier, similar to Eloquent’s default incremental ID, used to reference a specific entity in the system.

ObjectIDs are powerful because they can be **generated independently and in a decentralized manner** by any trusted party. This eliminates the need to rely on a database or a centrally managed registry during ID creation. The generated IDs are designed to be sufficiently unique for most use cases, making **collisions highly unlikely**.

### ObjectID is More Than a Generic ID

[](#objectid-is-more-than-a-generic-id)

ObjectIDs inherently contain a timestamp. This property is extremely useful, for example, when performing time-based queries:

Suppose we want to count the cats registered in the past week:

```
$end = Carbon::now('Asia/Tokyo')->startOfWeek();
$start = ObjectId::fromTime($end->subWeek(), unique: false);
$end = ObjectId::fromTime($end, unique: false);

$lastWeekCatCount = Cat::where('id', '>=', OI::val($start))
    ->where('id', '', $lastKnownCat->id)
    ->orderBy('id')
    ->limit($perPage)
    ->get();
```

This query is fast because the `where('id', '>', ...)` condition can efficiently leverage the primary key index for lookup.

Attempting the same with only a timestamp field has a critical flaw:

```
Cat::where('created_at', '>', $lastKnownCat->created_at)
    ->orderBy('created_at')
    ->limit($perPage)
    ->get();
```

While this could be fast if `created_at` is indexed, the logic is broken because the `created_at` timestamp is not guaranteed to be unique. If two entities are created in the same second, this query might incorrectly skip or miss records.

Guess what else is chronologically ordered and guaranteed to be unique?

```
Cat::where('id', '>', OI::val($lastKnownCat->id))
    ->orderBy('id')
    ->limit($perPage)
    ->get();
```

That's right: **ObjectID**!

### ObjectID is Also More Than an Incremental ID

[](#objectid-is-also-more-than-an-incremental-id)

A major limitation of traditional keyset (or cursor) pagination, when relying only on a sequential incremental ID, is the inability to **jump to an arbitrary point** in the dataset; users must navigate linearly from the start or from a known cursor.

This is where the **ObjectID's embedded timestamp** provides a unique advantage, transforming the approach to pagination by enabling **chronological chunking and navigation**.

The embedded time component allows developers to define predictable boundaries in the collection—like the start of a month or year—and generate an optimized cursor for that boundary without needing to query for a specific ID first.

This capability unlocks powerful UX patterns:

- **Archival Navigation:** Users can view a collection organized into **monthly or yearly "archive boxes"** (e.g., "See all posts from December 2024"), making large datasets feel organized and intuitive.
- **Time-Based Jumping:** Users can instantly jump to a specific time in a feed (e.g., a social media feed or log history) instead of scrolling endlessly.
- **Keyset Efficiency Retained:** Regardless of the time-based jump, the subsequent fetching of records remains fast because it leverages the index.

In essence, ObjectID provides the efficient scanning of incremental IDs while adding the **random-access power of an embedded timestamp**, making complex archival navigation simple and performant.

### Various Ways to Utilize This Invention

[](#various-ways-to-utilize-this-invention)

As demonstrated, the ObjectID gives you the best of what both a timestamp and a unique, incremental ID have to offer. There is more than one way to utilize this powerful identifier. Have fun explore its full potential!

#### Note on Usage

[](#note-on-usage)

In the following section, I will use ObjectID as a drop-in replacement for Eloquent's incremental ID.

While I do provide the helper function `OI::setDefault`, I personally do not believe this is the most effective or interesting way to utilize ObjectIDs.

If you bring forth the ObjectID's full potential, you'll likely find yourself not needing to use `OI::setDefault` at all.

🚀 Usage
-------

[](#-usage)

### Database Migration

[](#database-migration)

Use the `objectId` column type in your migrations. This creates a binary column suitable for storing the ObjectId.

```
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::create('cats', function (Blueprint $table) {
    $table->objectId('id')->primary(); // string('name');
});
```

### Model Setup

[](#model-setup)

In your Eloquent model, cast the field using `SlimeSystems\EloquentObjectId\ObjectIdCast`.

```
use Illuminate\Database\Eloquent\Model;
use SlimeSystems\EloquentObjectId\ObjectIdCast;

class Cat extends Model
{
    public $timestamps = false;
    protected $guarded = []; // for demonstration purposes

    protected $casts = [
        'id' => ObjectIdCast::class,
    ];
}
```

### Auto-generating IDs

[](#auto-generating-ids)

Models can be configured to autogenerate an ObjectId. An example using the `OI::setDefault` helper in the `booted` method is provided below.

```
use Illuminate\Database\Eloquent\Model;
use SlimeSystems\EloquentObjectId\ObjectIdCast;
use SlimeSystems\EloquentObjectId\OI;

class Cat extends Model
{
    protected $casts = [
        'id' => ObjectIdCast::class,
    ];

    protected static function booted()
    {
        static::creating(OI::setDefault('id')); //  'Luna']);

// Create with explicit ID
$id = new ObjectId;
Cat::create(['id' => $id, 'name' => 'Peanut']);

// Examples
$cat = Cat::latest()->first();
$cat->id->toString();  // a hex string
$id->equals($cat->id); // true
```

You can access all `SlimeSystems\ObjectId` methods documented at .

### Querying

[](#querying)

`OI::val()` can be used to ensure that ObjectId is correctly formatted for compatibility with Eloquent queries.

```
use SlimeSystems\EloquentObjectId\OI;
use SlimeSystems\ObjectId;

$someId = new ObjectId;

// Find by ID
$cat = Cat::find(OI::val($someId));

// Comparison queries
$cats = Cat::where('id', '>', OI::val($someId))->get();

// `::val` also ensures compatibility with hexadecimal and binary formats of ObjectId
$cat = Cat::find(OI::val('0123456789abcdef1011121')); //
