https://github.com/kofan/deferred-collection
PHP collections with deferred operations
https://github.com/kofan/deferred-collection
deferred php php-collection
Last synced: 5 months ago
JSON representation
PHP collections with deferred operations
- Host: GitHub
- URL: https://github.com/kofan/deferred-collection
- Owner: kofan
- License: mit
- Created: 2017-06-27T03:53:42.000Z (almost 9 years ago)
- Default Branch: master
- Last Pushed: 2017-07-13T05:14:36.000Z (almost 9 years ago)
- Last Synced: 2025-07-20T23:27:33.989Z (11 months ago)
- Topics: deferred, php, php-collection
- Language: PHP
- Homepage:
- Size: 69.3 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# Deferred Collection - PHP collections with deferred data processing
[](https://php.net/)
[](https://packagist.org/packages/kofan/deferred-collection)
[](https://travis-ci.org/kofan/deferred-collection)
[](https://coveralls.io/github/kofan/deferred-collection?branch=master)
[](https://styleci.io/repos/95515563)
[](https://opensource.org/licenses/MIT)
[](https://packagist.org/packages/kofan/deferred-collection)
## Introduction and motivation
The main purpose of this library is to defer execution of different operations on collection items until your application really needs it.
It turns out that very often the reason of application poor performance is an execution of unneeded operations on the collection of items.
Moreover, performing heavy operations on the whole collection at once is usually very inefficient and takes too much memory.
So, for example, let's take a look at the code
```php
query($query, MYSQLI_USE_RESULT)
$models = [];
// ... Dummy code ...
while ($record = $result->fetch_assoc()) {
if ($record['department'] === 'developers') {
$models[] = new MyModel($record);
}
}
// ...
if (somethingWrongHappened()) {
throw new RuntimeException('Error happened!!!');
}
// ...
// ... Somewhere in the view ... //
foreach ($models as $model) {
echo "
{$model->id} - {$model->name}";
if (isEnough()) {
break;
}
}
```
So there are several problems with this code there.
1. First of all, it tries to read all the models to the process memory at once. So if there are 1000 records found then it will try to read all 1000 into the process memory.
2. Second of all, it could be that this query is not needed at all if `somethingWrongHappened()` because in that case, an error is going to be thrown. So in this situation, the database query and its results are the waste of resources.
3. And, of course, during the data rendering it might happen that we won't need to iterate through all queries at all, even though we have fetched them from the database.
Thus, Deferred Collections are aiming to solve this problem.
All the operations are actually going to be performed only when the collection is started being iterated through.
For example:
```php
query($query, MYSQLI_USE_RESULT)
while ($record = $result->fetch_assoc()) {
yield $record;
}
});
// The collection is not going to be executed yet
$collection
->matchProperty('department', 'developers')
->instantiate(MyModel::class)
// ...
if (somethingWrongHappened()) {
throw new RuntimeException('Error happened!!!');
}
// ...
// NOW the collection is going to be executed, but only 1 record per time will be processed
// we are not collecting all the records in a single array as it was done before,
// instead of that, Deferred Collection uses generators for all the data manipulations behind the scenes
foreach ($collection as $model) {
echo "
{$model->id} - {$model->name}";
if (isEnough()) {
break;
}
}
```