Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/database/extension.neon
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ services:
-
class: Hypervel\Database\PHPStan\ModelScopeMethodResolver
-
class: Hypervel\Database\PHPStan\ForwardedFluentMethodExtension
class: Hypervel\Database\PHPStan\ForwardedBuilderMethodExtension
tags:
- phpstan.broker.methodsClassReflectionExtension
-
Expand Down
13 changes: 13 additions & 0 deletions src/database/src/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,8 @@ public function firstOrNew(array $attributes = [], Closure|array $values = []):
*/
public function firstOrCreate(array $attributes = [], Closure|array $values = []): Model
{
$this->ensureCanCreateOrFirst();
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.

if (! is_null($instance = (clone $this)->where($attributes)->first())) {
return $instance;
}
Expand All @@ -658,13 +660,24 @@ public function firstOrCreate(array $attributes = [], Closure|array $values = []
*/
public function createOrFirst(array $attributes = [], Closure|array $values = []): Model
{
$this->ensureCanCreateOrFirst();
Comment thread
coderabbitai[bot] marked this conversation as resolved.

try {
return $this->withSavepointIfNeeded(fn () => $this->create(array_merge($attributes, value($values))));
} catch (UniqueConstraintViolationException $e) {
return $this->useWritePdo()->where($attributes)->first() ?? throw $e;
}
}

/**
* Validate first-or-create and create-or-first operations, including relationship calls.
*
* Helpers delegate to each other, so this may run more than once per operation; keep overrides side-effect-free.
*/
public function ensureCanCreateOrFirst(): void
{
}

/**
* Create or update a record matching the attributes, and fill it with values.
*
Expand Down
4 changes: 4 additions & 0 deletions src/database/src/Eloquent/Relations/BelongsToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,8 @@ public function firstOrNew(array $attributes = [], Closure|array $values = []):
*/
public function firstOrCreate(array $attributes = [], Closure|array $values = [], array $joining = [], bool $touch = true): Model
{
$this->getQuery()->ensureCanCreateOrFirst();

if (is_null($instance = (clone $this)->where($attributes)->first())) {
if (is_null($instance = $this->related->where($attributes)->first())) {
$instance = $this->createOrFirst($attributes, $values, $joining, $touch);
Expand All @@ -620,6 +622,8 @@ public function firstOrCreate(array $attributes = [], Closure|array $values = []
*/
public function createOrFirst(array $attributes = [], Closure|array $values = [], array $joining = [], bool $touch = true): Model
{
$this->getQuery()->ensureCanCreateOrFirst();

try {
return $this->getQuery()->withSavepointIfNeeded(fn () => $this->create(array_merge($attributes, value($values)), $joining, $touch));
} catch (UniqueConstraintViolationException $exception) {
Expand Down
4 changes: 4 additions & 0 deletions src/database/src/Eloquent/Relations/HasOneOrMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ public function firstOrNew(array $attributes = [], Closure|array $values = []):
*/
public function firstOrCreate(array $attributes = [], Closure|array $values = []): Model
{
$this->getQuery()->ensureCanCreateOrFirst();

if (is_null($instance = (clone $this)->where($attributes)->first())) {
$instance = $this->createOrFirst($attributes, $values);
}
Expand All @@ -254,6 +256,8 @@ public function firstOrCreate(array $attributes = [], Closure|array $values = []
*/
public function createOrFirst(array $attributes = [], Closure|array $values = []): Model
{
$this->getQuery()->ensureCanCreateOrFirst();

try {
return $this->getQuery()->withSavepointIfNeeded(fn () => $this->create(array_merge($attributes, value($values))));
} catch (UniqueConstraintViolationException $e) {
Expand Down
4 changes: 4 additions & 0 deletions src/database/src/Eloquent/Relations/HasOneOrManyThrough.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ public function firstOrNew(array $attributes = [], array $values = []): Model
*/
public function firstOrCreate(array $attributes = [], Closure|array $values = []): Model
{
$this->getQuery()->ensureCanCreateOrFirst();

if (! is_null($instance = (clone $this)->where($attributes)->first())) {
return $instance;
}
Expand All @@ -219,6 +221,8 @@ public function firstOrCreate(array $attributes = [], Closure|array $values = []
*/
public function createOrFirst(array $attributes = [], Closure|array $values = []): Model
{
$this->getQuery()->ensureCanCreateOrFirst();

try {
return $this->getQuery()->withSavepointIfNeeded(fn () => $this->create(array_merge($attributes, value($values))));
} catch (UniqueConstraintViolationException $exception) {
Expand Down
12 changes: 7 additions & 5 deletions src/database/src/Migrations/DatabaseMigrationRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ public function getRan(): array
/**
* Get the list of migrations.
*
* @return object{id: int, migration: string, batch: int}[]
* Driver-owned migration schemas may omit id and return numeric-string batches.
*
* @return object{migration: string, batch: int|numeric-string}[]
*/
public function getMigrations(int $steps): array
{
Expand All @@ -56,7 +58,7 @@ public function getMigrations(int $steps): array
/**
* Get the list of the migrations by batch number.
*
* @return object{id: int, migration: string, batch: int}[]
* @return object{migration: string, batch: int|numeric-string}[]
*/
public function getMigrationsByBatch(int $batch): array
{
Expand All @@ -70,7 +72,7 @@ public function getMigrationsByBatch(int $batch): array
/**
* Get the last migration batch.
*
* @return object{id: int, migration: string, batch: int}[]
* @return object{migration: string, batch: int|numeric-string}[]
*/
public function getLast(): array
{
Expand All @@ -82,7 +84,7 @@ public function getLast(): array
/**
* Get the completed migrations with their batch numbers.
*
* @return array<string, int>
* @return array<string, int|numeric-string>
*/
public function getMigrationBatches(): array
{
Expand All @@ -105,7 +107,7 @@ public function log(string $file, int $batch): void
/**
* Remove a migration from the log.
*
* @param object{id?: int, migration: string, batch?: int} $migration
* @param object{migration: string} $migration
*/
public function delete(object $migration): void
{
Expand Down
12 changes: 7 additions & 5 deletions src/database/src/Migrations/MigrationRepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,30 @@ public function getRan(): array;
/**
* Get the list of migrations.
*
* @return object{id: int, migration: string, batch: int}[]
* Driver-owned migration schemas may omit id and return numeric-string batches.
*
* @return object{migration: string, batch: int|numeric-string}[]
*/
public function getMigrations(int $steps): array;

/**
* Get the list of the migrations by batch.
*
* @return object{id: int, migration: string, batch: int}[]
* @return object{migration: string, batch: int|numeric-string}[]
*/
public function getMigrationsByBatch(int $batch): array;

/**
* Get the last migration batch.
*
* @return object{id: int, migration: string, batch: int}[]
* @return object{migration: string, batch: int|numeric-string}[]
*/
public function getLast(): array;

/**
* Get the completed migrations with their batch numbers.
*
* @return array<string, int>
* @return array<string, int|numeric-string>
*/
public function getMigrationBatches(): array;

Expand All @@ -49,7 +51,7 @@ public function log(string $file, int $batch): void;
/**
* Remove a migration from the log.
*
* @param object{id?: int, migration: string, batch?: int} $migration
* @param object{migration: string} $migration
*/
public function delete(object $migration): void;

Expand Down
3 changes: 2 additions & 1 deletion src/database/src/Migrations/Migrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ public function rollback(array|string $paths = [], array $options = []): array
* Get the migrations for a rollback operation.
*
* @param array<string, mixed> $options
* @return object{id: int, migration: string, batch: int}[]
* @return object{migration: string, batch: int|numeric-string}[]
*/
protected function getMigrationsForRollback(array $options): array
{
Expand All @@ -283,6 +283,7 @@ protected function getMigrationsForRollback(array $options): array
/**
* Rollback the given migrations.
*
* @param object{migration: string}[] $migrations
* @param string|string[] $paths
* @param array<string, mixed> $options
* @return string[]
Expand Down
Loading
Loading