dqpfl2508589
dqpfl2508589
2017-04-20 06:10

修改php内存排气中的数组值

已采纳

I have a piece of php code as follows:

foreach($collection as $key => $item) {
  $collection[$key]['column'] = 'test';
  $item['column'] = 'test';
}

When the collection array has more than 30,000 rows, I get this error PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 89 bytes) .

If I remove the line $collection[$key]['column'], the forloop can finish successfully.

What I cannot understand is that aren't line 2 and line 3 basically the same? They are both changing the same item in the $collection array.

What am i missing here?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

2条回答

  • duanlou2917 duanlou2917 4年前

    To answer your question , let us first take a quick look at the foreach docs

    On each iteration, the value of the current element is assigned to $value and the internal array pointer is advanced by one (so on the next iteration, you'll be looking at the next element).

    First let's step up your first question and let's take your second question.

    What I cannot understand is that aren't line 2 and line 3 basically the same?

    Actually they are not the same, take those quick examples :

    $array = ['a', 'a', 'a', 'a'];
    
    foreach ($array as $key => $value) {
        $value = 'b';
    }
    
    print_r($array);
    // Output : Array ( [0] => a [1] => a [2] => a [3] => a )
    

    while in the second case :

    $array = ['a', 'a', 'a', 'a'];
    
    foreach ($array as $key => $value) {
        $array[$key] = 'b';
    }
    
    print_r($array);
    // Output : Array ( [0] => b [1] => b [2] => b [3] => b )
    

    so, it's totally clear that in your first case, you had modified some copy value or assigned value so to speak, and did not touched the actual value.

    so we can say that -so to speak- foreach as php functions has it's own context, for example :

    foreach ($array as $key => $value) {
        // $value variable will be only visible here
        // within the foreach context
    }
    echo $value; // will output Undefined variable
    

    They are both changing the same item in the $collection array.

    you can say -or assume- that you've passed a variable to foreach by value, so php -as mentioned in foreach docs- had modified a copy of your array element , not the actual value.

    while in second example, you've modified the real value of the array $array not just a copy of it.

    in my examples context, to modify your array in the place, you will need to pass your variable to foreach by reference to be able to edit your array value directly , for example :

    $array = ['a', 'a', 'a', 'a'];
    
    foreach ($array as $key => &$value) {
    //                         ^
        $value = 'b';
    }
    
    print_r($array);
    // Output : Array ( [0] => b [1] => b [2] => b [3] => b )
    

    let's move to your other question :

    If I remove the line $collection[$key]['column'], the forloop can finish successfully.

    this is happens because as mentioned above , you are passing your variable to foreach by value, so for each iteration over your 30,000 array there are three operations php will perform :-

    1) copy every element of your array to another place in your memory
    2) update this copied element
    3) update your collection array

    which i think takes more memory that your maximum memory limit.

    so, as Christopher mentioned in his comment, and as mentioned in foreach doc page :

    In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.

    passing your value by reference may reduce the memory usage of your script.

    点赞 评论 复制链接分享
  • dru5089 dru5089 4年前

    Try using this :

    ini_set('memory_limit', '-1');
    

    This is not suggested to be done but in you case it is needed. This will override the default PHP memory limit.

    点赞 评论 复制链接分享