Skip to content

Instantly share code, notes, and snippets.

@fancyweb
Created January 3, 2018 16:12
Show Gist options
  • Save fancyweb/7f7259ea9f9975ad7ff822ac42f16039 to your computer and use it in GitHub Desktop.
Save fancyweb/7f7259ea9f9975ad7ff822ac42f16039 to your computer and use it in GitHub Desktop.
Doctrine ignore unknown discriminator values
<?php
private function ignoreUnknownDiscriminatorValues()
if (method_exists(BasicEntityPersister::class, '_loadOneToManyCollection')) {
return;
}
$refl = new \ReflectionClass(BasicEntityPersister::class);
if (1676129169 !== crc32(file_get_contents($refl->getFileName()))) {
throw new \Exception(sprintf('The file "%s" has changed, please check that the "loadOneToManyCollection" method override is still working as expected.', BasicEntityPersister::class));
}
$code = <<<'EOT'
$classMetadata = $coll->getTypeClass();
if ($classMetadata->isRootEntity() && !empty($classMetadata->discriminatorMap)) {
$offset = null; // OVERRIDE
$limit = null; // OVERRIDE
$this->switchPersisterContext($offset, $limit);
$criteria = array();
$parameters = array();
$owningAssoc = $this->class->associationMappings[$assoc['mappedBy']];
$sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']);
$tableAlias = $this->getSQLTableAlias(isset($owningAssoc['inherited']) ? $owningAssoc['inherited'] : $this->class->name);
foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) {
if ($sourceClass->containsForeignIdentifier) {
$field = $sourceClass->getFieldForColumn($sourceKeyColumn);
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
if (isset($sourceClass->associationMappings[$field])) {
$value = $this->em->getUnitOfWork()->getEntityIdentifier($value);
$value = $value[$this->em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]];
}
$criteria[$tableAlias . "." . $targetKeyColumn] = $value;
$parameters[] = array(
'value' => $value,
'field' => $field,
'class' => $sourceClass,
);
continue;
}
$field = $sourceClass->fieldNames[$sourceKeyColumn];
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
$criteria[$tableAlias . "." . $targetKeyColumn] = $value;
$parameters[] = array(
'value' => $value,
'field' => $field,
'class' => $sourceClass,
);
}
list($params, $types) = $this->expandToManyParameters($parameters);
/// OVERRIDE ///
$discriminatorFieldName = $classMetadata->discriminatorColumn['fieldName'];
$knownDiscriminatorValues = array_keys($classMetadata->discriminatorMap);
$criteria[sprintf('%s.%s', $tableAlias, $discriminatorFieldName)] = $knownDiscriminatorValues;
$params[] = $knownDiscriminatorValues;
$types[] = Doctrine\DBAL\Connection::PARAM_STR_ARRAY;
/// END OVERRIDE ///
$sql = $this->getSelectSQL($criteria, $assoc, null, $limit, $offset);
$stmt = $this->conn->executeQuery($sql, $params, $types);
return $this->loadCollectionFromStatement($assoc, $stmt, $coll);
}
return call_user_func_array(array($this, '_loadOneToManyCollection'), func_get_args());
EOT;
// http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/limitations-and-known-issues.html
// "Currently there is no way to overwrite the persister implementation for a given entity"
class_exists(BasicEntityPersister::class);
call_user_func_array('runkit_method_copy', array(
BasicEntityPersister::class,
'_loadOneToManyCollection',
BasicEntityPersister::class,
'loadOneToManyCollection'
));
call_user_func_array('runkit_method_redefine', array(
BasicEntityPersister::class,
'loadOneToManyCollection',
'array $assoc, $sourceEntity, Doctrine\ORM\PersistentCollection $coll',
$code
));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment