简体   繁体   English

为什么我的数组填充了对象而不是附加它们?

[英]Why does my array get filled with objects instead of appending them?

I'm building an app which receives from my server a list of products(for example) and displays them.我正在构建一个应用程序,它从我的服务器接收产品列表(例如)并显示它们。 I am using PHP and Apache to retrieve the list from a SQL Server database(pretty much a REST API).我正在使用 PHP 和 Apache 从 SQL Server 数据库(几乎是 REST API)中检索列表。 When I am building the array and encoding it, I notice that my array has 10 elements (or more, currently I set this limit for testing) and each one of them is the last one.当我构建数组并对其进行编码时,我注意到我的数组有 10 个元素(或更多,目前我为测试设置了这个限制)并且每个元素都是最后一个。

I've tried to use $arr[] = $prod or array_push($arr, $prod) , or creating a temporary array and merging them, but still the same result.我尝试使用$arr[] = $prodarray_push($arr, $prod) ,或者创建一个临时数组并合并它们,但结果仍然相同。 I also tried switching from a macOS Apache to a Windows install or Linux one (I thought it might be the Apache/PHP version).我还尝试从 macOS Apache 切换到 Windows 安装或 Linux 安装(我认为可能是 Apache/PHP 版本)。

$prod = new StdClass(); $arr = array();

$search = $_GET['search'];
$search = "%$search%";

$sql = "SELECT TOP 10
            product, qty
        FROM
            table
        WHERE
            product LIKE ?";
$stmt = sqlsrv_prepare( $conn, $sql, array($search));
sqlsrv_execute( $stmt );
$i = 0;
if ( $stmt === false ) {
    die( print_r( sqlsrv_errors(), true) );
}
else {
    while ( $row=sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) ) {
        $prod->mainInfo =  $row['product'];
        $prod->secondInfo = $row['qty'];
        $arr[] = $prod;
    }
}
http_response_code(200);
echo json_encode($arr);

The result is something among these lines(there are more lines, but i only include three since it is irrelevant):结果是这些行中的一些内容(还有更多行,但我只包含三行,因为它无关紧要):

[
  {
    "mainInfo": "product3",
    "secondInfo": "qty3"
  },
  {
    "mainInfo": "product3",
    "secondInfo": "qty3"
  },
  {
    "mainInfo": "product3",
    "secondInfo": "qty3"
  }
]

If there are three products that i am loading.如果我正在加载三种产品。 The third product is shown in all of the array's elements.第三个乘积显示在数组的所有元素中。 It should be something like this:它应该是这样的:

[
  {
    "mainInfo": "product1",
    "secondInfo": "qty1"
  },
  {
    "mainInfo": "product2",
    "secondInfo": "qty2"
  },
  {
    "mainInfo": "product3",
    "secondInfo": "qty3"
  }
]

You're modifying the same object over and over again.您一遍又一遍地修改同一个对象。 Even when it was already added to the array, it affects that single object.即使它已经添加到数组中,它也会影响该单个对象。 And your arrays just gets multiple references to the same, single object.并且您的数组只是获得对同一单个对象的多个引用。

To solve this, make sure that $prod is a new object at each start of the iteration.要解决这个问题,请确保$prod在每次迭代开始时都是一个新对象。

So move this line:所以移动这一行:

$prod = new StdClass(); 

...inside the loop: ...在循环内:

while ( $row=sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) ) {
    $prod = new StdClass(); // <----
    $prod->mainInfo =  $row['product'];
    $prod->secondInfo = $row['qty'];
    $arr[] = $prod;
}

Alternatively, you can use the (object) cast and assign the new object in one go without the need of a $prod variable:或者,您可以使用(object) cast 并一次性分配新对象,而无需$prod变量:

while ( $row=sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) ) {
    $arr[] = (object) [
        "mainInfo" => $row['product'],
        "secondInfo" => $row['qty']
    ];
}

Objects in php are always treated by reference . php 中的对象总是按引用处理。 So, everytime you modify $prod in one place, it is modified everywhere else.因此,每次您在一处修改$prod ,其他地方都会修改它。 To avoid this, clone object and work with cloned copy:为避免这种情况, clone对象并使用克隆副本:

while ( $row=sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) ) {
    $newProd = clone $prod;
    $newProd->mainInfo =  $row['product'];
    $newProd->secondInfo = $row['qty'];
    $arr[] = $newProd;
}

Objects update by reference.对象通过引用更新。

What this means is that the values will dynamically change as you modify the object, even you put the object in the array in the past.这意味着当您修改对象时,即使您过去将对象放入数组,这些值也会动态更改。 Basically your modifying the same object over and over.基本上你一遍又一遍地修改同一个对象。

You can create a new instance of the object with new or clone您可以使用newclone创建对象的新实例

while ( $row=sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) ) {
    $_prod = clone $prod; //copy the object
    $_prod ->mainInfo =  $row['product'];
    $_prod ->secondInfo = $row['qty'];
    $arr[] = $_prod;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM