Skip to content
Permalink
Browse files

Add the ability to add automatic fields.

When selecting specific fields (such as computed fields) it is often
really helpful to also select all the fields in the model. Instead of
having to type out all the columns in the schema, the autoFields()
method can be used to tell an ORM\Query to also include the automatic
fields. This new method also works in contain() builders.

Refs #4360
  • Loading branch information...
markstory committed Aug 24, 2014
1 parent f11629f commit 44fee92558f540433d92ae5adfee37fae262977d
Showing with 100 additions and 3 deletions.
  1. +6 −1 src/ORM/Association.php
  2. +26 −1 src/ORM/Query.php
  3. +68 −1 tests/TestCase/ORM/QueryTest.php
@@ -596,13 +596,18 @@ protected function _dispatchBeforeFind($query) {
protected function _appendFields($query, $surrogate, $options) {
$options['fields'] = $surrogate->clause('select') ?: $options['fields'];
$target = $this->_targetTable;
if (empty($options['fields'])) {
$autoFields = $surrogate->autoFields();
if (empty($options['fields']) && !$autoFields) {
$f = isset($options['fields']) ? $options['fields'] : null;
if ($options['includeFields'] && ($f === null || $f !== false)) {
$options['fields'] = $target->schema()->columns();
}
}
if ($autoFields === true) {
$options['fields'] = array_merge((array)$options['fields'], $target->schema()->columns());
}
if (!empty($options['fields'])) {
$query->select($query->aliasFields($options['fields'], $target->alias()));
}
@@ -66,6 +66,14 @@ class Query extends DatabaseQuery implements JsonSerializable {
*/
protected $_hasFields;
/**
* Tracks whether or not the original query should include
* fields from the top level model.
*
* @var bool
*/
protected $_autoFields;
/**
* Boolean for tracking whether or not buffered results
* are enabled.
@@ -625,7 +633,7 @@ protected function _addDefaultFields() {
$select = $this->clause('select');
$this->_hasFields = true;
if (!count($select)) {
if (!count($select) || $this->_autoFields === true) {
$this->_hasFields = false;
$this->select($this->repository()->schema()->columns());
$select = $this->clause('select');
@@ -756,4 +764,21 @@ public function jsonSerialize() {
return $this->all();
}
/**
* Get/Set whether or not the ORM should automatically append fields.
*
* By default calling select() will disable auto-fields. You can re-enable
* auto-fields with this method.
*
* @param bool $value The value to set or null to read the current value.
* @return bool|$this Either the current value or the query object.
*/
public function autoFields($value = null) {
if ($value === null) {
return $this->_autoFields;
}
$this->_autoFields = (bool)$value;
return $this;
}
}
@@ -27,7 +27,6 @@
/**
* Tests Query class
*
*/
class QueryTest extends TestCase {
@@ -2006,4 +2005,72 @@ public function testJsonSerialize() {
);
}
/**
* Test that addFields() works in the basic case.
*
* @return void
*/
public function testAutoFields() {
$table = TableRegistry::get('Articles');
$result = $table->find('all')
->select(['myField' => 'id + 20'])
->autoFields(true)
->hydrate(false)
->first();
$this->assertArrayHasKey('myField', $result);
$this->assertArrayHasKey('id', $result);
$this->assertArrayHasKey('title', $result);
}
/**
* Test autoFields with auto fields.
*
* @return void
*/
public function testAutoFieldsWithAssociations() {
$table = TableRegistry::get('Articles');
$table->belongsTo('Authors');
$result = $table->find()
->select(['myField' => '(SELECT RAND())'])
->autoFields(true)
->hydrate(false)
->contain('Authors')
->first();
$this->assertArrayHasKey('myField', $result);
$this->assertArrayHasKey('title', $result);
$this->assertArrayHasKey('author', $result);
$this->assertNotNull($result['author']);
$this->assertArrayHasKey('name', $result['author']);
}
/**
* Test autoFields in contain query builder
*
* @return void
*/
public function testAutoFieldsWithContainQueryBuilder() {
$table = TableRegistry::get('Articles');
$table->belongsTo('Authors');
$result = $table->find()
->select(['myField' => '(SELECT RAND())'])
->autoFields(true)
->hydrate(false)
->contain(['Authors' => function($q) {
return $q->select(['compute' => '2 + 20'])
->autoFields(true);
}])
->first();
$this->assertArrayHasKey('myField', $result);
$this->assertArrayHasKey('title', $result);
$this->assertArrayHasKey('author', $result);
$this->assertNotNull($result['author']);
$this->assertArrayHasKey('name', $result['author']);
$this->assertArrayHasKey('compute', $result);
}
}

0 comments on commit 44fee92

Please sign in to comment.
You can’t perform that action at this time.