Skip to content

Commit

Permalink
Merge pull request cakephp#17873 from cakephp/5.1-associations-preser…
Browse files Browse the repository at this point in the history
…ve-keys

Allow preserving keys when using select loaders.
  • Loading branch information
markstory authored Aug 31, 2024
2 parents 9c2f478 + 514b828 commit 1d87350
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 4 deletions.
15 changes: 12 additions & 3 deletions src/ORM/Association/Loader/SelectLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -485,16 +485,25 @@ protected function _buildResultMap(SelectQuery $fetchQuery, array $options): arr
$this->bindingKey;
$key = (array)$keys;

foreach ($fetchQuery->all() as $result) {
$preserveKeys = $fetchQuery->getOptions()['preserveKeys'] ?? false;

foreach ($fetchQuery->all() as $i => $result) {
$values = [];
foreach ($key as $k) {
$values[] = $result[$k];
}

if ($singleResult) {
$resultMap[implode(';', $values)] = $result;
} else {
$resultMap[implode(';', $values)][] = $result;
continue;
}

if ($preserveKeys) {
$resultMap[implode(';', $values)][$i] = $result;
continue;
}

$resultMap[implode(';', $values)][] = $result;
}

return $resultMap;
Expand Down
9 changes: 8 additions & 1 deletion src/ORM/Association/Loader/SelectWithPivotLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ protected function _buildResultMap(SelectQuery $fetchQuery, array $options): arr
{
$resultMap = [];
$key = (array)$options['foreignKey'];
$preserveKeys = $fetchQuery->getOptions()['preserveKeys'] ?? false;

foreach ($fetchQuery->all() as $result) {
foreach ($fetchQuery->all() as $i => $result) {
if (!isset($result[$this->junctionProperty])) {
throw new DatabaseException(sprintf(
'`%s` is missing from the belongsToMany results. Results cannot be created.',
Expand All @@ -191,6 +192,12 @@ protected function _buildResultMap(SelectQuery $fetchQuery, array $options): arr
foreach ($key as $k) {
$values[] = $result[$this->junctionProperty][$k];
}

if ($preserveKeys) {
$resultMap[implode(';', $values)][$i] = $result;
continue;
}

$resultMap[implode(';', $values)][] = $result;
}

Expand Down
33 changes: 33 additions & 0 deletions tests/TestCase/ORM/Query/SelectQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
use ReflectionProperty;
use TestApp\Model\Table\ArticlesTable;
use TestApp\Model\Table\AuthorsTable;
use TestApp\Model\Table\TagsTable;

/**
* Tests SelectQuery class
Expand Down Expand Up @@ -1432,6 +1433,24 @@ public function testFormatResultsBelongsToMany(): void
$this->assertInstanceOf(DateTime::class, $first->tags[0]->created);
}

public function testBelongsToManyWithPreservedKeys(): void
{
$table = $this->getTableLocator()->get('Articles');
$this->getTableLocator()->get('Tags', ['className' => TagsTable::class]);
$table->belongsToMany('Tags');

$first = $table->find()
->where(['Articles.id' => 1])
->contain([
'Tags' => ['finder' => 'slugged'],
])
->first();

$this->assertArrayHasKey('tag1', $first->tags);
$this->assertArrayHasKey('tag2', $first->tags);
$this->assertSame('tag1', $first->tags['tag1']->name);
}

/**
* Tests that belongsTo relations are correctly hydrated
*/
Expand Down Expand Up @@ -3028,6 +3047,18 @@ public function testContainFinderHasMany(): void
],
]);

$resultWithSlugIndexedArticles = $table->find('all')
->where(['id' => 1])
->contain([
'Articles' => [
'finder' => [
'slugged' => [
'preserveKeys' => true,
],
],
],
]);

$this->assertCount(2, $resultWithArticles->first()->articles);
$this->assertCount(2, $resultWithArticlesArray->first()->articles);

Expand All @@ -3038,6 +3069,8 @@ public function testContainFinderHasMany(): void
);

$this->assertCount(0, $resultWithoutArticles->first()->articles);

$this->assertSame('First-Article', key($resultWithSlugIndexedArticles->first()->articles));
}

/**
Expand Down
10 changes: 10 additions & 0 deletions tests/test_app/TestApp/Model/Table/ArticlesTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use Cake\ORM\Query\SelectQuery;
use Cake\ORM\Table;
use Cake\Utility\Text;

/**
* Article table class
Expand Down Expand Up @@ -69,6 +70,15 @@ public function findTitled(SelectQuery $query, array $options): SelectQuery
return $query;
}

public function findSlugged(SelectQuery $query): SelectQuery
{
return $query->formatResults(function ($results) {
return $results->indexBy(function ($row) {
return Text::slug($row['title']);
});
});
}

/**
* Example public method
*/
Expand Down
12 changes: 12 additions & 0 deletions tests/test_app/TestApp/Model/Table/TagsTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
*/
namespace TestApp\Model\Table;

use Cake\ORM\Query\SelectQuery;
use Cake\ORM\Table;
use Cake\Utility\Text;

/**
* Tag table class
Expand All @@ -27,4 +29,14 @@ public function initialize(array $config): void
$this->belongsToMany('Articles');
$this->hasMany('ArticlesTags', ['propertyName' => 'extraInfo']);
}

public function findSlugged(SelectQuery $query): SelectQuery
{
return $query->applyOptions(['preserveKeys' => true])
->formatResults(function ($results) {
return $results->indexBy(function ($record) {
return Text::slug($record->name);
});
});
}
}

0 comments on commit 1d87350

Please sign in to comment.