如何将数据库中的信息添加到现有的对象数组中?

3

我有一个数组,格式如下:

// echo '<pre>' . var_export($this->viewableFields, true) . '</pre>';

array (
  0 => 
  (object) array(
     'formId' => '4',
     'userId' => '7'
  ),
  1 => 
  (object) array(
     'formId' => '4',
     'userId' => '4'
  )
) 

我需要修改数据并在此数组中添加另一个键/值。我需要使用数组中的userId值,查询MySQL数据库并返回该值。我需要为每个数组元素执行此操作。
因此,对于每个数组元素,我希望运行以下查询;
SELECT group from users WHERE userId = [userId in array]

我想把这个值添加到数组中,最终的数组应该是这样的:
array (
  0 => 
  (object) array(
     'formId' => '4',
     'userId' => '7',
     'group' => 'Registered'
  ),
  1 => 
  (object) array(
     'formId' => '4',
     'userId' => '4',
     'group' => 'Admin'
  )
) 

我知道可以使用array_walk为数组元素添加附加值,就像这样:

array_walk($this->viewableFields, function(&$arr) {
    $arr->group = 'Registered';
});

我不确定如何从数据库检索值并插入到现有的数组中。
我该如何实现呢?

为什么不使用array_push? - iJamesPHP2
使用for循环遍历数组。然后在每次迭代中,通过用户ID查询数据库,并使用从查询中获得的组将其array_push到数组中。 - iJamesPHP2
你应该从数据库中一次性获取所有这些。 - iJamesPHP2
3个回答

4

为每条记录执行一次额外查询是一个非常糟糕的想法,也是“N+1问题”的明显例子:当您需要获取一个实体的“N”个子元素时,只有父实体最初被获取。

如果您的初始查询有100个用户,则最终将进行101个查询。如果稍后需要一些其他不相关的字段,则这种情况会迅速失控。

这对性能来说非常不好,随着应用程序变得越来越复杂,它很容易对其产生严重影响。

假设您无法修改初始查询并进行简单的JOIN查询以获取所需数据,则最好只进行两个查询并拼接结果数据。即使您可以修改原始查询,这样做也可能更有效。

如何处理:

假设您具有带有“formId”和“userId”公共属性的初始对象数组,请首先获取您感兴趣的所有用户ID:

$index = [];
$ids = array_reduce($array, function($ids, $object) use (&$index) {
    $ids[]                  = $object->userId;
    $index[$object->userId] = $object;

    return $ids;
});

$ids_for_sql = '(' . implode(', ', $ids) . ')';

你还需要建立一个“索引” ($index),以便可以直接访问数组中的对象,而不必再次遍历它。

现在,您可以进行第二个查询以获取“group”属性:

$groups_query = "SELECT userId, group from users WHERE userId IN $ids_for_sql";

现在只是将来自两个查询的数据“拼接”在一起的问题:
foreach ($conn->query($groups_query) as $row) {
    $index[$row['userId']]->group = $row['group'];
}

现在,您的包含“用户”对象的原始$array将被正确更新,并且仅进行了2个查询而不是11个。这样可以实现更好的性能和可扩展性,而且不会增加太多复杂性。

您可以在这里看到一个简单的工作演示(使用数组而不是SQL查询)here


1

首先,我们将从对象数组中获取userID的值,然后在数据库中查询它,假设数组为$arr。

foreach($arr AS $key=>$item) 
{
    $userid=$item["userId"];  // getting userId from object
    $query= $con->query("SELECT group from users WHERE userId='$userid'");
    if($query->num_rows>0)  //checking if query has some result
    {
        $row=$result->fetch_assoc();      //fetching the result
        $arr[$key]->group=$row['group'];  // lastly attaching group key to the arr.
    }
}

@jonboy 是的,我的错,应该是 $arr[$key]->group,因为它是一个对象。 - Prabhjot Singh Kainth
@RahulKoshti 谁说循环中不能执行查询? - Prabhjot Singh Kainth
1
@RahulKoshti,请参考您之前的陈述,您说过您无法解决这个问题吗?每个人都知道应该避免向服务器发送多个请求,但OP并不关心速度和优化。如果您在谈论优化,那么还有其他各种因素。最好提供一个答案,而不仅仅是评论其他答案。 - Prabhjot Singh Kainth
1
@jonboy 你需要先存储所有的用户ID,然后使用MySQL的IN函数进行查询。 - Prabhjot Singh Kainth
1
@jonboy,你需要先存储所有用户ID,然后使用MySQL的IN函数进行查询。这就是我所说的,你可以使用IN而不是在循环中执行查询的方法。 - Rahul Koshti
显示剩余5条评论

-2

你需要使用foreach循环遍历数组中的每个元素,获取其ID,并通过SQL语句查询相关数据。

示例:

foreach($array as $key=>$item) {
    $sql = "SELECT group from users WHERE userId = ".$item["userId"];
    $result = $conn->query($sql);
    if ($result->num_rows > 0) {
        $db_data = $result->fetch_assoc();
        //do stuff with db data

        $array[$key]["group"] = $group; //insert group to this variable
    }
}

这会抛出一个错误,因为 $group 未定义。应该是 $db_data['group']。 - Prabhjot Singh Kainth
@PrabhjotSinghKainth 是的,这就是为什么我写注释,如果你看不到的话。 - Marty1452

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接