Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions framework/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Yii Framework 2 Change Log
- Enh #20247: Support for variadic console controller action methods (brandonkelly)
- Bug #20256: Add support for dropping views in MSSQL server when running migrate/fresh (ambrozt)
- Enh #20248: Add support for attaching behaviors in configurations with Closure (timkelty)
- Enh #20268: Minor optimisation in `\yii\helpers\BaseArrayHelper::map` (chriscpty)

2.0.51 July 18, 2024
--------------------
Expand Down
3 changes: 3 additions & 0 deletions framework/helpers/BaseArrayHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,9 @@ public static function getColumn($array, $name, $keepKeys = true)
*/
public static function map($array, $from, $to, $group = null)
{
if (is_string($from) && is_string($to) && $group === null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also add a check that both $from and $to don't contain a dot (.).
The ArrayHelper::getValue() function supports getting a value by a "path" string.
Without this check the following code would break:

$array = [
    [
        'prop' => [
            'a' => 'foo',
            'b' => 'bar',
        ],
    ],
];

ArrayHelper::map($array, 'prop.a', 'prop.b');

Copy link
Member

@samdark samdark Oct 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It is necessary. @chriscpty would you please redo performance test with such a check?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

performance with the added check:

before: 1729233314.6667
after: 1729233315.4382
elapsed: 0.77146291732788
before: 1729233315.4382
after: 1729233316.245
elapsed: 0.80677795410156
before: 1729233316.245
after: 1729233317.0443
elapsed: 0.79932498931885
before: 1729233317.0443
after: 1729233317.8304
elapsed: 0.78613996505737
before: 1729233317.8305
after: 1729233318.6256
elapsed: 0.79515385627747
bench size: 18000

I'll add the fix (and related tests) in a second

return array_column($array, $to, $from);
}
$result = [];
foreach ($array as $element) {
$key = static::getValue($element, $from);
Expand Down
40 changes: 39 additions & 1 deletion tests/framework/helpers/ArrayHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,44 @@ public function testMap()
'345' => 'ccc',
],
], $result);

$result = ArrayHelper::map($array,
static function (array $group) {
return $group['id'] . $group['name'];
},
static function (array $group) {
return $group['name'] . $group['class'];
}
);

$this->assertEquals([
'123aaa' => 'aaax',
'124bbb' => 'bbbx',
'345ccc' => 'cccy',
], $result);

$result = ArrayHelper::map($array,
static function (array $group) {
return $group['id'] . $group['name'];
},
static function (array $group) {
return $group['name'] . $group['class'];
},
static function (array $group) {
return $group['class'] . '-' . $group['class'];
}
);

$this->assertEquals([
'x-x' => [
'123aaa' => 'aaax',
'124bbb' => 'bbbx',
],
'y-y' => [
'345ccc' => 'cccy',
],
], $result);

}

public function testKeyExists()
Expand All @@ -759,7 +797,7 @@ public function testKeyExistsWithFloat()
if (version_compare(PHP_VERSION, '8.1.0', '>=')) {
$this->markTestSkipped('Using floats as array key is deprecated.');
}

$array = [
1 => 3,
2.2 => 4, // Note: Floats are cast to ints, which means that the fractional part will be truncated.
Expand Down
Loading