Browse Source

Merge pull request #5560 from cakephp/issue-5143

Fix documentation and add exception for foreignKey in contain
José Lorenzo Rodríguez 11 years ago
parent
commit
774f255567
3 changed files with 73 additions and 3 deletions
  1. 5 0
      src/ORM/Association/HasMany.php
  2. 4 3
      src/ORM/Query.php
  3. 64 0
      tests/TestCase/ORM/QueryTest.php

+ 5 - 0
src/ORM/Association/HasMany.php

@@ -128,6 +128,11 @@ class HasMany extends Association
     {
         $links = [];
         $name = $this->alias();
+        if ($options['foreignKey'] === false) {
+            $msg = 'Cannot have foreignKey = false for hasMany associations. ' .
+                   'You must provide a foreignKey column.';
+            throw new \RuntimeException($msg);
+        }
 
         foreach ((array)$options['foreignKey'] as $key) {
             $links[] = sprintf('%s.%s', $name, $key);

+ 4 - 3
src/ORM/Query.php

@@ -226,7 +226,8 @@ class Query extends DatabaseQuery implements JsonSerializable
      * options that can be set per association are:
      *
      * - foreignKey: Used to set a different field to match both tables, if set to false
-     *   no join conditions will be generated automatically
+     *   no join conditions will be generated automatically. `false` can only be used on
+     *   joinable associations and cannot be used with hasMany or belongsToMany associations.
      * - fields: An array with the fields that should be fetched from the association
      * - queryBuilder: Equivalent to passing a callable instead of an options array
      *
@@ -245,9 +246,9 @@ class Query extends DatabaseQuery implements JsonSerializable
      * Failing to do so will trigger exceptions.
      *
      * {{{
-     * // Use special join conditions for getting an author's hasMany 'likes'
+     * // Use special join conditions for getting an Articles's belongsTo 'authors'
      * $query->contain([
-     *   'Likes' => [
+     *   'Authors' => [
      *     'foreignKey' => false,
      *     'queryBuilder' => function ($q) {
      *       return $q->where(...); // Add full filtering conditions

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

@@ -1665,6 +1665,70 @@ class QueryTest extends TestCase
     }
 
     /**
+     * Integration test to ensure that filtering associations with the queryBuilder
+     * option works.
+     *
+     * @expectedException \RuntimeException
+     * @return void
+     */
+    public function testContainWithQueryBuilderHasManyError()
+    {
+        $table = TableRegistry::get('Authors');
+        $table->hasMany('Articles');
+        $query = new Query($this->connection, $table);
+        $query->select()
+            ->contain([
+                'Articles' => [
+                    'foreignKey' => false,
+                    'queryBuilder' => function ($q) {
+                        return $q->where(['articles.id' => 1]);
+                    }
+                ]
+            ]);
+        $query->toArray();
+    }
+
+    /**
+     * Integration test to ensure that filtering associations with the queryBuilder
+     * option works.
+     *
+     * @return void
+     */
+    public function testContainWithQueryBuilderJoinableAssociation()
+    {
+        $table = TableRegistry::get('Authors');
+        $table->hasOne('Articles');
+        $query = new Query($this->connection, $table);
+        $query->select()
+            ->contain([
+                'Articles' => [
+                    'foreignKey' => false,
+                    'queryBuilder' => function ($q) {
+                        return $q->where(['Articles.id' => 1]);
+                    }
+                ]
+            ]);
+        $result = $query->toArray();
+        $this->assertEquals(1, $result[0]->article->id);
+        $this->assertEquals(1, $result[1]->article->id);
+
+        $articles = TableRegistry::get('Articles');
+        $articles->belongsTo('Authors');
+        $query = new Query($this->connection, $articles);
+        $query->select()
+            ->contain([
+                'Authors' => [
+                    'foreignKey' => false,
+                    'queryBuilder' => function ($q) {
+                        return $q->where(['Authors.id' => 1]);
+                    }
+                ]
+            ]);
+        $result = $query->toArray();
+        $this->assertEquals(1, $result[0]->author->id);
+    }
+
+    /**
      * Tests the formatResults method
      *
      * @return void