-
-
Notifications
You must be signed in to change notification settings - Fork 394
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add support for create or first (#1809)
- Loading branch information
Showing
9 changed files
with
303 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
<?php | ||
|
||
namespace Illuminate\Database\Eloquent\Relations; | ||
|
||
/** | ||
* @template TRelatedModel of \Illuminate\Database\Eloquent\Model | ||
* @extends Relation<TRelatedModel> | ||
*/ | ||
class BelongsToMany extends Relation | ||
{ | ||
/** | ||
* Find a related model by its primary key or return new instance of the related model. | ||
* | ||
* @param mixed $id | ||
* @param array<int, (model-property<TRelatedModel>|'*')>|model-property<TRelatedModel>|'*' $columns | ||
* @return ($id is (\Illuminate\Contracts\Support\Arrayable<array-key, mixed>|array<mixed>) ? \Illuminate\Support\Collection<int, TRelatedModel> : TRelatedModel) | ||
*/ | ||
public function findOrNew($id, $columns = ['*']); | ||
|
||
/** | ||
* Get the first related model record matching the attributes or instantiate it. | ||
* | ||
* @param array<string, mixed> $attributes | ||
* @return TRelatedModel | ||
*/ | ||
public function firstOrNew(array $attributes); | ||
|
||
/** | ||
* Get the first related record matching the attributes or create it. | ||
* | ||
* @param array<string, mixed> $attributes | ||
* @param array<mixed> $joining | ||
* @param bool $touch | ||
* @return TRelatedModel | ||
*/ | ||
public function firstOrCreate(array $attributes, array $joining = [], $touch = true); | ||
|
||
/** | ||
* Attempt to create the record. If a unique constraint violation occurs, attempt to find the matching record. | ||
* | ||
* @param array<string, mixed> $attributes | ||
* @param array<mixed> $joining | ||
* @param bool $touch | ||
* @return TRelatedModel | ||
*/ | ||
public function createOrFirst(array $attributes, array $joining = [], $touch = true); | ||
|
||
/** | ||
* Create or update a related record matching the attributes, and fill it with values. | ||
* | ||
* @param array<string, mixed> $attributes | ||
* @param array<mixed> $values | ||
* @param array<mixed> $joining | ||
* @param bool $touch | ||
* @return TRelatedModel | ||
*/ | ||
public function updateOrCreate(array $attributes, array $values = [], array $joining = [], $touch = true); | ||
|
||
/** | ||
* Find a related model by its primary key. | ||
* | ||
* @param mixed $id | ||
* @param array<int, mixed> $columns | ||
* @return ($id is (\Illuminate\Contracts\Support\Arrayable<array-key, mixed>|array<mixed>) ? \Illuminate\Database\Eloquent\Collection<int, TRelatedModel> : TRelatedModel|null) | ||
*/ | ||
public function find($id, $columns = ['*']); | ||
|
||
/** | ||
* Find multiple related models by their primary keys. | ||
* | ||
* @param \Illuminate\Contracts\Support\Arrayable<array-key, mixed>|int[] $ids | ||
* @param array<int, mixed> $columns | ||
* @return \Illuminate\Database\Eloquent\Collection<int, TRelatedModel> | ||
*/ | ||
public function findMany($ids, $columns = ['*']); | ||
|
||
/** | ||
* Find a related model by its primary key or throw an exception. | ||
* | ||
* @param mixed $id | ||
* @param array<int, mixed> $columns | ||
* @return ($id is (\Illuminate\Contracts\Support\Arrayable<array-key, mixed>|array<mixed>) ? \Illuminate\Database\Eloquent\Collection<int, TRelatedModel> : TRelatedModel) | ||
* | ||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException | ||
*/ | ||
public function findOrFail($id, $columns = ['*']); | ||
|
||
/** | ||
* Execute the query and get the first result. | ||
* | ||
* @param array<int, mixed> $columns | ||
* @return TRelatedModel|null | ||
*/ | ||
public function first($columns = ['*']); | ||
|
||
/** | ||
* Execute the query and get the first result or throw an exception. | ||
* | ||
* @param array<int, mixed> $columns | ||
* @return TRelatedModel | ||
* | ||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException | ||
*/ | ||
public function firstOrFail($columns = ['*']); | ||
|
||
/** | ||
* Create a new instance of the related model. | ||
* | ||
* @param array<model-property<TRelatedModel>, mixed> $attributes | ||
* @param mixed[] $joining | ||
* @param bool $touch | ||
* @return TRelatedModel | ||
*/ | ||
public function create(array $attributes = [], array $joining = [], $touch = true); | ||
|
||
/** | ||
* Get the results of the relationship. | ||
* | ||
* @phpstan-return \Traversable<int, TRelatedModel> | ||
*/ | ||
public function getResults(); | ||
|
||
/** | ||
* Get a paginator for the "select" statement. | ||
* | ||
* @param int|null $perPage | ||
* @param array<int, mixed> $columns | ||
* @param string $pageName | ||
* @param int|null $page | ||
* @return \Illuminate\Pagination\LengthAwarePaginator<TRelatedModel> | ||
*/ | ||
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null); | ||
|
||
/** | ||
* Paginate the given query into a simple paginator. | ||
* | ||
* @param int|null $perPage | ||
* @param array<int, mixed> $columns | ||
* @param string $pageName | ||
* @param int|null $page | ||
* @return \Illuminate\Pagination\Paginator<TRelatedModel> | ||
*/ | ||
public function simplePaginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null); | ||
|
||
/** | ||
* Paginate the given query into a cursor paginator. | ||
* | ||
* @param int|null $perPage | ||
* @param array<int, mixed> $columns | ||
* @param string $cursorName | ||
* @param string|null $cursor | ||
* @return \Illuminate\Pagination\CursorPaginator<TRelatedModel> | ||
*/ | ||
public function cursorPaginate($perPage = null, $columns = ['*'], $cursorName = 'cursor', $cursor = null); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
<?php | ||
|
||
namespace Illuminate\Database\Eloquent\Relations; | ||
|
||
/** | ||
* @template TRelatedModel of \Illuminate\Database\Eloquent\Model | ||
* @extends Relation<TRelatedModel> | ||
*/ | ||
abstract class HasOneOrMany extends Relation | ||
{ | ||
/** | ||
* Create a new has one or many relationship instance. | ||
* | ||
* @param \Illuminate\Database\Eloquent\Builder<TRelatedModel> $query | ||
* @param TRelatedModel $parent | ||
* @param string $foreignKey | ||
* @param string $localKey | ||
* @return void | ||
*/ | ||
public function __construct(\Illuminate\Database\Eloquent\Builder $query, \Illuminate\Database\Eloquent\Model $parent, $foreignKey, $localKey); | ||
|
||
/** | ||
* @param array<model-property<TRelatedModel>, mixed> $attributes | ||
* @phpstan-return TRelatedModel | ||
*/ | ||
public function make(array $attributes = []); | ||
|
||
/** | ||
* Find a model by its primary key or return new instance of the related model. | ||
* | ||
* @param mixed $id | ||
* @param array<int, mixed> $columns | ||
* @return ($id is (\Illuminate\Contracts\Support\Arrayable<array-key, mixed>|array<mixed>) ? \Illuminate\Support\Collection<int, TRelatedModel> : TRelatedModel) | ||
*/ | ||
public function findOrNew($id, $columns = ['*']); | ||
|
||
/** | ||
* Get the first related model record matching the attributes or instantiate it. | ||
* | ||
* @param array<model-property<TRelatedModel>, mixed> $attributes | ||
* @param array<mixed, mixed> $values | ||
* @return TRelatedModel | ||
*/ | ||
public function firstOrNew(array $attributes, array $values = []); | ||
|
||
/** | ||
* Get the first related record matching the attributes or create it. | ||
* | ||
* @param array<model-property<TRelatedModel>, mixed> $attributes | ||
* @param array<mixed, mixed> $values | ||
* @return TRelatedModel | ||
*/ | ||
public function firstOrCreate(array $attributes, array $values = []); | ||
|
||
/** | ||
* Attempt to create the record. If a unique constraint violation occurs, attempt to find the matching record. | ||
* | ||
* @param array<model-property<TRelatedModel>, mixed> $attributes | ||
* @param array<mixed, mixed> $values | ||
* @return TRelatedModel | ||
*/ | ||
public function createOrFirst(array $attributes, array $values = []); | ||
|
||
/** | ||
* Create or update a related record matching the attributes, and fill it with values. | ||
* | ||
* @param array<model-property<TRelatedModel>, mixed> $attributes | ||
* @param array<array-key, mixed> $values | ||
* @return TRelatedModel | ||
*/ | ||
public function updateOrCreate(array $attributes, array $values = []); | ||
|
||
/** | ||
* Attach a model instance to the parent model. | ||
* | ||
* @param \Illuminate\Database\Eloquent\Model $model | ||
* @return TRelatedModel|false | ||
*/ | ||
public function save(\Illuminate\Database\Eloquent\Model $model); | ||
|
||
/** | ||
* @phpstan-param array<model-property<TRelatedModel>, mixed> $attributes | ||
* | ||
* @phpstan-return TRelatedModel | ||
*/ | ||
public function create(array $attributes = []); | ||
|
||
/** | ||
* Create a Collection of new instances of the related model. | ||
* | ||
* @param iterable<mixed> $records | ||
* @return \Illuminate\Database\Eloquent\Collection<int, TRelatedModel> | ||
*/ | ||
public function createMany(iterable $records); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?php | ||
|
||
/** @var \App\User $user */ | ||
$user->accounts()->createOrFirst(['foo' => 'bar']); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<?php | ||
|
||
namespace Model; | ||
|
||
use App\User; | ||
|
||
use function PHPStan\Testing\assertType; | ||
|
||
function testCreateOrFirst() | ||
{ | ||
assertType('App\User', User::createOrFirst([])); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
|
||
namespace ModelRelations; | ||
|
||
use App\Account; | ||
use App\User; | ||
|
||
use function PHPStan\Testing\assertType; | ||
|
||
function test(User $user, \App\Address $address, Account $account, ExtendsModelWithPropertyAnnotations $model, Tag $tag, User|Account $union) | ||
{ | ||
assertType('App\Account', $user->accounts()->createOrFirst([])); | ||
} |