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_split
will 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
foreach
ing over aITraversable
or callingITraversable::asArray
, all non scalar keys will be mapped to integers to maintain compatability. - Added
ITraversable::iterate
method to iterate all values and unaltered keys over the supplied function. - Added
ITraversable::keys
to select the keys as the values - Added
ITraversable::reindex
to index the values by their 0-based position. - Added
ITraversable::getTrueIterator
to 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
,IRepository
should all return their respective types for each query method.- Because of this, the
Traversable
andCollection
classes are now extendable, custom methods can be added and everything should work smoothly. - Removed
ITraversable::asQueryable
,ITraversable::asRepository
.
- Because of this, the
Implemented new
ITraversable
source semantics:- A source
ITraversable
is 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 sourceITraversable
or itself if it is the source. - Removed unnecessary caching in
Traversable
queries.Traversable
can be used with nondeterministic/mutable sources and query parameters.Traversable
classes can no longer be serialized when queried with closures.- Because of this combined with covariant return types,
ICollection
/IRepository
has 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
/groupJoin
APIIJoiningOnTraversable::onEquality
will not matchnull
s 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::groupBy
implicitly 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
IGroupedTraversable
and henceIGroupedTraversable::andBy
:ITraversable::groupBy
implicitly indexes each group by the group key.- You cannot use multiple grouping functions any more, instead use
ITraversable::groupBy
with 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::exists
in favour ofITraversable::isEmpty
. Traversable
/Collection
are now extendable.- Fixed issue with
ITraversable::union
not reindexing keys. - Fixed issue with
Iterators\Common\Set
not detecting null values.
- Removed
Improvements to internals
- Refactored iterator structure:
- Abstracted iterator implementations under
Iterators\IIteratorScheme
.Traversable
andCollection
now 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
Queries
namespace)- New builder API (under
Builders
) to build query objects from expression trees.Queryable
/Repository
now 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
IParameterRegistry
instance. - New common
ISource
interface for a another sequence inside a query:->intersect(...)
,->join(...)
Removed
FunctionExpressionTree
in favour of dedicated function types (underQueries\Functions
namespace) 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
ISourceInfo
to store source information of aIQueryable
.Renamed
Segments\Operation::getTraversable
togetValues
Refactored
Join
query segments / operations.Removed redundant
...Expression
from 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\PHPParser
toParsing\PhpParser
.
Implemented necessary interfaces for fluent query building under
Interfaces
namespace.IOrdered*
,IJoiningOn*
,IJoiningTo*
with respective covariant return types.
Refactored caching implementation:
Caching\Provider
renamed toCaching\CacheProvider
Caching\IQueryCache
now acts as a wrapper toCaching\ICacheAdapter
.- Any type of value can be cached and retrieved through the cache adapter.
- Implemented namespacing API.