Search code examples
doctrine-ormdql

Getting Doctrine DQL results the SQL way


When performing a DQL query such as:

SELECT u AS user, t AS transaction
FROM Model\User u
JOIN Model\Transaction t WITH t.user = u

You get alternating rows of results, such as:

  • ['user' => Model\User(1)]
  • ['transaction' => Model\Transaction(1)]
  • ['transaction' => Model\Transaction(2)]
  • ['user' => Model\User(2)]
  • ['transaction' => Model\Transaction(3)]
  • ['transaction' => Model\Transaction(4)]
  • ['transaction' => Model\Transaction(5)]

Is it possible to get the result the SQL way, like:

  • ['user' => Model\User(1), 'transaction' => Model\Transaction(1)]
  • ['user' => Model\User(1), 'transaction' => Model\Transaction(2)]
  • ['user' => Model\User(2), 'transaction' => Model\Transaction(3)]
  • ['user' => Model\User(2), 'transaction' => Model\Transaction(4)]
  • ['user' => Model\User(2), 'transaction' => Model\Transaction(5)]

It would be much easier to deal with than alternating objects.


Solution

  • The way I do it now is:

    $query = $em->createQuery('
        SELECT u, t
        FROM Model\User u
        JOIN Model\Transaction t WITH t.user = u
    ');
    
    $rows = $query->getResult();
    $rowCount = count($rows);
    
    $result = [];
    
    for ($i = 0; $i < $rowCount; $i += 2) {
        /** @var Model\User $user */
        $user = $rows[$i];
    
        /** @var Model\Transaction $transaction */
        $transaction = $rows[$i + 1];
    
        $result[] = new UserTransactionDTO($user, $transaction);
    }
    
    return $result;
    

    Which is clean enough.

    Note that this example is a bad one, as you could only return Transactions and get the User from there; but I regularly encounter use cases where a single object does not hold all the information.