Skip to content

Instantly share code, notes, and snippets.

@aelfannir
Last active August 25, 2024 18:22
Show Gist options
  • Save aelfannir/b1c0a75d7bc5139331c52097d0070c26 to your computer and use it in GitHub Desktop.
Save aelfannir/b1c0a75d7bc5139331c52097d0070c26 to your computer and use it in GitHub Desktop.
LIMIT in DQL subquery
# config/packages/doctrine.yaml
doctrine:
# ...
orm:
#...
dql:
#...
string_functions:
FIRST: App\Doctrine\DQL\FirstFunction
<?php
namespace App\Doctrine;
use Doctrine\ORM\Query\AST\ASTException;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\AST\Subselect;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\QueryException;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\TokenType;
/**
* FirstFunction ::= FIRST" "(" Subselect ")"
*/
class FirstFunction extends FunctionNode
{
private Subselect $subselect;
/**
* {@inheritdoc}
* @throws QueryException
*/
public function parse(Parser $parser): void
{
$parser->match(TokenType::T_IDENTIFIER);
$parser->match(TokenType::T_OPEN_PARENTHESIS);
$this->subselect = $parser->Subselect();
$parser->match(TokenType::T_CLOSE_PARENTHESIS);
}
/**
* {@inheritdoc}
* @throws ASTException
*/
public function getSql(SqlWalker $sqlWalker): string
{
return '(' . $this->subselect->dispatch($sqlWalker) . ' LIMIT 1)';
}
}
<?php
namespace App\Repository;
use Doctrine\ORM\EntityManager;
class ProductRepository
{
private EntityManager $entityManager;
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
public function findProductWithHighestCurrentPrice(): ?Product
{
$qb = $this->entityManager->createQueryBuilder();
$subQuery = $this->entityManager->createQueryBuilder();
$subQuery->select('IDENTITY(pp.product)')
->from('App\Entity\ProductPrice', 'pp')
->where('pp.isCurrentPrice = :isCurrentPrice')
->orderBy('pp.amount', 'DESC')
->setParameter('isCurrentPrice', true);
$qb->select('p')
->where(
$qb->expr()->eq(
'p.id',
$qb->expr()->literal(
sprintf('FIRST(%s)', $subQuery->getDQL())
)
)
)
->setMaxResults(1)
->setParameters($subQuery->getParameters());
return $qb->getQuery()->getOneOrNullResult();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment