OO + PHP +数组iSSUE

时间:2011-10-11 02:08:10

标签: php arrays

我真的不明白我的数组的输出。在一开始它接缝很简单,但我已经在这个问题上花了几个小时。看代码:

public function getAllProducts($limit){
$result = mysql_query("SELECT * FROM products ORDER BY RAND() LIMIT $limit") or die(mysql_error());
        $productArray = array();
        $count = 0;
        while($row = mysql_fetch_row($result)){
            $this->id = $row[0];
            $this->category_id = $row[1];
            $this->title = $row[2];
            $this->short_description = $row[3];
            $this->long_description = $row[4];
            $this->tag = $row[5];
            $this->price = $row[6];
            $this->weight = $row[7];
            $this->stock = $row[8];   
            $productArray[$count] = $this;
            $count++;
        }

            echo'<pre>';
            print_r($productArray);
            echo'</pre>';

        return $productArray;

    }

输出:

Array
(
    [0] => Product Object
        (
            [id] => 2
            [category_id] => 2
            [title] => Cart�o de Pascoa
            [short_description] => Short description bout this product 
            [long_description] => Long description about thi product but we don
            [tag] => Pascoa Coelho Cart�o Cartao Card
            [price] => 60,00
            [weight] => 1
            [stock] => 1
        )

    [1] => Product Object
        (
            [id] => 2
            [category_id] => 2
            [title] => Cart�o de Pascoa
            [short_description] => Short description bout this product 
            [long_description] => Long description about thi product but we don
            [tag] => Pascoa Coelho Cart�o Cartao Card
            [price] => 60,00
            [weight] => 1
            [stock] => 1
        )

)

现在,我将只在print_r函数中进行调整:

 echo'<pre>';
 print_r($productArray[0]);
 echo'</pre>';

新输出:

Product Object
(
    [id] => 1
    [category_id] => 1
    [title] => Cart�o de Natal
    [short_description] => Short descroption about this product
    [long_description] => Long description of this product. Nor used ri
    [tag] => Cart�o de Natal Natal Presente de Natal
    [price] => 55,00
    [weight] => 1
    [stock] => 1
)

再调整一次:

echo'<pre>';
print_r($productArray[1]);
echo'</pre>';

OutPut:

Product Object
(
    [id] => 2
    [category_id] => 2
    [title] => Cart�o de Pascoa
    [short_description] => Short description bout this product 
    [long_description] => Long description about thi product but we don
    [tag] => Pascoa Coelho Cart�o Cartao Card
    [price] => 60,00
    [weight] => 1
    [stock] => 1
)

数据库:

1   1   Cartão de Natal Short descroption about this product    Long description of this product. Nor used ri   Cartão de Natal Natal Presente de Natal 55,00   1   1

2   2   Cartão de Pascoa    Short description bout this product Long description about thi product but we don   Pascoa Coelho Cartão Cartao Card    60,00   1   1

您是否注意到当我在$ productArray中执行print_r或var_dump时输出错误,当我们执行$ productArray [0]或$ productArray [1]时,我们得到正确的输出。有人在我的代码中发现了一些错误吗?

非常感谢先进!

4 个答案:

答案 0 :(得分:4)

在PHP5中,当对象插入数组或传递给函数时,不会复制它们。所以你只是多次将一个对象插入到数组中,然后为每个循环迭代覆盖它的属性。

你应该:

1)创建一个新的类实例:

    while($row = mysql_fetch_row($result)){
        $object = new self();
        $object->id = $row[0];
        $object->category_id = $row[1];

2)或者在将对象插入数组时克隆该对象:

        $this->stock = $row[8];   
        $productArray[$count] = clone $this;
        $count++;
    }

答案 1 :(得分:2)

问题是您始终将值分配给$this,然后将其存储在数组中。对象始终存储为引用,因此您只需在$this中反复存储对$productArray对象的引用。当您最终打印数组的内容时,您只有几次包含相同的对象,其中包含您分配给它的 last 数据。

那个var_dump($productArray[0])应该可以工作似乎很可疑,也许你在覆盖值之前在循环中调用它?

答案 2 :(得分:1)

我无法完全解释这种行为,但原因是这一行:

$productArray[$count] = $this;

您正在重复使用$this special variable来存储一些静态数据。将其替换为while循环中的其他变量名称(如$data),您应该没问题:

    while($row = mysql_fetch_row($result)){
        $properties = array
        (
            'id', 'category_id', 'title', 'short_description', 'long_description'
            , 'tag', 'price', 'weight', 'stock'
        );
        $data = (object) array_combine($properties, $row);   
        $productArray[$count] = $data;
        $count++;
    }

如果您使用$this,则每次特定对象实例更改时,数组内的数据都将更改。你会得到一种不可预知的行为(正如你已经注意到的那样)。

答案 3 :(得分:0)

$ this的使用是一个特殊变量,它始终通过引用传递Object。继续使用它将在整个循环中更改当前对象的状态,并将当前对象的引用分配给数组,这将导致数组的最终结果具有对同一对象的X个引用数。

与$ productArray [$ var]的区别只是巧合。如果你用

运行它
echo '<pre>';
print_r($productArray);
echo '/n';
print_r($productArray[0]);
echo '/n';
print_r($productArray[1]);
echo '</pre>';

您应该注意到它们都是相同的对象输出。

如果您创建了一个新对象,它将按预期运行。

public function getAllProducts($limit){

    $sql = "SELECT * FROM products
            ORDER BY RAND()
            LIMIT $limit";

    $result = mysql_query($sql) or die(mysql_error());

    $productArray = array();
    $count = 0;

    while($row = mysql_fetch_row($result)){
        $that = new Product; // Whatever your product object would be or stdClass.
        $that->id = $row[0];
        $that->category_id = $row[1];
        $that->title = $row[2];
        $that->short_description = $row[3];
        $that->long_description = $row[4];
        $that->tag = $row[5];
        $that->price = $row[6];
        $that->weight = $row[7];
        $that->stock = $row[8];   
        $productArray[$count] = $that;
        $count++;
    }

    echo'<pre>';
    print_r($productArray);
    echo'</pre>';

    return $productArray;

}

我会通过添加一个函数来返回一个新实例化的对象,而不是分配公共变量。如果您决定在创建对象时使用特殊方法,则可以更轻松地维护代码。

public static function getProductFromRow(Array $row) {
    $that = new Product; // Whatever your product object would be.
    $that->id = $row[0];
    $that->category_id = $row[1];
    $that->title = $row[2];
    $that->short_description = $row[3];
    $that->long_description = $row[4];
    $that->tag = $row[5];
    $that->price = $row[6];
    $that->weight = $row[7];
    $that->stock = $row[8];

    return $that;
}

public function getAllProducts($limit) {

    $sql = "SELECT * FROM products
            ORDER BY RAND()
            LIMIT $limit";

    $result = mysql_query($sql) or die(mysql_error());

    $productArray = array();
    $count = 0;

    while($row = mysql_fetch_row($result)){
        $productArray[$count] = Product::getProductFromRow($row);
        $count++;
    }

    return $productArray;

}