Reputation: 171
I really dont understand the output of my array. In the start it seams to be very simple but I am already some hours in this problem. Look the code:
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;
}
The output:
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
)
)
Now, I will do only an ajustment in the print_r function:
echo'<pre>';
print_r($productArray[0]);
echo'</pre>';
The New Output:
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
)
One more adjust:
echo'<pre>';
print_r($productArray[1]);
echo'</pre>';
The 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
)
The DataBase:
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
Have you noticed that when I do a print_r or a var_dump in the $productArray we have an wrong output and when we do $productArray[0] or $productArray[1] we get the correct one. Have anyone noticed something wrong in my code?
Thanks a lot in advanced!
Upvotes: 2
Views: 90
Reputation: 5710
The usage of $this is a special variable that always passes the Object by reference. The continued usage of this will change the current object's state throughout the loop and assign a reference to the current object into the array which would result in an end result of an array with X number of references to the same object.
The difference with the $productArray[$var] is just coincidence. If you run it with
echo '<pre>';
print_r($productArray);
echo '/n';
print_r($productArray[0]);
echo '/n';
print_r($productArray[1]);
echo '</pre>';
You should notice that they are all the same object output.
If you created a new object instead it would function as you expect it.
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;
}
I would approach this by adding a function to return a newly instantiated object instead of assigning public variables. This can allow much easier maintenance of the code if you decide to have special methods upon creation of the object.
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;
}
Upvotes: 0
Reputation: 198123
I can't fully explain the behaviour, but the cause is this line:
$productArray[$count] = $this;
You are re-using the $this
special variable to just store some static data. Replace it with some other variable name in the while loop (like $data
) and you should be fine:
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++;
}
If you take $this
, each time that specific object instance changes, the data inside the array will change. You get a sort of unpredictable behavior (as you notice it already).
Upvotes: 1
Reputation: 522332
The problem is you're always assigning the values to $this
, then store it in an array. Objects are always stored as reference, so you're just storing a reference to the $this
object over and over in the $productArray
. When you finally print the content of the array, you only have the same object in it several times which contains the last data you have assigned to it.
That var_dump($productArray[0])
should work seems suspect, maybe you're calling it within the loop before the values got overwritten?
Upvotes: 2
Reputation: 1290
In PHP5, objects are not copied when they are inserted into arrays or passed to functions. So you are only inserting one object multiple times into the array, and then overwriting its properties for each loop iteration.
You should either:
1) Create a new instance of the class:
while($row = mysql_fetch_row($result)){
$object = new self();
$object->id = $row[0];
$object->category_id = $row[1];
2) Or clone the object when you insert it into the array:
$this->stock = $row[8];
$productArray[$count] = clone $this;
$count++;
}
Upvotes: 4