Skip to content

Commit

Permalink
Starting to remove to level keys for grouping results, instead nesting
Browse files Browse the repository at this point in the history
results inside each record for associations
  • Loading branch information
lorenzo committed May 19, 2013
1 parent 1040f3a commit a62c6ca
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 51 deletions.
28 changes: 27 additions & 1 deletion lib/Cake/ORM/Association.php
Expand Up @@ -91,6 +91,13 @@ abstract class Association {
*/
protected $_joinType = 'LEFT';

/**
* The property name that should be filled with data from the target table
* in the source table record.
*
* @var string
*/
protected $_property;

/**
* Constructor. Subclasses can override _options function to get the original
Expand All @@ -108,7 +115,8 @@ public function __construct($name, array $options = []) {
'dependent',
'sourceTable',
'targetTable',
'joinType'
'joinType',
'property'
];
foreach ($defaults as $property) {
if (isset($options[$property])) {
Expand All @@ -122,6 +130,10 @@ public function __construct($name, array $options = []) {
if (empty($this->_className)) {
$this->_className = $this->_name;
}

if (empty($this->_property)) {
$this->property($name);
}
}

/**
Expand Down Expand Up @@ -245,6 +257,20 @@ public function joinType($type = null) {
return $this->_joinType = $type;
}

/**
* Sets the property name that should be filled with data from the target table
* in the source table record.
* If no arguments are passed, currently configured type is returned.
*
* @return string
*/
function property($name = null) {
if ($name !== null) {
$this->_property = $name;
}
return $this->_property;
}

/**
* Override this function to initialize any concrete association class, it will
* get passed the original list of options used in the constructor
Expand Down
4 changes: 2 additions & 2 deletions lib/Cake/ORM/Association/HasMany.php
Expand Up @@ -84,14 +84,14 @@ public function eagerLoader($results, $options = []) {
$resultMap = [];
$key = $target->primaryKey();
foreach ($fetchQuery->execute() as $result) {
$resultMap[$result[$alias][$key]][] = $result;
$resultMap[$result[$key]][] = $result;
}

$sourceKey = key($fetchQuery->aliasField(
$source->primaryKey(),
$source->alias()
));
$targetKey = key($fetchQuery->aliasField($alias, $source->alias()));
$targetKey = key($fetchQuery->aliasField($this->property(), $source->alias()));
return function($row) use ($alias, $resultMap, $sourceKey, $targetKey) {
if (isset($resultMap[$row[$sourceKey]])) {
$row[$targetKey] = $resultMap[$row[$sourceKey]];
Expand Down
13 changes: 7 additions & 6 deletions lib/Cake/ORM/Query.php
Expand Up @@ -161,10 +161,9 @@ protected function _addContainments() {
}

foreach ($contain as $relation => $meta) {
$associated = $this->_table->association($relation);
if (!$associated->canBeJoined()) {
if ($meta['instance'] && !$meta['instance']->canBeJoined()) {
$this->_eagerLoading = true;
$this->_loadEagerly[$relation] = [$associated, $meta];
$this->_loadEagerly[$relation] = $meta;
}
}
}
Expand All @@ -177,12 +176,14 @@ protected function _normalizeContain(Table $parent, $alias, $options) {
'fields' => 1
];

$table = $parent->association($alias)->target();
$instance = $parent->association($alias);
$table = $instance->target();
$this->_aliasMap[$alias] = $table;

$extra = array_diff_key($options, $defaults);
$config = [
'associations' => [],
'instance' => $instance,
'config' => array_diff_key($options, $extra)
];

Expand All @@ -199,7 +200,7 @@ protected function _normalizeContain(Table $parent, $alias, $options) {
protected function _resolveFirstLevel($source, $associations) {
$result = [];
foreach ($associations as $table => $options) {
$associated = $source->association($table);
$associated = $options['instance'];
if ($associated && $associated->canBeJoined()) {
$result[$table] = [
'association' => $associated,
Expand All @@ -226,7 +227,7 @@ protected function _eagerLoad($statement) {

$statement->rewind();
foreach ($this->_loadEagerly as $association => $meta) {
$f = $meta[0]->eagerLoader($keys[$alias], $meta[1]);
$f = $meta['instance']->eagerLoader($keys[$alias], $meta);
$statement = new CallbackStatement($statement, $this->connection()->driver(), $f);
}

Expand Down
18 changes: 13 additions & 5 deletions lib/Cake/ORM/ResultSet.php
Expand Up @@ -86,17 +86,25 @@ protected function _groupResult() {
if (empty($this->_map[$key])) {
$parts = explode('__', $key);
if (count($parts) > 1) {
if ($parts[0] !== $table) {
$assoc = $this->_query->repository()->association($parts[0]);
$parts[2] = $assoc->property();
}
$this->_map[$key] = $parts;
}
}

if (!empty($this->_map[$key])) {
list($table, $field) = $this->_map[$key];
$value = $this->_castValue($table, $field, $value);
}
$parts = $this->_map[$key];
list($table, $field) = $parts;
$value = $this->_castValue($table, $field, $value);

$results[$table][$field] = $value;
if (!empty($parts[2])) {
$results[$parts[2]][$field] = $value;
} else {
$results[$field] = $value;
}
}

return $results;
}

Expand Down
62 changes: 25 additions & 37 deletions lib/Cake/Test/TestCase/ORM/QueryTest.php
Expand Up @@ -283,24 +283,20 @@ public function testContainResultFetchingOneLevel() {
$results = $query->repository($table)->select()->contain('author')->toArray();
$expected = [
[
'article' => [
'id' => 1,
'title' => 'a title',
'body' => 'a body',
'author_id' => 1
],
'id' => 1,
'title' => 'a title',
'body' => 'a body',
'author_id' => 1,
'author' => [
'id' => 1,
'name' => 'Chuck Norris'
]
],
[
'article' => [
'id' => 2,
'title' => 'another title',
'body' => 'another body',
'author_id' => 2
],
'id' => 2,
'title' => 'another title',
'body' => 'another body',
'author_id' => 2,
'author' => [
'id' => 2,
'name' => 'Bruce Lee'
Expand All @@ -321,39 +317,31 @@ public function testHasManyEagerLoading() {
$query = new Query($this->connection);
$table = Table::build('author', ['connection' => $this->connection]);
Table::build('article', ['connection' => $this->connection]);
$table->hasMany('article');
$table->hasMany('article', ['property' => 'articles']);

$results = $query->repository($table)->select()->contain('article')->toArray();
$expected = [
[
'author' => [
'id' => 1,
'name' => 'Chuck Norris',
'article' => [
[
'article' => [
'id' => 1,
'title' => 'a title',
'body' => 'a body',
'author_id' => 1
]
]
'id' => 1,
'name' => 'Chuck Norris',
'articles' => [
[
'id' => 1,
'title' => 'a title',
'body' => 'a body',
'author_id' => 1
]
]
],
[
'author' => [
'id' => 2,
'name' => 'Bruce Lee',
'article' => [
[
'article' => [
'id' => 2,
'title' => 'another title',
'body' => 'another body',
'author_id' => 2
]
]
'id' => 2,
'name' => 'Bruce Lee',
'articles' => [
[
'id' => 2,
'title' => 'another title',
'body' => 'another body',
'author_id' => 2
]
]
]
Expand Down

0 comments on commit a62c6ca

Please sign in to comment.