3

I'm trying to push objects containing elements from a sql result set into an array. My code is like:

$data = array();
$sql = "SELECT id,type,name,username FROM users";
foreach ($conn->query($sql) as $row) { 
    $this->set_id($row['id']);
    $this->set_type($row['type']);
    $this->set_username($row['username']);
    $this->set_password($row['password']);

    $data[] = $this;
}

My resultset is correct but I get my array cells overwritten with values from the last recordset after the foreach loop ends. For example, if I have these results {1,'type1','user','pass'}, {2,'type2','foo','bar'}, when I print_r my $data array ouside of the loop, I get only the second resultset repeated twice. What am I doing wrong?

1
  • 2
    You're updating a single instance of $this each time you loop, and then pointing each array element to the same $this.... if $this is your model, then you need a new instance for each array element Commented Feb 28, 2013 at 9:28

4 Answers 4

3

Inside an instance method, $this always refers to the current class instance; at every loop iteration you modify the instance itself and then add it to $data; but at the point of assignment a copy is not made and a reference to the same instance is added instead.

In the end you have an array with the same object at each index.

You would need to create a new instance of the class you're in at every loop iteration:

foreach ($conn->query($sql) as $row) { 
    $obj = new self; // create new instance of ourselves

    $obj->set_id($row['id']);
    $obj->set_type($row['type']);
    $obj->set_username($row['username']);
    $obj->set_password($row['password']);

    $data[] = $obj;
}

This is a personal suggestion, but I would either move this code inside a static method or a separate class altogether.

Sign up to request clarification or add additional context in comments.

Comments

1

Objects don't work like that, $this is always the same object and you modify it in every iteration. You could use $data[] = clone $this; to create a new instance every time but this is bad class design and you would be better off to break your class into two separate classes.

A class should not have more than one responsibility, but yours acts as database gateway and domain model at one time.

1 Comment

Thanks fab, I solved this separating model and database tasks!
0

Whatever $this is, it's a reference to some kind of object. So, when you update that object, all of the references saved in the array are still pointing to that same object. You have to define a new object in each loop.

Comments

0

You are not creating new $this object at the beginning of the iteration. In both iterations you are modifying the same object, and adding it twice to the array. When dealing with objects, those are passed by reference, meaning that you do not add a copy to the array, but add a reference to $this variable. Maybe you should add $row to the array instead, but you would still overwrite the data you save into $this.

You might also use clone keyword (see manual) to save a copy of the object.

More info: http://php.net/manual/en/language.references.php

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.