diff --git a/docs/en/reference/query-builder.rst b/docs/en/reference/query-builder.rst index 3070cc234df..521e6ee5e27 100644 --- a/docs/en/reference/query-builder.rst +++ b/docs/en/reference/query-builder.rst @@ -611,3 +611,28 @@ same query of example 6 written using ->add('from', new Expr\From('User', 'u')) ->add('where', new Expr\Comparison('u.id', '=', '?1')) ->add('orderBy', new Expr\OrderBy('u.name', 'ASC')); + +Binding Parameters to Placeholders +---------------------------------- + +It is often not necessary to know about the exact placeholder names +during the building of a query. You can use two helper methods +to bind a value to a placeholder and directly use that placeholder +in your query as a return value: + +.. code-block:: php + + select('u') + ->from('User', 'u') + ->where('u.email = ' . $qb->createNamedParameter($userInputEmail)) + ; + // SELECT u FROM User u WHERE email = :dcValue1 + + $qb->select('id') + ->from('User', 'u') + ->where('u.email = ' . $qb->createPositionalParameter($userInputEmail)) + ; + // SELECT u FROM User u WHERE email = ? diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index 6ab942f5239..46afd3b3593 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -8,7 +8,6 @@ use Doctrine\Common\Collections\Criteria; use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\ParameterType; -use Doctrine\DBAL\Types\Type; use Doctrine\ORM\Internal\NoUnknownNamedArguments; use Doctrine\ORM\Internal\QueryType; use Doctrine\ORM\Query\Expr; diff --git a/tests/Tests/ORM/QueryBuilderTest.php b/tests/Tests/ORM/QueryBuilderTest.php index 577c86581bf..37bd16dbf8b 100644 --- a/tests/Tests/ORM/QueryBuilderTest.php +++ b/tests/Tests/ORM/QueryBuilderTest.php @@ -8,6 +8,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Criteria; use Doctrine\Common\Collections\Order; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Cache; use Doctrine\ORM\Query; use Doctrine\ORM\Query\Expr\Join; @@ -1285,4 +1286,64 @@ public function testDeleteWithoutAlias(): void $this->expectExceptionMessage('Doctrine\ORM\QueryBuilder::delete(): The alias for entity Doctrine\Tests\Models\CMS\CmsUser u must not be omitted.'); $qb->delete(CmsUser::class . ' u'); } + + public function testCreateNamedParameter(): void + { + $qb = $this->entityManager->createQueryBuilder(); + + $qb->select('u') + ->from(CmsUser::class, 'u') + ->where( + $qb->expr()->eq('u.name', $qb->createNamedParameter('john doe', Types::STRING)), + ) + ->orWhere( + $qb->expr()->eq('u.rank', $qb->createNamedParameter(100, Types::INTEGER)), + ); + + self::assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = :dcValue1 OR u.rank = :dcValue2', $qb->getDQL()); + self::assertEquals('john doe', $qb->getParameter('dcValue1')->getValue()); + self::assertEquals(Types::STRING, $qb->getParameter('dcValue1')->getType()); + self::assertEquals(100, $qb->getParameter('dcValue2')->getValue()); + self::assertEquals(Types::INTEGER, $qb->getParameter('dcValue2')->getType()); + } + + public function testCreateNamedParameterCustomPlaceholder(): void + { + $qb = $this->entityManager->createQueryBuilder(); + + $qb->select('u') + ->from(CmsUser::class, 'u') + ->where( + $qb->expr()->eq('u.name', $qb->createNamedParameter('john doe', Types::STRING, ':test')), + ) + ->andWhere( + $qb->expr()->eq('u.rank', $qb->createNamedParameter(100, Types::INTEGER)), + ); + + self::assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = :test AND u.rank = :dcValue1', $qb->getDQL()); + self::assertEquals('john doe', $qb->getParameter('test')->getValue()); + self::assertEquals(Types::STRING, $qb->getParameter('test')->getType()); + self::assertEquals(100, $qb->getParameter('dcValue1')->getValue()); + self::assertEquals(Types::INTEGER, $qb->getParameter('dcValue1')->getType()); + } + + public function testCreatePositionalParameter(): void + { + $qb = $this->entityManager->createQueryBuilder(); + + $qb->select('u') + ->from(CmsUser::class, 'u') + ->where( + $qb->expr()->eq('u.name', $qb->createPositionalParameter('john doe', Types::STRING)), + ) + ->orWhere( + $qb->expr()->eq('u.rank', $qb->createPositionalParameter(100, Types::INTEGER)), + ); + + self::assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = ? OR u.rank = ?', $qb->getDQL()); + self::assertEquals('john doe', $qb->getParameter(0)->getValue()); + self::assertEquals(Types::STRING, $qb->getParameter(0)->getType()); + self::assertEquals(100, $qb->getParameter(1)->getValue()); + self::assertEquals(Types::INTEGER, $qb->getParameter(1)->getType()); + } }