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

Eager Load Pivot Relations Laravel Package

audunru/eager-load-pivot-relations

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require audunru/eager-load-pivot-relations
    

    No additional configuration is required—just use the trait in your models.

  2. First Use Case: For a BelongsToMany relationship where the pivot table has its own relations (e.g., ItemPlan via plan_item with unit_id):

    use audunru\EagerLoadPivotRelations\EagerLoadPivotTrait;
    
    class Item extends Model
    {
        use EagerLoadPivotRelations;
    
        public function plans()
        {
            return $this->belongsToMany(Plan::class)->withPivot('unit_id');
        }
    }
    

    Eager-load the pivot relation (e.g., Unit for unit_id):

    $items = Item::with('plans.unit')->get();
    

Implementation Patterns

Core Workflow

  1. Define Pivot Relations: Extend the pivot model or use withPivot() to specify relations:

    // In Item model
    public function plans()
    {
        return $this->belongsToMany(Plan::class)
            ->withPivot('unit_id')
            ->using(PlanItem::class); // Optional: Custom pivot model
    }
    
  2. Eager-Loading: Use with() to load pivot relations alongside the main relationship:

    // Load pivot relations for all items
    $items = Item::with('plans.unit')->get();
    
    // Load pivot relations conditionally
    $items = Item::with(['plans.unit' => function ($query) {
        $query->where('name', 'pc');
    }])->get();
    
  3. Accessing Data:

    foreach ($items as $item) {
        foreach ($item->plans as $plan) {
            $unit = $plan->pivot->unit; // Access pivot relation
            echo $unit->name; // e.g., "pc"
        }
    }
    

Advanced Patterns

  • Custom Pivot Model: If using a custom pivot model (e.g., PlanItem), define relations there:

    class PlanItem extends Pivot
    {
        public function unit()
        {
            return $this->belongsTo(Unit::class);
        }
    }
    
  • Dynamic Eager-Loading: Use closures to conditionally load pivot relations:

    $items = Item::when($loadUnits, function ($query) {
        return $query->with('plans.unit');
    })->get();
    
  • API Responses: Serialize pivot relations directly in JSON:

    return Item::with('plans.unit')->get()->map(function ($item) {
        return [
            'name' => $item->name,
            'plans' => $item->plans->map(function ($plan) {
                return [
                    'plan_id' => $plan->id,
                    'unit' => $plan->pivot->unit->name,
                ];
            }),
        ];
    });
    

Gotchas and Tips

Pitfalls

  1. N+1 Queries Without with(): Forgetting to use with('plans.unit') will trigger N+1 queries when accessing pivot relations. Fix: Always eager-load pivot relations explicitly.

  2. Pivot Model Not Defined: If using a custom pivot model (e.g., PlanItem), ensure it’s specified in the relationship:

    return $this->belongsToMany(Plan::class)->using(PlanItem::class);
    

    Fix: Add ->using(PivotModel::class) to the relationship.

  3. Circular References: Deeply nested pivot relations (e.g., unit.category) may cause serialization issues. Fix: Use ->with() selectively or exclude problematic relations with ->without().

  4. Laravel Version Mismatch: The package supports Laravel 8+. Using it on older versions may break. Fix: Check the releases for compatibility.

Debugging Tips

  • Query Logging: Enable query logging to verify eager-loading works:

    DB::enableQueryLog();
    $items = Item::with('plans.unit')->get();
    dd(DB::getQueryLog());
    
  • Check Pivot Relations: Inspect the pivot model’s relations:

    dd($item->plans->first()->pivot->unit); // Should return the Unit model
    
  • Fallback for Missing Relations: Handle cases where pivot relations might be null:

    $unitName = $plan->pivot->unit?->name ?? 'N/A';
    

Extension Points

  1. Customizing Pivot Loading: Override the eagerLoadPivotRelations method in the trait for custom logic:

    protected function eagerLoadPivotRelations(array $relations)
    {
        // Custom logic here
        return parent::eagerLoadPivotRelations($relations);
    }
    
  2. Global Eager-Loading: Use model observers or service providers to auto-load pivot relations:

    Item::observe(PlanItemObserver::class);
    
    class PlanItemObserver {
        public function retrieved(PlanItem $planItem) {
            $planItem->load('unit');
        }
    }
    
  3. Performance Optimization:

    • Selective Loading: Load only necessary pivot fields:
      $items = Item::with(['plans.unit' => function ($query) {
          $query->select('id', 'name'); // Limit columns
      }])->get();
      
    • Caching: Cache frequently accessed pivot relations:
      $unit = Cache::remember("unit_{$plan->pivot->unit_id}", now()->addHours(1), function () {
          return Unit::find($plan->pivot->unit_id);
      });
      
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.
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
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope