dqpfl2508589 2017-04-20 06:10
浏览 47
已采纳

修改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 2017-04-20 07:34
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler
  • ¥15 oracle集群安装出bug
  • ¥15 关于#python#的问题:自动化测试
  • ¥20 问题请教!vue项目关于Nginx配置nonce安全策略的问题