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

Advanced Eloquent Laravel Package

reinink/advanced-eloquent

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require reinink/advanced-eloquent
    

    Add to config/app.php under providers:

    Reinink\AdvancedEloquent\AdvancedEloquentServiceProvider::class,
    
  2. First Use Case: Enable the package by publishing the config (optional but recommended):

    php artisan vendor:publish --provider="Reinink\AdvancedEloquent\AdvancedEloquentServiceProvider"
    

    Test a basic macro in a model:

    use Reinink\AdvancedEloquent\Macros\HasManyThrough;
    
    class Post extends Model
    {
        public static function boot()
        {
            parent::boot();
            static::addMacros(HasManyThrough::class);
        }
    }
    
  3. Key Entry Points:

    • Check config/advanced-eloquent.php for enabled macros.
    • Review src/Macros/ for available macros (e.g., HasManyThrough, Orderable, Filterable).
    • Start with HasManyThrough for nested relationships or Orderable for drag-and-drop sorting.

Implementation Patterns

Common Workflows

1. Nested Relationships (HasManyThrough)

  • Use Case: Query a model through multiple intermediate tables (e.g., User → Posts → Comments).
  • Pattern:
    class User extends Model
    {
        public static function boot()
        {
            static::addMacros(HasManyThrough::class);
        }
    
        public function posts()
        {
            return $this->hasMany(Post::class);
        }
    }
    
    // Usage:
    $user->postsThrough('comments', Comment::class, 'post_id', 'user_id');
    
  • Integration Tip: Cache the relationship results if performance is critical:
    $user->postsThrough('comments', Comment::class, 'post_id', 'user_id', [], true);
    

2. Drag-and-Drop Sorting (Orderable)

  • Use Case: Manage ordered lists (e.g., menu items, playlists).
  • Pattern:
    class MenuItem extends Model
    {
        use \Reinink\AdvancedEloquent\Traits\Orderable;
    
        protected $orderable = [
            'order_column' => 'position',
            'scope' => 'menu_id',
        ];
    }
    
  • Workflow:
    • Update order via API:
      $item->move(5); // Move to position 5
      $item->moveUp();
      $item->moveDown();
      
    • Query ordered results:
      MenuItem::orderBy('position')->get();
      

3. Filterable Collections

  • Use Case: Dynamic filtering (e.g., search, date ranges).
  • Pattern:
    class Product extends Model
    {
        public static function boot()
        {
            static::addMacros(\Reinink\AdvancedEloquent\Macros\Filterable::class);
        }
    }
    
    // Usage:
    $products = Product::filter(['price_min' => 10, 'price_max' => 100])->get();
    
  • Tip: Define custom filters in app/Providers/AppServiceProvider:
    \Reinink\AdvancedEloquent\Macros\Filterable::extend('price_range', function ($query, $value) {
        return $query->whereBetween('price', [$value['min'], $value['max']]);
    });
    

4. Soft Deletes with Trashed Scope

  • Use Case: Filter soft-deleted records easily.
  • Pattern:
    $trashed = Model::trashed()->get();
    $active = Model::active()->get(); // Non-trashed
    

Integration Tips

  • Macro Registration: Register macros in AppServiceProvider@boot() for global availability:
    Model::addMacros([
        \Reinink\AdvancedEloquent\Macros\HasManyThrough::class,
        \Reinink\AdvancedEloquent\Macros\Orderable::class,
    ]);
    
  • Model-Specific Macros: Use boot() in individual models to avoid global bloat.
  • API Layer: Pair Filterable with Laravel API Resources for dynamic responses:
    return new ProductResource(Product::filter($request->all())->paginate());
    

Gotchas and Tips

Pitfalls

  1. Macro Conflicts:

    • Issue: Overwriting built-in Eloquent methods (e.g., orderBy).
    • Fix: Prefix custom macros or check for conflicts in config/advanced-eloquent.php:
      'conflicts' => [
          'orderBy' => false, // Disable if using Orderable macro
      ],
      
  2. Performance with HasManyThrough:

    • Issue: N+1 queries when eager-loading.
    • Fix: Use with() or load() explicitly:
      $user->load('postsThrough.comments');
      
  3. Orderable Scope Misconfiguration:

    • Issue: Incorrect scope in $orderable causes duplicate positions.
    • Fix: Ensure scope matches a unique column (e.g., menu_id):
      protected $orderable = [
          'order_column' => 'position',
          'scope' => 'menu_id', // Must be unique per group
      ];
      
  4. Filterable Security:

    • Issue: Arbitrary SQL injection via dynamic filters.
    • Fix: Whitelist allowed filters in AppServiceProvider:
      \Reinink\AdvancedEloquent\Macros\Filterable::allowedFilters(['price_min', 'price_max']);
      

Debugging

  • Macro Not Loading:

    • Verify the macro is registered in config/advanced-eloquent.php under macros.
    • Check for typos in class names (e.g., HasManyThrough vs. HasManyThroughMacro).
  • Orderable Not Working:

    • Ensure position column exists and is numeric.
    • Check for database transactions rolling back changes.
  • Filterable Errors:

    • Enable query logging in config/logging.php to inspect generated SQL:
      'default' => env('LOG_CHANNEL', 'single'),
      'channels' => [
          'single' => [
              'driver' => 'single',
              'path' => storage_path('logs/laravel.log'),
              'level' => env('LOG_LEVEL', 'debug'),
          ],
      ],
      

Extension Points

  1. Custom Macros:

    • Extend existing macros by subclassing (e.g., HasManyThrough):
      class CustomHasManyThrough extends \Reinink\AdvancedEloquent\Macros\HasManyThrough
      {
          public static function addToBuilder($builder)
          {
              parent::addToBuilder($builder);
              // Add custom logic
          }
      }
      
  2. Filterable Extensions:

    • Add custom filter types:
      \Reinink\AdvancedEloquent\Macros\Filterable::extend('custom', function ($query, $value) {
          return $query->whereRaw("custom_column LIKE ?", ["%{$value}%"]);
      });
      
  3. Orderable Events:

    • Listen for order changes via events (not natively supported; use trait events):
      class MenuItem extends Model
      {
          protected static function booted()
          {
              static::updated(function ($item) {
                  if ($item->isDirty('position')) {
                      event(new PositionUpdated($item));
                  }
              });
          }
      }
      

Configuration Quirks

  • Disabled Macros:

    • Set enabled => false in config/advanced-eloquent.php to disable all macros globally.
    • Override per-macro in the same config:
      'macros' => [
          'orderable' => false,
          'filterable' => true,
      ],
      
  • Database Schema:

    • Ensure position column for Orderable is integer (not string).
    • For HasManyThrough, intermediate tables must exist before querying.
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.
daikazu/eloquent-salesforce-objects
unseen-codes/chat
romalytar/yammi-jobs-monitoring-laravel
kisame76/filament-db-table-state
nqxcode/laravel-lucene-search
dpfx/laravel-livewire-wizards
workos/workos-php-laravel
sofa/laravel-global-scope
nawasara/auth-primitives
adhocrat-io/arkhe-main
make-dev/orca-harpoon
itsemon245/lamet
baks-dev/dashboard
amoifr/pickle-panther-bundle
make-dev/orca
dmstr/symfony-system-resources-bundle
dmstr/symfony-job-queue-bundle
dmstr/openapi-json-schema-bundle
dmstr/keycloak-security-bundle
dmstr/doctrine-audit-log-bundle