2017-10-18 116 views
2

我搜索了很多在Stack /谷歌並沒有找到一個合適的回答我的問題,所以我來到這裏:在foreach裏查詢可以嗎?

我知道用了一些計算和東西完全是不好的做法,如:

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

最近我看到的代碼奇怪的做法,我的工作:

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

這是確定把直接在foreach中發現,像計數($項目)或排序的?我不喜歡這個想法,所以本能地避免了放入一些變種,但現在我的任務是改進/審查代碼,我想結束對此的無知,有人可以澄清我是否可以接受實現爲什麼?

我知道foreach是一個智能實現,只是不知道這個結構是否做這種優化。

+1

好吧,我不知道在這種情況下優化,但是當涉及到可讀性和清晰的代碼,我敢肯定,這是清潔劑只使用一個變量'$ models'容納結果。我有興趣知道這種代碼是否有一些性能缺陷 – teeyo

回答

1

相反for(),其中每個指令在每次迭代評估,foreach()得到array在開始,然後移動指針來遍歷它:

第一種形式循環中給出的陣列上由array_expression。在每次迭代中,當前元素的值被分配給$值,並且內部數組指針被提前一個(所以在下一次迭代中,您將看到下一個元素)。

重點煤礦

所以你的函數被調用一次。你可以看到這個行爲看着操作碼。

Without assignment

<?php 
function find() { 
    return [1, 2, 3, 4, 5, 6, 7, 8]; 
} 

foreach (find() as $n) { 
    echo $n.PHP_EOL; 
} 

操作碼:

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 

而且with assignment

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

操作碼:

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 

正如您所看到的,唯一的區別是ASSIGN指令,即指定給$f的指令。

所以這主要是一個可讀性問題。在我看來,使用合適的名稱將變量的返回賦值給一個變量會更具可讀性。 Bob大叔,但是,國家在清潔守則相反:

for循環控制變量通常應在循環語句中聲明,如從同一來源這個可愛的小功能。

public int countTestCases() { 
    int count= 0; 
    for (Test each : tests) 
   count += each.countTestCases(); 
   return count; 
} 
2

如果您有for循環,則會在每次迭代中檢查條件。因此,不要僅僅將var與一個值進行比較,而必須在每次迭代中調用一個函數(count)。因此,移動計數條件的循環有差別

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

foreach表現不同了。而不是在每次迭代中評估SomeModel::find(),這部分只評估一次並保存爲循環。您還可以將SomeModel::find()的結果保存在var中,並將該var用於foreach循環,但這沒有什麼區別。如果你使用var 只有作爲循環,編譯器應該完全一樣。

但請記住。如果你只有幾次迭代,那麼這種優化應該是編譯器的一部分,時序優勢應該接近於0。

+0

您的回答很好,但@ishegg解釋了很好的細節,謝謝! – calexandre