PINQ V3.0.0
A lot of work has gone into improving PINQ for V3.0.0. Both the external API and internal implementation has been much improved. See below for the list of changes from the previous version. To view the full list of changes click here.
Improvements to the API
Query methods that take user supplied functions as parameters, now pass each element's associated key as the second parameter:
-
$strings->select(function ($string, $key) { return $key . $string; }); - We have still maintained compatibility with single parameter internal functions like
strlen. - Functions that take two parameters like
str_splitwill behave differently as previously the second parameter would have been omitted. To fix this simply wrap functions like these in a closure as such://This will no longer work as expected $strings->selectMany('str_split'); //Use this instead $strings->selectMany(function ($string) { return str_split($string); });
-
Proper support for non scalar keys:
- When using
ITraversable::indexBy, you can now return any type of value and this will be handled correctly. Note that duplicate indexes will be associated with the first value for that index. - When
foreaching over aITraversableor callingITraversable::asArray, all non scalar keys will be mapped to integers to maintain compatability. - Added
ITraversable::iteratemethod to iterate all values and unaltered keys over the supplied function. - Added
ITraversable::keysto select the keys as the values - Added
ITraversable::reindexto index the values by their 0-based position. - Added
ITraversable::getTrueIteratorto get the iterator for all values and unaltered keys. This should not beforeach'ed in <= PHP 5.5.0
- When using
Updated interfaces annotations with covariant return types.
ITraversable,ICollection,IQueryable,IRepositoryshould all return their respective types for each query method.- Because of this, the
TraversableandCollectionclasses are now extendable, custom methods can be added and everything should work smoothly. - Removed
ITraversable::asQueryable,ITraversable::asRepository.
- Because of this, the
Implemented new
ITraversablesource semantics:- A source
ITraversableis the instance containing the original underlying elements. - Added
ITraversable::isSource, returns whether the instance is the sourceITraversable:$elements = Traversable::from(range(1, 100)); $elements->isSource(); //true $someElements = $elements->where(function ($i) { return $i > 50; }); $someElements->isSource(); //false - Added
ITraversable::getSource, returns the sourceITraversableor itself if it is the source. - Removed unnecessary caching in
Traversablequeries.Traversablecan be used with nondeterministic/mutable sources and query parameters.Traversableclasses can no longer be serialized when queried with closures.- Because of this combined with covariant return types,
ICollection/IRepositoryhas a new and improved mutable query API:$collection = Collection::from(range(1, 10)); $collection ->where(function ($i) { return $i >= 5; }) ->apply(function (&$i) { $i *= 10; }); $collection->asArray();//[1, 2, 3, 4, 50, 60, 70, 80, 90, 100] ... $collection = Collection::from(range(1, 10)); $collection ->where(function ($i) { return $i <= 5; }) ->clear();//[6, 7, 8, 9, 10]
- A source
Improved
join/groupJoinAPIIJoiningOnTraversable::onEqualitywill not matchnulls as equal like C#.- New
->join/groupJoin(...)->apply(...)query operation forICollection/IRepository - Implemented optional default value for
ITraversable::join/ITraversable::groupJoin:Traversable::from(range(1, 6)) ->join(range(1, 20)) ->on(function ($outer, $inner) { return $outer % 2 === 0 && $outer * 2 === $inner; }) ->withDefault('<Odd>') ->to(function ($outer, $inner) { return $outer . ':' . $inner; }); //Will produce: ['1:<Odd>', '2:4', '3:<Odd>', '4:8', '5:<Odd>', '6:12']
ITraversable::groupByimplicitly indexes each group by the group key value returned from the supplied function:-
$strings ->groupBy(function ($i) { return strlen($i); }) ->select(function (ITraversable $strings, $length) { return $length . ':' . $strings->implode(','); });
-
Removed
IGroupedTraversableand henceIGroupedTraversable::andBy:ITraversable::groupByimplicitly indexes each group by the group key.- You cannot use multiple grouping functions any more, instead use
ITraversable::groupBywith an array instead://No longer supported $strings->groupBy('strlen')->andBy(function ($i) { return $i[0]; }); //Instead use the following $strings->groupBy(function ($i) { return [strlen($i), $i[0]]; });
Implemented static analysis for expression trees with
Misc changes
- Removed
ITraversable::existsin favour ofITraversable::isEmpty. Traversable/Collectionare now extendable.- Fixed issue with
ITraversable::unionnot reindexing keys. - Fixed issue with
Iterators\Common\Setnot detecting null values.
- Removed
Improvements to internals
- Refactored iterator structure:
- Abstracted iterator implementations under
Iterators\IIteratorScheme.TraversableandCollectionnow use this abstraction as factory for the required iterators rather than hard coded classes. - Now supports generators for automatic performance improvement and reduced memory usage for >= PHP 5.5.0
- Will fall back to iterators for <= PHP 5.5.0
- Native iterators have also been improved with regards to performance.
- Abstracted iterator implementations under
Improved query representations (under
Queriesnamespace)- New builder API (under
Builders) to build query objects from expression trees.Queryable/Repositorynow only construct the query expression tree. These classes parse the expression tree into the equivalent query structure. - Query parameters are now externalized from the query object. Under a
IParameterRegistryinstance. - New common
ISourceinterface for a another sequence inside a query:->intersect(...),->join(...) Removed
FunctionExpressionTreein favour of dedicated function types (underQueries\Functionsnamespace) for all types of functions in a query:ElementProjection:->select(function ($value, $key) { return ... })ElementMutator:->apply(function (&$value, $key) { ... })ConnectorProjection:->join(...)->to(function ($outerValue, $innerValue, $outerKey, $innerKey) { return ... })ConnectorMutator:->join(...)->apply(function (&$outerValue, $innerValue, $outerKey, $innerKey) { ... })Aggregator:->aggregate(function ($aggregate, $value) { return ... })
New
ISourceInfoto store source information of aIQueryable.Renamed
Segments\Operation::getTraversabletogetValuesRefactored
Joinquery segments / operations.Removed redundant
...Expressionfrom getter methods on expressions.New expression classes
- New builder API (under
Restructured and improved function parsing
- Upgraded to nikic/php-parser v1.0.0 with compatibility with PHP 5.6 language features
- New function reflection API
- Correctly handle resolving magic constants (
__DIR__...) and scopes (self::...). - Largely improved signature matching using all reflection data to resolve to the correct function. Functions now have to be defined on the same line with identical signatures to cause an ambiguity.
- Fixed fully qualified namespace detection in AST parsing.
- Updated namespace:
Parsing\PHPParsertoParsing\PhpParser.
Implemented necessary interfaces for fluent query building under
Interfacesnamespace.IOrdered*,IJoiningOn*,IJoiningTo*with respective covariant return types.
Refactored caching implementation:
Caching\Providerrenamed toCaching\CacheProviderCaching\IQueryCachenow acts as a wrapper toCaching\ICacheAdapter.- Any type of value can be cached and retrieved through the cache adapter.
- Implemented namespacing API.