0

I want to add an object to an array of objects only if it's not already in the array (I don't want clones). My code doesn't work.

$roleCount = 0;
$roles = Array();

foreach ($result as $row) {

    // create a new Role

    $role = new Role();
    $role->setId($row['role_id']);
    $role->setName($row['roleName']);

    // add $role to $roles only if it's different from those that already are inside $roles array

    if (!in_array($role, $roles)) {
        print_r($role); // This is for test purposes
        $roles[$roleCount] = $role;
        $roleCount++;
        echo "new role added ";
    }

I thought that in_array loose comparison should have worked, but it doesn't seem to.

I read on the object comparison page that

Two object instances are equal if they have the same attributes and values, and are instances of the same class.

So, why doesn't my code work? It adds the same role more than once, even if its properties are the same of the role already in the array.

Note: print_r($role) outputs this:

Role Object ( [id:Role:private] => 55 [name:Role:private] => user [description:Role:private] => [services:Role:private] => Array ( ) )
Role Object ( [id:Role:private] => 55 [name:Role:private] => user [description:Role:private] => [services:Role:private] => Array ( ) ) 

so it seems that objects properties are the same. Am I wrong?

2
  • I guess a better question would be why do you have duplicate IDs in whatever storage you're keeping the roles? If you're using a database, a PRIMARY KEY on the ID column should solve your problem. Commented Mar 8, 2014 at 17:43
  • @SecondRikudo I don't have duplicate IDs on db, I'm iterating over a result of a JOIN query in a many to many relationship (so I've got multiple references to the same role). Commented Mar 8, 2014 at 17:47

2 Answers 2

1

Simplest solution: Use the role's ID as a key to the array (IDs are unique, right??)

$roles = Array();

foreach ($result as $row) {

    // create a new Role

    $role = new Role();
    $role->setId($row['role_id']);
    $role->setName($row['roleName']);

    // add $role to $roles only if it's different from those that already are inside $roles array

    if (!array_key_exists($role->getId(), $roles)) { //Check if ID already exists as an array key.
        $roles[$role->getId()] = $role;
        echo "new role added ";
    }

I'm assuming Role has a getId() method, if not, $row["role_id"] would work just fine as well.

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

4 Comments

It worked :) But why didn't in_array() worked as I expected? Isn't it supposed to check if objects properties are equal?
@KurtBourbaki: It does. 3v4l.org/CcjLK. It's possible that you have other differences. Note that all of the properties on both objects must be identical. (as in, === identical).
I edited my question. The properties of the two $role objects seem to be identical. Could the problem be due to the fact that properties are private?
I answer to myself: changing properties visibility in Role doesn't help.
0

The role's ID is different, therefore not equal.

You may want to keep an array of role names, rather than trying to compare objects.

1 Comment

role_id is not different, it's the same (it's just a column of a row in my db). I need an array of objects because I've got to pass it to a User object :)

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.