使用查询作为Laravel(或一般的PHP)中循环的数据


Using queries as data for loop in Laravel (or PHP in general)

这是我第一次在这里提问,请耐心等待,因为我不久前刚刚开始编码。不久前,我的同事看到了我的代码

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

他评论说,我把查询放在迭代中的方式是错误的,我应该把它改为

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

他告诉我,如果我把查询作为数组表达式放在foreach循环中,它会在每个循环中引用数据库,最终会减慢整个网站的速度。我想知道这是真是假,以及背后的逻辑。

$roles->get();打开数据库连接,进行查询,关闭连接。

每个到DB的连接(通常)都是到另一个主机的TCP连接,如果你把它放在一个循环中,它会被调用(n)次。通过让每次迭代都等待DB连接,可以降低循环的速度。如果您一次获取所有数据(如$roles->all()),它会将数据放入RAM,而不需要调用DBforeach项。

希望它能帮助

foreach循环中,PHP获取可迭代变量一次,并使用内部迭代器对其进行处理。您同事的反对意见适用于简单的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,则将处理副本,并且可以在不影响原始数据的情况下修改工作值。

之间没有显著差异

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

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

在这两种情况下CCD_ 4将仅被调用一次。这意味着数据库连接将只执行一次。