Eimsas
Eimsas

Reputation: 492

Doctrine findAll() does not find column when using addMetaResult

I use Doctrine and ResultSetMappingBuilder with addMetaResult(). I got native query in my repository with mapping to entity and it works nicely, the code structure is like this:

 $rsm = new ResultSetMappingBuilder($entityManager);
 $rsm->addRootEntityFromClassMetadata('AppBundle\Entity\Example', 'e');
 $rsm->addFieldResult('e', 'id', 'id');
 $rsm->addMetaResult('e', 'value', 'value');

 $sql = "SELECT id, 5 as value FROM table";
 $query = $entityManager->createNativeQuery($sql, $rsm)
 $result = $query->getResult();

My entity.yml looks like that:

AppBundle\Entity\Example:  
  ...
  fields:
     id:
        type: smallint
        nullable: false
        options:
            unsigned: true
        id: true
        generator:
            strategy: IDENTITY
     value:
       type: integer

But when I use that entity somewhere else with standard entity manager methods like this:

$this->exampleRepo->find(5);

Then I get the error:

Column not found: 1054 Unknown column 't0.value' in 'field list'

it is because I do not have real column 'value' in my table, it is meta column. Do there is any config to skip that column if it is not in Native Query or to skip if it does not exists or I have to override method find() in repository and add mapping in it?

Upvotes: 1

Views: 1075

Answers (1)

Jason Roman
Jason Roman

Reputation: 8276

Have a look at this question, and this answer and this answer to that question for more context.

The short answer is that you're running into a limitation with Doctrine in that you cannot have virtual properties that appear to be database columns but aren't. So when you add this to your entity.yml:

value:
    type: integer

What you're telling Doctrine is that there is a value column on your Example entity. So any Doctrine query you're attempting to run except is going to break. The reason why your original query does not is because you are running a native query and explicitly performing the mapping yourself.

So you probably felt like you found a way to workaround Doctrine's limitation, but you did not.

The simplest solution would be to maintain a non-mapped value field inside your Example entity, then when you need to query that, simply add it to your Doctrine query and then manually set what you need. Something like this:

$entityResults = [];

/**
 * return array of arrays like: [
 *     ['example' => Example entity, 'value' => int value],
 *     ['example' => Example entity, 'value' => int value],
 * ]
 */
$results = $em
    ->createQuery('SELECT e AS example, 5 AS value FROM AppBundle:Example')
    ->getResult();

foreach ($results as $result) {
    $result['example']->setValue($result['value]);
    $entityResults[] = $result['example'];
}

return $entityResults;

If you want something a little more global you could look at adding a custom hydrator instead.

Upvotes: 1

Related Questions