Browse Source

Changing the way eager loaded values are nested under each result.

The old way was making ResultSet confused about hydrating results having
the same association alias in the associaitons map
Jose Lorenzo Rodriguez 12 years ago
parent
commit
889f835f39

+ 5 - 4
src/ORM/Association/ExternalAssociationTrait.php

@@ -96,10 +96,11 @@ trait ExternalAssociationTrait {
 	public function transformRow($row) {
 		$sourceAlias = $this->source()->alias();
 		$targetAlias = $this->target()->alias();
-		$values = $row[$this->_name];
 
-		if (isset($values[$this->_name]) && is_array($values[$this->_name])) {
-			$values = $values[$this->_name];
+		if (isset($row[$this->_name . '___collection_'])) {
+			$values = $row[$this->_name . '___collection_'];
+		} else {
+			$values = $row[$this->_name];
 		}
 
 		$row[$sourceAlias][$this->property()] = $values;
@@ -164,7 +165,7 @@ trait ExternalAssociationTrait {
 			$sourceKeys[] = key($fetchQuery->aliasField($key, $sAlias));
 		}
 
-		$nestKey = $tAlias . '__' . $tAlias;
+		$nestKey = $tAlias . '___collection_';
 
 		if (count($sourceKeys) > 1) {
 			return $this->_multiKeysInjector($resultMap, $sourceKeys, $nestKey);

+ 17 - 5
src/ORM/ResultSet.php

@@ -305,7 +305,8 @@ class ResultSet implements Countable, Iterator, Serializable, JsonSerializable {
 		$map = [];
 		$visitor = function($level) use (&$visitor, &$map) {
 			foreach ($level as $assoc => $meta) {
-				$map[$assoc] = [
+				$map[$meta['aliasPath']] = [
+					'alias' => $assoc,
 					'instance' => $meta['instance'],
 					'canBeJoined' => $meta['canBeJoined'],
 					'entityClass' => $meta['instance']->target()->entityClass()
@@ -350,6 +351,11 @@ class ResultSet implements Countable, Iterator, Serializable, JsonSerializable {
 			$table = $defaultAlias;
 			$field = $key;
 
+			if (strpos($key, '___collection_') !== false) {
+				$results[$key] = $value;
+				continue;
+			}
+
 			if (empty($this->_map[$key])) {
 				$parts = explode('__', $key);
 				if (count($parts) > 1) {
@@ -377,21 +383,27 @@ class ResultSet implements Countable, Iterator, Serializable, JsonSerializable {
 			'markNew' => false,
 			'guard' => false
 		];
-		foreach (array_reverse($this->_associationMap) as $alias => $assoc) {
-			if (!isset($results[$alias])) {
+		foreach (array_reverse($this->_associationMap) as $assoc) {
+			$alias = $assoc['alias'];
+			if (!isset($results[$alias]) && !isset($results[$alias . '___collection_'])) {
 				continue;
 			}
+
 			$instance = $assoc['instance'];
 			$target = $instance->target();
-			$results[$alias] = $this->_castValues($target, $results[$alias]);
-			unset($presentAliases[$alias]);
 			$options['source'] = $target->alias();
+			unset($presentAliases[$alias]);
+
+			if ($assoc['canBeJoined']) {
+				$results[$alias] = $this->_castValues($target, $results[$alias]);
+			}
 
 			if ($this->_hydrate && $assoc['canBeJoined']) {
 				$entity = new $assoc['entityClass']($results[$alias], $options);
 				$entity->clean();
 				$results[$alias] = $entity;
 			}
+
 			$results = $instance->transformRow($results);
 		}
 

+ 9 - 0
tests/TestCase/ORM/QueryTest.php

@@ -1867,4 +1867,13 @@ class QueryTest extends TestCase {
 		$this->assertSame($expected, $results);
 	}
 
+	public function testRepeatedAssociationAliases() {
+		$table = TableRegistry::get('ArticlesTags');
+		$table->belongsTo('Articles');
+		$table->belongsTo('Tags');
+		TableRegistry::get('Tags')->belongsToMany('Articles');
+		$results = $table->find()->contain(['Articles', 'Tags.Articles'])->hydrate(false)->toArray();
+		debug($results);
+	}
+
 }