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

Ids Laravel Package

pchapl/ids

pchapl/ids is a lightweight Laravel package for generating and managing unique identifiers for Eloquent models. It makes it easy to add custom ID behavior to your models with minimal configuration, reducing boilerplate while keeping identifiers consistent and application-specific.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and pin

composer require pchapl/ids

Pin to the concrete release rather than a floating constraint, since the package shipped a single 1.0.0 in September 2021 and has had no activity since:

"pchapl/ids": "^1.0"

That constraint is fine for patch safety, but treat it as effectively frozen — there is no upstream to lean on if something breaks.

Where to look first (in this order)

  1. vendor/pchapl/ids/composer.json — confirms the PHP and illuminate/* version bounds. This is the fastest way to know whether your Laravel version (8/9/10/11) is actually supported or merely tolerated.
  2. vendor/pchapl/ids/src/ — find the service provider. Look for register() / boot() to see what gets bound into the container, and whether there is a publishes() call for a config file.
  3. Any config/ids.php in the package — publish it with php artisan vendor:publish --tag=ids (verify the tag in the provider source; the README does not document it).
  4. The facade class, if one exists, to learn the public entry point. If there is no facade, the package is likely resolved from the container directly.

First use case

The realistic first use is generating a collision-resistant, human-friendly identifier for a model — an order reference, invoice number, or short public slug — without hand-rolling a Str::random() wrapper. Start with a single throwaway integration:

use Pchapl\Ids\Facades\Ids; // confirm actual namespace from src/

$id = Ids::generate();        // verify method name in source

Write one test asserting uniqueness over a loop of 10k generations and one asserting the format matches your expectation. If those two pass, you understand the API better than the description does.

Before you commit

Because the description is generic ("configurable ID handling", "extensible foundation") and the release notes were empty, spend 20 minutes reading src/. You are adopting an undocumented, dormant, WTFPL-licensed package. That is acceptable for a low-risk utility; it is not acceptable for anything where identifier collision or predictability has a business consequence.

Implementation Patterns

Wrap it behind your own interface

This is the single most important pattern given the package's stagnation. Do not let Pchapl\Ids types leak across your codebase:

namespace App\Support;

interface IdGenerator
{
    public function generate(?string $prefix = null): string;
}

final class PackageIdGenerator implements IdGenerator
{
    public function generate(?string $prefix = null): string
    {
        $id = Ids::generate();

        return $prefix ? "{$prefix}-{$id}" : $id;
    }
}

Bind it in a SupportServiceProvider, and inject IdGenerator everywhere. Replacing the package later — with Str::ulid(), a UUIDv7 implementation, or an in-house scheme — becomes a one-file change.

Model integration via a trait or booted() hook

Keep the generation out of controllers:

protected static function booted(): void
{
    static::creating(function (self $model) {
        $model->reference ??= app(IdGenerator::class)->generate('ORD');
    });
}

Use ??= so explicit values (seeders, imports, test fixtures) are not overwritten. If the identifier must be unique at the database level, back it with a unique index regardless of what the package promises — never rely on application-level uniqueness alone.

Column type and indexing

Store generated identifiers in a string column sized to your actual format, not bigint. Add a unique index. For MySQL/InnoDB, random-looking string primary keys fragment the clustered index; if this is a primary key on a high-write table, keep the auto-increment id as the PK and put the generated identifier in a secondary unique column.

Environment-appropriate generation

If the package is configurable (check the config file), use short/readable formats in local and dev, and the full-strength format in production. If it is not configurable to that degree, do the branching in your adapter rather than in call sites.

Idempotency and retries

When generating an identifier inside a queued job or an HTTP retry, generate it once at the start and carry it through. Do not generate inside a loop that may re-execute — a retried job should reuse the same identifier so downstream consumers see one entity, not two.

Testing

  • Unit-test the adapter, not the package. Your tests should not break when the dependency changes.
  • Assert uniqueness over a large loop (10k+) once. Do not repeat this in every test — it is slow.
  • For tests asserting a deterministic ID, bind a fake IdGenerator in the container rather than trying to seed the package's randomness.

Gotchas and Tips

The documentation is effectively absent. The description lists capabilities, not an API. Do not guess method names from the description — Ids::generate(), Ids::make(), Ids::create() are all plausible. Read src/ before writing a single call site, and note what you find in a comment above your adapter so the next developer does not repeat the work.

Abandonment risk is the headline issue. Last release was 2021-09-25, zero stars, single release. There is no maintainer roadmap, no security policy, and no upgrade path. Pin the version, vendored-fork it into your repo if it becomes load-bearing, and never let it be the only thing standing between you and a unique key on a revenue-critical table.

WTFPL requires legal sign-off in most organizations. It is permissive, but it is not OSI-approved and many dependency scanners flag it or refuse to classify it. Get explicit approval before it ships in a commercial product; if approval is slow, the adapter interface means you can ship with Str::ulid() and swap later.

Check the illuminate/* bounds before anything else. A 2021 package likely declares ^8.0 and may not install cleanly on Laravel 11. If Composer resolves it, it may still pull a transitive version you did not intend. Run composer why pchapl/ids after install to see what actually got resolved.

Config caching will bite you. If you publish a config file, php artisan config:cache must be part of your deploy script, and any environment-dependent behaviour must read through config(), not env(), at runtime. env() calls outside config files return null once config is cached — a classic source of "works locally, wrong in production" identifier bugs.

Predictability vs. opacity. Short, human-readable identifiers are guessable and enumerable. If these IDs appear in URLs, in APIs, or anywhere a user could probe, add authorization checks per-object rather than relying on unguessability. If you need non-enumerable public IDs, that is a different design decision — do not assume this package gives it to you because the description says "unique."

Collision handling must be explicit. Whatever the package does internally, your write path should handle a duplicate-key exception. A retry loop of 3 attempts with a fresh generation is cheap insurance:

retry(3, fn () => Order::create(['reference' => $ids->generate('ORD')]), 0);

Extension points are unverified. The description advertises an "extensible foundation," but with no docs you cannot know whether that means a contract to bind, a strategy class, or nothing at all. Before designing around extensibility, grep the source for interface, abstract, and container bindings. If there is no bind/singleton in the provider, "extensible" likely means "fork it."

Debugging tip. If generation appears to return duplicates, first check that you are not resolving a fresh instance per call in a way that resets an internal counter or seed. Second, check that the package is not falling back to a degraded mode (e.g. uniqid()-style time-based generation) where two calls in the same microsecond collide. A quick ray()/dd() inside src/ is faster than reasoning about it from the outside — and because the package is tiny, temporarily patching vendor/ to log is a legitimate debugging move.

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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core