Skip to content

Instantly share code, notes, and snippets.

@joubertredrat
Created April 2, 2018 13:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joubertredrat/7a9e50eb4edc36ed3cbed2b02d0aa1ce to your computer and use it in GitHub Desktop.
Save joubertredrat/7a9e50eb4edc36ed3cbed2b02d0aa1ce to your computer and use it in GitHub Desktop.
Doctrine custom walker
<?php
namespace Application\Infrastructure\Repository;
use Application\Domain\Model\TransactionStatus;
use Application\Infrastructure\Component\DoctrineExtensions\Query\SortableNullsWalker;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
/**
* MyCool Repository
*
* @package Application\Infrastructure\Repository
*/
class MyCoolRepository extends EntityRepository
{
/**
* @param \DateTime $datePayAttemptInterval
* @return array<MyEntity>
*/
public function myAmazingGetData(\DateTime $datePayAttemptInterval): array
{
$queryBuilder = $this->createQueryBuilder('t');
$query = $queryBuilder
->where(
$queryBuilder
->expr()
->andX(
$queryBuilder
->expr()
->eq('t.status.status', ':status')
,
$queryBuilder
->expr()
->orX(
$queryBuilder
->expr()
->isNull('t.lastDatePayAttempt')
,
$queryBuilder
->expr()
->lt('t.lastDatePayAttempt', ':datePayAttemptInterval')
)
)
)
->setParameter('status', TransactionStatus::CONCILIATED)
->setParameter('datePayAttemptInterval', $datePayAttemptInterval->format('Y-m-d H:i:s'))
->orderBy('t.lastDatePayAttempt', 'ASC')
->getQuery()
;
$query->setHint(
Query::HINT_CUSTOM_OUTPUT_WALKER,
SortableNullsWalker::class
);
$query->setHint(
"sortableNulls.fields",
[
"t.lastDatePayAttempt" => SortableNullsWalker::NULLS_LAST,
]
);
return $query->getResult();
}
}
<?php
namespace Application\Infrastructure\Component\DoctrineExtensions\Query;
use Doctrine\ORM\Query\AST\PathExpression;
use Doctrine\ORM\Query\SqlWalker;
/**
* SortableNullsWalker
*
* @package Application\Infrastructure\Component\DoctrineExtensions\Query
*/
class SortableNullsWalker extends SqlWalker
{
/**
* Null order types
*/
const NULLS_FIRST = 'NULLS_FIRST';
const NULLS_LAST = 'NULLS_LAST';
/**
* {@inheritdoc}
* @throws \Doctrine\ORM\Query\QueryException
*/
public function walkOrderByItem($orderByItem)
{
$sql = parent::walkOrderByItem($orderByItem);
$hint = $this
->getQuery()
->getHint('sortableNulls.fields')
;
$expr = $orderByItem->expression;
if (is_array($hint) && count($hint)) {
if ($expr instanceof PathExpression &&
$expr->type == PathExpression::TYPE_STATE_FIELD
) {
$fieldName = $expr->field;
$index = $expr->identificationVariable . '.' . $fieldName;
$sqlParts = [];
$sqlParts[] = $this->walkPathExpression($expr) . ' ' . self::getSqlPart($hint[$index]);
if ($sql) {
$sqlParts[] = $sql;
}
$sql = implode(', ', $sqlParts);
}
}
return $sql;
}
/**
* @param string $order
* @return string
*/
public static function getSqlPart(string $order): string
{
switch ($order) {
case self::NULLS_FIRST:
return 'IS NOT NULL';
break;
case self::NULLS_LAST:
return 'IS NULL';
break;
default:
return '';
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment