Browse Source

selectAllExcept() pull request. #1125 Select columns from a table except columns in exclusion list.

Eugene Ritter 8 years ago
parent
commit
89d45aad2c
2 changed files with 111 additions and 0 deletions
  1. 25 0
      src/ORM/Query.php
  2. 86 0
      tests/TestCase/ORM/QueryTest.php

+ 25 - 0
src/ORM/Query.php

@@ -17,6 +17,7 @@ namespace Cake\ORM;
 use ArrayObject;
 use Cake\Database\ExpressionInterface;
 use Cake\Database\Query as DatabaseQuery;
+use Cake\Database\Schema\TableSchema;
 use Cake\Database\TypedResultInterface;
 use Cake\Database\TypeMap;
 use Cake\Database\ValueBinder;
@@ -195,6 +196,30 @@ class Query extends DatabaseQuery implements JsonSerializable, QueryInterface
     }
 
     /**
+     * Select all the columns associated to $table except the $excludedFields.
+     * Excluded fields should not be aliased names.
+     *
+     *
+     * @param Table|Association $table The table to use to get an array of columns
+     * @param array $excludedFields The un-aliased column names you do not want selected from $table
+     * @param bool $overwrite Whether to reset/remove previous selected fields
+     * @return Query
+     */
+    public function selectAllExcept($table, array $excludedFields, $overwrite = false)
+    {
+        if ($table instanceof Association) {
+            $table = $table->getTarget();
+        }
+        $aliasedFields = [];
+        if ($table instanceof Table) {
+            $fields = array_diff($table->getSchema()->columns(), $excludedFields);
+            $aliasedFields = $this->aliasFields($fields);
+        }
+
+        return $this->select($aliasedFields, $overwrite);
+    }
+
+    /**
      * Hints this object to associate the correct types when casting conditions
      * for the database. This is done by extracting the field types from the schema
      * associated to the passed table object. This prevents the user from repeating

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

@@ -3569,4 +3569,90 @@ class QueryTest extends TestCase
 
         $this->assertEquals(1, $query->__debugInfo()['decorators'], 'Only one typecaster should exist');
     }
+
+    /**
+     * Test to see that the excluded fields are not in the select clause
+     *
+     * @return void
+     */
+    public function testSelectAllExcept()
+    {
+        $table = $this->getTableLocator()->get('Articles');
+        $result = $table
+            ->find()
+            ->selectAllExcept($table, ['body']);
+        $selectedFields = $result->clause('select');
+        $expected = [
+            'Articles__id' => 'Articles.id',
+            'Articles__author_id' => 'Articles.author_id',
+            'Articles__title' => 'Articles.title',
+            'Articles__published' => 'Articles.published'
+        ];
+        $this->assertEquals($expected, $selectedFields);
+    }
+
+    /**
+     * Test that the excluded fields are not included
+     * in the final query result.
+     *
+     * @return void
+     */
+    public function testSelectAllExceptWithContains()
+    {
+        $table = $this->getTableLocator()->get('Articles');
+        $this->getTableLocator()->get('Articles');
+        $table->hasMany('Comments');
+        $table->belongsTo('Authors');
+
+        $result = $table
+            ->find()
+            ->contain(['Comments' => function ($query) use ($table) {
+                return $query->selectAllExcept($table->Comments, ['published']);
+            }])
+            ->selectAllExcept($table, ['body'])
+            ->first();
+        $this->assertNull($result->comments[0]->published);
+        $this->assertNull($result->body);
+        $this->assertNotEmpty($result->id);
+        $this->assertNotEmpty($result->comments[0]->id);
+    }
+
+    /**
+     * Test what happens if you call selectAllExcept() more
+     * than once.
+     *
+     * @return void
+     */
+    public function testSelectAllExceptWithMulitpleCalls()
+    {
+        $table = $this->getTableLocator()->get('Articles');
+        $this->getTableLocator()->get('Articles');
+
+        $result = $table
+            ->find()
+            ->selectAllExcept($table, ['body'])
+            ->selectAllExcept($table, ['published']);
+        $selectedFields = $result->clause('select');
+        $expected = [
+            'Articles__id' => 'Articles.id',
+            'Articles__author_id' => 'Articles.author_id',
+            'Articles__title' => 'Articles.title',
+            'Articles__published' => 'Articles.published',
+            'Articles__body' => 'Articles.body'
+        ];
+        $this->assertEquals($expected, $selectedFields);
+
+        $result = $table
+            ->find()
+            ->selectAllExcept($table, ['body'])
+            ->selectAllExcept($table, ['published', 'body']);
+        $selectedFields = $result->clause('select');
+        $expected = [
+            'Articles__id' => 'Articles.id',
+            'Articles__author_id' => 'Articles.author_id',
+            'Articles__title' => 'Articles.title',
+            'Articles__published' => 'Articles.published'
+        ];
+        $this->assertEquals($expected, $selectedFields);
+    }
 }