Repository navigation
Collection: bug fixes, dot notation, multi-key sorting, 21 new methods, higher-order proxies - #352
Merged
Merged
Conversation
…s, higher-order proxies
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request Checklist
Summary
An audit of
Phaseolies\Support\Collection, with each suspected problem reproduced before changing anything. It found six real bugs (one of which madegroupBy('date')throw), several everyday methods missing, and no way to reach nested values or sort by more than one key. This PR fixes the bugs and fills those gaps. Everything that worked before behaves the same; the exceptions are listed under "Behaviour changes".Bug fixes
buildKeyResolver()testedis_callable($key)on strings, sogroupBy('date'),keyBy('date')andsortBy('date')threwTypeError: date(): Argument #1 ($format) must be of type string, array given(same forcount,time,key,min,max,sort, ...). A string is now always a key; closures and array callables still work.$collection[] = $xandadd()stored the item under the key"".offsetSet()did not handle anulloffset (and raised a "null as array offset" deprecation), so a secondadd()overwrote the first. Anulloffset now appends.first($callback)silently ignored its argument and returned the first item (PHP drops extra arguments to a user method).first()andlast()now accept?callable $callbackand a$default(aClosuredefault is called).merge()andgetType()crashed with "Typed propertyRamsey\Collection\Collection::$collectionTypemust not be accessed before initialization": they are inherited from the Ramsey collection, whose state the Doppar constructor never sets. Both are overridden.merge()accepts collections, arrays and iterators and followsarray_mergerules.unique()treated1.5and1.2as the same value, and raised "Implicit conversion from float to int loses precision", because scalars were used directly as array keys. They are now keyed by their string form.filter()could not be called without a callback. Without one it now removes falsy items (null,false,0,'',[]).New
Reading nested values.
valueFrom($item, 'a.b.c')works on arrays, objects (including models) andArrayAccessvalues; a key that really contains a dot is tried as it is first. It is used bypluck,sortBy,groupBy,keyBy,unique,duplicatesand the new methods below, sopluck('profile.city')andsortBy('profile.city')work.Sorting by several keys.
sortBy(['age', 'name']),sortBy([['age', 'desc'], ['name', 'asc']]), callbacks in the list, a default direction from the existing$descendingargument, and theSORT_*flags (SORT_STRING | SORT_FLAG_CASE,SORT_NATURAL,SORT_NUMERIC). Stable. An array callable such as[$object, 'method']is still treated as a callback.Methods:
reject,every,some,reverse,keys,only,except,firstWhere(1, 2 or 3 arguments, operators= == === != <> !== < > <= >=),whereIn,whereNotIn,whereNull,whereNotNull,countBy,implode,flatMap,collapse,skip,slice,concat,search,median,when,unless. All return aCollectionof the same model, exceptcountBy(an array, likegroupBy),every/some(bool),implode(string),search,medianandfirstWhere.Higher-order access.
HigherOrderCollectionProxyreplaces the two anonymous classes in__get(). Besides the existing$c->map->nameand$c->each->save(), it addsfilter,reject,sum,avg,min,max,sortBy,sortByDesc,groupBy,keyBy,unique,every,someandflatMap:mapandeachkeep their precedence over a data key of the same name. The new names only act when no data key has that name, so existing$collection->filterstyle data access is unaffected.each->method()still skips items that do not have the method.Behaviour changes
staticwhere they wereself(33 methods). The docblocks already said@return static/@return $this, and the methods returnnew staticor$this; the declarations now agree (this also clears the IDE's "documented type is not compatible" hints). Nothing in this repository or the sibling packages extendsCollection; a subclass that overrides one of these methods with: selfwould need: static.unique()(non-strict) compares scalars by string form. Different floats are now different, and0andfalseare no longer treated as the same value ('1',1,trueand1.0still are).unique(null, true)is unchanged.groupBy/keyBy/sortBymust pass a closure (fn($x) => strtolower($x)).first()/last()/filter()gain optional parameters only; existing calls behave as before.HigherOrderCollectionProxyis a new public class;Collection::valueFrom()is a new public method.Files
src/Phaseolies/Support/Collection.phpsrc/Phaseolies/Support/HigherOrderCollectionProxy.php(new)phpstan-baseline.neon(one entry removed)tests/CollectionFeaturesTest.php(new)Checklist