Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Eloquent Identity Laravel Package

sprocketbox/eloquent-identity

View on GitHub
Deep Wiki
Context7

Getting Started

Install and verify compatibility first. The package's last tagged release is from January 2021, so before anything else check composer.json for its Laravel/PHP constraints and confirm it installs cleanly against your app (Laravel 8/9-era code may need --with-all-dependencies, and Laravel 10/11 support is not guaranteed):

composer require sprocketbox/eloquent-identity

If the package ships a service provider and/or config file, publish it (php artisan vendor:publish) and skim the config before touching models——the defaults are what you'll be living with.

Where to look first. Read the README's trait section, then the package's Concerns/IdentityMap source. There are only two things you actually need to understand: (1) which trait you use on a model to opt it in, and (2) how instances are keyed (almost certainly model class + primary key) and where the map lives (static/global, so it persists for the life of the PHP process).

First use case. Apply the trait to a model you fetch repeatedly in one request:

class Post extends Model
{
    use \Sprocketbox\Eloquent\Identity\Concerns\HasIdentity; // confirm exact FQCN in README
}

Then:

$a = Post::find(1);
$b = Post::find(1);

var_dump($a === $b); // true — same object, not two hydrations

That's the whole value proposition: one row, one object, so mutable in-memory state can't diverge between two "copies" of the same record.

Set expectations correctly: this is not a query cache. Every find()/get() still runs SQL; the package only deduplicates the hydrated model. You're buying object identity, not fewer queries.

Implementation Patterns

Request-scoped, not application-scoped. Treat the map as living exactly as long as a single HTTP request. The moment you have a long-lived process (Octane, queue workers, artisan commands that loop), add a flush at the boundary:

// in a middleware terminate(), a job's handle() wrapper, or an Octane listener
app(IdentityMap::class)->flush(); // name per README

Without this, the map grows unboundedly across requests/jobs and you leak memory plus serve stale models between tenants.

Pass models around instead of IDs. The package shines in service/repository code that currently re-fetches to "be safe." With identity mapping you can thread a Post through three collaborators and know that a later Post::find($id) returns the same object any of them mutated. This is where === assertions and spl_object_id() checks become meaningful:

$this->assertSame($post, $service->loadPost($post->id));

Relations and eager loads. When you eager-load $posts->load('author') and separately Author::find($id), identity mapping collapses them into one instance — handy in view composers and API resources that touch the same parent from multiple places.

Testing. This is arguably the best day-to-day use: deterministic object identity in feature tests, so assertSame works and mutation assertions don't depend on which query loaded the model first. Add a flush() in setUp() (or a base TestCase) so tests stay isolated.

Custom keys. If you use UUIDs or composite keys, check whether key resolution is overridable before you commit — a package this small likely assumes a single auto-increment getKey(), and you don't want to discover that after wiring it into ten models.

Gotchas and Tips

  • Partially hydrated models poison the map. Post::select('id','name')->find(1) may register a model missing columns; a later Post::find(1) returns that same incomplete instance instead of a full row. Avoid column-limited selects on identity-mapped models, or flush around them.
  • Stale after out-of-band writes. The map only knows what went through Eloquent in this process. DB::table('posts')->update(...), a second connection, a queued job in another worker, or a cron job will all leave you reading stale attributes. For those paths, refresh()/fresh() behaviour is critical — verify empirically whether fresh() returns the cached instance or bypasses the map. That's the single most important thing to test before relying on this.
  • refresh() vs. the map. Confirm that refresh() actually reloads from the DB and updates the cached instance, rather than returning the stale cached object. Write one test for this; it will save you a production incident.
  • Soft deletes and global scopes. withTrashed(), onlyTrashed(), and withoutGlobalScopes() interplay is a classic identity-map edge case — deleting a model should remove it from the map, otherwise a trashed row keeps appearing.
  • chunk()/cursor() memory wins are lost. The map retains every hydrated model by design, so streaming large tables becomes more memory-hungry, not less. Flush between chunks for bulk jobs.
  • Don't use it everywhere. Apply the trait deliberately to models where identity semantics matter. Blanket-applying it maximises the stale-data and memory risks for negligible benefit on write-once tables (logs, pivots).
  • Debugging. When something looks stale, log count($map) and spl_object_id() before/after a fetch; confirm you're actually hitting the cache and not a second instance. If === is still false, the trait isn't on the model or the map was flushed between calls.
  • Version risk. With no release since early 2021, pin the version in composer.json, and expect to own the source if Laravel changes newFromBuilder()/Builder internals. Budget for a fork-and-patch path, and check the repo's issue tracker for the Laravel version matrix before you build a design around it.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle