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

Laravel Composite Relations Laravel Package

reedware/laravel-composite-relations

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require reedware/laravel-composite-relations
    

    No publisher required—just install and use.

  2. First Use Case: Define a composite belongsTo relation in a model (e.g., OrderItem):

    use Reedware\CompositeRelations\HasCompositeRelations;
    
    class OrderItem extends Model
    {
        use HasCompositeRelations;
    
        public function order()
        {
            return $this->belongsTo(
                Order::class,
                ['order_id', 'user_id'], // Composite keys
                ['id', 'user_id']        // Composite keys on parent
            );
        }
    }
    
    • Key Insight: The method signature mirrors Eloquent’s native syntax but accepts arrays for composite keys.
  3. Where to Look First:

    • README for syntax examples.
    • Tests for edge cases (e.g., eager loading, polymorphic relations).

Implementation Patterns

Core Workflows

  1. Defining Relations:

    • Belongs To:
      return $this->belongsTo(
          RelatedModel::class,
          ['fk1', 'fk2'], // Child keys
          ['pk1', 'pk2']  // Parent keys
      );
      
    • Has One/Has Many:
      return $this->hasOne(
          RelatedModel::class,
          ['parent_fk1', 'parent_fk2'],
          ['fk1', 'fk2']
      );
      
    • Polymorphic:
      return $this->belongsToPolymorphic(
          ['fk1', 'fk2', 'fk3'],
          ['parent_pk1', 'parent_pk2']
      );
      
  2. Querying:

    • Use relations like native Eloquent:
      $orderItem->order; // Accessor
      $orderItem->load('order'); // Eager loading
      
    • Composite Where Clauses:
      OrderItem::whereComposite('order_id', 'user_id', '=', [1, 2])->get();
      
  3. Migrations:

    • Add composite foreign keys with foreignId():
      $table->foreignId('fk1')->constrained('orders', 'id');
      $table->foreignId('fk2')->constrained('orders', 'user_id');
      
  4. Integration with Existing Code:

    • Replace manual joins with composite relations for cleaner logic:
      // Before (manual join)
      DB::table('order_items')
          ->join('orders', function ($join) {
              $join->on('order_items.order_id', '=', 'orders.id')
                   ->on('order_items.user_id', '=', 'orders.user_id');
          });
      
      // After (composite relation)
      OrderItem::with('order')->get();
      
  5. API Responses:

    • Use with() to include nested composite relations in JSON:
      return OrderItem::with(['order', 'order.user'])->get();
      

Gotchas and Tips

Pitfalls

  1. Key Order Sensitivity:

    • Composite keys must match the order defined in the relation. Mixing ['fk1', 'fk2'] with ['fk2', 'fk1'] will fail silently (no match found).
    • Fix: Ensure migrations and relation definitions align exactly.
  2. Eager Loading Quirks:

    • N+1 queries may persist if relations aren’t loaded explicitly:
      // Avoid:
      foreach ($orderItems as $item) { $item->order; } // N+1
      
      // Prefer:
      OrderItem::with('order')->get();
      
    • Debug Tip: Use Laravel Debugbar to inspect queries.
  3. Polymorphic Relations:

    • The type column must still exist for polymorphic relations, even with composite keys.
    • Workaround: Extend the package or use a custom accessor if the type column isn’t needed.
  4. Mass Assignment:

    • Composite relations do not auto-fill related models. Use save() or associate() manually:
      $orderItem->order()->associate($order);
      $orderItem->save();
      
  5. Soft Deletes:

    • Composite relations ignore soft deletes by default. Explicitly add withTrashed() if needed:
      $this->belongsTo(Order::class, ['fk1', 'fk2'], ['pk1', 'pk2'])
           ->withTrashed();
      

Debugging

  1. Query Logs:

    • Enable query logging in config/database.php:
      'log_queries' => true,
      
    • Check storage/logs/laravel.log for malformed composite joins.
  2. Common Errors:

    • RelationNotFound: Verify composite key columns exist in both tables.
    • SQLSTATE[23000]: Foreign key constraint violations (check key orders).
  3. Testing:

    • Use CompositeRelationTestCase from the package’s tests as a template for your own tests.

Extension Points

  1. Custom Constraints:

    • Override CompositeRelation::getQuery() to add custom where clauses:
      $this->belongsTo(Order::class, ['fk1', 'fk2'], ['pk1', 'pk2'])
           ->constrain(function ($query) {
               $query->where('orders.status', 'active');
           });
      
  2. Composite Primary Keys:

    • If the parent model uses composite primary keys, define them in the relation:
      $this->belongsTo(
          Order::class,
          ['order_fk1', 'order_fk2'],
          ['pk1', 'pk2'] // Parent's composite PK
      );
      
  3. Dynamic Composite Keys:

    • Use closures for dynamic keys (e.g., tenant-aware relations):
      $this->belongsTo(Order::class, function () {
          return ['order_' . tenantId(), 'user_' . auth()->id()];
      }, ['id', 'user_id']);
      
  4. Performance:

    • For large datasets, index composite keys in migrations:
      $table->index(['fk1', 'fk2']);
      
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