Browse Source

Merge pull request #4834 from cakephp/issue-4804

Fix deep associations being hydrated incorrectly.
Mark Story 11 years ago
parent
commit
0b3255499d
3 changed files with 35 additions and 2 deletions
  1. 4 1
      src/ORM/EagerLoader.php
  2. 2 1
      src/ORM/ResultSet.php
  3. 29 0
      tests/TestCase/ORM/QueryRegressionTest.php

+ 4 - 1
src/ORM/EagerLoader.php

@@ -454,7 +454,6 @@ class EagerLoader {
 			);
 			$statement = new CallbackStatement($statement, $driver, $f);
 		}
-
 		return $statement;
 	}
 
@@ -510,6 +509,10 @@ class EagerLoader {
 		$keys = [];
 		while ($result = $statement->fetch('assoc')) {
 			foreach ($collectKeys as $parts) {
+				// Missed joins will have null in the results.
+				if ($parts[2] && !isset($result[$parts[1][0]])) {
+					continue;
+				}
 				if ($parts[2]) {
 					$keys[$parts[0]][] = $result[$parts[1][0]];
 					continue;

+ 2 - 1
src/ORM/ResultSet.php

@@ -390,6 +390,7 @@ class ResultSet implements ResultSetInterface {
 			$alias = $assoc['nestKey'];
 			$instance = $assoc['instance'];
 
+			// Doing this before we're sure the root assoc has data is the problem.
 			if (!isset($results[$alias])) {
 				$results = $instance->defaultRowValue($results, $assoc['canBeJoined']);
 				continue;
@@ -404,7 +405,7 @@ class ResultSet implements ResultSetInterface {
 
 				$hasData = false;
 				foreach ($results[$alias] as $v) {
-					if ($v !== null) {
+					if ($v !== null && $v !== []) {
 						$hasData = true;
 						break;
 					}

+ 29 - 0
tests/TestCase/ORM/QueryRegressionTest.php

@@ -473,4 +473,33 @@ class QueryRegressionTest extends TestCase {
 		$this->assertEquals(2, $count);
 	}
 
+/**
+ * Test that deep containments don't generate empty entities for
+ * intermediary relations.
+ *
+ * @return void
+ */
+	public function testContainNoEmptyAssociatedObjects() {
+		$comments = TableRegistry::get('Comments');
+		$comments->belongsTo('Users');
+		$users = TableRegistry::get('Users');
+		$users->hasMany('Articles', [
+			'foreignKey' => 'author_id'
+		]);
+
+		$comments->updateAll(['user_id' => 99], ['id' => 1]);
+
+		$result = $comments->find()
+			->contain(['Users'])
+			->where(['Comments.id' => 1])
+			->first();
+		$this->assertNull($result->user, 'No record should be null.');
+
+		$result = $comments->find()
+			->contain(['Users', 'Users.Articles'])
+			->where(['Comments.id' => 1])
+			->first();
+		$this->assertNull($result->user, 'No record should be null.');
+	}
+
 }