Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Improving hasMany support by making it possible to filter by conditions
and select only certain fields
  • Loading branch information
lorenzo committed May 20, 2013
1 parent dbcb723 commit c3ef110
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 10 deletions.
23 changes: 14 additions & 9 deletions lib/Cake/ORM/Association/HasMany.php
Expand Up @@ -67,22 +67,27 @@ public function eagerLoader($results, $options = []) {
$fetchQuery = $target->find('all');
$options += [
'foreignKey' => $this->foreignKey(),
'conditions' => [],
'conditions' => []
];
$options['conditions'] = array_merge($this->conditions(), $options['conditions']);
$fetchQuery->where($options['conditions']);

if (!empty($options['foreignKey'])) {
$key = sprintf('%s.%s in', $alias, $options['foreignKey']);
$fetchQuery->where([$key => $results]);
}
$key = sprintf('%s.%s in', $alias, $options['foreignKey']);
$fetchQuery
->where($options['conditions'])
->andWhere([$key => $results]);

if (!empty($options['fields'])) {
$fetchQuery->select($query->aliasFields($options['fields'], $alias));
$fields = $fetchQuery->aliasFields($options['fields'], $alias);
$required = $alias . '.' . $options['foreignKey'];
if (!in_array($required, $fields)) {
throw new \InvalidArgumentException(
sprintf('You are required to select the "%s" field', $required)
);
}
$fetchQuery->select($fields);
}

$resultMap = [];
$key = $target->primaryKey();
$key = $options['foreignKey'];
foreach ($fetchQuery->execute() as $result) {
$resultMap[$result[$key]][] = $result;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Cake/ORM/Query.php
Expand Up @@ -227,7 +227,7 @@ protected function _eagerLoad($statement) {

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

Expand Down
66 changes: 66 additions & 0 deletions lib/Cake/Test/TestCase/ORM/QueryTest.php
Expand Up @@ -347,6 +347,72 @@ public function testHasManyEagerLoading() {
]
];
$this->assertEquals($expected, $results);

$results = $query->repository($table)
->select()
->contain(['article' => ['conditions' => ['id' => 2]]])
->toArray();
unset($expected[0]['articles']);
$this->assertEquals($expected, $results);
}

/**
* Tests that it is possible to select only certain fields on
* eagerly loaded has many associations
*
* @return void
**/
public function testHasManyEagerLoadingFields() {
$this->_insertTwoRecords();

$query = new Query($this->connection);
$table = Table::build('author', ['connection' => $this->connection]);
Table::build('article', ['connection' => $this->connection]);
$table->hasMany('article', ['property' => 'articles']);

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

/**
* Tests that not selecting the foreignKey for a hasMany association will
* throw an exception
*
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage You are required to select the "article.author_id"
* @return void
**/
public function testHasManyEagerLoadingFieldsError() {
$this->_insertTwoRecords();

$query = new Query($this->connection);
$table = Table::build('author', ['connection' => $this->connection]);
Table::build('article', ['connection' => $this->connection]);
$table->hasMany('article', ['property' => 'articles']);

$results = $query->repository($table)
->select()
->contain(['article' => ['fields' => ['title']]])
->toArray();
}

}

0 comments on commit c3ef110

Please sign in to comment.