diff --git a/lib/Doctrine/Collection.php b/lib/Doctrine/Collection.php index 2db1d53d5..ef80abde2 100644 --- a/lib/Doctrine/Collection.php +++ b/lib/Doctrine/Collection.php @@ -235,7 +235,24 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator { return end($this->data); } - + /** + * returns the last record in the collection + * + * @return mixed + */ + public function end() + { + return end($this->data); + } + /** + * returns the current key + * + * @return mixed + */ + public function key() + { + return key($this->data); + } /** * setReference * sets a reference pointer diff --git a/lib/Doctrine/Hydrate.php b/lib/Doctrine/Hydrate.php index 01107b535..de93e2b94 100644 --- a/lib/Doctrine/Hydrate.php +++ b/lib/Doctrine/Hydrate.php @@ -1059,6 +1059,10 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab foreach ($this->_aliasMap as $alias => $data) { $componentName = $data['table']->getComponentName(); $listeners[$componentName] = $data['table']->getRecordListener(); + $identifierMap[$alias] = array(); + $currData[$alias] = array(); + $prev[$alias] = array(); + $id[$alias] = ''; } while ($data = $stmt->fetch(Doctrine::FETCH_ASSOC)) { @@ -1076,7 +1080,6 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab $cache[$key]['alias'] = $this->_tableAliases[strtolower(implode('__', $e))]; } - $map = $this->_aliasMap[$cache[$key]['alias']]; $table = $map['table']; $alias = $cache[$key]['alias']; @@ -1087,21 +1090,17 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab } - if ( ! isset($currData[$alias])) { - $currData[$alias] = array(); - } - - if ( ! isset($prev[$alias])) { - $prev[$alias] = array(); + if ($table->isIdentifier($field)) { + $id[$alias] .= '|' . $value; } $currData[$alias][$field] = $table->prepareValue($field, $value); + if ($value !== null) { $identifiable[$alias] = true; } } - // dealing with root component $table = $this->_aliasMap[$rootAlias]['table']; $componentName = $table->getComponentName(); @@ -1111,8 +1110,13 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab $oneToOne = false; - $index = $isSimpleQuery ? false : $driver->search($element, $array); - + if ($isSimpleQuery) { + $index = false; + } else { + $index = isset($identifierMap[$rootAlias][$id[$rootAlias]]) ? + $identifierMap[$rootAlias][$id[$rootAlias]] : false; + } + if ($index === false) { $event->set('data', $element); $listeners[$componentName]->postHydrate($event); @@ -1132,7 +1136,10 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab } else { $array[] = $element; } + + $identifierMap[$rootAlias][$id[$rootAlias]] = $driver->getLastKey($array); } + $this->_setLastElement($prev, $array, $index, $rootAlias, $oneToOne); unset($currData[$rootAlias]); @@ -1150,6 +1157,8 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab $relation = $map['relation']; $componentAlias = $map['relation']->getAlias(); + $path = $parent . '.' . $alias; + if ( ! isset($prev[$parent])) { break; } @@ -1162,7 +1171,12 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab // append element if (isset($identifiable[$alias])) { - $index = $isSimpleQuery ? false : $driver->search($element, $prev[$parent][$componentAlias]); + if ($isSimpleQuery) { + $index = false; + } else { + $index = isset($identifierMap[$path][$id[$parent]][$id[$alias]]) ? + $identifierMap[$path][$id[$parent]][$id[$alias]] : false; + } if ($index === false) { $event->set('data', $element); @@ -1180,6 +1194,8 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab } else { $prev[$parent][$componentAlias][] = $element; } + + $identifierMap[$path][$id[$parent]][$id[$alias]] = $driver->getLastKey($prev[$parent][$componentAlias]); } } // register collection for later snapshots @@ -1195,7 +1211,9 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab } $coll =& $prev[$parent][$componentAlias]; $this->_setLastElement($prev, $coll, $index, $alias, $oneToOne); + $id[$alias] = ''; } + $id[$rootAlias] = ''; } $driver->flush(); diff --git a/lib/Doctrine/Hydrate/Array.php b/lib/Doctrine/Hydrate/Array.php index 393d1f74a..6c9465fca 100644 --- a/lib/Doctrine/Hydrate/Array.php +++ b/lib/Doctrine/Hydrate/Array.php @@ -60,24 +60,14 @@ class Doctrine_Hydrate_Array { return null; } - public function search(array $element, array $data) + public function getLastKey(&$data) { - foreach ($data as $key => $val) { - $found = true; - foreach ($element as $k => $e) { - if (isset($val[$k]) && $val[$k] !== $e) { - $found = false; - break; - } - } - if ($found) { - return $key; - } - } - return false; + end($data); + return key($data); } + public function flush() { } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Hydrate/Record.php b/lib/Doctrine/Hydrate/Record.php index 52fa8ba4e..1a737fcb3 100644 --- a/lib/Doctrine/Hydrate/Record.php +++ b/lib/Doctrine/Hydrate/Record.php @@ -46,9 +46,12 @@ class Doctrine_Hydrate_Record extends Doctrine_Locator_Injectable return $coll; } - public function search(Doctrine_Record $record, Doctrine_Collection $coll) + + public function getLastKey($coll) { - return array_search($record, $coll->getData(), true); + $coll->end(); + + return $coll->key(); } public function initRelated($record, $name) {