cocur / chain Goto Github PK
View Code? Open in Web Editor NEWChain provides you with a consistent and chainable way to work with arrays in PHP.
License: MIT License
Chain provides you with a consistent and chainable way to work with arrays in PHP.
License: MIT License
This would also be a great addition:
http://php.net/manual/fr/function.natcasesort.php
I'm not sure what's best:
Also you may also consider other case insensitive operations like a CI unique and intersect.
Fill is actually a Trait.
https://github.com/cocur/chain/blob/master/src/Link/Fill.php
This is the only Trait that don't operate on an instance and also the only one that is static.
Other Traits are all instance methods, this one is a factory.
This code should be moved to the Chain class which host other factory methods create
and createFormString
. This would be an entirely transparent change, it would make the code more consistent and would prevent statistical analysis failing:
map()
s callable receives two arguments, the value and its index. This makes using standard library functions like trim
and intval
problematic without wrapping them in an anonymous or arrow function (because those functions have a second argument that alters behaviour).
It would be useful to have an alternative map()
that does not supply the index. Without breaking the API this would need to be something like mapValue()
, whereas it might have been preferable to have map()
and mapWithIndex()
.
In part, the lack of documentation for each of Chain
's methods, in regards to the Callable's parameters, doesn't help, without digging into the source.
I have a scenario where i need to merge multiple domain value objects and it would be handy if one could just do:
Chain::merge($object->getOutsidePhotos(), $object->getInsidePhotos())
->map(fn (Photo $photo) => $photo->getUrl())
->map(fn (string $url) => $this....);
compared to:
Chain::create(array_merge($object->getOutsidePhotos(), $object->getInsidePhotos()))
->map(fn (Photo $photo) => $photo->getUrl())
->map(fn (string $url) => $this....);
Also different function of merge can be implemented, for example according to Optimizing array merge operation you will get better speed if you do not use the array_merge function in large arrays, because of some conditions php check internally.
What do you think?
It will be useful if Chain will implement JsonSerializable interface to use Chain values in json_encode.
Drop support for PHP < 7.1.
https://www.php.net/supported-versions.php
This will make possible to add strong typing and return types everywhere.
It would be good if generics are added, for better static analysis. For example, the find method should return T|false
.
Reference: https://phpstan.org/blog/generics-in-php-using-phpdocs
It would be great if a join or implode method could be added. The Link would work like implode($glue, $array)
.
$array = [1, 2, 3];
Chain::create($array)->join('&'); // "1&2&3"
When you filter an array, it may become 'sparse'. PHP deals with this situation by turning it to an associative array:
https://eval.in/916518
<?php
$a1 = ['a', 'z', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'q', 's', 'd'];
$a2 = ['a', 'z', 'e', 'r', 't', 'y', 'u', 'i', 'o'];
echo json_encode(array_filter($a1, function($i){ return $i != 's'; }));
echo json_encode(array_filter($a2, function($i){ return $i != 's'; }));
{"0":"a","1":"z","2":"e","3":"r","4":"t","5":"y","6":"u","7":"i","8":"o","9":"p","10":"q","12":"d"}
["a","z","e","r","t","y","u","i","o"]
This is really disturbing and unintuitive, no other language (AFAIK) do that. I know PHP always had this permanent confusion between lists and maps, but this doesn't feel right: if I filter a list I should get a filtered list in return.
Would you consider adding a boolean argument forceList
or adding a filterList
method who always return array_values
in the internal state ?
A flatMap method would be really handy.
I made a matrix comparing JS array API, PHP anc Chain.
I've matched the methods when possible.
I haven't dig into JS objects API, nor lodash or reactivex yet.
JS | PHP | Chain | comments | |
---|---|---|---|---|
✔️ | length | count | count | |
copyWithin | ||||
✔️ | fill | array_fill | fill | |
array_fill_keys | ||||
✔️ | array_flip | flip | ||
✔️ | pop | array_pop | pop | |
✔️ | push | array_push | push | |
✔️ | reverse | array_reverse | reverse | |
✔️ | shift | array_shift | shift | |
✔️ | splice | array_splice | splice | |
✔️ | unshift | array_unshift | unshift | |
✔️ | concat | array_merge | merge | |
✔️ | array_merge_recursive | merge (with option recursive = true) | ||
✔️ | includes | in_array | implemented | |
✔️ | indexOf | array_search | search | |
lastIndexOf | ||||
✔️ | join | implode | join | |
✔️ | slice | array_slice | slice | |
entries | ||||
✔️ | every | implemented | ||
✔️ | filter | array_filter | filter | |
✔️ | find | find | ||
findIndex | ||||
❕ | forEach | array_walk | TODO: implement, what would be a good name? walk, or tap (used in reactivex, also used in lodash but with different semantic) or peek (used in java streams API) | |
❕ | array_walk_recursive | TODO: implement as an option | ||
✔️ | keys | array_keys | keys | |
❕ | flat | TODO: implement | ||
✔️ | flatMap | flatMap | ||
✔️ | map | map | ||
❌ | array_map | PHP implementation is… let's just say it's weird. Better not reuse that. | ||
✔️ | reduce | array_reduce | reduce | |
❕ | reduceRight | TODO: implement, as an option of reduce maybe ? | ||
✔️ | some | implemented | ||
❕ | range | TODO: implement | ||
✔️ | values | array_values | values | |
✔️ | array_combine | combine | ||
✔️ | array_key_exists | keyExists | ||
✔️ | array_pad | pad | ||
✔️ | array_product | product | ||
✔️ | array_rand | rand | ||
✔️ | array_sum | sum | ||
✔️ | shuffle | shuffle | ||
✔️ | array_unique | unique | ||
✔️ | reset | first | ||
✔️ | end | last | ||
❕ | array_key_first | TODO: implement for orthogonality, we already have the methods for the values | ||
❕ | array_key_last | TODO: implement for orthogonality, we already have the methods for the values | ||
✔️ | array_replace | replace | ||
❔ | array_replace_recursive | should replace have a recursive option, like merge ? | ||
✔️ | array_change_key_case | changeKeyCase | ||
❕ | array_chunk | TODO: implement | ||
❕ | array_column | TODO: implement, I think pluck (used in underscore, lodash, data tables, …) would be a better name | ||
✔️ | array_count_values | countValues | ||
✔️ | uasort | sort (with callable parameter and option assoc = true) | ||
✔️ | sort | usort | sort (with callable parameter) | |
✔️ | arsort | sort (with option assoc = true and reverse = true) | ||
✔️ | asort | sort (with option assoc = true) | ||
✔️ | rsort | sort (with option reverse = true) | ||
✔️ | sort | sort | sort | |
✔️ | uksort | sortKeys (with callable parameter) | ||
✔️ | krsort | sortKeys (with option reverse = true) | ||
✔️ | ksort | sortKeys | ||
✔️ | array_diff | diff | ||
❔ | array_diff_assoc | shouldn't diff have a bunch of options like sort ? | ||
❔ | array_diff_key | shouldn't diff have a bunch of options like sort ? | ||
❔ | array_diff_uassoc | shouldn't diff have a bunch of options like sort ? | ||
❔ | array_diff_ukey | shouldn't diff have a bunch of options like sort ? | ||
❔ | array_udiff | shouldn't diff have a bunch of options like sort ? | ||
❔ | array_udiff_assoc | shouldn't diff have a bunch of options like sort ? | ||
❔ | array_udiff_uassoc | shouldn't diff have a bunch of options like sort ? | ||
✔️ | array_intersect | intersect | ||
array_intersect_assoc | intersectAssoc | shouldn't intersect have a bunch of options like sort ? Should this be deprecated in favor of intersect with option assoc = true for consistency ? | ||
❔ | array_intersect_uassoc | shouldn't intersect have a bunch of options like sort ? | ||
✔️ | array_intersect_key | intersectKey | ||
❔ | array_intersect_ukey | shouldn't intersectKey have a bunch of options like sort ? | ||
❔ | array_uintersect | shouldn't that be in one of the existing intersect operators ? | ||
❔ | array_uintersect_assoc | shouldn't that be in one of the existing intersect operators ? | ||
❔ | array_uintersect_uassoc | shouldn't that be in one of the existing intersect operators ? | ||
natsort | ||||
natcasesort | ||||
array_multisort | ||||
❌ | compact | do not really see use case seems like a legacy method, prefer merge, unshift or push |
What I think needs to be implemented:
includes
(in_array
)every
flat
some
range
chunk
pluck
firstKey
lastKey
walk
/ tap
/ peek
, not sure about the nameI also noticed that diff and intersect needs some work, some modes aren't supported. Also it would be nice to keep consistency with what has been done in sort.
What's your opinion about that ?
Tooling is out of date and cause tests to fail:
If you want I can take some time to provide a PR.
PHP 8.1 requires the offsetGet function to be compatible with the ArrayAccess declaration, i.e. to have a mixed return type. Without this, the Chain library produces deprecation notices like this:
PHP Deprecated: Return type of Cocur\Chain\AbstractChain::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in .../vendor/cocur/chain/src/AbstractChain.php on line 46
Mixed type is only available in PHP 8, Chain supports 7.2, so the only way to meet the new requirements is to add the #[\ReturnTypeWillChange]
attribute.
Please add a find method.
The Values
Trait is never imported in Chain
, trying to use it will spawn a Fatal error: undefined method.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.