Skip to content

Commit a62c6ca

Browse files
committed
Starting to remove to level keys for grouping results, instead nesting
results inside each record for associations
1 parent 1040f3a commit a62c6ca

File tree

5 files changed

+74
-51
lines changed

5 files changed

+74
-51
lines changed

lib/Cake/ORM/Association.php

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ abstract class Association {
9191
*/
9292
protected $_joinType = 'LEFT';
9393

94+
/**
95+
* The property name that should be filled with data from the target table
96+
* in the source table record.
97+
*
98+
* @var string
99+
*/
100+
protected $_property;
94101

95102
/**
96103
* Constructor. Subclasses can override _options function to get the original
@@ -108,7 +115,8 @@ public function __construct($name, array $options = []) {
108115
'dependent',
109116
'sourceTable',
110117
'targetTable',
111-
'joinType'
118+
'joinType',
119+
'property'
112120
];
113121
foreach ($defaults as $property) {
114122
if (isset($options[$property])) {
@@ -122,6 +130,10 @@ public function __construct($name, array $options = []) {
122130
if (empty($this->_className)) {
123131
$this->_className = $this->_name;
124132
}
133+
134+
if (empty($this->_property)) {
135+
$this->property($name);
136+
}
125137
}
126138

127139
/**
@@ -245,6 +257,20 @@ public function joinType($type = null) {
245257
return $this->_joinType = $type;
246258
}
247259

260+
/**
261+
* Sets the property name that should be filled with data from the target table
262+
* in the source table record.
263+
* If no arguments are passed, currently configured type is returned.
264+
*
265+
* @return string
266+
*/
267+
function property($name = null) {
268+
if ($name !== null) {
269+
$this->_property = $name;
270+
}
271+
return $this->_property;
272+
}
273+
248274
/**
249275
* Override this function to initialize any concrete association class, it will
250276
* get passed the original list of options used in the constructor

lib/Cake/ORM/Association/HasMany.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ public function eagerLoader($results, $options = []) {
8484
$resultMap = [];
8585
$key = $target->primaryKey();
8686
foreach ($fetchQuery->execute() as $result) {
87-
$resultMap[$result[$alias][$key]][] = $result;
87+
$resultMap[$result[$key]][] = $result;
8888
}
8989

9090
$sourceKey = key($fetchQuery->aliasField(
9191
$source->primaryKey(),
9292
$source->alias()
9393
));
94-
$targetKey = key($fetchQuery->aliasField($alias, $source->alias()));
94+
$targetKey = key($fetchQuery->aliasField($this->property(), $source->alias()));
9595
return function($row) use ($alias, $resultMap, $sourceKey, $targetKey) {
9696
if (isset($resultMap[$row[$sourceKey]])) {
9797
$row[$targetKey] = $resultMap[$row[$sourceKey]];

lib/Cake/ORM/Query.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,9 @@ protected function _addContainments() {
161161
}
162162

163163
foreach ($contain as $relation => $meta) {
164-
$associated = $this->_table->association($relation);
165-
if (!$associated->canBeJoined()) {
164+
if ($meta['instance'] && !$meta['instance']->canBeJoined()) {
166165
$this->_eagerLoading = true;
167-
$this->_loadEagerly[$relation] = [$associated, $meta];
166+
$this->_loadEagerly[$relation] = $meta;
168167
}
169168
}
170169
}
@@ -177,12 +176,14 @@ protected function _normalizeContain(Table $parent, $alias, $options) {
177176
'fields' => 1
178177
];
179178

180-
$table = $parent->association($alias)->target();
179+
$instance = $parent->association($alias);
180+
$table = $instance->target();
181181
$this->_aliasMap[$alias] = $table;
182182

183183
$extra = array_diff_key($options, $defaults);
184184
$config = [
185185
'associations' => [],
186+
'instance' => $instance,
186187
'config' => array_diff_key($options, $extra)
187188
];
188189

@@ -199,7 +200,7 @@ protected function _normalizeContain(Table $parent, $alias, $options) {
199200
protected function _resolveFirstLevel($source, $associations) {
200201
$result = [];
201202
foreach ($associations as $table => $options) {
202-
$associated = $source->association($table);
203+
$associated = $options['instance'];
203204
if ($associated && $associated->canBeJoined()) {
204205
$result[$table] = [
205206
'association' => $associated,
@@ -226,7 +227,7 @@ protected function _eagerLoad($statement) {
226227

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

lib/Cake/ORM/ResultSet.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,25 @@ protected function _groupResult() {
8686
if (empty($this->_map[$key])) {
8787
$parts = explode('__', $key);
8888
if (count($parts) > 1) {
89+
if ($parts[0] !== $table) {
90+
$assoc = $this->_query->repository()->association($parts[0]);
91+
$parts[2] = $assoc->property();
92+
}
8993
$this->_map[$key] = $parts;
9094
}
9195
}
9296

93-
if (!empty($this->_map[$key])) {
94-
list($table, $field) = $this->_map[$key];
95-
$value = $this->_castValue($table, $field, $value);
96-
}
97+
$parts = $this->_map[$key];
98+
list($table, $field) = $parts;
99+
$value = $this->_castValue($table, $field, $value);
97100

98-
$results[$table][$field] = $value;
101+
if (!empty($parts[2])) {
102+
$results[$parts[2]][$field] = $value;
103+
} else {
104+
$results[$field] = $value;
105+
}
99106
}
107+
100108
return $results;
101109
}
102110

lib/Cake/Test/TestCase/ORM/QueryTest.php

Lines changed: 25 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -283,24 +283,20 @@ public function testContainResultFetchingOneLevel() {
283283
$results = $query->repository($table)->select()->contain('author')->toArray();
284284
$expected = [
285285
[
286-
'article' => [
287-
'id' => 1,
288-
'title' => 'a title',
289-
'body' => 'a body',
290-
'author_id' => 1
291-
],
286+
'id' => 1,
287+
'title' => 'a title',
288+
'body' => 'a body',
289+
'author_id' => 1,
292290
'author' => [
293291
'id' => 1,
294292
'name' => 'Chuck Norris'
295293
]
296294
],
297295
[
298-
'article' => [
299-
'id' => 2,
300-
'title' => 'another title',
301-
'body' => 'another body',
302-
'author_id' => 2
303-
],
296+
'id' => 2,
297+
'title' => 'another title',
298+
'body' => 'another body',
299+
'author_id' => 2,
304300
'author' => [
305301
'id' => 2,
306302
'name' => 'Bruce Lee'
@@ -321,39 +317,31 @@ public function testHasManyEagerLoading() {
321317
$query = new Query($this->connection);
322318
$table = Table::build('author', ['connection' => $this->connection]);
323319
Table::build('article', ['connection' => $this->connection]);
324-
$table->hasMany('article');
320+
$table->hasMany('article', ['property' => 'articles']);
325321

326322
$results = $query->repository($table)->select()->contain('article')->toArray();
327323
$expected = [
328324
[
329-
'author' => [
330-
'id' => 1,
331-
'name' => 'Chuck Norris',
332-
'article' => [
333-
[
334-
'article' => [
335-
'id' => 1,
336-
'title' => 'a title',
337-
'body' => 'a body',
338-
'author_id' => 1
339-
]
340-
]
325+
'id' => 1,
326+
'name' => 'Chuck Norris',
327+
'articles' => [
328+
[
329+
'id' => 1,
330+
'title' => 'a title',
331+
'body' => 'a body',
332+
'author_id' => 1
341333
]
342334
]
343335
],
344336
[
345-
'author' => [
346-
'id' => 2,
347-
'name' => 'Bruce Lee',
348-
'article' => [
349-
[
350-
'article' => [
351-
'id' => 2,
352-
'title' => 'another title',
353-
'body' => 'another body',
354-
'author_id' => 2
355-
]
356-
]
337+
'id' => 2,
338+
'name' => 'Bruce Lee',
339+
'articles' => [
340+
[
341+
'id' => 2,
342+
'title' => 'another title',
343+
'body' => 'another body',
344+
'author_id' => 2
357345
]
358346
]
359347
]

0 commit comments

Comments
 (0)