cirlmcesc/laravel-hashids
Laravel package to obfuscate model IDs and route parameters using Hashids. Adds a model trait that automatically encodes ID and *_id fields on serialization, decodes for route model binding, and provides helper methods plus Artisan install/test commands.
Installation:
composer require cirlmcesc/laravel-hashids
Publish the config file (if needed):
php artisan vendor:publish --provider="Cirlmcesc\LaravelHashids\HashidsServiceProvider"
Configuration:
Edit config/hashids.php to set:
salt (default: LaravelHashids)min_length (default: 8)alphabet (default: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)First Use Case: Apply the trait to a model:
use Cirlmcesc\LaravelHashids\HashidsTrait;
class Post extends Model
{
use HashidsTrait;
}
Now, Post::create() will auto-generate a hashid column alongside the default id.
Auto-Generated HashIDs:
hashid column (type: string) on model creation.Post::first()->hashid → "a3F7x9Y2" (instead of 1).Manual Generation:
$hashid = Hashids::encode(123); // Manually encode an ID
$originalId = Hashids::decode($hashid); // Decode back to original
Querying by HashID:
// Find a model by its hashid
$post = Post::where('hashid', 'a3F7x9Y2')->first();
// Or use the provided scope
$post = Post::hashid('a3F7x9Y2')->first();
Custom Columns:
Override the default hashid column name in the model:
class Post extends Model
{
use HashidsTrait;
protected $hashidColumn = 'slug';
}
Integration with API Resources:
public function toArray($request)
{
return [
'id' => $this->id,
'hashid' => $this->hashid, // Expose hashid in API
'title' => $this->title,
];
}
Seeding:
Use Hashids::encode() in seeders to generate pre-hashed IDs:
$post = Post::create([
'title' => 'Test Post',
'hashid' => Hashids::encode(999), // Force a specific hashid
]);
Database Schema Mismatch:
hashid column if it doesn’t exist. Ensure your migrations don’t conflict:
Schema::table('posts', function (Blueprint $table) {
$table->string('hashid')->unique()->nullable(); // Avoid duplicate column errors
});
Collision Risk:
min_length is too short (e.g., 4), collisions become more likely. Test with:
Hashids::encode(1000000); // Ensure it fits your max ID range
Alphabet Restrictions:
l, 1, O, 0). Customize if needed:
'alphabet' => 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789',
Performance:
private $decodedId;
public function getDecodedIdAttribute()
{
return $this->decodedId ?? ($this->decodedId = Hashids::decode($this->hashid));
}
Migration Conflicts:
hashid column already exists, the package won’t overwrite it. Manually drop/recreate if needed.URL-Friendly HashIDs:
Use shorter min_length (e.g., 6) for URLs, but balance collision risk:
'min_length' => 6,
Custom Hashids Instance:
Bind a custom Hashids instance in a service provider for per-environment salts:
$this->app->singleton('hashids', function () {
return new \Hashids\Hashids(config('hashids.salt'), 8, 'abcdef');
});
Testing: Mock the trait in tests to avoid database calls:
class PostTest extends TestCase
{
use RefreshDatabase;
public function testHashidGeneration()
{
$post = Post::factory()->create();
$this->assertEquals(8, strlen($post->hashid));
}
}
Fallback to Raw ID: Provide a fallback in APIs for debugging:
public function toArray($request)
{
return [
'hashid' => $this->hashid,
'raw_id' => $this->id, // For admins/devs
];
}
Batch Processing:
Use Hashids::encode() in queues/jobs for bulk operations:
foreach ($ids as $id) {
$hashids[] = Hashids::encode($id);
}
How can I help you explore Laravel packages today?