Weave Code
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

Eloquent Calamari Laravel Package

rossbearman/eloquent-calamari

View on GitHub
Deep Wiki
Context7
## Getting Started

### Installation
1. **Install via Composer**:
   ```bash
   composer require rossbearman/eloquent-calamari
  1. Publish the config (optional, but recommended for customization):

    php artisan vendor:publish --provider="RossBearman\EloquentCalamari\EloquentCalamariServiceProvider" --tag="config"
    
  2. Configure the package in config/eloquent-calamari.php:

    • Set enabled to true.
    • Define sqid options (e.g., alphabet, minLength, minLengthForId).
    • Optionally configure route_model_binding if using SqidBasedRouting.
  3. Apply the trait to your models:

    use RossBearman\EloquentCalamari\EloquentCalamari;
    
    class Link extends Model
    {
        use EloquentCalamari;
    }
    
    • This automatically replaces auto-incrementing IDs with Sqids in all queries, responses, and route binding.
  4. First use case:

    • Create a record:
      $link = Link::create(['url' => 'https://example.com']);
      
      The id will now be a Sqid (e.g., 2fC37YMkO).
    • Retrieve via Sqid:
      $link = Link::find('2fC37YMkO'); // Works seamlessly
      
    • Route binding (if enabled):
      Route::get('/link/{link}', function (Link $link) {
          return $link->url;
      });
      
      Accessing /link/2fC37YMkO will automatically resolve to the Link model.

Implementation Patterns

Core Workflows

  1. Transparent ID Obfuscation:

    • All create(), find(), first(), and where() operations automatically handle Sqid conversion.
    • No manual conversion needed for CRUD operations:
      // 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);
      
  2. Route Model Binding:

    • Enable route_model_binding: true in config.
    • Bind routes to Sqids without extra middleware:
      Route::get('/users/{user}', function (User $user) {
          return $user->name;
      });
      
    • Supports optional canonical_id for fallback to numeric IDs:
      Route::get('/users/{user:canonical}', function (User $user) {
          return $user->name;
      });
      
  3. Query Scoping:

    • Use where() with Sqids:
      $links = Link::where('sqid', '2fC37YMkO')->get();
      
    • Under the hood, the package converts Sqids to numeric IDs for database queries.
  4. API Responses:

    • Serialization (e.g., JSON) automatically includes Sqids:
      {
        "id": "2fC37YMkO",
        "url": "https://example.com"
      }
      
    • Customize serialization via toArray() or API resources:
      public function toArray()
      {
          return [
              'sqid' => $this->sqid,
              'url' => $this->url,
          ];
      }
      
  5. Bulk Operations:

    • Collections and eager loading work out of the box:
      $links = Link::with('comments')->get();
      
    • Sqids are preserved in relationships.

Integration Tips

  1. Database Migrations:

    • No schema changes required. The package works with existing auto-incrementing id columns.
    • If using canonical_id binding, ensure your routes are configured to accept either Sqids or numeric IDs.
  2. Testing:

    • Mock Sqid generation in tests:
      $this->app->singleton(Sqids::class, function () {
          return new Sqids('0123456789', 8, 8);
      });
      
    • Use find() with numeric IDs for deterministic tests.
  3. Customization:

    • Override Sqid generation per model:
      class Link extends Model
      {
          use EloquentCalamari;
      
          protected $sqidOptions = [
              'alphabet' => 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789',
              'minLength' => 8,
          ];
      }
      
    • Extend the trait for custom logic (e.g., validation):
      public function getSqidAttribute($value)
      {
          if (strlen($value) < 6) {
              throw new \InvalidArgumentException('Sqid too short');
          }
          return $value;
      }
      
  4. Performance:

    • Sqid generation is lightweight. Benchmark if using in high-throughput APIs.
    • Cache Sqid generation for frequently accessed models (e.g., using Laravel's cache).
  5. Legacy Systems:

    • Gradually migrate by enabling the package for specific models.
    • Use numeric IDs in admin panels or internal tools while exposing Sqids to users.

Gotchas and Tips

Pitfalls

  1. Route Binding Conflicts:

    • If using canonical_id binding, ensure route parameters don’t conflict with other route models.
    • Example: /users/{user:canonical} may conflict with /users/{id}/profile. Use route groups or prefixes to avoid ambiguity.
  2. Case Sensitivity:

    • Sqids are case-sensitive by default. Ensure your routes and client-side code handle this (e.g., URL normalization).
    • Customize the alphabet in config to control case sensitivity.
  3. ID Collisions:

    • Sqids are unique per model but not globally. Avoid reusing Sqids across models if they share routes.
    • Example: A Link with Sqid 2fC37YMkO and a Video with the same Sqid could cause confusion in /link/{link} and /video/{video} routes.
  4. Database Indexes:

    • The package does not modify your database schema, but ensure your id column is indexed for performance.
    • Sqids are not indexed in the database; they’re converted to numeric IDs at query time.
  5. Serialization Edge Cases:

    • Custom toArray() or toJson() methods may override Sqid inclusion. Explicitly include sqid if needed:
      public function toArray()
      {
          return array_merge(parent::toArray(), ['sqid' => $this->sqid]);
      }
      
  6. Testing Quirks:

    • Sqids are generated dynamically, so tests may fail if not mocked. Use fixed Sqids in tests:
      $this->app->singleton(Sqids::class, fn () => new Sqids('0123456789', 8, 8));
      $user = User::create(['name' => 'Test']);
      $user->fresh()->sqid; // Always returns '01234567'
      

Debugging

  1. Sqid Generation Issues:

    • Check config/eloquent-calamari.php for valid alphabet and minLength values.
    • Log Sqid generation:
      \Log::debug('Generated Sqid:', ['sqid' => $model->sqid, 'id' => $model->id]);
      
  2. Route Binding Failures:

    • Verify route_model_binding is enabled in config.
    • Check for typos in route parameters (e.g., {user} vs {user:canonical}).
    • Use php artisan route:list to debug route resolution.
  3. Performance Bottlenecks:

    • Profile Sqid generation with Xdebug or Blackfire.
    • Avoid regenerating Sqids unnecessarily (e.g., in accessors).

Extension Points

  1. Custom Sqid Providers:

    • Bind a custom Sqids implementation:
      $this->app->bind(Sqids::class, function () {
          return new CustomSqids();
      });
      
  2. Event Hooks:

    • Listen for 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}");
      });
      
  3. Middleware for Sqid Validation:

    • Validate Sqids in incoming requests:
      public function handle($request, Closure $
      
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle