Browse Source

Managed to not use matching() for loading belognsToMany

This will help with separating the results from matching and everything else
Jose Lorenzo Rodriguez 11 years ago
parent
commit
bc07bcf327
3 changed files with 31 additions and 9 deletions
  1. 11 3
      src/ORM/Association/BelongsToMany.php
  2. 19 6
      src/ORM/EagerLoader.php
  3. 1 0
      src/ORM/ResultSet.php

+ 11 - 3
src/ORM/Association/BelongsToMany.php

@@ -868,7 +868,9 @@ class BelongsToMany extends Association {
 /**
  * Auxiliary function to construct a new Query object to return all the records
  * in the target table that are associated to those specified in $options from
- * the source table
+ * the source table.
+ *
+ * This is used for eager loading records on the target table based on conditions.
  *
  * @param array $options options accepted by eagerLoader()
  * @return \Cake\ORM\Query
@@ -888,8 +890,14 @@ class BelongsToMany extends Association {
 			]
 		];
 
-		$joins = $matching + $joins;
-		$query->join($joins, [], true)->matching($name);
+		$assoc = $this->target()->association($name);
+		$query
+			->join($matching + $joins, [], true)
+			->autoFields(empty($query->clause('select')))
+			->select($query->aliasFields((array)$assoc->foreignKey(), $name));
+
+		$query->eagerLoader()->addToJoinsMap($name, $assoc);
+		$assoc->attachTo($query);
 		return $query;
 	}
 

+ 19 - 6
src/ORM/EagerLoader.php

@@ -84,6 +84,8 @@ class EagerLoader {
  */
 	protected $_matching;
 
+	protected $_joinsMap = [];
+
 /**
  * Sets the list of associations that should be eagerly loaded along for a
  * specific table using when a query is provided. The list of associated tables
@@ -501,29 +503,40 @@ class EagerLoader {
 	public function associationsMap($table) {
 		$map = [];
 
-		if (!$this->matching() && !$this->contain()) {
+		if (!$this->matching() && !$this->contain() && empty($this->_joinsMap)) {
 			return $map;
 		}
 
-		$visitor = function ($level) use (&$visitor, &$map) {
+		$visitor = function ($level, $matching = false) use (&$visitor, &$map) {
 			foreach ($level as $assoc => $meta) {
 				$map[$meta['aliasPath']] = [
 					'alias' => $assoc,
 					'instance' => $meta['instance'],
 					'canBeJoined' => $meta['canBeJoined'],
 					'entityClass' => $meta['instance']->target()->entityClass(),
-					'nestKey' => $meta['canBeJoined'] ? $assoc : $meta['aliasPath']
+					'nestKey' => $meta['canBeJoined'] ? $assoc : $meta['aliasPath'],
+					'matching' => $matching
 				];
 				if ($meta['canBeJoined'] && !empty($meta['associations'])) {
-					$visitor($meta['associations']);
+					$visitor($meta['associations'], $matching);
 				}
 			}
 		};
-		$visitor($this->normalized($table), []);
-		$visitor($this->_matching->normalized($table), []);
+		$visitor($this->_matching->normalized($table), true);
+		$visitor($this->normalized($table));
+		$visitor($this->_joinsMap);
 		return $map;
 	}
 
+	public function addToJoinsMap($alias, $assoc) {
+		$this->_joinsMap[$alias] = [
+			'aliasPath' => $alias,
+			'instance' => $assoc,
+			'canBeJoined' => true,
+			'associations' => []
+		];
+	}
+
 /**
  * Helper function used to return the keys from the query records that will be used
  * to eagerly load associations.

+ 1 - 0
src/ORM/ResultSet.php

@@ -401,6 +401,7 @@ class ResultSet implements ResultSetInterface {
 				$entity->clean();
 				$results[$alias] = $entity;
 			}
+
 			$results = $instance->transformRow($results, $alias, $assoc['canBeJoined']);
 		}