Comments (13)
I spent some time digging into the source myself so see if I could isolate the problem, and arrived at this minimal example that reproduces the issues:
<?php
require_once 'inc/prelude.php';
use loophp\iterators\ClosureIteratorAggregate;
use loophp\collection\Iterator\PsrCacheIterator;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use loophp\iterators\FilterIterableAggregate;
$fromDate = '2023-09-15 00:00:00';
$toDate = '2023-09-30 23:59:59';
$query = "SELECT *
FROM communication
WHERE `date` BETWEEN :fromDate AND :toDate";
$statement = $pdo->prepare($query);
$statement->bindValue('fromDate', $fromDate, PDO::PARAM_STR);
$statement->bindValue('toDate', $toDate, PDO::PARAM_STR);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
echo $statement->rowCount();
$cached = new ClosureIteratorAggregate(fn () => yield from new PsrCacheIterator($statement->getIterator(), new ArrayAdapter()), []);
$get = fn () => yield from new FilterIterableAggregate($cached, fn()=>true);
$get()->current();
$get()->current();
foreach ($cached as $i=> $r){
var_dump($i, $r);
}
However, "unwapping" the ClosureIteratorAggregate
seems to solve the issue. This code produces the expected results:
<?php
require_once 'inc/prelude.php';
use loophp\iterators\ClosureIteratorAggregate;
use loophp\collection\Iterator\PsrCacheIterator;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use loophp\iterators\FilterIterableAggregate;
$fromDate = '2023-09-15 00:00:00';
$toDate = '2023-09-30 23:59:59';
$query = "SELECT *
FROM communication
WHERE `date` BETWEEN :fromDate AND :toDate";
$statement = $pdo->prepare($query);
$statement->bindValue('fromDate', $fromDate, PDO::PARAM_STR);
$statement->bindValue('toDate', $toDate, PDO::PARAM_STR);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
echo $statement->rowCount();
$cached = new PsrCacheIterator($statement->getIterator(), new ArrayAdapter());
$get = fn () => yield from new FilterIterableAggregate($cached, fn()=>true);
$get()->current();
$get()->current();
foreach ($cached as $i=> $r){
var_dump($i, $r);
}
Therefore the issue may actually be in the dependency loophp\iterators.
from collection.
Since this issue has not had any activity within the last 5 days, I have marked it as stale.
I will close it if no further activity occurs within the next 5 days.
from collection.
Hello,
I apologize for the delayed response; my schedule has been quite packed lately. Thank you for your patience.
Were you able to find a solution to the issue in the meantime?
from collection.
No worries, it's not a sin to have a life outside of Github. Take the time you need with what is important to you.
I was able to work around the issue by using fetchAll
to convert the iterable to an array before turning it into a Collection
. Not being able to use cache
in unfortunate, but it isn't a show-stopper.
However, I never did manage to identify the root cause of the issue or create an actual fix. I suspect that somewhere along the chain of iteratables there is one that isn't fully abstracting over the previous one in the chain, but I spent several hours looking and couldn't find it.
from collection.
I have to admit that I wish I could reproduce this easily at home, but I don't have any project using Doctrine right now, so I don't know how to do this.
Do you have a way to reproduce this easily with a SQLite based project, for example? So we could share a project and reproduce the issue?
from collection.
I'm actually not using Doctrine either, I'm using PDO.
Sure, here is a complete, self-contained script that reproduces the issue using SQLite:
<?php require_once 'vendor/autoload.php';
use loophp\iterators\ClosureIteratorAggregate;
use loophp\collection\Iterator\PsrCacheIterator;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use loophp\iterators\FilterIterableAggregate;
$pdo = new PDO('sqlite::memory:');
$pdo->query("CREATE TABLE communication(
id INTEGER PRIMARY KEY,
date TEXT,
remarks TEXT
);");
$pdo->query("INSERT INTO communication
(id, date, remarks)
VALUES
(1, '2023-09-17 11:47:11', 'This is the first one'),
(2, '2023-09-18 07:52:19', 'This is the second one'),
(3, '2023-09-19 13:05:17', 'This is the third one');
");
$fromDate = '2023-09-15 00:00:00';
$toDate = '2023-09-30 23:59:59';
$query = "SELECT *
FROM communication
WHERE `date` BETWEEN :fromDate AND :toDate";
$statement = $pdo->prepare($query);
$statement->bindValue('fromDate', $fromDate, PDO::PARAM_STR);
$statement->bindValue('toDate', $toDate, PDO::PARAM_STR);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
$cached = new ClosureIteratorAggregate(fn () => yield from new PsrCacheIterator($statement->getIterator(), new ArrayAdapter()), []);
$get = fn () => yield from new FilterIterableAggregate($cached, fn()=>true);
$get()->current();
$get()->current();
foreach ($cached as $i=> $r){
var_dump($i, $r);
}
Actual output:
int(0)
array(3) {
["id"]=>
int(3)
["date"]=>
string(19) "2023-09-19 13:05:17"
["remarks"]=>
string(21) "This is the third one"
}
Expected output:
int(0)
array(3) {
["id"]=>
int(1)
["date"]=>
string(19) "2023-09-17 11:47:11"
["remarks"]=>
string(21) "This is the first one"
}
int(1)
array(3) {
["id"]=>
int(2)
["date"]=>
string(19) "2023-09-18 07:52:19"
["remarks"]=>
string(22) "This is the second one"
}
int(2)
array(3) {
["id"]=>
int(3)
["date"]=>
string(19) "2023-09-19 13:05:17"
["remarks"]=>
string(21) "This is the third one"
}
from collection.
Thanks for the snippet.
I modified it a bit:
<?php declare(strict_types=1);
namespace Bug;
use loophp\collection\Collection;
use PDO;
require_once __DIR__ . '/vendor/autoload.php';
$pdo = new PDO('sqlite::memory:');
$pdo->query("CREATE TABLE communication(
id INTEGER PRIMARY KEY,
date TEXT,
remarks TEXT
);");
$pdo->query("INSERT INTO communication
(id, date, remarks)
VALUES
(1, '2023-09-17 11:47:11', 'This is the first one'),
(2, '2023-09-18 07:52:19', 'This is the second one'),
(3, '2023-09-19 13:05:17', 'This is the third one');
");
$fromDate = '2023-09-15 00:00:00';
$toDate = '2023-09-30 23:59:59';
$query = "SELECT *
FROM communication
WHERE `date` BETWEEN :fromDate AND :toDate";
$statement = $pdo->prepare($query);
$statement->bindValue('fromDate', $fromDate, PDO::PARAM_STR);
$statement->bindValue('toDate', $toDate, PDO::PARAM_STR);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
$collection = Collection::fromIterable($statement->getIterator());
$collection->current();
$collection->current();
foreach ($collection as $i => $r){
var_dump($i, $r);
}
And the bug seems to be gone.
Is it working on your side?
from collection.
Yes, that code seem to give the expected result. I played around with it a little, and the change that seems to make the difference is using $statement->getIterator()
rather than just $statement
. It's interesting to me, since PDOStatement
implements IteratorAggregate
, so I would generally consider it to be iterable all by itself. Now I'm really curious why that makes a difference.
from collection.
I have the feeling that it is something internal... maybe it would be nice to reproduce the issue without using any libraries and submit it upstream.
from collection.
I'm beginning to wonder the same thing; the bug may be with PDO or PHP itself.
from collection.
I'll do further tests tomorrow. In any case, nice catch :)
from collection.
Since this issue has not had any activity within the last 5 days, I have marked it as stale.
I will close it if no further activity occurs within the next 5 days.
from collection.
@dmjohnsson23 The issue now closed, let me know if you need more assistance or eventually if you find more information about this issue.
Feel free to reopen it in any case.
from collection.
Related Issues (20)
- `Partition` Operation - Awkward to use? HOT 18
- Add find/search/where/single/firstWhere method HOT 23
- Modify `all` operation to prevent data loss HOT 6
- PHPStan 1.0 upgrade HOT 1
- Typed collection support HOT 17
- API oddities HOT 6
- Reduction operations should return a single value HOT 9
- Issue with cache and fromCallable HOT 13
- PHPStan reporting an error for missing optional parameters HOT 6
- [Question] Rename Collection interface to CollectionInterface HOT 1
- Dependency Dashboard HOT 51
- Collection interface doesn't extend Countable HOT 9
- Plus operation RFC HOT 10
- Palm cannot infer types when using some operations HOT 4
- Unexpected behavior of pair operation over empty collection HOT 1
- [Feature request] Implement stable sorting HOT 12
- Memory size exhausted for large collections HOT 15
- Issue with distinct HOT 3
- Distinct is slow HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from collection.