Skip to content

Commit af1298c

Browse files
authored
fix: findOr and firstOr generics (#52037)
1 parent bc3f5fa commit af1298c

File tree

7 files changed

+45
-38
lines changed

7 files changed

+45
-38
lines changed

src/Illuminate/Database/Eloquent/Builder.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -530,15 +530,15 @@ public function findOrNew($id, $columns = ['*'])
530530
/**
531531
* Find a model by its primary key or call a callback.
532532
*
533-
* @template TFindOrValue
533+
* @template TValue
534534
*
535535
* @param mixed $id
536-
* @param \Closure|array|string $columns
537-
* @param (\Closure(): TFindOrValue)|null $callback
536+
* @param (\Closure(): TValue)|list<string>|string $columns
537+
* @param (\Closure(): TValue)|null $callback
538538
* @return (
539539
* $id is (\Illuminate\Contracts\Support\Arrayable<array-key, mixed>|array<mixed>)
540540
* ? \Illuminate\Database\Eloquent\Collection<int, TModel>
541-
* : ($callback is null ? TModel|null : TModel|TFindOrValue)
541+
* : TModel|TValue
542542
* )
543543
*/
544544
public function findOr($id, $columns = ['*'], ?Closure $callback = null)
@@ -640,11 +640,11 @@ public function firstOrFail($columns = ['*'])
640640
/**
641641
* Execute the query and get the first result or call a callback.
642642
*
643-
* @template TFirstOrValue
643+
* @template TValue
644644
*
645-
* @param \Closure|array|string $columns
646-
* @param (\Closure(): TFirstOrValue)|null $callback
647-
* @return ($callback is null ? TModel|null : TModel|TFirstOrValue)
645+
* @param (\Closure(): TValue)|list<string> $columns
646+
* @param (\Closure(): TValue)|null $callback
647+
* @return TModel|TValue
648648
*/
649649
public function firstOr($columns = ['*'], ?Closure $callback = null)
650650
{

src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -737,15 +737,15 @@ public function findOrFail($id, $columns = ['*'])
737737
/**
738738
* Find a related model by its primary key or call a callback.
739739
*
740-
* @template TFindOrValue
740+
* @template TValue
741741
*
742742
* @param mixed $id
743-
* @param \Closure|array $columns
744-
* @param (\Closure(): TFindOrValue)|null $callback
743+
* @param (\Closure(): TValue)|list<string>|string $columns
744+
* @param (\Closure(): TValue)|null $callback
745745
* @return (
746746
* $id is (\Illuminate\Contracts\Support\Arrayable<array-key, mixed>|array<mixed>)
747-
* ? \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>
748-
* : ($callback is null ? TRelatedModel|null : TRelatedModel|TFindOrValue)
747+
* ? \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>|TValue
748+
* : TRelatedModel|TValue
749749
* )
750750
*/
751751
public function findOr($id, $columns = ['*'], ?Closure $callback = null)
@@ -818,11 +818,11 @@ public function firstOrFail($columns = ['*'])
818818
/**
819819
* Execute the query and get the first result or call a callback.
820820
*
821-
* @template TFirstOrValue
821+
* @template TValue
822822
*
823-
* @param \Closure|array $columns
824-
* @param (\Closure(): TFirstOrValue)|null $callback
825-
* @return ($callback is null ? TRelatedModel|null : TRelatedModel|TFirstOrValue)
823+
* @param (\Closure(): TValue)|list<string> $columns
824+
* @param (\Closure(): TValue)|null $callback
825+
* @return TRelatedModel|TValue
826826
*/
827827
public function firstOr($columns = ['*'], ?Closure $callback = null)
828828
{

src/Illuminate/Database/Eloquent/Relations/HasOneOrManyThrough.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -303,11 +303,11 @@ public function firstOrFail($columns = ['*'])
303303
/**
304304
* Execute the query and get the first result or call a callback.
305305
*
306-
* @template TFirstOrValue
306+
* @template TValue
307307
*
308-
* @param \Closure|array $columns
309-
* @param (\Closure(): TFirstOrValue)|null $callback
310-
* @return ($callback is null ? TRelatedModel|null : TRelatedModel|TFirstOrValue)
308+
* @param (\Closure(): TValue)|list<string> $columns
309+
* @param (\Closure(): TValue)|null $callback
310+
* @return TRelatedModel|TValue
311311
*/
312312
public function firstOr($columns = ['*'], ?Closure $callback = null)
313313
{
@@ -391,15 +391,15 @@ public function findOrFail($id, $columns = ['*'])
391391
/**
392392
* Find a related model by its primary key or call a callback.
393393
*
394-
* @template TFindOrValue
394+
* @template TValue
395395
*
396396
* @param mixed $id
397-
* @param \Closure|array $columns
398-
* @param (\Closure(): TFindOrValue)|null $callback
397+
* @param (\Closure(): TValue)|list<string>|string $columns
398+
* @param (\Closure(): TValue)|null $callback
399399
* @return (
400400
* $id is (\Illuminate\Contracts\Support\Arrayable<array-key, mixed>|array<mixed>)
401-
* ? \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>
402-
* : ($callback is null ? TRelatedModel|null : TRelatedModel|TFindOrValue)
401+
* ? \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>|TValue
402+
* : TRelatedModel|TValue
403403
* )
404404
*/
405405
public function findOr($id, $columns = ['*'], ?Closure $callback = null)

src/Illuminate/Database/Query/Builder.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2894,7 +2894,7 @@ public function toRawSql()
28942894
*
28952895
* @param int|string $id
28962896
* @param array|string $columns
2897-
* @return mixed|static
2897+
* @return object|null
28982898
*/
28992899
public function find($id, $columns = ['*'])
29002900
{
@@ -2904,10 +2904,12 @@ public function find($id, $columns = ['*'])
29042904
/**
29052905
* Execute a query for a single record by ID or call a callback.
29062906
*
2907+
* @template TValue
2908+
*
29072909
* @param mixed $id
2908-
* @param \Closure|array|string $columns
2909-
* @param \Closure|null $callback
2910-
* @return mixed|static
2910+
* @param (\Closure(): TValue)|list<string>|string $columns
2911+
* @param (\Closure(): TValue)|null $callback
2912+
* @return object|TValue
29112913
*/
29122914
public function findOr($id, $columns = ['*'], ?Closure $callback = null)
29132915
{

types/Database/Eloquent/Builder.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ function test(
3838
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $query->findOr([1], callback: fn () => 42));
3939
assertType('User', $query->findOrFail(1));
4040
assertType('User|null', $query->find(1));
41-
assertType('User|null', $query->findOr(1));
41+
assertType('int|User', $query->findOr(1, fn () => 42));
4242
assertType('int|User', $query->findOr(1, callback: fn () => 42));
4343
assertType('User|null', $query->first());
44-
assertType('User|null', $query->firstOr());
44+
assertType('int|User', $query->firstOr(fn () => 42));
4545
assertType('int|User', $query->firstOr(callback: fn () => 42));
4646
assertType('User', $query->firstOrNew(['id' => 1]));
4747
assertType('User', $query->findOrNew(1));

types/Database/Eloquent/Relations.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,15 @@ function test(User $user, Post $post, Comment $comment, ChildUser $child): void
4646
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findMany([1, 2, 3]));
4747
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findOrNew([1]));
4848
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findOrFail([1]));
49-
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findOr([1], callback: fn () => 42));
49+
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>|int', $user->roles()->findOr([1], fn () => 42));
50+
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>|int', $user->roles()->findOr([1], callback: fn () => 42));
5051
assertType('Illuminate\Types\Relations\Role', $user->roles()->findOrNew(1));
5152
assertType('Illuminate\Types\Relations\Role', $user->roles()->findOrFail(1));
5253
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->find(1));
53-
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->findOr(1));
54+
assertType('Illuminate\Types\Relations\Role|int', $user->roles()->findOr(1, fn () => 42));
5455
assertType('Illuminate\Types\Relations\Role|int', $user->roles()->findOr(1, callback: fn () => 42));
5556
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->first());
56-
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->firstOr());
57+
assertType('Illuminate\Types\Relations\Role|int', $user->roles()->firstOr(fn () => 42));
5758
assertType('Illuminate\Types\Relations\Role|int', $user->roles()->firstOr(callback: fn () => 42));
5859
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->firstWhere('foo'));
5960
assertType('Illuminate\Types\Relations\Role', $user->roles()->firstOrNew());
@@ -77,12 +78,13 @@ function test(User $user, Post $post, Comment $comment, ChildUser $child): void
7778
assertType('Illuminate\Database\Eloquent\Relations\HasOneThrough<Illuminate\Types\Relations\Car, Illuminate\Types\Relations\Mechanic, Illuminate\Types\Relations\User>', $user->car());
7879
assertType('Illuminate\Types\Relations\Car|null', $user->car()->getResults());
7980
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>', $user->car()->find([1]));
80-
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>', $user->car()->findOr([1], callback: fn () => 42));
81+
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>|int', $user->car()->findOr([1], fn () => 42));
82+
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>|int', $user->car()->findOr([1], callback: fn () => 42));
8183
assertType('Illuminate\Types\Relations\Car|null', $user->car()->find(1));
82-
assertType('Illuminate\Types\Relations\Car|null', $user->car()->findOr(1));
84+
assertType('Illuminate\Types\Relations\Car|int', $user->car()->findOr(1, fn () => 42));
8385
assertType('Illuminate\Types\Relations\Car|int', $user->car()->findOr(1, callback: fn () => 42));
8486
assertType('Illuminate\Types\Relations\Car|null', $user->car()->first());
85-
assertType('Illuminate\Types\Relations\Car|null', $user->car()->firstOr());
87+
assertType('Illuminate\Types\Relations\Car|int', $user->car()->firstOr(fn () => 42));
8688
assertType('Illuminate\Types\Relations\Car|int', $user->car()->firstOr(callback: fn () => 42));
8789
assertType('Illuminate\Support\LazyCollection<int, Illuminate\Types\Relations\Car>', $user->car()->lazy());
8890
assertType('Illuminate\Support\LazyCollection<int, Illuminate\Types\Relations\Car>', $user->car()->lazyById());

types/Database/Query/Builder.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
function test(Builder $query, EloquentBuilder $userQuery): void
1212
{
1313
assertType('object|null', $query->first());
14+
assertType('object|null', $query->find(1));
15+
assertType('int|object', $query->findOr(1, fn () => 42));
16+
assertType('int|object', $query->findOr(1, callback: fn () => 42));
1417
assertType('Illuminate\Database\Query\Builder', $query->selectSub($userQuery, 'alias'));
1518
assertType('Illuminate\Database\Query\Builder', $query->fromSub($userQuery, 'alias'));
1619
assertType('Illuminate\Database\Query\Builder', $query->from($userQuery, 'alias'));

0 commit comments

Comments
 (0)