## Getting Started
### Installation
1. **Install via Composer**:
```bash
composer require rossbearman/eloquent-calamari
Publish the config (optional, but recommended for customization):
php artisan vendor:publish --provider="RossBearman\EloquentCalamari\EloquentCalamariServiceProvider" --tag="config"
Configure the package in config/eloquent-calamari.php:
enabled to true.sqid options (e.g., alphabet, minLength, minLengthForId).route_model_binding if using SqidBasedRouting.Apply the trait to your models:
use RossBearman\EloquentCalamari\EloquentCalamari;
class Link extends Model
{
use EloquentCalamari;
}
First use case:
$link = Link::create(['url' => 'https://example.com']);
The id will now be a Sqid (e.g., 2fC37YMkO).$link = Link::find('2fC37YMkO'); // Works seamlessly
Route::get('/link/{link}', function (Link $link) {
return $link->url;
});
Accessing /link/2fC37YMkO will automatically resolve to the Link model.Transparent ID Obfuscation:
create(), find(), first(), and where() operations automatically handle Sqid conversion.// Create
$user = User::create(['name' => 'Alice']);
// Find by Sqid
$user = User::find($user->sqid); // Returns User model
// Find by numeric ID (still works)
$user = User::find(1);
Route Model Binding:
route_model_binding: true in config.Route::get('/users/{user}', function (User $user) {
return $user->name;
});
canonical_id for fallback to numeric IDs:
Route::get('/users/{user:canonical}', function (User $user) {
return $user->name;
});
Query Scoping:
where() with Sqids:
$links = Link::where('sqid', '2fC37YMkO')->get();
API Responses:
{
"id": "2fC37YMkO",
"url": "https://example.com"
}
toArray() or API resources:
public function toArray()
{
return [
'sqid' => $this->sqid,
'url' => $this->url,
];
}
Bulk Operations:
$links = Link::with('comments')->get();
Database Migrations:
id columns.canonical_id binding, ensure your routes are configured to accept either Sqids or numeric IDs.Testing:
$this->app->singleton(Sqids::class, function () {
return new Sqids('0123456789', 8, 8);
});
find() with numeric IDs for deterministic tests.Customization:
class Link extends Model
{
use EloquentCalamari;
protected $sqidOptions = [
'alphabet' => 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789',
'minLength' => 8,
];
}
public function getSqidAttribute($value)
{
if (strlen($value) < 6) {
throw new \InvalidArgumentException('Sqid too short');
}
return $value;
}
Performance:
Legacy Systems:
Route Binding Conflicts:
canonical_id binding, ensure route parameters don’t conflict with other route models./users/{user:canonical} may conflict with /users/{id}/profile. Use route groups or prefixes to avoid ambiguity.Case Sensitivity:
alphabet in config to control case sensitivity.ID Collisions:
Link with Sqid 2fC37YMkO and a Video with the same Sqid could cause confusion in /link/{link} and /video/{video} routes.Database Indexes:
id column is indexed for performance.Serialization Edge Cases:
toArray() or toJson() methods may override Sqid inclusion. Explicitly include sqid if needed:
public function toArray()
{
return array_merge(parent::toArray(), ['sqid' => $this->sqid]);
}
Testing Quirks:
$this->app->singleton(Sqids::class, fn () => new Sqids('0123456789', 8, 8));
$user = User::create(['name' => 'Test']);
$user->fresh()->sqid; // Always returns '01234567'
Sqid Generation Issues:
config/eloquent-calamari.php for valid alphabet and minLength values.\Log::debug('Generated Sqid:', ['sqid' => $model->sqid, 'id' => $model->id]);
Route Binding Failures:
route_model_binding is enabled in config.{user} vs {user:canonical}).php artisan route:list to debug route resolution.Performance Bottlenecks:
Xdebug or Blackfire.Custom Sqid Providers:
Sqids implementation:
$this->app->bind(Sqids::class, function () {
return new CustomSqids();
});
Event Hooks:
eloquent-calamari.generated events to log or validate Sqids:
Event::listen('eloquent-calamari.generated', function ($model, $sqid) {
\Log::info("Generated Sqid for {$model->getTable()}: {$sqid}");
});
Middleware for Sqid Validation:
public function handle($request, Closure $
How can I help you explore Laravel packages today?