VOOZH about

URL: https://deepwiki.com/hypervel/components/5.4-relationships-and-pivot-models

⇱ Relationships and Pivot Models | hypervel/components | DeepWiki


Loading...
Last indexed: 7 March 2026 (96fbab)
Menu

Relationships and Pivot Models

This document covers Hypervel's pivot table system for many-to-many relationships, including custom pivot models, pivot events, and pivot collections. Pivot models represent records in intermediate tables that connect two related models.

For information about defining relationships themselves (e.g., belongsToMany(), morphToMany()), see the relationship configuration documentation. This page focuses specifically on the pivot model layer that sits between related models.


Overview of Pivot Models

Hypervel provides two base pivot model classes that extend Hyperf's pivot functionality with event support, custom collections, and enhanced attribute handling:

ClassPurposeUse Case
PivotStandard pivot modelbelongsToMany() relationships
MorphPivotPolymorphic pivot modelmorphToMany() relationships

Both pivot classes integrate the same trait composition as regular Eloquent models, providing attribute casting, timestamps, observers, callbacks, and collection customization.

Sources: src/core/src/Database/Eloquent/Relations/Pivot.php1-63 src/core/src/Database/Eloquent/Relations/MorphPivot.php1-69


Pivot Model Class Hierarchy


Sources: src/core/src/Database/Eloquent/Relations/Pivot.php17-24 src/core/src/Database/Eloquent/Relations/MorphPivot.php17-24


Creating Custom Pivot Classes

Custom pivot classes allow you to add business logic, attributes, casts, and event handlers to pivot records. Define a custom pivot class by extending Pivot or MorphPivot:


Attach the custom pivot class to a relationship using ->using():


Sources: tests/Core/Database/Eloquent/Relations/BelongsToManyPivotEventsTest.php318-368 tests/Core/Database/Eloquent/Relations/MorphToManyPivotEventsTest.php349-399


Pivot Model Event System

When a custom pivot class is specified via ->using(), pivot operations trigger model events. Without a custom class, Hypervel uses performant bulk queries that bypass events.

Event Flow Comparison


Sources: src/core/src/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php1-184

InteractsWithPivotTable Trait

The InteractsWithPivotTable trait overrides Hyperf's bulk query methods to use model instances when $this->using is set:

MethodWithout Custom PivotWith Custom Pivot
attach()Raw INSERT querynewPivot()->save() fires events
detach()Raw DELETE querypivot->delete() fires events
updateExistingPivot()Raw UPDATE querypivot->fill()->save() fires events

The trait provides these key methods:

Sources: src/core/src/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php10-184


Pivot Event Lifecycle

Composite Key Pivot Deletion

Both Pivot and MorphPivot override the delete() method to ensure events fire even for composite key pivots (which lack a primary key):


The delete() implementation handles both single-key and composite-key scenarios:

For MorphPivot, an additional morph type constraint is added to the delete query src/core/src/Database/Eloquent/Relations/MorphPivot.php59

Sources: src/core/src/Database/Eloquent/Relations/Pivot.php41-62 src/core/src/Database/Eloquent/Relations/MorphPivot.php42-68


MorphPivot Type Handling

MorphPivot extends pivot functionality to support polymorphic relationships by storing and managing morph type information:


The MorphToMany::newPivot() method ensures morph type and class are set on pivot instances src/core/src/Database/Eloquent/Relations/MorphToMany.php89-106:


When deleting, MorphPivot adds a morph type constraint to prevent accidentally deleting records for other polymorphic types sharing the same pivot table src/core/src/Database/Eloquent/Relations/MorphPivot.php59

Sources: src/core/src/Database/Eloquent/Relations/MorphPivot.php1-69 src/core/src/Database/Eloquent/Relations/MorphToMany.php56-106


Pivot Model Collections

Pivot models support custom collection classes through the same HasCollection trait used by regular models. Specify a custom collection using either:

  1. Attribute: #[CollectedBy(CustomCollection::class)]
  2. Property: protected static string $collectionClass = CustomCollection::class

Collection Resolution Flow


Example custom pivot collection:


Sources: src/core/src/Database/Eloquent/Concerns/HasCollection.php1-60 tests/Core/Database/Eloquent/Relations/PivotCollectionTest.php1-257


Pivot Instance Creation

Model::newPivot() Method

The Model::newPivot() method creates pivot instances for relationships. It accepts a custom pivot class via the $using parameter:


Implementation at src/core/src/Database/Eloquent/Model.php168-171:


Relationship newPivot() Override

Both BelongsToMany and MorphToMany relationships override newPivot() to include pivotValues (values set via ->withPivotValue()) in the attributes src/core/src/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php166-183:


Sources: src/core/src/Database/Eloquent/Model.php161-171 src/core/src/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php166-183


Pivot Attributes and Timestamps

Pivot models inherit attribute casting and timestamp management from their trait composition:

HasAttributes Integration

The HasAttributes trait provides:

HasTimestamps Integration

The HasTimestamps trait overrides freshTimestamp() to use the Date facade, allowing applications to configure a custom date class (e.g., CarbonImmutable) globally:


This ensures pivot timestamps respect the application's date configuration set via Date::use().

Sources: src/core/src/Database/Eloquent/Concerns/HasAttributes.php1-143 src/core/src/Database/Eloquent/Concerns/HasTimestamps.php1-28


Relationship Type Compatibility

RelationshipPivot ClassTrait Used
belongsToMany()PivotInteractsWithPivotTable
morphToMany()MorphPivotInteractsWithPivotTable (with morph handling)

The MorphToMany relationship overrides getCurrentlyAttachedPivots() to handle morph type/class assignment src/core/src/Database/Eloquent/Relations/MorphToMany.php57-79:


Sources: src/core/src/Database/Eloquent/Relations/MorphToMany.php1-107


Testing Pivot Events

The test suite validates pivot event behavior across multiple scenarios:

BelongsToMany Event Tests

Located at tests/Core/Database/Eloquent/Relations/BelongsToManyPivotEventsTest.php these tests verify:

MorphToMany Event Tests

Located at tests/Core/Database/Eloquent/Relations/MorphToManyPivotEventsTest.php these tests verify:

Sources: tests/Core/Database/Eloquent/Relations/BelongsToManyPivotEventsTest.php1-369 tests/Core/Database/Eloquent/Relations/MorphToManyPivotEventsTest.php1-400


Key Architectural Decisions

Performance vs. Events Trade-off

Hypervel provides two operational modes:

  1. Without custom pivot class: Uses raw bulk queries for maximum performance. Events do not fire.
  2. With custom pivot class: Uses model instances with full event support. Slightly slower due to model hydration.

This design allows developers to opt into event-driven behavior only when needed, maintaining backward compatibility with Laravel's approach while offering enhanced functionality when required.

Trait Composition

Both Pivot and MorphPivot use the same trait composition as regular Model classes:

  • HasAttributes - Attribute casting and date handling
  • HasCallbacks - Model lifecycle callbacks
  • HasCollection - Custom collection support
  • HasGlobalScopes - Query scope application
  • HasObservers - Observer pattern support
  • HasTimestamps - Timestamp management

This consistent trait composition ensures pivot models behave like first-class models with all expected features.

Sources: src/core/src/Database/Eloquent/Relations/Pivot.php17-34 src/core/src/Database/Eloquent/Relations/MorphPivot.php17-34