-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #20268: Minor optimisation in \yii\helpers\BaseArrayHelper::map
#20269
Conversation
+ use array_column for faster mapping if no callbacks or grouping are required
+ changelog
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #20269 +/- ##
============================================
- Coverage 64.95% 64.84% -0.11%
- Complexity 11396 11401 +5
============================================
Files 430 430
Lines 36925 37138 +213
============================================
+ Hits 23984 24083 +99
- Misses 12941 13055 +114 ☔ View full report in Codecov by Sentry. |
+ also test with callbacks
I'm afraid this will change behavior for keys with dots, for example |
@@ -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) { |
There was a problem hiding this comment.
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');
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
! don't use array_column if ArrayHelper strings are paths + add according tests + add BaseStringHelper::contains() helper function and according tests
I also added a |
o code style fixes
I'm not sure if it is worth to polyfill function, that exists in PHP since 4 years. This method is already redundant for ~70% of framework users. |
if that number is true, that'd mean not including the polyfill would be a breaking change for 30% of users. Yii2's minimum supported php version is still 7.3 as far as I'm aware & I don't want to introduce breaking changes for a minor optimisation. Whether yii2 should bother supporting PHP versions that are EOL is a separate question that is up to the maintainers to answer. |
In what scenario not adding new function would be a BC break? 70% of framework installations is for PHP8 - in that case developer could use |
so in other words, you'd rather have it as a construct like if (function_exists('str_contains') ? str_contains([...]) : (mb_strpos([...]) !== -1)) ? I originally considered doing that, but figured it'd make the condition for the optimisation ugly to read. EDIT: or am I mistunderstanding and what you're saying is "this optimisation is not worth adding a new function, so you'd rather not add it"? I'd get that, but also don't think there's harm in adding it |
My suggestion is:
If we really want some kind |
! use strpos rather than polyfill - remove BaseStringHelper::contains
alright, done :) |
\yii\helpers\BaseArrayHelper::map
Thank you! |
Information re: what this does is in the issue.
In the process, I also improved the ArrayHelper::map() tests a bit to also test cases where callbacks are passed in for the three parameters.