Skip to content

Commit

Permalink
Fixing select strategy for BelongsTo when the source table has composite
Browse files Browse the repository at this point in the history
primary key
  • Loading branch information
lorenzo committed Apr 1, 2014
1 parent e6f3e8e commit 63410a8
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 7 deletions.
38 changes: 38 additions & 0 deletions src/ORM/Association/SelectableAssociationTrait.php
Expand Up @@ -81,10 +81,15 @@ protected function _buildQuery($options) {
$key = $this->_linkField($options);

$filter = $options['keys'];

if ($options['strategy'] === $this::STRATEGY_SUBQUERY) {
$filter = $this->_buildSubquery($options['query']);
}

if (is_array($filter) && count(current($filter)) > 1) {
$filter = $this->_extractFilteringColumns($filter);
}

$fetchQuery = $this
->find('all')
->where($options['conditions'])
Expand Down Expand Up @@ -117,6 +122,39 @@ protected function _buildQuery($options) {
return $fetchQuery;
}

/**
* Returns an array containing only the values from the foreignKey for the
* target table that can be used for a matching query. The values are
* taken from another array containing all the primary key columns and
* theirs values from another query.
*
* @param array $keys the primary key values extracted from a source query
* @return array
*/
protected function _extractFilteringColumns($keys) {
$primary = (array)$this->source()->primaryKey();
$foreignKeys = (array)$this->foreignKey();

if (count($primary) === count($foreignKeys)) {
return $keys;
}

$positions = array_keys(array_intersect($primary, $foreignKeys));
$single = count($foreignKeys) === 1;
return array_map(function($keys) use ($positions, $single) {
if ($single) {
return $keys[$positions[0]];
}

$result = [];
foreach ($positions as $p) {
$result[] = $keys[$p];
}

return $result;
}, $keys);
}

/**
* Appends any conditions required to load the relevant set of records in the
* target table query given a filter key and some filtering values.
Expand Down
17 changes: 10 additions & 7 deletions tests/TestCase/ORM/QueryTest.php
Expand Up @@ -1148,12 +1148,13 @@ public function testHydrateBelongsToMany() {
/**
* Tests that belongsTo relations are correctly hydrated
*
* @dataProvider internalStategiesProvider
* @return void
*/
public function testHydrateBelongsTo() {
public function testHydrateBelongsTo($strategy) {
$table = TableRegistry::get('articles');
TableRegistry::get('authors');
$table->belongsTo('authors');
$table->belongsTo('authors', ['strategy' => $strategy]);

$query = new Query($this->connection, $table);
$results = $query->select()
Expand All @@ -1171,16 +1172,17 @@ public function testHydrateBelongsTo() {
/**
* Tests that deeply nested associations are also hydrated correctly
*
* @dataProvider internalStategiesProvider
* @return void
*/
public function testHydrateDeep() {
public function testHydrateDeep($strategy) {
$table = TableRegistry::get('authors');
$article = TableRegistry::get('articles');
$table->hasMany('articles', [
'propertyName' => 'articles',
'sort' => ['articles.id' => 'asc']
]);
$article->belongsTo('authors');
$article->belongsTo('authors', ['strategy' => $strategy]);
$query = new Query($this->connection, $table);

$results = $query->select()
Expand Down Expand Up @@ -1900,12 +1902,13 @@ public function testColumnsFromJoin() {
* Tests that it is possible to use the same association aliases in the association
* chain for contain
*
* @dataProvider internalStategiesProvider
* @return void
*/
public function testRepeatedAssociationAliases() {
public function testRepeatedAssociationAliases($strategy) {
$table = TableRegistry::get('ArticlesTags');
$table->belongsTo('Articles');
$table->belongsTo('Tags');
$table->belongsTo('Articles', ['strategy' => $strategy]);
$table->belongsTo('Tags', ['strategy' => $strategy]);
TableRegistry::get('Tags')->belongsToMany('Articles');
$results = $table->find()->contain(['Articles', 'Tags.Articles'])->hydrate(false)->toArray();
$this->assertNotEmpty($results[0]['tag']['articles']);
Expand Down

0 comments on commit 63410a8

Please sign in to comment.