Try Live
Add Docs
Rankings
Pricing
Docs
Install
Install
Docs
Pricing
More...
More...
Try Live
Rankings
Enterprise
Create API Key
Add Docs
Laravel Prefixed IDs
https://github.com/spatie/laravel-prefixed-ids
Admin
Laravel Prefixed IDs is a Laravel package that generates friendly prefixed unique identifiers for
...
Tokens:
5,322
Snippets:
38
Trust Score:
8.5
Update:
2 weeks ago
Context
Skills
Chat
Benchmark
96.1
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Laravel Prefixed IDs Laravel Prefixed IDs is a package by Spatie that generates friendly, human-recognizable prefixed identifiers for Laravel Eloquent models. Inspired by Stripe's ID format (e.g., `cus_abc123`, `sk_live_xyz`), this package automatically creates unique IDs with custom prefixes that help users and developers instantly identify the type of resource they're working with. The package provides a simple trait-based approach for adding prefixed IDs to your models, along with helper methods for finding models by their prefixed ID across different model types. It integrates seamlessly with Laravel's Eloquent ORM and supports customizable ID generation, making it ideal for APIs, webhooks, and any scenario where readable, type-identifiable IDs improve developer experience. ## Installation Install the package via Composer. ```bash composer require spatie/laravel-prefixed-ids ``` ## Database Migration Add a `prefixed_id` column to your model's table. ```php <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class AddPrefixedIdToUsersTable extends Migration { public function up() { Schema::table('users', function (Blueprint $table) { $table->string('prefixed_id')->nullable()->unique(); }); } public function down() { Schema::table('users', function (Blueprint $table) { $table->dropColumn('prefixed_id'); }); } } ``` ## HasPrefixedId Trait Add the `HasPrefixedId` trait to your Eloquent model to enable automatic prefixed ID generation when creating new records. ```php <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Spatie\PrefixedIds\Models\Concerns\HasPrefixedId; class User extends Model { use HasPrefixedId; } class Order extends Model { use HasPrefixedId; } class Product extends Model { use HasPrefixedId; } ``` ## PrefixedIds::registerModels() Register your models with their desired prefixes. This is typically done in a service provider. The prefix string will be prepended to the unique identifier. ```php <?php namespace App\Providers; use App\Models\Order; use App\Models\Product; use App\Models\User; use Illuminate\Support\ServiceProvider; use Spatie\PrefixedIds\PrefixedIds; class AppServiceProvider extends ServiceProvider { public function boot() { PrefixedIds::registerModels([ 'user_' => User::class, 'order_' => Order::class, 'prod_' => Product::class, ]); } } // Now when you create models, they automatically get prefixed IDs: $user = User::create(['name' => 'John Doe', 'email' => 'john@example.com']); echo $user->prefixed_id; // Output: user_550e8400e29b41d4a716446655440000 $order = Order::create(['total' => 99.99]); echo $order->prefixed_id; // Output: order_6ba7b8109dad11d180b400c04fd430c8 $product = Product::create(['name' => 'Widget']); echo $product->prefixed_id; // Output: prod_f47ac10b58cc4372a5670e02b2c3d479 ``` ## Model::findByPrefixedId() Find a specific model instance by its prefixed ID. Returns the model or `null` if not found. ```php <?php use App\Models\User; // Find a user by their prefixed ID $user = User::findByPrefixedId('user_550e8400e29b41d4a716446655440000'); if ($user) { echo "Found user: {$user->name}"; } else { echo "User not found"; } // Returns null for non-existing IDs $notFound = User::findByPrefixedId('user_nonexistent'); var_dump($notFound); // Output: NULL ``` ## Model::findByPrefixedIdOrFail() Find a model by its prefixed ID or throw a `NoPrefixedModelFound` exception if not found. Useful for controller actions where you want to return a 404 response. ```php <?php use App\Models\User; use Spatie\PrefixedIds\Exceptions\NoPrefixedModelFound; // In a controller class UserController extends Controller { public function show(string $prefixedId) { try { $user = User::findByPrefixedIdOrFail($prefixedId); return response()->json([ 'id' => $user->prefixed_id, 'name' => $user->name, 'email' => $user->email, ]); } catch (NoPrefixedModelFound $e) { return response()->json([ 'error' => 'User not found', 'message' => $e->getMessage(), ], 404); } } } // Usage: // GET /api/users/user_550e8400e29b41d4a716446655440000 // Response: {"id": "user_550e8400...", "name": "John Doe", "email": "john@example.com"} // GET /api/users/user_invalid // Response: {"error": "User not found", "message": "Could not find a prefixed model `user_invalid`"} ``` ## PrefixedIds::find() Find any model across all registered model types by its prefixed ID. The method automatically determines the correct model class based on the prefix. ```php <?php use Spatie\PrefixedIds\PrefixedIds; // Find models of different types using a single method $user = PrefixedIds::find('user_550e8400e29b41d4a716446655440000'); $order = PrefixedIds::find('order_6ba7b8109dad11d180b400c04fd430c8'); $product = PrefixedIds::find('prod_f47ac10b58cc4372a5670e02b2c3d479'); // Each variable is an instance of its respective model class echo get_class($user); // Output: App\Models\User echo get_class($order); // Output: App\Models\Order echo get_class($product); // Output: App\Models\Product // Returns null for unknown prefixes or non-existing IDs $unknown = PrefixedIds::find('unknown_prefix_abc123'); var_dump($unknown); // Output: NULL // Useful for webhook handlers or API endpoints that accept any resource ID function handleWebhook(string $resourceId): void { $model = PrefixedIds::find($resourceId); if ($model instanceof User) { // Handle user-related webhook } elseif ($model instanceof Order) { // Handle order-related webhook } } ``` ## PrefixedIds::findOrFail() Find any model by its prefixed ID or throw an exception. Similar to `find()` but throws `NoPrefixedModelFound` if the model cannot be found. ```php <?php use Spatie\PrefixedIds\Exceptions\NoPrefixedModelFound; use Spatie\PrefixedIds\PrefixedIds; // API endpoint that handles any resource type class ResourceController extends Controller { public function show(string $prefixedId) { try { $model = PrefixedIds::findOrFail($prefixedId); return response()->json([ 'type' => class_basename($model), 'id' => $model->prefixed_id, 'data' => $model->toArray(), ]); } catch (NoPrefixedModelFound $e) { return response()->json([ 'error' => 'Resource not found', ], 404); } } } // Works with any registered model type: // GET /api/resources/user_abc123 -> Returns User data // GET /api/resources/order_xyz789 -> Returns Order data // GET /api/resources/invalid_id -> Returns 404 ``` ## PrefixedIds::getModelClass() Get the model class name for a given prefixed ID without fetching the model from the database. Useful for validation or routing logic. ```php <?php use Spatie\PrefixedIds\PrefixedIds; // Determine the model type from a prefixed ID $modelClass = PrefixedIds::getModelClass('user_550e8400e29b41d4a716446655440000'); echo $modelClass; // Output: App\Models\User $modelClass = PrefixedIds::getModelClass('order_6ba7b8109dad11d180b400c04fd430c8'); echo $modelClass; // Output: App\Models\Order // Returns null for unknown prefixes $unknown = PrefixedIds::getModelClass('invalid_prefix_abc'); var_dump($unknown); // Output: NULL // Useful for request validation class ResourceRequest extends FormRequest { public function rules() { $modelClass = PrefixedIds::getModelClass($this->resource_id); if ($modelClass === User::class) { return ['action' => 'required|in:activate,deactivate']; } if ($modelClass === Order::class) { return ['action' => 'required|in:ship,cancel,refund']; } throw new ValidationException('Unknown resource type'); } } ``` ## PrefixedIds::generateUniqueIdUsing() Customize the unique ID generation algorithm. By default, the package uses UUID v4 (with dashes removed). You can provide your own generator for shorter IDs, sequential IDs, or any custom format. ```php <?php use Spatie\PrefixedIds\PrefixedIds; use Illuminate\Support\Str; // Use a shorter 8-character ID PrefixedIds::generateUniqueIdUsing(function () { return substr(md5(uniqid(mt_rand(), true)), 0, 8); }); $user = User::create(['name' => 'Jane']); echo $user->prefixed_id; // Output: user_a1b2c3d4 // Use Laravel's Str helper for a different format PrefixedIds::generateUniqueIdUsing(function () { return Str::random(12); }); $order = Order::create(['total' => 50.00]); echo $order->prefixed_id; // Output: order_Xk9mP2nQ4rT1 // Use ULID for sortable IDs PrefixedIds::generateUniqueIdUsing(function () { return strtolower((string) Str::ulid()); }); $product = Product::create(['name' => 'Gadget']); echo $product->prefixed_id; // Output: prod_01aryz6s41tsp2m3xqjvwy // Reset to default UUID generation PrefixedIds::generateUniqueIdUsing(null); ``` ## Route Model Binding Use prefixed IDs in your Laravel routes by implementing the `getRouteKeyName` method on your model. ```php <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Spatie\PrefixedIds\Models\Concerns\HasPrefixedId; class User extends Model { use HasPrefixedId; public function getRouteKeyName() { return 'prefixed_id'; } } // In routes/api.php Route::get('/users/{user}', function (User $user) { return response()->json([ 'id' => $user->prefixed_id, 'name' => $user->name, ]); }); // Now you can access users by their prefixed ID: // GET /api/users/user_550e8400e29b41d4a716446655440000 // Response: {"id": "user_550e8400...", "name": "John Doe"} ``` ## Configuration Publish and customize the configuration file to change the attribute name used for storing prefixed IDs. ```bash php artisan vendor:publish --provider="Spatie\PrefixedIds\PrefixedIdsServiceProvider" --tag="prefixed-ids-config" ``` ```php <?php // config/prefixed-ids.php return [ /* * The attribute name used to store prefixed ids on a model. * Change this if you want to use a different column name. */ 'prefixed_id_attribute_name' => 'prefixed_id', // Example: use 'public_id' instead // 'prefixed_id_attribute_name' => 'public_id', ]; // If you change the attribute name, update your migration accordingly: Schema::table('users', function (Blueprint $table) { $table->string('public_id')->nullable()->unique(); }); // And access it via the new attribute: $user = User::create(['name' => 'John']); echo $user->public_id; // Output: user_550e8400... ``` ## Summary Laravel Prefixed IDs is ideal for building APIs where human-readable, type-identifiable IDs improve developer experience. Common use cases include exposing public-facing IDs in REST APIs (instead of auto-incrementing integers), handling webhooks that reference multiple resource types, building admin interfaces where resource types need to be quickly identified, and creating shareable URLs that remain meaningful to users. The package integrates smoothly with Laravel's existing patterns including route model binding, Eloquent relationships, and service providers. For best results, register all your prefixed models in a service provider's `boot` method, use the `PrefixedIds::find()` method for polymorphic lookups in webhook handlers, and consider customizing the ID generator for shorter, more URL-friendly identifiers. The package works with Laravel 11, 12, and 13, requiring PHP 8.2 or higher.