Browse Source

Remove errors when aliases don't match.

This hard error makes using the `targetTable` option in associations
really hard as it always triggers this condition. By reworking how we
generate aliases and eagerloader names we can enable the `targetTable`
option to behave as intended. The foreignKey will need to be set, but
I think that is reasonble given how key generation uses the table's
alias for other reasons.

Refs #7125
Refs #10410
Mark Story 9 years ago
parent
commit
cb5f4d3adc

+ 2 - 2
src/ORM/Association.php

@@ -1144,7 +1144,7 @@ abstract class Association
         }
 
         if ($fields) {
-            $query->select($query->aliasFields($fields, $target->getAlias()));
+            $query->select($query->aliasFields($fields, $this->_name));
         }
         $query->addDefaultTypes($target);
     }
@@ -1245,7 +1245,7 @@ abstract class Association
     protected function _joinCondition($options)
     {
         $conditions = [];
-        $tAlias = $this->getTarget()->getAlias();
+        $tAlias = $this->_name;
         $sAlias = $this->getSource()->getAlias();
         $foreignKey = (array)$options['foreignKey'];
         $bindingKey = (array)$this->getBindingKey();

+ 1 - 1
src/ORM/Association/BelongsTo.php

@@ -151,7 +151,7 @@ class BelongsTo extends Association
     protected function _joinCondition($options)
     {
         $conditions = [];
-        $tAlias = $this->getTarget()->getAlias();
+        $tAlias = $this->_name;
         $sAlias = $this->_sourceTable->getAlias();
         $foreignKey = (array)$options['foreignKey'];
         $bindingKey = (array)$this->getBindingKey();

+ 0 - 7
src/ORM/EagerLoader.php

@@ -497,13 +497,6 @@ class EagerLoader
                 sprintf('%s is not associated with %s', $parent->getAlias(), $alias)
             );
         }
-        if ($instance->getAlias() !== $alias) {
-            throw new InvalidArgumentException(sprintf(
-                "You have contained '%s' but that association was bound as '%s'.",
-                $alias,
-                $instance->getAlias()
-            ));
-        }
 
         $paths += ['aliasPath' => '', 'propertyPath' => '', 'root' => $alias];
         $paths['aliasPath'] .= '.' . $alias;

+ 0 - 15
tests/TestCase/ORM/EagerLoaderTest.php

@@ -436,21 +436,6 @@ class EagerLoaderTest extends TestCase
     }
 
     /**
-     * Check that normalizing contains checks alias names.
-     *
-     * @expectedException \InvalidArgumentException
-     * @expectedExceptionMessage You have contained 'Clients' but that association was bound as 'clients'
-     * @return void
-     */
-    public function testNormalizedChecksAliasNames()
-    {
-        $contains = ['Clients'];
-        $loader = new EagerLoader;
-        $loader->contain($contains);
-        $loader->normalized($this->table);
-    }
-
-    /**
      * Tests that the path for getting to a deep association is materialized in an
      * array key
      *

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

@@ -17,6 +17,7 @@ namespace Cake\Test\TestCase\ORM;
 use Cake\Core\Plugin;
 use Cake\Database\Expression\Comparison;
 use Cake\Database\Expression\QueryExpression;
+use Cake\Datasource\EntityInterface;
 use Cake\Event\Event;
 use Cake\I18n\Time;
 use Cake\ORM\TableRegistry;
@@ -91,6 +92,48 @@ class QueryRegressionTest extends TestCase
     }
 
     /**
+     * Tests that eagerloading and hydration works for associations that have
+     * different aliases in the association and targetTable
+     *
+     * @return void
+     */
+    public function testEagerLoadingMismatchingAliasInBelongsTo()
+    {
+        $this->loadFixtures('Articles', 'Users');
+        $table = TableRegistry::get('Articles');
+        $users = TableRegistry::get('Users');
+        $table->belongsTo('Authors', [
+            'targetTable' => $users,
+            'foreignKey' => 'author_id'
+        ]);
+        $result = $table->find()->where(['Articles.id' => 1])->contain('Authors')->first();
+        $this->assertInstanceOf(EntityInterface::class, $result);
+        $this->assertInstanceOf(EntityInterface::class, $result->author);
+        $this->assertSame('mariano', $result->author->username);
+    }
+
+    /**
+     * Tests that eagerloading and hydration works for associations that have
+     * different aliases in the association and targetTable
+     *
+     * @return void
+     */
+    public function testEagerLoadingMismatchingAliasInHasOne()
+    {
+        $this->loadFixtures('Articles', 'Users');
+        $articles = TableRegistry::get('Articles');
+        $users = TableRegistry::get('Users');
+        $users->hasOne('Posts', [
+            'targetTable' => $articles,
+            'foreignKey' => 'author_id'
+        ]);
+        $result = $users->find()->where(['Users.id' => 1])->contain('Posts')->first();
+        $this->assertInstanceOf(EntityInterface::class, $result);
+        $this->assertInstanceOf(EntityInterface::class, $result->post);
+        $this->assertSame('First Article', $result->post->title);
+    }
+
+    /**
      * Tests that eagerloading belongsToMany with find list fails with a helpful message.
      *
      * @expectedException \InvalidArgumentException