Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

What is an elegant way to remove an object from an array of objects in PHP ?

Just to be clear ..

class Data{

  private $arrObservers;

  public add(Observer $o) {  
    array_push($this->arrObservers, $o);  
  }    
  public remove(Observer $o) {  
    // I NEED THIS CODE to remove $o from $this->arrObservers
  }  

}
share|improve this question
I suppose you mean array_push($this->arrObservers, $o)? – deceze Aug 26 '10 at 8:48

8 Answers

up vote 14 down vote accepted

You can do

function unsetValue(array $array, $value, $strict = TRUE)
{
    if(($key = array_search($value, $array, $strict)) !== FALSE) {
        unset($array[$key]);
    }
    return $array;
}

You can also use spl_object_hash to create a hash for the objects and use that as array key.

However, PHP also has a native Data Structure for Object collections with SplObjectStorage:

$a = new StdClass; $a->id = 1;
$b = new StdClass; $b->id = 2;
$c = new StdClass; $c->id = 3;

$storage = new SplObjectStorage;
$storage->attach($a);
$storage->attach($b);
$storage->attach($c);
echo $storage->count(); // 3

// trying to attach same object again
$storage->attach($c);
echo $storage->count(); // still 3

var_dump( $storage->contains($b) ); // TRUE
$storage->detach($b);
var_dump( $storage->contains($b) ); // FALSE

SplObjectStorage is Traversable, so you can foreach over it as well.

On a sidenote, PHP also has native interfaces for Subject and Observer.

share|improve this answer
3  
+1 that's the best approach. Not to mention that as of PHP 5.3, SplObjectStorage implements ArrayAccess. – IonuČ› G. Stan Aug 26 '10 at 8:56
1  
I would suggest to use if(($key = array_search($value, $array, $strict)) !== false) cuz 0 == false – Anpher Aug 27 '10 at 9:01
@Anpher good call. Fixed. Though I really think the OP should use SplObjectStorage if there is only objects to handle. – Gordon Aug 27 '10 at 9:16
Upvoted for the reference of SplObjectStorage - exactly what I need. – Christian Mar 8 at 14:04

I recommend using the ID (if you have one, anything that will be unique to that object should work within reason) of the object as the array key. This way you can address the object within the array without having to run through a loop or store the ID in another location. The code would look something like this:

$obj_array[$obj1->getId()] = $obj1;
$obj_array[$obj2->getId()] = $obj2;
$obj_array[$obj3->getId()] = $obj3;

unset($obj_array[$object_id]);

UPDATE:

class Data{

  private $arrObservers;

  public add(Observer $o) {  
    $this->arrObservers[$o->getId()] = $o;  
  }    
  public remove(Observer $o) {  
    unset($this->arrObservers[$o->getId()]);
  }  

}
share|improve this answer
You will need a getId() method for the Observer object, though. – Cody Snider Aug 26 '10 at 8:49
$obj_array['obj1'] = $obj1;
$obj_array['obj2'] = $obj2;
$obj_array['obj3'] = $obj3;
unset($obj_array['obj3']);
share|improve this answer
2  
-1 because OP gives object to the function, not the key and hence this example is incomplete. – Mikulas Dite Aug 27 '10 at 8:58

I agree with the answers above, but for the sake of completeness (where you may not have unique IDs to use as a key) my preferred methods of removing values from an array are as follows:

/**
 * Remove each instance of a value within an array
 * @param array $array
 * @param mixed $value
 * @return array
 */
function array_remove(&$array, $value)
{
    return array_filter($array, function($a) use($value) {
        return $a !== $value;
    });
}

/**
 * Remove each instance of an object within an array (matched on a given property, $prop)
 * @param array $array
 * @param mixed $value
 * @param string $prop
 * @return array
 */
function array_remove_object(&$array, $value, $prop)
{
    return array_filter($array, function($a) use($value, $prop) {
        return $a->$prop !== $value;
    });
}

Which are used in the following way:

$values = array(
    1, 2, 5, 3, 5, 6, 7, 1, 2, 4, 5, 6, 6, 8, 8,
);
print_r(array_remove($values, 6));

class Obj {
    public $id;
    public function __construct($id) {
        $this->id = $id;
    }
}
$objects = array(
    new Obj(1), new Obj(2), new Obj(4), new Obj(3), new Obj(6), new Obj(4), new Obj(3), new Obj(1), new Obj(5),
);
print_r(array_remove_object($objects, 1, 'id'));

Hope that helps.

share|improve this answer

unset($myArray[$index]); where $index is the index of the element you want to remove. If you wan't a more specific answer, show some code or describe what you're trying to do.

share|improve this answer
This is ok ,but How do I find the index of an object? Search by values in the array ? – danip Aug 26 '10 at 8:29
@daniphp You can compar objects with ===. – Richard Knop Aug 26 '10 at 8:31

Use this for your internal object storage instead: http://us2.php.net/manual/en/class.splobjectstorage.php

share|improve this answer
Works in PHP 5 >= 5.3.0 – quantme Nov 24 '12 at 14:51

I believe this is the best way

$index = array_search($o,$this->arrObservers,true); unset($this->arrObservers[$index]);

share|improve this answer

Try this, will solve your problem.

class Data{
  private $arrObservers;

  public add(Observer $o) {  
    array_push($this->arrObservers,$o);  
  }    

  public remove($Observer $o) {  
    unset($this->arrObservers[$o]);  
  }  
}
share|improve this answer
array_push will assign a numeric key, so you wouldnt find $o as key, even if arrays could use objects for keys – Gordon Aug 26 '10 at 9:27

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.