Search code examples
phpsymfonydoctrine-ormdqlsymfony-2.8

Symonfy2, Doctrine: duplicate, default, or ignore DiscriminatorMap?


How do I enable duplicate Discriminator Maps, allow a "default" mapping, or completely ignore Discriminator mappings when running a DQL query?

Setup:

// DQL Query:
$this->createQueryBuilder('s')
     ->select(['s.serverId', 'p.projectName'])
     ->leftJoin('s.serverServices', 'ss')
     ->leftJoin('ss.serverServiceProjects', 'ps')
     ->leftJoin('ps.project', 'p')
     ->getQuery()
     ->getArrayResult()

// Mapping
/**
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="service_type_id", type="integer")
 * @ORM\DiscriminatorMap({
 *     "1" = "AppBundle\Entity\ServerService",
 *     "2" = "AppBundle\Entity\ServerService",
 *       [...]
 *     "12" = "AppBundle\Entity\Service\SubService",
 *     "" = "AppBundle\Entity\ServerService"
 * })
 */

The join portion that's generated:

   LEFT JOIN server_services s2_ ON s0_.server_id = s2_.server_id AND s2_.service_type_id IN ('1', '12') 

This is entirely incorrect. I have an entire mapping of 1 - 12. And an "" empty string match. If a row does not have a known mapping (in my code) OR if it's empty, it should be set to the default base ServerService.

I did find this post: Leave out discriminator part of Doctrine' generated SQL

However, it's back in 2014, made mention of a difference in version, and does not compensate for duplicate, or default Mappings.

EDIT: For the record, I tried the ignore route -- it didn't work.

   $q->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER, MySqlWalker::class)
        ->setHint(MySqlWalker::IGNORE_DISCRIMINATION, array('ss'));

Still returns the above SQL Joint statement. It does call MySqlWalker; it does go into the setInheritanceType() call, but it does not ignore the Discriminator mapping. :/


Solution

  • Found an answer to one option: Ignoring

    In Doctrine 2.2.x, my statements were in the JOIN, not WHERE clause. Using the example in Leave out discriminator part of Doctrine' generated SQL, I had to overload the ->walkJoin() method to get ignore to work properly:

    /**
     * {@inheritdoc}
     */
    public function walkJoin($join)
    {
        $this->checkForHint();
        return parent::walkJoin($join);
    }
    
    protected function checkForHint()
    {
        $ignoreDescription = $this->getQuery()->getHint(self::IGNORE_DISCRIMINATION);
    
        if ($ignoreDescription) {
            foreach ($this->getQueryComponents() as $k => $component) {
                if (in_array($k, $ignoreDescription)) {
                    /** @var $meta ClassMetadata */
                    $meta = $component['metadata'];
                    $meta->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_NONE);
                }
            }
        }
    }
    

    Still have not resolved Duplicate or Default discriminator values...