Custom DQL functions in doctrine2

血红的双手。 提交于 2019-12-03 14:22:18

How do you use custom DQL functions in partials to hydrate query result.

The partial keyword tells doctrine to return entities that are only partially hydrated and allows you to specify which fields you want to be hydrated.

When retrieving partial entities you are limited to selecting the fields of the entity (because otherwise where would doctrine 'store' the field you're selecting?), so it's not possible to specify a DQL function as a field of a partial object.

What about this?

    $qb = $this->_em->createQueryBuilder()
            ->select( 't.id, t.description, '
                    . 'ut.id, ut.firstName, '
                    . 'ut.lastName, ut.email, '
                    . 'DATE_FORMAT( ut.created, \'%m-%d-Y\' )' )
            ->from( 'PMIUserBundle:Task', 't' )
            ->leftjoin( 't.users', 'ut' );

    $result = $qb->getQuery()->getResult();

Assuming that you are using this in a Repository class (that's why the call to $this->_em ).

I have noticed 2 other things regarding the custom function:

  1. I have personally it defined as a "string_functions:" instead in the config.yml file
  2. I know at least one Bundle that implements this custom function: https://github.com/beberlei/DoctrineExtensions

Hope This helps,

Tam

Not supported

PARTIAL ut.{id, firstName, lastName, email, DATE_FORMAT(created, '%m-%d-Y')}

Using DQL functions inside the selection of partial entities like this is not supported.

It doesn't make much sense either. In this case you've (probably) mapped the field created as a datetime field, so you'll expect a full DateTime value in there. But now you're suddenly just using the date part. And it get worse: you've formatted the value in such a way a DateTime object cannot be created (it expects Y-m-d H:i:s, and the date type expects Y-m-d).

For any partial selection: You cannot, and should not, change the value of a field.

Alternative

In stead of hydrating into partial entities, you could just use arrays. Use $q->getArrayResult() or $q->getScalarResult(), whichever suits your purpose better.

If you like, you can group/nest the results in the Repository method. Example:

public function getSomeData()
{
    $result = array();

    $dql = <<<EOQ
SELECT
t.id AS t_id,
t.description AS t_description,
u.id AS u_id,
u.firstName AS u_firstName,
u.lastName AS u_lastName,
u.email AS u_email,
DATE_FORMAT(u.created, '%m-%d-Y') AS u_created
FROM PMIUserBundle:Task t
LEFT JOIN t.users u
EOQ;

    $q = $this->getEntityManager()->createQuery($dql);

    foreach ($q->getScalarResult() as $row) {
        if (!isset($result[$row['t_id']])) {
            $result[$row['t_id']] = array(
                'id'          => $row['t_id'],
                'description' => $row['t_description'],
                'users'       => array()
            );

            $result[$row['t_id']]['users'][] = array(
                'u.id'        => $row['u_id'],
                'u.firstName' => $row['u_firstName'],
                'u.lastName'  => $row['u_lastName'],
                'u.email'     => $row['u_email'],
                'u.created'   => $row['u_created']
            );
        }
    }

    return $result;
}

Nesting DQL functions

Nesting DQL functions should be no problem (if you wrote them correctly). And DISTINCT is supported out of the box.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!