ソースを参照

Implemented notMatching for belongsToMany tables

Jose Lorenzo Rodriguez 10 年 前
コミット
cd4cc09882

+ 13 - 8
src/ORM/Association.php

@@ -499,14 +499,6 @@ abstract class Association
             }
         }
 
-        if ($options['negateMatch']) {
-            $primaryKey = $query->aliasFields((array)$target->primaryKey(), $this->_name);
-            $query->andWhere(function ($exp) use ($primaryKey) {
-                array_map([$exp, 'isNull'], $primaryKey);
-                return $exp;
-            });
-        }
-
         list($finder, $opts) = $this->_extractFinder($options['finder']);
         $dummy = $this
             ->find($finder, $opts)
@@ -531,6 +523,19 @@ abstract class Association
         $this->_appendFields($query, $dummy, $options);
         $this->_formatAssociationResults($query, $dummy, $options);
         $this->_bindNewAssociations($query, $dummy, $options);
+        $this->_appendNotMatching($query, $options);
+    }
+
+    protected function _appendNotMatching($query, $options)
+    {
+        $target = $this->_targetTable;
+        if (!empty($options['negateMatch'])) {
+            $primaryKey = $query->aliasFields((array)$target->primaryKey(), $this->_name);
+            $query->andWhere(function ($exp) use ($primaryKey) {
+                array_map([$exp, 'isNull'], $primaryKey);
+                return $exp;
+            });
+        }
     }
 
     /**

+ 12 - 0
src/ORM/Association/BelongsToMany.php

@@ -262,6 +262,18 @@ class BelongsToMany extends Association
         $query->eagerLoader()->addToJoinsMap($junction->alias(), $assoc, true);
     }
 
+    protected function _appendNotMatching($query, $options)
+    {
+        $target = $junction = $this->junction();
+        if (!empty($options['negateMatch'])) {
+            $primaryKey = $query->aliasFields((array)$target->primaryKey(), $target->alias());
+            $query->andWhere(function ($exp) use ($primaryKey) {
+                array_map([$exp, 'isNull'], $primaryKey);
+                return $exp;
+            });
+        }
+    }
+
     /**
      * {@inheritDoc}
      */

+ 3 - 1
src/ORM/EagerLoader.php

@@ -191,9 +191,11 @@ class EagerLoader
         $containments = [];
         $pointer =& $containments;
         $options += ['joinType' => 'INNER'];
+        $opts = ['matching' => true] + $options;
+        unset($opts['negateMatch']);
 
         foreach ($assocs as $name) {
-            $pointer[$name] = ['matching' => true] + $options;
+            $pointer[$name] = $opts;
             $pointer =& $pointer[$name];
         }
 

+ 32 - 1
tests/TestCase/ORM/QueryTest.php

@@ -2848,7 +2848,7 @@ class QueryTest extends TestCase
     public function testNotMatching()
     {
         $table = TableRegistry::get('authors');
-        $articles = $table->hasMany('articles');
+        $table->hasMany('articles');
 
         $results = $table->find()
             ->hydrate(false)
@@ -2874,4 +2874,35 @@ class QueryTest extends TestCase
         ];
         $this->assertEquals($expected, $results);
     }
+
+    public function testNotMatchingBelongsToMany()
+    {
+        $table = TableRegistry::get('articles');
+        $table->belongsToMany('tags');
+
+        $results = $table->find()
+            ->hydrate(false)
+            ->notMatching('tags', function ($q) {
+                return $q->where(['tags.name' => 'tag2']);
+            })
+            ->toArray();
+
+        $expected = [
+            [
+                'id' => 2,
+                'author_id' => 3,
+                'title' => 'Second Article',
+                'body' => 'Second Article Body',
+                'published' => 'Y'
+            ],
+            [
+                'id' => 3,
+                'author_id' => 1,
+                'title' => 'Third Article',
+                'body' => 'Third Article Body',
+                'published' => 'Y'
+            ]
+        ];
+        $this->assertEquals($expected, $results);
+    }
 }