diff --git a/src/Query.php b/src/Query.php index 7bd5b9a..dde793f 100644 --- a/src/Query.php +++ b/src/Query.php @@ -701,6 +701,17 @@ public function createSubQuery(Model $target, string $targetPath, ?Model $from = ->setDb($this->getDb()) ->setModel($target); + if (! str_starts_with($targetPath, $this->getModel()->getTableAlias() . '.')) { + trigger_error(sprintf( + 'Target path "%s" does not start with the source model\'s table alias "%s".' + . ' This is deprecated and will be removed in a future version. Use "%s" as target path instead.', + $targetPath, + $this->getModel()->getTableAlias(), + $this->getModel()->getTableAlias() . '.' . $targetPath + ), E_USER_DEPRECATED); + $targetPath = $this->getModel()->getTableAlias() . '.' . $targetPath; + } + $subQueryResolver = $subQuery->getResolver(); $forwardHops = array_slice(explode('.', $targetPath), 0, -1); diff --git a/tests/QueryTest.php b/tests/QueryTest.php index e071323..6e186a9 100644 --- a/tests/QueryTest.php +++ b/tests/QueryTest.php @@ -622,6 +622,31 @@ public function testUnreferencedTargetCanBePassedToCreateSubQuery(): void $this->assertInstanceOf(Query::class, $query); } + public function testCreateSubQueryAcceptsRelativeTargetPaths(): void + { + $deprecations = []; + set_error_handler(function ($_, $message) use (&$deprecations) { + $deprecations[] = $message; + + return true; + }, E_USER_DEPRECATED); + + try { + $query = Profile::on(new TestConnection()) + ->createSubQuery(new User(), 'user'); + } finally { + restore_error_handler(); + } + + $this->assertNotEmpty($deprecations, 'createSubQuery did not emit a deprecation'); + $this->assertStringContainsString( + 'Target path "user" does not start with the source model\'s table alias "profile".', + $deprecations[0] + ); + + $this->assertInstanceOf(Query::class, $query); + } + public function testDeriveLetsTheBaseModelBeReferencedAsSelfInFilters(): void { $user = new User(['id' => 1, 'username' => 'test']);