Skip to content

Commit

Permalink
fix: findOr and firstOr generics (#52037)
Browse files Browse the repository at this point in the history
  • Loading branch information
calebdw committed Jul 5, 2024
1 parent bc3f5fa commit af1298c
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 38 deletions.
16 changes: 8 additions & 8 deletions src/Illuminate/Database/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -530,15 +530,15 @@ public function findOrNew($id, $columns = ['*'])
/**
* Find a model by its primary key or call a callback.
*
* @template TFindOrValue
* @template TValue
*
* @param mixed $id
* @param \Closure|array|string $columns
* @param (\Closure(): TFindOrValue)|null $callback
* @param (\Closure(): TValue)|list<string>|string $columns
* @param (\Closure(): TValue)|null $callback
* @return (
* $id is (\Illuminate\Contracts\Support\Arrayable<array-key, mixed>|array<mixed>)
* ? \Illuminate\Database\Eloquent\Collection<int, TModel>
* : ($callback is null ? TModel|null : TModel|TFindOrValue)
* : TModel|TValue
* )
*/
public function findOr($id, $columns = ['*'], ?Closure $callback = null)
Expand Down Expand Up @@ -640,11 +640,11 @@ public function firstOrFail($columns = ['*'])
/**
* Execute the query and get the first result or call a callback.
*
* @template TFirstOrValue
* @template TValue
*
* @param \Closure|array|string $columns
* @param (\Closure(): TFirstOrValue)|null $callback
* @return ($callback is null ? TModel|null : TModel|TFirstOrValue)
* @param (\Closure(): TValue)|list<string> $columns
* @param (\Closure(): TValue)|null $callback
* @return TModel|TValue
*/
public function firstOr($columns = ['*'], ?Closure $callback = null)
{
Expand Down
18 changes: 9 additions & 9 deletions src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -737,15 +737,15 @@ public function findOrFail($id, $columns = ['*'])
/**
* Find a related model by its primary key or call a callback.
*
* @template TFindOrValue
* @template TValue
*
* @param mixed $id
* @param \Closure|array $columns
* @param (\Closure(): TFindOrValue)|null $callback
* @param (\Closure(): TValue)|list<string>|string $columns
* @param (\Closure(): TValue)|null $callback
* @return (
* $id is (\Illuminate\Contracts\Support\Arrayable<array-key, mixed>|array<mixed>)
* ? \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>
* : ($callback is null ? TRelatedModel|null : TRelatedModel|TFindOrValue)
* ? \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>|TValue
* : TRelatedModel|TValue
* )
*/
public function findOr($id, $columns = ['*'], ?Closure $callback = null)
Expand Down Expand Up @@ -818,11 +818,11 @@ public function firstOrFail($columns = ['*'])
/**
* Execute the query and get the first result or call a callback.
*
* @template TFirstOrValue
* @template TValue
*
* @param \Closure|array $columns
* @param (\Closure(): TFirstOrValue)|null $callback
* @return ($callback is null ? TRelatedModel|null : TRelatedModel|TFirstOrValue)
* @param (\Closure(): TValue)|list<string> $columns
* @param (\Closure(): TValue)|null $callback
* @return TRelatedModel|TValue
*/
public function firstOr($columns = ['*'], ?Closure $callback = null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,11 +303,11 @@ public function firstOrFail($columns = ['*'])
/**
* Execute the query and get the first result or call a callback.
*
* @template TFirstOrValue
* @template TValue
*
* @param \Closure|array $columns
* @param (\Closure(): TFirstOrValue)|null $callback
* @return ($callback is null ? TRelatedModel|null : TRelatedModel|TFirstOrValue)
* @param (\Closure(): TValue)|list<string> $columns
* @param (\Closure(): TValue)|null $callback
* @return TRelatedModel|TValue
*/
public function firstOr($columns = ['*'], ?Closure $callback = null)
{
Expand Down Expand Up @@ -391,15 +391,15 @@ public function findOrFail($id, $columns = ['*'])
/**
* Find a related model by its primary key or call a callback.
*
* @template TFindOrValue
* @template TValue
*
* @param mixed $id
* @param \Closure|array $columns
* @param (\Closure(): TFindOrValue)|null $callback
* @param (\Closure(): TValue)|list<string>|string $columns
* @param (\Closure(): TValue)|null $callback
* @return (
* $id is (\Illuminate\Contracts\Support\Arrayable<array-key, mixed>|array<mixed>)
* ? \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>
* : ($callback is null ? TRelatedModel|null : TRelatedModel|TFindOrValue)
* ? \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>|TValue
* : TRelatedModel|TValue
* )
*/
public function findOr($id, $columns = ['*'], ?Closure $callback = null)
Expand Down
10 changes: 6 additions & 4 deletions src/Illuminate/Database/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2894,7 +2894,7 @@ public function toRawSql()
*
* @param int|string $id
* @param array|string $columns
* @return mixed|static
* @return object|null
*/
public function find($id, $columns = ['*'])
{
Expand All @@ -2904,10 +2904,12 @@ public function find($id, $columns = ['*'])
/**
* Execute a query for a single record by ID or call a callback.
*
* @template TValue
*
* @param mixed $id
* @param \Closure|array|string $columns
* @param \Closure|null $callback
* @return mixed|static
* @param (\Closure(): TValue)|list<string>|string $columns
* @param (\Closure(): TValue)|null $callback
* @return object|TValue
*/
public function findOr($id, $columns = ['*'], ?Closure $callback = null)
{
Expand Down
4 changes: 2 additions & 2 deletions types/Database/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ function test(
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $query->findOr([1], callback: fn () => 42));
assertType('User', $query->findOrFail(1));
assertType('User|null', $query->find(1));
assertType('User|null', $query->findOr(1));
assertType('int|User', $query->findOr(1, fn () => 42));
assertType('int|User', $query->findOr(1, callback: fn () => 42));
assertType('User|null', $query->first());
assertType('User|null', $query->firstOr());
assertType('int|User', $query->firstOr(fn () => 42));
assertType('int|User', $query->firstOr(callback: fn () => 42));
assertType('User', $query->firstOrNew(['id' => 1]));
assertType('User', $query->findOrNew(1));
Expand Down
14 changes: 8 additions & 6 deletions types/Database/Eloquent/Relations.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,15 @@ function test(User $user, Post $post, Comment $comment, ChildUser $child): void
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findMany([1, 2, 3]));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findOrNew([1]));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findOrFail([1]));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findOr([1], callback: fn () => 42));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>|int', $user->roles()->findOr([1], fn () => 42));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>|int', $user->roles()->findOr([1], callback: fn () => 42));
assertType('Illuminate\Types\Relations\Role', $user->roles()->findOrNew(1));
assertType('Illuminate\Types\Relations\Role', $user->roles()->findOrFail(1));
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->find(1));
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->findOr(1));
assertType('Illuminate\Types\Relations\Role|int', $user->roles()->findOr(1, fn () => 42));
assertType('Illuminate\Types\Relations\Role|int', $user->roles()->findOr(1, callback: fn () => 42));
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->first());
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->firstOr());
assertType('Illuminate\Types\Relations\Role|int', $user->roles()->firstOr(fn () => 42));
assertType('Illuminate\Types\Relations\Role|int', $user->roles()->firstOr(callback: fn () => 42));
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->firstWhere('foo'));
assertType('Illuminate\Types\Relations\Role', $user->roles()->firstOrNew());
Expand All @@ -77,12 +78,13 @@ function test(User $user, Post $post, Comment $comment, ChildUser $child): void
assertType('Illuminate\Database\Eloquent\Relations\HasOneThrough<Illuminate\Types\Relations\Car, Illuminate\Types\Relations\Mechanic, Illuminate\Types\Relations\User>', $user->car());
assertType('Illuminate\Types\Relations\Car|null', $user->car()->getResults());
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>', $user->car()->find([1]));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>', $user->car()->findOr([1], callback: fn () => 42));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>|int', $user->car()->findOr([1], fn () => 42));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>|int', $user->car()->findOr([1], callback: fn () => 42));
assertType('Illuminate\Types\Relations\Car|null', $user->car()->find(1));
assertType('Illuminate\Types\Relations\Car|null', $user->car()->findOr(1));
assertType('Illuminate\Types\Relations\Car|int', $user->car()->findOr(1, fn () => 42));
assertType('Illuminate\Types\Relations\Car|int', $user->car()->findOr(1, callback: fn () => 42));
assertType('Illuminate\Types\Relations\Car|null', $user->car()->first());
assertType('Illuminate\Types\Relations\Car|null', $user->car()->firstOr());
assertType('Illuminate\Types\Relations\Car|int', $user->car()->firstOr(fn () => 42));
assertType('Illuminate\Types\Relations\Car|int', $user->car()->firstOr(callback: fn () => 42));
assertType('Illuminate\Support\LazyCollection<int, Illuminate\Types\Relations\Car>', $user->car()->lazy());
assertType('Illuminate\Support\LazyCollection<int, Illuminate\Types\Relations\Car>', $user->car()->lazyById());
Expand Down
3 changes: 3 additions & 0 deletions types/Database/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
function test(Builder $query, EloquentBuilder $userQuery): void
{
assertType('object|null', $query->first());
assertType('object|null', $query->find(1));
assertType('int|object', $query->findOr(1, fn () => 42));
assertType('int|object', $query->findOr(1, callback: fn () => 42));
assertType('Illuminate\Database\Query\Builder', $query->selectSub($userQuery, 'alias'));
assertType('Illuminate\Database\Query\Builder', $query->fromSub($userQuery, 'alias'));
assertType('Illuminate\Database\Query\Builder', $query->from($userQuery, 'alias'));
Expand Down

0 comments on commit af1298c

Please sign in to comment.