Skip to content
Permalink
Browse files

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 c3ef110dcef6d319201f7a339aad69d86ffe099a
Showing with 81 additions and 10 deletions.
  1. +14 −9 lib/Cake/ORM/Association/HasMany.php
  2. +1 −1 lib/Cake/ORM/Query.php
  3. +66 −0 lib/Cake/Test/TestCase/ORM/QueryTest.php
@@ -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;
}
@@ -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);
}
@@ -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.
You can’t perform that action at this time.