diff --git a/src/Helpers/QueriesRelationships.php b/src/Helpers/QueriesRelationships.php index 1f1ffa34b..143af54be 100644 --- a/src/Helpers/QueriesRelationships.php +++ b/src/Helpers/QueriesRelationships.php @@ -104,6 +104,8 @@ protected function isAcrossConnections(Relation $relation) */ public function addHybridHas(Relation $relation, $operator = '>=', $count = 1, $boolean = 'and', ?Closure $callback = null) { + $this->assertHybridRelationSupported($relation); + $hasQuery = $relation->getQuery(); if ($callback) { $hasQuery->callScope($callback); @@ -128,6 +130,26 @@ public function addHybridHas(Relation $relation, $operator = '>=', $count = 1, $ return $this->whereIn($this->getRelatedConstraintKey($relation), $relatedIds, $boolean, $not); } + /** + * @param Relation $relation + * + * @return void + * + * @throws Exception + */ + public function assertHybridRelationSupported(Relation $relation): void + { + if ( + $relation instanceof HasOneOrMany + || $relation instanceof BelongsTo + || ($relation instanceof BelongsToMany && ! $this->isAcrossConnections($relation)) + ) { + return; + } + + throw new Exception(class_basename($relation) . ' is not supported for hybrid query constraints.'); + } + /** * @param Builder $hasQuery * @param Relation $relation @@ -213,6 +235,8 @@ protected function getConstrainedRelatedIds($relations, $operator, $count) */ protected function getRelatedConstraintKey(Relation $relation) { + $this->assertHybridRelationSupported($relation); + if ($relation instanceof HasOneOrMany) { return $relation->getLocalKeyName(); } @@ -221,7 +245,7 @@ protected function getRelatedConstraintKey(Relation $relation) return $relation->getForeignKeyName(); } - if ($relation instanceof BelongsToMany && ! $this->isAcrossConnections($relation)) { + if ($relation instanceof BelongsToMany) { return $this->model->getKeyName(); } diff --git a/tests/HybridRelationsTest.php b/tests/HybridRelationsTest.php index 08423007c..71fb0830b 100644 --- a/tests/HybridRelationsTest.php +++ b/tests/HybridRelationsTest.php @@ -78,7 +78,7 @@ public function testSqlRelations() $this->assertEquals('John Doe', $role->sqlUser->name); // MongoDB User - $user = new User(); + $user = new User(); $user->name = 'John Doe'; $user->save(); @@ -105,7 +105,7 @@ public function testSqlRelations() public function testHybridWhereHas() { - $user = new SqlUser(); + $user = new SqlUser(); $otherUser = new SqlUser(); $this->assertInstanceOf(SqlUser::class, $user); $this->assertInstanceOf(SQLiteConnection::class, $user->getConnection()); @@ -114,11 +114,11 @@ public function testHybridWhereHas() // SQL User $user->name = 'John Doe'; - $user->id = 2; + $user->id = 2; $user->save(); // Other user $otherUser->name = 'Other User'; - $otherUser->id = 3; + $otherUser->id = 3; $otherUser->save(); // Make sure they are created $this->assertIsInt($user->id); @@ -159,7 +159,7 @@ public function testHybridWhereHas() public function testHybridWith() { - $user = new SqlUser(); + $user = new SqlUser(); $otherUser = new SqlUser(); $this->assertInstanceOf(SqlUser::class, $user); $this->assertInstanceOf(SQLiteConnection::class, $user->getConnection()); @@ -168,11 +168,11 @@ public function testHybridWith() // SQL User $user->name = 'John Doe'; - $user->id = 2; + $user->id = 2; $user->save(); // Other user $otherUser->name = 'Other User'; - $otherUser->id = 3; + $otherUser->id = 3; $otherUser->save(); // Make sure they are created $this->assertIsInt($user->id); @@ -268,6 +268,23 @@ public function testHybridBelongsToMany() $this->assertEquals(1, $check->skills->count()); } + public function testQueryingHybridBelongsToManyRelationFails() + { + $user = new SqlUser(); + $this->assertInstanceOf(SQLiteConnection::class, $user->getConnection()); + + // Create Mysql Users + $user->fill(['name' => 'John Doe'])->save(); + $skill = Skill::query()->create(['name' => 'MongoDB']); + $user->skills()->save($skill); + + $this->expectExceptionMessage('BelongsToMany is not supported for hybrid query constraints.'); + + SqlUser::whereHas('skills', function ($query) { + return $query->where('name', 'LIKE', 'MongoDB'); + }); + } + public function testHybridMorphToManySqlModelToMongoModel() { // SqlModel -> MorphToMany -> MongoModel