Skip to content

Instantly share code, notes, and snippets.

@vantezzen
Last active April 28, 2025 16:29
Show Gist options
  • Save vantezzen/b5ac132138b592b7a0505178d7ee1ae4 to your computer and use it in GitHub Desktop.
Save vantezzen/b5ac132138b592b7a0505178d7ee1ae4 to your computer and use it in GitHub Desktop.
Using Stripe-like, human-readable IDs in Laravel Models and Migrations

Using Stripe-like, human-readable IDs in Laravel Models and Migrations. This will fully use Stripe-like IDs (like "usr_123123123" or "team_123123123") instead of auto-incrementing IDs or UUIDs in your models.

  1. In your migrations, change $table->id(); to $table->string('id')->primary();
  2. Add the new HasHashIds trait to app/Traits/HasHashIds.php
<?php

namespace App\Traits;

use Illuminate\Database\Eloquent\Concerns\HasUniqueStringIds;
use Illuminate\Support\Str;

trait HasHashIds
{
    use HasUniqueStringIds;

    /**
     * Generate a new unique key for the model.
     *
     * @return string
     */
    public function newUniqueId()
    {
        return (string) $this->hashPrefix . Str::ulid();
    }

    /**
     * Determine if given key is valid.
     *
     * @param  mixed  $value
     * @return bool
     */
    protected function isValidUniqueId($value): bool
    {
        return Str::startsWith($value, $this->hashPrefix);
    }
}
  1. In your model classes, use the trait and define a descriptive hash prefix to use (like "usr_", "team_" or "project_"):
<?php

namespace App\Models;

use App\Traits\HasHashIds;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;



class Project extends Model
{
    /** @use HasFactory<\Database\Factories\ProjectFactory> */
    use HasFactory;
    
    use HasHashIds;
    protected $hashPrefix = 'proj_';
}
  1. Using foreignIdFor in your migrations will not work anymore since it only supports UUID and integer IDs. To reference tables, you will instead need to define a custom macro. For this, create a provider DatabaseServiceProvider (or whatever you want to call it) and add this content:
<?php

namespace App\Providers;

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\ServiceProvider;

class DatabaseServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap services.
     */
    public function boot(): void
    {
        Blueprint::macro('foreignHashIdFor', function ($model, $column = null, $length = null) {
            $instance = new $model;
            $column = $column ?: $instance->getForeignKey();
            $length = $length ?: 255;
            
            $this->string($column, $length);
            
            return $this->foreign($column)
                ->references($instance->getKeyName())
                ->on($instance->getTable());
        });
    }
}

This creates a new function foreignHashIdFor that you can call with the model class, exactly like foreignIdFor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment