2016-04-15 2 views
2

ここで質問するのは初めてのことです。 しばらく前に、私の同僚は、彼は私が反復内の私のクエリを置く方法が間違っているとコメントしLaravel(または一般的なPHP)のループのデータとしてクエリを使用しています。

$roles = new Roles(); 
foreach($roles->get as $role) 
{ 
    ...irrelevant operation here 
} 

私のコードを見て、私は

$roles = $roles->get(); 
foreach($roles as $role) 

にそれを変更する必要があり、彼は私に言った場合、そのI foreachループで配列式としてクエリを実行すると、データベースごとにループが参照され、最終的にサイト全体が減速します。私はそれが真実であるかどうか、そしてその背後にある論理を知りたい。

+0

オブジェクトRoles()は何をしますか? – johnny

+0

テーブルを表す雄弁なモデルで、データベースとのやりとりが可能です。基本的には、$ roles-> get()は、ロールが表すテーブルから、私の場合はテーブルUser__rolesをすべて返します。 – Yanaro

答えて

0

foreachループPHPはiterable変数を1回取り、それを内部イテレータで処理します。あなたの同僚の反対は、すべての反復の前に毎回継続条件が実行される単純なforループに適用されます。

あなたは簡単にテストケースを作成することができます

<?php 
class testClass 
{ 
    private 
    $_iteratable = ['a', 'b', 'c']; 

    public function get() 
    { 
    echo "get called<br>\n"; 
    return $this->_iteratable; 
    } 
} 

echo "foreach<br>\n"; 
$obj = new testClass(); 
foreach($obj->get() as $key => $value) 
{ 
    echo "$key: $value<br>\n"; 
} 

/* OUTPUT: 
foreach 
get called 
0: a 
1: b 
2: c 
*/ 

echo "<p>for<br>\n"; 
$obj = new testClass(); 
for($i = 0; $i < count($obj->get()); $i++) 
{ 
    echo "$i: {$obj->get()[$i]}<br>\n"; 
} 

/* OUTPUT: 
for 
get called 
get called 
0: a 
get called 
get called 
1: b 
get called 
get called 
2: c 
get called 
?> 

あなたの代わりに各反復をコピーして、おそらく大きなデータ値のデータへの参照のみ以来foreach($iteratable as &$reference)を使用する場合がありますパフォーマンスを向上させるために。そうすることで、foreachループに渡された元のデータを処理します。つまり、そのデータを操作することさえできます。 foreachを値で使用すると、コピーを処理し、元のデータにアタッチすることなく作業値を変更できます。

+0

あなたの提案をお寄せいただきありがとうございます。私は大きなプロジェクトこのようなデータ参照が必要です。 – Yanaro

2

$ roles-> get(); db接続を開き、クエリを行い、接続を閉じます。

DBへの接続(たぶん)は別のホストへのTCP接続です。ループ内に置くと、(n)回呼び出されます。 DB接続を待機するたびにループが遅くなります。 すべてのデータを一度に取得すると($ roles-> all()のように)、データをRAMに格納し、DB foreach項目を呼び出す必要はありません。

はそれが$roles->get()は一度だけ呼び出されますどちらの場合も

$roles = $roles->get(); 
foreach($roles as $role) 

foreach($roles->get() as $role) 

間に有意差はありません

+0

私はall()を使用することはありませんでしたが、get()はデータベースからオブジェクトの配列を返し、それをループします。制約を使用しない場合、get()はall()と同じものを返す必要があります。その場合、データベースに複数回接続する必要がありますか? – Yanaro

+0

Quasimodoが述べているように、私は単純な "for"ループを考えていました。 私はまた、 "get"がループボディの内部にあることを確信していました:( 明確化とテストケースのための@quasimodoのおかげで) – Pietro

0

を助け願っています。つまり、データベース接続は1回だけ実行されます。

関連する問題