dsy6639 2017-10-18 15:17
浏览 92
已采纳

查询foreach内部是否可以?

I searched a lot in the Stack/Google and didn't find a proper answer to my question, so here I go:

I know that using some calculations and stuff in for is utterly bad practice like:

for ($i = 0; $i < count($items); $i++) 

Recently I saw a strange practice in the code that I'm working:

foreach (SomeModel::find() as $item)

It's ok to put the find directly in the foreach, like a count($items) or sort of? I don't like the idea, so instinctively I avoid that putting in some var, but now my task is improve/review the code and I want to put a end in my ignorance about that, someone can clarify me if it's acceptable that implementation and why?

I know that foreach is an intelligent implementation, just don't know if this structure do that kind of optimization.

  • 写回答

2条回答 默认 最新

  • douba6365 2017-10-18 15:32
    关注

    In contrast to for(), where each instruction is evaluated in each iteration, foreach() gets the array at the beginning, and then moves the pointer to iterate through it:

    The first form loops over the array given by array_expression. 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).

    Emphasis mine

    So your function gets called just once. You can see this behavior looking at the opcodes.

    Without assignment:

    <?php
    function find() {
        return [1, 2, 3, 4, 5, 6, 7, 8];
    }
    
    foreach (find() as $n) {
        echo $n.PHP_EOL;
    }
    

    Opcodes:

    line     #* E I O op                           fetch          ext  return  operands
    -------------------------------------------------------------------------------------
       3     0  E >   NOP                                                      
       7     1        INIT_FCALL                                               'find'
             2        DO_FCALL                                      0  $1      
             3      > FE_RESET_R                                       $2      $1, ->8
             4    > > FE_FETCH_R                                               $2, !0, ->8
       8     5    >   CONCAT                                           ~3      !0, '%0A'
             6        ECHO                                                     ~3
             7      > JMP                                                      ->4
             8    >   FE_FREE                                                  $2
       9     9      > RETURN                                                   1
    

    And with assignment:

    <?php
    function find() {
        return [1, 2, 3, 4, 5, 6, 7, 8];
    }
    $f = find();
    foreach ($f as $n) {
        echo $n.PHP_EOL;
    }
    

    Opcodes:

    line     #* E I O op                           fetch          ext  return  operands
    -------------------------------------------------------------------------------------
       3     0  E >   NOP                                                      
       6     1        INIT_FCALL                                               'find'
             2        DO_FCALL                                      0  $2      
             3        ASSIGN                                                   !0, $2
       7     4      > FE_RESET_R                                       $4      !0, ->9
             5    > > FE_FETCH_R                                               $4, !1, ->9
       8     6    >   CONCAT                                           ~5      !1, '%0A'
             7        ECHO                                                     ~5
             8      > JMP                                                      ->5
             9    >   FE_FREE                                                  $4
       9    10      > RETURN                                                   1
    

    As you can see, the only difference is the ASSIGN instruction, which is when the assignment to $f is made.

    So this is mostly a readability issue. In my opinion, it's a bit more readable to assign the return of the method in a variable with an appropriate name. Uncle Bob, however, states the contrary in Clean Code:

    Control variables for loops should usually be declared within the loop statement, as in this cute little function from the same source.

    public int countTestCases() {
        int count= 0;
        for (Test each : tests)
            count += each.countTestCases();
        return count;
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!