2

We might consider foreach to be painful and a headache while using it to deal with thousands or millions of records. Even more so if we have a nested foreach.

For example,

foreach ($parent as $parentData) {
    // few conditional added here
    $parentObj = $this->extract();
    foreach ($chilren as $childrenData) {
        if ($childrenData['id'] === $parentData['id']) {
            $childrenObj = $this->extract();
            $parentObj->setData($childrenObj);
            // and even more evil things come here....
        }
    }
    $parentObj->save();
}

In my situation, I have two foreach loops. And each one contains approximate 50,000 ~ 70,000 records. $parent and $children are parameters passed to the method.

The raw data source both of $parent and $children are CSV files. And I'm using yield to transform them to be traversable with foreach.

There is no trouble with yield.

If you concern about the code: https://stackoverflow.com/a/37342184/2932590

I tried to unset both of $parentObj and $childrenObj at the end of first foreach, but unfortunately it's not working. I also tried to use the references &$parentData, but the result is same.

How could I make this work?

I was advised to use SPL Iterators in this case. Can anyone please explain me how it works?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Toan Nguyen
  • 911
  • 13
  • 35

3 Answers3

0

To use SPL iterator:

// create a new ArrayIterator and pass in the array
$parentDataIter = new ArrayIterator($parentData);

// loop through the object one item at a time memory-wise
foreach ($parentDataIter as $key => $value) {
    // ...
}
j4hangir
  • 2,532
  • 1
  • 13
  • 14
0

SPL iterators are not a uniform thing but just the collective name for them (Standard PHP Library iterators). The ones available works quite differently but the following stack-overflow thread has already tried to explain their uses and pros/cons quite well. PHP - Reasons to use Iterators?.

Community
  • 1
  • 1
Björn Fyrvall
  • 231
  • 1
  • 7
  • I need to reduce my memory usage. That is why I choose Iterators, and yes I read that question before create this one. – Toan Nguyen Jun 03 '16 at 10:20
0

probably, $parentObj = $this->extract(); doesn't use a reference and $parentObj->setData($childrenObj); makes PHP to create a copy from initial array for each element that is changed.

another approach is to move the pointer in a while loop:

reset($array);
while (list($key, $val) = each($array)) {
    $array[$key] = ++$val;
    echo "$array[$key]\n";
}
altcatalin
  • 11
  • 3
  • based on the information you provided it seems like there is a problem with the way you update an array - [explanation](http://stackoverflow.com/a/14854568/1539119). for a better response, we need a more details about these methods $this->extract(), $parentObj->setData($childrenObj), `code`$parentObj->save()`code` at least in pseudocode – altcatalin Jun 07 '16 at 20:50