From 3fde05b486e73c3bae6c88ba3e9a86e522b0b690 Mon Sep 17 00:00:00 2001 From: Liam Duckett Date: Sun, 26 Jan 2025 17:19:13 +0000 Subject: [PATCH 01/11] first pass at allowing querying non existence of nullable morph - will need moving up --- .../Eloquent/Concerns/QueriesRelationships.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php index e064689a8f54..924fa035eb90 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php @@ -311,9 +311,19 @@ public function orHasMorph($relation, $types, $operator = '>=', $count = 1) * @param \Closure|null $callback * @return $this */ - public function doesntHaveMorph($relation, $types, $boolean = 'and', ?Closure $callback = null) + public function doesntHaveMorph($relation, $types = ['*'], $boolean = 'and', ?Closure $callback = null) { - return $this->hasMorph($relation, $types, '<', 1, $boolean, $callback); + if (is_string($relation)) { + $relation = $this->getRelationWithoutConstraints($relation); + } + + return $this + ->hasMorph($relation, $types, '<', 1, $boolean, $callback) + ->when($types === ['*'], fn(self $query) => $query + ->orWhere(fn(self $query) => $query + ->whereNull([$relation->getMorphType(), $relation->getForeignKeyName()]) + ), + ); } /** From 4698ebc352057109560d07543ca34d6b02615d11 Mon Sep 17 00:00:00 2001 From: Liam Duckett Date: Sun, 26 Jan 2025 17:31:04 +0000 Subject: [PATCH 02/11] move querying non existence of nullable morph to has morph method --- .../Eloquent/Concerns/QueriesRelationships.php | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php index 924fa035eb90..62a2d20d5062 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php @@ -230,6 +230,10 @@ public function hasMorph($relation, $types, $operator = '>=', $count = 1, $boole $types = (array) $types; + if($types === ['*'] && $operator === '<' && $count === 1) { + return $this->whereMorphedTo($relation, null); + } + if ($types === ['*']) { $types = $this->model->newModelQuery()->distinct()->pluck($relation->getMorphType()) ->filter() @@ -313,17 +317,7 @@ public function orHasMorph($relation, $types, $operator = '>=', $count = 1) */ public function doesntHaveMorph($relation, $types = ['*'], $boolean = 'and', ?Closure $callback = null) { - if (is_string($relation)) { - $relation = $this->getRelationWithoutConstraints($relation); - } - - return $this - ->hasMorph($relation, $types, '<', 1, $boolean, $callback) - ->when($types === ['*'], fn(self $query) => $query - ->orWhere(fn(self $query) => $query - ->whereNull([$relation->getMorphType(), $relation->getForeignKeyName()]) - ), - ); + return $this->hasMorph($relation, $types, '<', 1, $boolean, $callback); } /** From 21857dccaabcd83e269281b5c37da0dcd88cbab9 Mon Sep 17 00:00:00 2001 From: Liam Duckett Date: Sun, 26 Jan 2025 17:44:30 +0000 Subject: [PATCH 03/11] handle checking for 0 has morphs the same as less than 1 has morphs --- .../Database/Eloquent/Concerns/QueriesRelationships.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php index 62a2d20d5062..2c4c2cad45d4 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php @@ -230,7 +230,14 @@ public function hasMorph($relation, $types, $operator = '>=', $count = 1, $boole $types = (array) $types; - if($types === ['*'] && $operator === '<' && $count === 1) { + // 1. does this deal with the callback? + // 2. does this handle types properly? + // 3. does this handle < 2 properly? + + $checkMorphNull = ($operator === '<' && $count === 1) + || ($operator === '=' && $count === 0); + + if($types === ['*'] && $checkMorphNull) { return $this->whereMorphedTo($relation, null); } From adc752ae5a582d2ef968679a4bcd4eaa352718bb Mon Sep 17 00:00:00 2001 From: Liam Duckett Date: Sun, 26 Jan 2025 17:55:00 +0000 Subject: [PATCH 04/11] work on assumption that has morph less than needs null check --- .../Database/Eloquent/Concerns/QueriesRelationships.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php index 2c4c2cad45d4..74cf5242f166 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php @@ -232,9 +232,9 @@ public function hasMorph($relation, $types, $operator = '>=', $count = 1, $boole // 1. does this deal with the callback? // 2. does this handle types properly? - // 3. does this handle < 2 properly? + // 3. does this handle other operators (>= > <= < = !=) - $checkMorphNull = ($operator === '<' && $count === 1) + $checkMorphNull = ($operator === '<') || ($operator === '=' && $count === 0); if($types === ['*'] && $checkMorphNull) { From 3d8ce4cdcb674928b737e25e8c529e4a874d3b1d Mon Sep 17 00:00:00 2001 From: Liam Duckett Date: Sun, 26 Jan 2025 18:14:18 +0000 Subject: [PATCH 05/11] attempt to handle all operators --- .../Concerns/QueriesRelationships.php | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php index 74cf5242f166..2d40bc1d7e3a 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php @@ -230,12 +230,36 @@ public function hasMorph($relation, $types, $operator = '>=', $count = 1, $boole $types = (array) $types; - // 1. does this deal with the callback? - // 2. does this handle types properly? - // 3. does this handle other operators (>= > <= < = !=) - - $checkMorphNull = ($operator === '<') - || ($operator === '=' && $count === 0); + // operators; + // 1. >= + // a) positive: doesnt need nulls as is inclusionary + // b) zero: will always be true... + // c) negative: will always be true... + // 2. > + // a) positive: doesnt need nulls as is inclusionary + // b) zero: doesnt need nulls as is inclusionary + // c) negative: will always be true... + // 3. <= + // a) positive: needs nulls as is exclusionary + // b) zero: needs nulls as is exclusionary + // c) negative: can never be true... + // 4. < + // a) positive: needs nulls as is exclusionary + // b) zero: can never be true... + // c) negative: can never be true... + // 5. = + // a) positive: doesnt need nulls as is inclusionary + // b) zero: needs nulls as is exclusionary + // c) negative: can never be true... + // 6. != + // a) positive: needs nulls as is exclusionary + // b) zero: doesnt need nulls as is inclusionary + // c) negative: will always be true... + + $checkMorphNull = ($operator === '<' && $count >= 1) + || ($operator === '<=' && $count >= 0) + || ($operator === '=' && $count === 0) + || ($operator === '!=' && $count >= 1); if($types === ['*'] && $checkMorphNull) { return $this->whereMorphedTo($relation, null); From c76a38c21d132f77c81cf868a59686397e625aa3 Mon Sep 17 00:00:00 2001 From: Liam Duckett Date: Sun, 26 Jan 2025 19:24:01 +0000 Subject: [PATCH 06/11] merge into existing query - all existing tests passing --- .../Concerns/QueriesRelationships.php | 92 +++++-------------- 1 file changed, 23 insertions(+), 69 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php index 2d40bc1d7e3a..06509ffa3d20 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php @@ -28,7 +28,6 @@ trait QueriesRelationships * @param string $operator * @param int $count * @param string $boolean - * @param \Closure|null $callback * @return $this * * @throws \RuntimeException @@ -123,7 +122,6 @@ public function orHas($relation, $operator = '>=', $count = 1) * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @param string $boolean - * @param \Closure|null $callback * @return $this */ public function doesntHave($relation, $boolean = 'and', ?Closure $callback = null) @@ -146,7 +144,6 @@ public function orDoesntHave($relation) * Add a relationship count / exists condition to the query with where clauses. * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation - * @param \Closure|null $callback * @param string $operator * @param int $count * @return $this @@ -162,7 +159,6 @@ public function whereHas($relation, ?Closure $callback = null, $operator = '>=', * Also load the relationship with same condition. * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation - * @param \Closure|null $callback * @param string $operator * @param int $count * @return $this @@ -177,7 +173,6 @@ public function withWhereHas($relation, ?Closure $callback = null, $operator = ' * Add a relationship count / exists condition to the query with where clauses and an "or". * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation - * @param \Closure|null $callback * @param string $operator * @param int $count * @return $this @@ -191,7 +186,6 @@ public function orWhereHas($relation, ?Closure $callback = null, $operator = '>= * Add a relationship count / exists condition to the query with where clauses. * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation - * @param \Closure|null $callback * @return $this */ public function whereDoesntHave($relation, ?Closure $callback = null) @@ -203,7 +197,6 @@ public function whereDoesntHave($relation, ?Closure $callback = null) * Add a relationship count / exists condition to the query with where clauses and an "or". * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation - * @param \Closure|null $callback * @return $this */ public function orWhereDoesntHave($relation, ?Closure $callback = null) @@ -219,7 +212,6 @@ public function orWhereDoesntHave($relation, ?Closure $callback = null) * @param string $operator * @param int $count * @param string $boolean - * @param \Closure|null $callback * @return $this */ public function hasMorph($relation, $types, $operator = '>=', $count = 1, $boolean = 'and', ?Closure $callback = null) @@ -230,40 +222,11 @@ public function hasMorph($relation, $types, $operator = '>=', $count = 1, $boole $types = (array) $types; - // operators; - // 1. >= - // a) positive: doesnt need nulls as is inclusionary - // b) zero: will always be true... - // c) negative: will always be true... - // 2. > - // a) positive: doesnt need nulls as is inclusionary - // b) zero: doesnt need nulls as is inclusionary - // c) negative: will always be true... - // 3. <= - // a) positive: needs nulls as is exclusionary - // b) zero: needs nulls as is exclusionary - // c) negative: can never be true... - // 4. < - // a) positive: needs nulls as is exclusionary - // b) zero: can never be true... - // c) negative: can never be true... - // 5. = - // a) positive: doesnt need nulls as is inclusionary - // b) zero: needs nulls as is exclusionary - // c) negative: can never be true... - // 6. != - // a) positive: needs nulls as is exclusionary - // b) zero: doesnt need nulls as is inclusionary - // c) negative: will always be true... - - $checkMorphNull = ($operator === '<' && $count >= 1) - || ($operator === '<=' && $count >= 0) - || ($operator === '=' && $count === 0) - || ($operator === '!=' && $count >= 1); - - if($types === ['*'] && $checkMorphNull) { - return $this->whereMorphedTo($relation, null); - } + $checkMorphNull = $types === ['*'] + && (($operator === '<' && $count >= 1) + || ($operator === '<=' && $count >= 0) + || ($operator === '=' && $count === 0) + || ($operator === '!=' && $count >= 1)); if ($types === ['*']) { $types = $this->model->newModelQuery()->distinct()->pluck($relation->getMorphType()) @@ -280,22 +243,24 @@ public function hasMorph($relation, $types, $operator = '>=', $count = 1, $boole $type = Relation::getMorphedModel($type) ?? $type; } - return $this->where(function ($query) use ($relation, $callback, $operator, $count, $types) { - foreach ($types as $type) { - $query->orWhere(function ($query) use ($relation, $callback, $operator, $count, $type) { - $belongsTo = $this->getBelongsToRelation($relation, $type); - - if ($callback) { - $callback = function ($query) use ($callback, $type) { - return $callback($query, $type); - }; - } - - $query->where($this->qualifyColumn($relation->getMorphType()), '=', (new $type)->getMorphClass()) - ->whereHas($belongsTo, $callback, $operator, $count); - }); - } - }, null, null, $boolean); + return $this + ->where(function ($query) use ($relation, $callback, $operator, $count, $types) { + foreach ($types as $type) { + $query->orWhere(function ($query) use ($relation, $callback, $operator, $count, $type) { + $belongsTo = $this->getBelongsToRelation($relation, $type); + + if ($callback) { + $callback = function ($query) use ($callback, $type) { + return $callback($query, $type); + }; + } + + $query->where($this->qualifyColumn($relation->getMorphType()), '=', (new $type)->getMorphClass()) + ->whereHas($belongsTo, $callback, $operator, $count); + }); + } + }, null, null, $boolean) + ->when($checkMorphNull, fn (self $query) => $query->orWhereMorphedTo($relation, null)); } /** @@ -343,7 +308,6 @@ public function orHasMorph($relation, $types, $operator = '>=', $count = 1) * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types * @param string $boolean - * @param \Closure|null $callback * @return $this */ public function doesntHaveMorph($relation, $types = ['*'], $boolean = 'and', ?Closure $callback = null) @@ -368,7 +332,6 @@ public function orDoesntHaveMorph($relation, $types) * * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types - * @param \Closure|null $callback * @param string $operator * @param int $count * @return $this @@ -383,7 +346,6 @@ public function whereHasMorph($relation, $types, ?Closure $callback = null, $ope * * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types - * @param \Closure|null $callback * @param string $operator * @param int $count * @return $this @@ -398,7 +360,6 @@ public function orWhereHasMorph($relation, $types, ?Closure $callback = null, $o * * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types - * @param \Closure|null $callback * @return $this */ public function whereDoesntHaveMorph($relation, $types, ?Closure $callback = null) @@ -411,7 +372,6 @@ public function whereDoesntHaveMorph($relation, $types, ?Closure $callback = nul * * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types - * @param \Closure|null $callback * @return $this */ public function orWhereDoesntHaveMorph($relation, $types, ?Closure $callback = null) @@ -965,11 +925,6 @@ public function mergeConstraintsFrom(Builder $from) /** * Updates the table name for any columns with a new qualified name. - * - * @param array $wheres - * @param string $from - * @param string $to - * @return array */ protected function requalifyWhereTables(array $wheres, string $from, string $to): array { @@ -985,7 +940,6 @@ protected function requalifyWhereTables(array $wheres, string $from, string $to) /** * Add a sub-query count clause to this query. * - * @param \Illuminate\Database\Query\Builder $query * @param string $operator * @param int $count * @param string $boolean From fe6193d6b10435205ad3f4e3b68153d39326cef2 Mon Sep 17 00:00:00 2001 From: Liam Duckett Date: Sun, 26 Jan 2025 19:55:47 +0000 Subject: [PATCH 07/11] add test --- tests/Integration/Database/EloquentWhereHasMorphTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/Integration/Database/EloquentWhereHasMorphTest.php b/tests/Integration/Database/EloquentWhereHasMorphTest.php index 15334b5788c2..8661571f959e 100644 --- a/tests/Integration/Database/EloquentWhereHasMorphTest.php +++ b/tests/Integration/Database/EloquentWhereHasMorphTest.php @@ -255,6 +255,13 @@ public function testModelScopesAreAccessible() $this->assertEquals([1, 4], $comments->pluck('id')->all()); } + + public function testWhereDoesntHaveMorphWithNullableMorph() + { + $comments = Comment::whereDoesntHaveMorph('commentable', '*')->orderBy('id')->get(); + + $this->assertEquals([3, 7, 8], $comments->pluck('id')->all()); + } } class Comment extends Model From cfc3dc03ee088ca44e6db4b4b137b3053ace09e9 Mon Sep 17 00:00:00 2001 From: Liam Duckett Date: Sun, 26 Jan 2025 20:19:54 +0000 Subject: [PATCH 08/11] revert signature change --- .../Database/Eloquent/Concerns/QueriesRelationships.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php index 06509ffa3d20..cb031cf66061 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php @@ -310,7 +310,7 @@ public function orHasMorph($relation, $types, $operator = '>=', $count = 1) * @param string $boolean * @return $this */ - public function doesntHaveMorph($relation, $types = ['*'], $boolean = 'and', ?Closure $callback = null) + public function doesntHaveMorph($relation, $types, $boolean = 'and', ?Closure $callback = null) { return $this->hasMorph($relation, $types, '<', 1, $boolean, $callback); } From 02b7f768e010987674e7a7f277f0615898564fdd Mon Sep 17 00:00:00 2001 From: Liam Duckett Date: Wed, 29 Jan 2025 20:50:15 +0000 Subject: [PATCH 09/11] readd docblocks --- .../Concerns/QueriesRelationships.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php index cb031cf66061..546f0ee0a580 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php @@ -28,6 +28,7 @@ trait QueriesRelationships * @param string $operator * @param int $count * @param string $boolean + * @param \Closure|null $callback * @return $this * * @throws \RuntimeException @@ -122,6 +123,7 @@ public function orHas($relation, $operator = '>=', $count = 1) * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @param string $boolean + * @param \Closure|null $callback * @return $this */ public function doesntHave($relation, $boolean = 'and', ?Closure $callback = null) @@ -144,6 +146,7 @@ public function orDoesntHave($relation) * Add a relationship count / exists condition to the query with where clauses. * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation + * @param \Closure|null $callback * @param string $operator * @param int $count * @return $this @@ -159,6 +162,7 @@ public function whereHas($relation, ?Closure $callback = null, $operator = '>=', * Also load the relationship with same condition. * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation + * @param \Closure|null $callback * @param string $operator * @param int $count * @return $this @@ -173,6 +177,7 @@ public function withWhereHas($relation, ?Closure $callback = null, $operator = ' * Add a relationship count / exists condition to the query with where clauses and an "or". * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation + * @param \Closure|null $callback * @param string $operator * @param int $count * @return $this @@ -186,6 +191,7 @@ public function orWhereHas($relation, ?Closure $callback = null, $operator = '>= * Add a relationship count / exists condition to the query with where clauses. * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation + * @param \Closure|null $callback * @return $this */ public function whereDoesntHave($relation, ?Closure $callback = null) @@ -197,6 +203,7 @@ public function whereDoesntHave($relation, ?Closure $callback = null) * Add a relationship count / exists condition to the query with where clauses and an "or". * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation + * @param \Closure|null $callback * @return $this */ public function orWhereDoesntHave($relation, ?Closure $callback = null) @@ -212,6 +219,7 @@ public function orWhereDoesntHave($relation, ?Closure $callback = null) * @param string $operator * @param int $count * @param string $boolean + * @param \Closure|null $callback * @return $this */ public function hasMorph($relation, $types, $operator = '>=', $count = 1, $boolean = 'and', ?Closure $callback = null) @@ -308,6 +316,7 @@ public function orHasMorph($relation, $types, $operator = '>=', $count = 1) * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types * @param string $boolean + * @param \Closure|null $callback * @return $this */ public function doesntHaveMorph($relation, $types, $boolean = 'and', ?Closure $callback = null) @@ -332,6 +341,7 @@ public function orDoesntHaveMorph($relation, $types) * * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types + * @param \Closure|null $callback * @param string $operator * @param int $count * @return $this @@ -346,6 +356,7 @@ public function whereHasMorph($relation, $types, ?Closure $callback = null, $ope * * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types + * @param \Closure|null $callback * @param string $operator * @param int $count * @return $this @@ -360,6 +371,7 @@ public function orWhereHasMorph($relation, $types, ?Closure $callback = null, $o * * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types + * @param \Closure|null $callback * @return $this */ public function whereDoesntHaveMorph($relation, $types, ?Closure $callback = null) @@ -372,6 +384,7 @@ public function whereDoesntHaveMorph($relation, $types, ?Closure $callback = nul * * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types + * @param \Closure|null $callback * @return $this */ public function orWhereDoesntHaveMorph($relation, $types, ?Closure $callback = null) @@ -925,6 +938,11 @@ public function mergeConstraintsFrom(Builder $from) /** * Updates the table name for any columns with a new qualified name. + * + * @param array $wheres + * @param string $from + * @param string $to + * @return array */ protected function requalifyWhereTables(array $wheres, string $from, string $to): array { @@ -940,6 +958,7 @@ protected function requalifyWhereTables(array $wheres, string $from, string $to) /** * Add a sub-query count clause to this query. * + * @param \Illuminate\Database\Query\Builder $query * @param string $operator * @param int $count * @param string $boolean From 127ea209ac9e78058430f94ba841aefa6ffc1391 Mon Sep 17 00:00:00 2001 From: Liam Duckett Date: Wed, 29 Jan 2025 20:51:04 +0000 Subject: [PATCH 10/11] fix space --- .../Database/Eloquent/Concerns/QueriesRelationships.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php index 546f0ee0a580..86e33b087302 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php @@ -146,7 +146,7 @@ public function orDoesntHave($relation) * Add a relationship count / exists condition to the query with where clauses. * * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation - * @param \Closure|null $callback + * @param \Closure|null $callback * @param string $operator * @param int $count * @return $this From cb10cb54430fda669c2321e6ed9397764a896ea3 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Thu, 6 Feb 2025 08:44:53 +0800 Subject: [PATCH 11/11] formatting --- .../Concerns/QueriesRelationships.php | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php index 86e33b087302..860351b1324c 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php @@ -251,24 +251,23 @@ public function hasMorph($relation, $types, $operator = '>=', $count = 1, $boole $type = Relation::getMorphedModel($type) ?? $type; } - return $this - ->where(function ($query) use ($relation, $callback, $operator, $count, $types) { - foreach ($types as $type) { - $query->orWhere(function ($query) use ($relation, $callback, $operator, $count, $type) { - $belongsTo = $this->getBelongsToRelation($relation, $type); - - if ($callback) { - $callback = function ($query) use ($callback, $type) { - return $callback($query, $type); - }; - } - - $query->where($this->qualifyColumn($relation->getMorphType()), '=', (new $type)->getMorphClass()) - ->whereHas($belongsTo, $callback, $operator, $count); - }); - } - }, null, null, $boolean) - ->when($checkMorphNull, fn (self $query) => $query->orWhereMorphedTo($relation, null)); + return $this->where(function ($query) use ($relation, $callback, $operator, $count, $types) { + foreach ($types as $type) { + $query->orWhere(function ($query) use ($relation, $callback, $operator, $count, $type) { + $belongsTo = $this->getBelongsToRelation($relation, $type); + + if ($callback) { + $callback = function ($query) use ($callback, $type) { + return $callback($query, $type); + }; + } + + $query->where($this->qualifyColumn($relation->getMorphType()), '=', (new $type)->getMorphClass()) + ->whereHas($belongsTo, $callback, $operator, $count); + }); + } + }, null, null, $boolean) + ->when($checkMorphNull, fn (self $query) => $query->orWhereMorphedTo($relation, null)); } /**