Skip to content

Commit

Permalink
Fix conditional types on 'through' relationships by introducing addit…
Browse files Browse the repository at this point in the history
…ional template type
  • Loading branch information
jnoordsij committed Nov 6, 2024
1 parent 0aa52d9 commit efe1781
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,11 @@ protected function guessBelongsToRelation()
* @return (
* $relationship is string
* ? \Illuminate\Database\Eloquent\PendingHasThroughRelationship<\Illuminate\Database\Eloquent\Model, $this>
* : \Illuminate\Database\Eloquent\PendingHasThroughRelationship<TIntermediateModel, $this>
* : (
* $relationship is \Illuminate\Database\Eloquent\Relations\HasMany<TIntermediateModel, $this>
* ? \Illuminate\Database\Eloquent\PendingHasThroughRelationship<TIntermediateModel, $this, \Illuminate\Database\Eloquent\Relations\HasMany<TIntermediateModel, $this>>
* : \Illuminate\Database\Eloquent\PendingHasThroughRelationship<TIntermediateModel, $this, \Illuminate\Database\Eloquent\Relations\HasOne<TIntermediateModel, $this>>
* )
* )
*/
public function through($relationship)
Expand Down
15 changes: 10 additions & 5 deletions src/Illuminate/Database/Eloquent/PendingHasThroughRelationship.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
/**
* @template TIntermediateModel of \Illuminate\Database\Eloquent\Model
* @template TDeclaringModel of \Illuminate\Database\Eloquent\Model
* @template TLocalRelationship of \Illuminate\Database\Eloquent\Relations\HasOneOrMany<TIntermediateModel, TDeclaringModel>
*/
class PendingHasThroughRelationship
{
Expand All @@ -23,15 +24,15 @@ class PendingHasThroughRelationship
/**
* The local relationship.
*
* @var \Illuminate\Database\Eloquent\Relations\HasMany<TIntermediateModel, TDeclaringModel>|\Illuminate\Database\Eloquent\Relations\HasOne<TIntermediateModel, TDeclaringModel>
* @var TLocalRelationship
*/
protected $localRelationship;

/**
* Create a pending has-many-through or has-one-through relationship.
*
* @param TDeclaringModel $rootModel
* @param \Illuminate\Database\Eloquent\Relations\HasMany<TIntermediateModel, TDeclaringModel>|\Illuminate\Database\Eloquent\Relations\HasOne<TIntermediateModel, TDeclaringModel> $localRelationship
* @param TLocalRelationship $localRelationship
*/
public function __construct($rootModel, $localRelationship)
{
Expand All @@ -50,9 +51,13 @@ public function __construct($rootModel, $localRelationship)
* $callback is string
* ? \Illuminate\Database\Eloquent\Relations\HasManyThrough<\Illuminate\Database\Eloquent\Model, TIntermediateModel, TDeclaringModel>|\Illuminate\Database\Eloquent\Relations\HasOneThrough<\Illuminate\Database\Eloquent\Model, TIntermediateModel, TDeclaringModel>
* : (
* $callback is callable(TIntermediateModel): \Illuminate\Database\Eloquent\Relations\HasOne<TRelatedModel, TIntermediateModel>
* ? \Illuminate\Database\Eloquent\Relations\HasOneThrough<TRelatedModel, TIntermediateModel, TDeclaringModel>
* : \Illuminate\Database\Eloquent\Relations\HasManyThrough<TRelatedModel, TIntermediateModel, TDeclaringModel>
* TLocalRelationship is \Illuminate\Database\Eloquent\Relations\HasMany<TIntermediateModel, TDeclaringModel>
* ? \Illuminate\Database\Eloquent\Relations\HasManyThrough<TRelatedModel, TIntermediateModel, TDeclaringModel>
* : (
* $callback is callable(TIntermediateModel): \Illuminate\Database\Eloquent\Relations\HasMany<TRelatedModel, TIntermediateModel>
* ? \Illuminate\Database\Eloquent\Relations\HasManyThrough<TRelatedModel, TIntermediateModel, TDeclaringModel>
* : \Illuminate\Database\Eloquent\Relations\HasOneThrough<TRelatedModel, TIntermediateModel, TDeclaringModel>
* )
* )
* )
*/
Expand Down
29 changes: 28 additions & 1 deletion types/Database/Eloquent/Relations.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ public function mechanic(): HasOne
return $this->hasOne(Mechanic::class);
}

/** @return HasMany<Mechanic, $this> */
public function mechanics(): HasMany
{
return $this->hasMany(Mechanic::class);
}

/** @return HasOneThrough<Car, Mechanic, $this> */
public function car(): HasOneThrough
{
Expand All @@ -187,7 +193,7 @@ public function car(): HasOneThrough

$through = $this->through($this->mechanic());
assertType(
'Illuminate\Database\Eloquent\PendingHasThroughRelationship<Illuminate\Types\Relations\Mechanic, $this(Illuminate\Types\Relations\User)>',
'Illuminate\Database\Eloquent\PendingHasThroughRelationship<Illuminate\Types\Relations\Mechanic, $this(Illuminate\Types\Relations\User), Illuminate\Database\Eloquent\Relations\HasOne<Illuminate\Types\Relations\Mechanic, $this(Illuminate\Types\Relations\User)>>',
$through,
);
assertType(
Expand All @@ -202,6 +208,27 @@ public function car(): HasOneThrough
return $hasOneThrough;
}

/** @return HasManyThrough<Car, Mechanic, $this> */
public function cars(): HasManyThrough
{
$through = $this->through($this->mechanics());
assertType(
'Illuminate\Database\Eloquent\PendingHasThroughRelationship<Illuminate\Types\Relations\Mechanic, $this(Illuminate\Types\Relations\User), Illuminate\Database\Eloquent\Relations\HasMany<Illuminate\Types\Relations\Mechanic, $this(Illuminate\Types\Relations\User)>>',
$through,
);
$hasManyThrough = $through->has(function ($mechanic) {
assertType('Illuminate\Types\Relations\Mechanic', $mechanic);

return $mechanic->car();
});
assertType(
'Illuminate\Database\Eloquent\Relations\HasManyThrough<Illuminate\Types\Relations\Car, Illuminate\Types\Relations\Mechanic, $this(Illuminate\Types\Relations\User)>',
$hasManyThrough,
);

return $hasManyThrough;
}

/** @return HasManyThrough<Part, Mechanic, $this> */
public function parts(): HasManyThrough
{
Expand Down

0 comments on commit efe1781

Please sign in to comment.