इसलिए ... क्या करना है जब हम सिद्धांत जीवन चक्र के बाहर एक परिवर्तन खोजना चाहते हैं? जैसा कि ऊपर @Ocramius 'पोस्ट पर मेरी टिप्पणी में उल्लेख किया गया है, शायद एक "पठनीय" विधि बनाना संभव है जो वास्तविक डॉक्ट्रिन दृढ़ता के साथ गड़बड़ नहीं करता है, लेकिन उपयोगकर्ता को जो भी बदल गया है उसका एक दृश्य देता है।
यहाँ एक उदाहरण है जो मैं सोच रहा हूँ ...
public static function diffDoctrineObject(EntityManager $em, $entity) {
$uow = $em->getUnitOfWork();
$class = $em->getClassMetadata(get_class($entity));
$oid = spl_object_hash($entity);
$entityChangeSets = array();
if ($uow->isReadOnly($entity)) {
return null;
}
if ( ! $class->isInheritanceTypeNone()) {
$class = $em->getClassMetadata(get_class($entity));
}
$actualData = array();
foreach ($class->reflFields as $name => $refProp) {
$value = $refProp->getValue($entity);
if ($class->isCollectionValuedAssociation($name) && $value !== null) {
if ($value instanceof PersistentCollection) {
if ($value->getOwner() === $entity) {
continue;
}
$value = new ArrayCollection($value->getValues());
}
if ( ! $value instanceof Collection) {
$value = new ArrayCollection($value);
}
$assoc = $class->associationMappings[$name];
$value = new PersistentCollection(
$em, $em->getClassMetadata($assoc['targetEntity']), $value
);
$value->setOwner($entity, $assoc);
$value->setDirty( ! $value->isEmpty());
$class->reflFields[$name]->setValue($entity, $value);
$actualData[$name] = $value;
continue;
}
if (( ! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity()) && ($name !== $class->versionField)) {
$actualData[$name] = $value;
}
}
$originalEntityData = $uow->getOriginalEntityData($entity);
if (empty($originalEntityData)) {
$originalEntityData = $actualData;
$changeSet = array();
foreach ($actualData as $propName => $actualValue) {
if ( ! isset($class->associationMappings[$propName])) {
$changeSet[$propName] = array(null, $actualValue);
continue;
}
$assoc = $class->associationMappings[$propName];
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
$changeSet[$propName] = array(null, $actualValue);
}
}
$entityChangeSets[$oid] = $changeSet;
} else {
$originalData = $originalEntityData;
$isChangeTrackingNotify = $class->isChangeTrackingNotify();
$changeSet = $isChangeTrackingNotify ? $uow->getEntityChangeSet($entity) : array();
foreach ($actualData as $propName => $actualValue) {
if ( ! (isset($originalData[$propName]) || array_key_exists($propName, $originalData))) {
continue;
}
$orgValue = $originalData[$propName];
if ($orgValue === $actualValue) {
continue;
}
if ( ! isset($class->associationMappings[$propName])) {
if ($isChangeTrackingNotify) {
continue;
}
$changeSet[$propName] = array($orgValue, $actualValue);
continue;
}
$assoc = $class->associationMappings[$propName];
if ($actualValue instanceof PersistentCollection) {
$owner = $actualValue->getOwner();
if ($owner === null) {
$actualValue->setOwner($entity, $assoc);
} else if ($owner !== $entity) {
if (!$actualValue->isInitialized()) {
$actualValue->initialize();
}
$newValue = clone $actualValue;
$newValue->setOwner($entity, $assoc);
$class->reflFields[$propName]->setValue($entity, $newValue);
}
}
if ($orgValue instanceof PersistentCollection) {
$changeSet[$propName] = $orgValue;
continue;
}
if ($assoc['type'] & ClassMetadata::TO_ONE) {
if ($assoc['isOwningSide']) {
$changeSet[$propName] = array($orgValue, $actualValue);
}
}
}
if ($changeSet) {
$entityChangeSets[$oid] = $changeSet;
}
}
return $entityChangeSets[$oid];
}
यह एक स्थिर विधि के रूप में यहाँ पर वर्णित है, लेकिन UnitOfWork के अंदर एक विधि बन सकती है ...?
मैं डॉक्ट्रिन के सभी इंटर्नल पर गति करने के लिए नहीं हूं, इसलिए ऐसा कुछ याद किया जा सकता है जिसका साइड इफेक्ट या गलत तरीका है कि यह विधि क्या करती है, लेकिन इसका (बहुत) त्वरित परीक्षण मुझे लगता है कि मुझे परिणाम देने की उम्मीद है देखना।
मुझे आशा है कि यह किसी की मदद करता है!