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 Hashids Laravel Package

matt-daneshvar/eloquent-hashids

Laravel package that adds Hashids support to Eloquent models, hiding auto-increment IDs behind short, reversible hashes. A trait encodes route keys and resolves models from hashids, keeping URLs clean and database IDs private with minimal setup.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package is a single Eloquent concern that hooks model lifecycle events to compute and persist a Hashids-encoded value on create. That is idiomatic Laravel: low surface area, no service provider gymnastics, no runtime interception of the query builder. Architecturally it fits cleanly into any Eloquent-based service that needs opaque external identifiers.

Integration feasibility. The blocker is not design, it is the dependency graph. The last release is June 2019 — prior to Laravel 6 LTS GA — so composer.json almost certainly pins illuminate/* to the 5.5–5.8 range and PHP to 7.1/7.2. On Laravel 10/11/12 (PHP 8.1+) composer require will fail resolution. Forcing it with --ignore-platform-reqs or version aliasing is not defensible for a production system.

Technical risk — high, on three independent axes.

  1. Abandonment. Repository is archived: read-only, no issue triage, no security response, no framework-upgrade PRs.
  2. Transitive decay. It depends on hashids/hashids, whose upstream is itself effectively retired and superseded by Sqids. You inherit two unmaintained layers.
  3. Conceptual misuse. Hashids is reversible obfuscation, not encryption. Anyone holding the salt can decode every identifier. If the hashid is derived deterministically from the primary key, the salt becomes a full enumeration key. This must be treated as a cosmetic control, never an access-control boundary.

Key questions to answer before any code is written.

  • Is the hashid derived deterministically from the primary key, or randomly generated? Deterministic means no collision handling but full reversibility; random means a unique index and a retry loop are mandatory.
  • Which events are hooked — creating only? Bulk insert()/upsert() and raw SQL bypass model events entirely. What is the backfill and null-handling story?
  • What happens on update, soft delete/restore, and replica reads?
  • Does it support non-incrementing keys (UUID/ULID), or does it assume auto-increment?
  • Is the column length fixed? What happens when the min_hash_length or salt changes post-launch?
  • Is there any DB-level uniqueness enforcement, or is uniqueness assumed?

Integration Approach

Stack fit. Appropriate for a Laravel monolith or API service exposing public IDs (URLs, webhooks, partner integrations) without leaking row counts or creation order. Inappropriate if the hashid is expected to provide any confidentiality guarantee.

Migration path — three options, ranked.

  1. Vendor the trait into app/Models/Concerns/. The implementation is small enough that copying it is cheaper than defending the dependency. Zero composer friction, full control, trivially upgradable to current Laravel.
  2. Fork and pin via VCS repository in composer.json. Only justified if multiple applications need to share identical behavior and you want centralized fixes.
  3. Replace outright with sqids/sqids (the maintained successor) or vinkla/hashids for encoding only, wrapped in your own trait or a custom Eloquent cast. This is the cleanest long-term position.

Compatibility checks. Inspect composer.json for illuminate/* and php constraints first — that single file determines whether this is a five-minute spike or a non-starter. Also confirm the Hashids library major version, since v1 and v2 differ in namespace and API, and any vendored code must be rewritten against the version you actually ship.

Sequencing.

  1. Read the source (it is small) and confirm generation semantics before writing anything.
  2. Spike on the target Laravel version in a disposable branch.
  3. Write integration tests covering: single create, bulk insert, update, soft-delete/restore, and collision retry.
  4. Decide vendor vs. fork vs. replace based on step 3's findings.
  5. Ship the unique index and backfill migration before any code that reads the column.

Operational Impact

Maintenance. Archived means you are the maintainer from day one. Budget it as internal code in your ownership model, not as a third-party dependency on someone else's upgrade calendar.

Support. None. No upstream responsiveness, no CVE channel, no framework-compatibility patches. Security scanners will flag the abandoned transitive dependency indefinitely; plan an allowlist entry or eliminate the dependency.

Scaling. Read path is a plain indexed column — no runtime cost and no N+1 risk. Write path adds one hash computation per insert, negligible. The real operational cost is the backfill on large tables and the lock profile of adding a unique index to a populated table.

Failure modes.

  • Event bypass. Seeders, DB::insert(), queue workers writing raw, and data imports produce rows with null hashids, surfacing later as null-pointer errors in routing or serialization.
  • Silent collisions. Random generation without a unique constraint yields duplicate public identifiers that are only discovered downstream.
  • Salt rotation. Invalidates every previously issued identifier; external links, webhooks, and partner integrations break simultaneously and irreversibly.
  • Length change. Same blast radius as salt rotation.
  • Salt leakage. Turns deterministic IDs into reversible ones, exposing row counts and enabling enumeration of the entire table.
  • Drift. Abandoned dependencies accumulate audit findings and eventually block framework upgrades.

Ramp-up. A mid-level Laravel developer understands the mechanism in under an hour. The cost is not comprehension — it is the decision to permanently own a frozen artifact, and the migration work later when you inevitably replace 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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package