Skip to content

Commit 6360f01

Browse files
committed
improve PHPDoc for relations to support subclasses
1 parent 54cf9db commit 6360f01

File tree

4 files changed

+73
-44
lines changed

4 files changed

+73
-44
lines changed

src/Illuminate/Database/Eloquent/Builder.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,8 +1537,10 @@ protected function createNestedWhere($whereSlice, $boolean = 'and')
15371537
/**
15381538
* Set the relationships that should be eager loaded.
15391539
*
1540-
* @param array<array-key, array|(\Closure(\Illuminate\Database\Eloquent\Relations\Relation<*,*,*>): mixed)|string>|string $relations
1541-
* @param (\Closure(\Illuminate\Database\Eloquent\Relations\Relation<*,*,*>): mixed)|string|null $callback
1540+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
1541+
* @param array<array-key, array|(\Closure(TRelation): mixed)|string>|string $relations
1542+
* @param (\Closure(TRelation): mixed)|string|null $callback
1543+
*
15421544
* @return $this
15431545
*/
15441546
public function with($relations, $callback = null)
@@ -1572,7 +1574,8 @@ public function without($relations)
15721574
/**
15731575
* Set the relationships that should be eager loaded while removing any previously added eager loading specifications.
15741576
*
1575-
* @param array<array-key, array|(\Closure(\Illuminate\Database\Eloquent\Relations\Relation<*,*,*>): mixed)|string>|string $relations
1577+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
1578+
* @param array<array-key, array|(\Closure(TRelation): mixed)|string>|string $relations
15761579
* @return $this
15771580
*/
15781581
public function withOnly($relations)

src/Illuminate/Database/Eloquent/Collection.php

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ public function findOrFail($key)
8484
/**
8585
* Load a set of relationships onto the collection.
8686
*
87-
* @param array<array-key, array|(callable(\Illuminate\Database\Eloquent\Relations\Relation<*, *, *>): mixed)|string>|string $relations
87+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
88+
* @param array<array-key, array|(callable(TRelation): mixed)|string>|string $relations
8889
* @return $this
8990
*/
9091
public function load($relations)
@@ -105,7 +106,8 @@ public function load($relations)
105106
/**
106107
* Load a set of aggregations over relationship's column onto the collection.
107108
*
108-
* @param array<array-key, array|(callable(\Illuminate\Database\Eloquent\Relations\Relation<*, *, *>): mixed)|string>|string $relations
109+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
110+
* @param array<array-key, array|(callable(TRelation): mixed)|string>|string $relations
109111
* @param string $column
110112
* @param string|null $function
111113
* @return $this
@@ -142,7 +144,8 @@ public function loadAggregate($relations, $column, $function = null)
142144
/**
143145
* Load a set of relationship counts onto the collection.
144146
*
145-
* @param array<array-key, array|(callable(\Illuminate\Database\Eloquent\Relations\Relation<*, *, *>): mixed)|string>|string $relations
147+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
148+
* @param array<array-key, array|(callable(TRelation): mixed)|string>|string $relations
146149
* @return $this
147150
*/
148151
public function loadCount($relations)
@@ -153,7 +156,8 @@ public function loadCount($relations)
153156
/**
154157
* Load a set of relationship's max column values onto the collection.
155158
*
156-
* @param array<array-key, array|(callable(\Illuminate\Database\Eloquent\Relations\Relation<*, *, *>): mixed)|string>|string $relations
159+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
160+
* @param array<array-key, array|(callable(TRelation): mixed)|string>|string $relations
157161
* @param string $column
158162
* @return $this
159163
*/
@@ -165,7 +169,8 @@ public function loadMax($relations, $column)
165169
/**
166170
* Load a set of relationship's min column values onto the collection.
167171
*
168-
* @param array<array-key, array|(callable(\Illuminate\Database\Eloquent\Relations\Relation<*, *, *>): mixed)|string>|string $relations
172+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
173+
* @param array<array-key, array|(callable(TRelation): mixed)|string>|string $relations
169174
* @param string $column
170175
* @return $this
171176
*/
@@ -177,7 +182,8 @@ public function loadMin($relations, $column)
177182
/**
178183
* Load a set of relationship's column summations onto the collection.
179184
*
180-
* @param array<array-key, array|(callable(\Illuminate\Database\Eloquent\Relations\Relation<*, *, *>): mixed)|string>|string $relations
185+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
186+
* @param array<array-key, array|(callable(TRelation): mixed)|string>|string $relations
181187
* @param string $column
182188
* @return $this
183189
*/
@@ -189,7 +195,8 @@ public function loadSum($relations, $column)
189195
/**
190196
* Load a set of relationship's average column values onto the collection.
191197
*
192-
* @param array<array-key, array|(callable(\Illuminate\Database\Eloquent\Relations\Relation<*, *, *>): mixed)|string>|string $relations
198+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
199+
* @param array<array-key, array|(callable(TRelation): mixed)|string>|string $relations
193200
* @param string $column
194201
* @return $this
195202
*/
@@ -201,7 +208,8 @@ public function loadAvg($relations, $column)
201208
/**
202209
* Load a set of related existences onto the collection.
203210
*
204-
* @param array<array-key, array|(callable(\Illuminate\Database\Eloquent\Relations\Relation<*, *, *>): mixed)|string>|string $relations
211+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
212+
* @param array<array-key, array|(callable(TRelation): mixed)|string>|string $relations
205213
* @return $this
206214
*/
207215
public function loadExists($relations)
@@ -212,7 +220,8 @@ public function loadExists($relations)
212220
/**
213221
* Load a set of relationships onto the collection if they are not already eager loaded.
214222
*
215-
* @param array<array-key, array|(callable(\Illuminate\Database\Eloquent\Relations\Relation<*, *, *>): mixed)|string>|string $relations
223+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
224+
* @param array<array-key, array|(callable(TRelation): mixed)|string>|string $relations
216225
* @return $this
217226
*/
218227
public function loadMissing($relations)
@@ -283,8 +292,9 @@ protected function loadMissingRelation(self $models, array $path)
283292
/**
284293
* Load a set of relationships onto the mixed relationship collection.
285294
*
295+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
286296
* @param string $relation
287-
* @param array<array-key, array|(callable(\Illuminate\Database\Eloquent\Relations\Relation<*, *, *>): mixed)|string> $relations
297+
* @param array<array-key, array|(callable(TRelation): mixed)|string> $relations
288298
* @return $this
289299
*/
290300
public function loadMorph($relation, $relations)
@@ -300,8 +310,9 @@ public function loadMorph($relation, $relations)
300310
/**
301311
* Load a set of relationship counts onto the mixed relationship collection.
302312
*
313+
* @template-covariant TRelation of \Illuminate\Database\Eloquent\Relations\Relation
303314
* @param string $relation
304-
* @param array<array-key, array|(callable(\Illuminate\Database\Eloquent\Relations\Relation<*, *, *>): mixed)|string> $relations
315+
* @param array<array-key, array|(callable(TRelation): mixed)|string> $relations
305316
* @return $this
306317
*/
307318
public function loadMorphCount($relation, $relations)

types/Database/Eloquent/Builder.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Illuminate\Database\Eloquent\HasBuilder;
77
use Illuminate\Database\Eloquent\Model;
88
use Illuminate\Database\Eloquent\Relations\HasMany;
9+
use Illuminate\Database\Eloquent\Relations\HasOne;
910
use Illuminate\Database\Eloquent\Relations\MorphTo;
1011
use Illuminate\Database\Query\Builder as QueryBuilder;
1112
use User;
@@ -25,14 +26,23 @@ function test(
2526
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->whereNot('status', 'active'));
2627
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->with('relation'));
2728
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->with(['relation' => ['foo' => fn ($q) => $q]]));
28-
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->with(['relation' => function ($query) {
29-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
29+
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->with(['relation' => function (HasMany $query): void {
30+
assertType('Illuminate\Database\Eloquent\Relations\HasMany', $query);
31+
}]));
32+
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->with(['relation' => function (HasOne $query): void {
33+
assertType('Illuminate\Database\Eloquent\Relations\HasOne', $query);
34+
}]));
35+
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->with(['relation' => function (MorphTo $query): void {
36+
assertType('Illuminate\Database\Eloquent\Relations\MorphTo', $query);
3037
}]));
3138
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->without('relation'));
3239
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->withOnly(['relation']));
3340
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->withOnly(['relation' => ['foo' => fn ($q) => $q]]));
34-
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->withOnly(['relation' => function ($query) {
35-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
41+
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->withOnly(['relation' => function (MorphTo $query) {
42+
assertType('Illuminate\Database\Eloquent\Relations\MorphTo', $query);
43+
}]));
44+
assertType('Illuminate\Database\Eloquent\Builder<User>', $query->withOnly(['relation' => function (HasOne $query): void {
45+
assertType('Illuminate\Database\Eloquent\Relations\HasOne', $query);
3646
}]));
3747
assertType('array<int, User>', $query->getModels());
3848
assertType('array<int, User>', $query->eagerLoadRelations([]));

types/Database/Eloquent/Collection.php

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
<?php
22

3+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
4+
use Illuminate\Database\Eloquent\Relations\HasMany;
5+
use Illuminate\Database\Eloquent\Relations\HasOne;
6+
use Illuminate\Database\Eloquent\Relations\MorphTo;
7+
38
use function PHPStan\Testing\assertType;
49

510
$collection = User::all();
@@ -11,77 +16,77 @@
1116
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->load('string'));
1217
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->load(['string']));
1318
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->load(['string' => ['foo' => fn ($q) => $q]]));
14-
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->load(['string' => function ($query) {
15-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
19+
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->load(['string' => function (BelongsTo $query) {
20+
assertType('Illuminate\Database\Eloquent\Relations\BelongsTo', $query);
1621
}]));
1722

1823
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadAggregate('string', 'string'));
1924
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadAggregate(['string'], 'string'));
2025
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadAggregate(['string' => ['foo' => fn ($q) => $q]], 'string'));
2126
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadAggregate(['string'], 'string', 'string'));
22-
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadAggregate(['string' => function ($query) {
23-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
27+
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadAggregate(['string' => function (BelongsTo $query) {
28+
assertType('Illuminate\Database\Eloquent\Relations\BelongsTo', $query);
2429
}], 'string', 'string'));
2530

2631
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadCount('string'));
2732
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadCount(['string']));
2833
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadCount(['string' => ['foo' => fn ($q) => $q]]));
29-
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadCount(['string' => function ($query) {
30-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
34+
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadCount(['string' => function (HasOne $query) {
35+
assertType('Illuminate\Database\Eloquent\Relations\HasOne', $query);
3136
}]));
3237

3338
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMax('string', 'string'));
3439
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMax(['string'], 'string'));
3540
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMax(['string' => ['foo' => fn ($q) => $q]], 'string'));
36-
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMax(['string' => function ($query) {
37-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
38-
}], 'string'));
41+
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMax(['string' => function (HasMany $query) {
42+
assertType('Illuminate\Database\Eloquent\Relations\HasMany', $query);
43+
}]));
3944

4045
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMin('string', 'string'));
4146
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMin(['string'], 'string'));
4247
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMin(['string' => ['foo' => fn ($q) => $q]], 'string'));
43-
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMin(['string' => function ($query) {
44-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
45-
}], 'string'));
48+
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMin(['string' => function (HasOne $query) {
49+
assertType('Illuminate\Database\Eloquent\Relations\HasOne', $query);
50+
}]));
4651

4752
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadSum('string', 'string'));
4853
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadSum(['string'], 'string'));
4954
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadSum(['string' => ['foo' => fn ($q) => $q]], 'string'));
50-
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadSum(['string' => function ($query) {
51-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
52-
}], 'string'));
55+
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadSum(['string' => function (HasMany $query) {
56+
assertType('Illuminate\Database\Eloquent\Relations\HasMany', $query);
57+
}]));
5358

5459
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadAvg('string', 'string'));
5560
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadAvg(['string'], 'string'));
5661
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadAvg(['string' => ['foo' => fn ($q) => $q]], 'string'));
57-
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadAvg(['string' => function ($query) {
58-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
59-
}], 'string'));
62+
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadAvg(['string' => function (BelongsTo $query) {
63+
assertType('Illuminate\Database\Eloquent\Relations\BelongsTo', $query);
64+
}]));
6065

6166
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadExists('string'));
6267
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadExists(['string']));
6368
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadExists(['string' => ['foo' => fn ($q) => $q]]));
64-
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadExists(['string' => function ($query) {
65-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
69+
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadExists(['string' => function (MorphTo $query) {
70+
assertType('Illuminate\Database\Eloquent\Relations\MorphTo', $query);
6671
}]));
6772

6873
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMissing('string'));
6974
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMissing(['string']));
7075
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMissing(['string' => ['foo' => fn ($q) => $q]]));
71-
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMissing(['string' => function ($query) {
72-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
76+
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMissing(['string' => function (HasOne $query) {
77+
assertType('Illuminate\Database\Eloquent\Relations\HasOne', $query);
7378
}]));
7479

7580
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMorph('string', ['string']));
7681
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMorph('string', ['string' => ['foo' => fn ($q) => $q]]));
77-
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMorph('string', ['string' => function ($query) {
78-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
82+
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMorph('string', ['string' => function (HasMany $query) {
83+
assertType('Illuminate\Database\Eloquent\Relations\HasMany', $query);
7984
}]));
8085

8186
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMorphCount('string', ['string']));
8287
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMorphCount('string', ['string' => ['foo' => fn ($q) => $q]]));
83-
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMorphCount('string', ['string' => function ($query) {
84-
// assertType('Illuminate\Database\Eloquent\Relations\Relation<*,*,*>', $query);
88+
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->loadMorphCount('string', ['string' => function (HasOne $query) {
89+
assertType('Illuminate\Database\Eloquent\Relations\HasOne', $query);
8590
}]));
8691

8792
assertType('bool', $collection->contains(function ($user) {

0 commit comments

Comments
 (0)