Comparing a PHP in_array object?

Can the in_array function compare objects?

For example, I have an array of objects, and I want to add them to another array. Is it possible to check if the object has already been added like this:

 in_array($distinct, $object); 

or is there any other way?

+15
source share
8 answers

The in_array function cannot compare objects.

You need to create unique key-value pairs from your objects and only compare these keys when inserting a new object into your final array.

Assuming each object has a unique id property, a possible solution would be the following:

 $unique_objects = array(); // $data represents your object collection foreach ($data as $item) { if (!array_key_exists($item->id, $unique_objects)) { $unique_objects[$item->id] = $obj; } } 
+11
source

You can use strict comparison:

 in_array($object, $array, TRUE); 

Usage example:

 $a = new stdClass(); $a->x = 42; $b = new stdClass(); $b->y = 42; $c = new stdClass(); $c->x = 42; $array = array($a,$b); echo in_array($a, $array, true); // 1 echo in_array($b, $array, true); // 1 echo in_array($c, $array, true); // 
+22
source

See http://php.net/manual/en/function.spl-object-hash.php

 if ( ! array_key_exists( spl_object_hash( $obj ), $objects ) ) { $objects[ spl_object_hash( $obj ) ] = $obj; } 

Greetings

+2
source

There are many ways to do this, as you can see. I just thought I'd add one more. I don’t know why, but when working with object arrays I like to use array functions that use callbacks.

If your objects have any identifier that they should, if you want to check them for duplication, the following will work:

 $found = array_filter($uniqueObjects, function($uniqueObject) use ($object) { return $uniqueObject->id == $object->id }); if (!$found) { $uniqueObjects[] = $object; } 

$object is the object you are looking for, and $uniqueObjects is an array of objects you are looking for to see if it exists. Just map uniqueObject and the object to an identification property like id .

+2
source

I don't know if this is due to the new version of PHP, but in my project, using PHP 5.3.16 on Ubuntu 12.04, it worked. He found the needle object in my array of objects. I also double-checked loading another object of the same class and testing it for the contents of an array that did not contain this object, and it really returned correctly.

So yes, in_array can compare objects.

+1
source

If "STRICT" is "FALSE", the comparison is done by converting to a string of elements. Therefore, if you redefine the magic function __toString, you should be available to compare the elements of objects.

0
source

I came up with a slightly different, I think, more reliable option.

 function array_add_unique(&$array, $new, $test, $cb) { if(is_array($array) && count($array)>0) { for($i = 0; $i < count($array); $i++) { if( $array[$i][$test] == $new[$test] ) { $do = $cb($array[$i], $new); if(is_bool($do) && $do) { $array[$i] = $new; } else if(!is_bool($do)) { $array[$i] = $do; } return; } } } array_push($array, $new); } 

The advantage of this solution is that it includes a user-defined callback to handle conflicts. When you add unique objects, you can save properties from both the old and the new object.

The callback, which can be an anonymous function, receives both a new object and an existing object, so the user can have his own calculation. Return true to simply replace the existing object or return a new (non-bool) object to replace it.

I do not know how this works on large datasets.

0
source

I conducted several tests comparing objects using the in_array function. This is my conclusion:

When you try to find the same instance of an object in an array (e.g. OP), then in_array can work with a logical set of strict comparison.

When you try to find an object of the same class, but with a different instance , in_array exhibits illogical behavior.

PHP.net has a great user comment about illogical extreme cases.

 // Example array $array = array( 'egg' => true, 'cheese' => false, 'hair' => 765, 'goblins' => null, 'ogres' => 'no ogres allowed in this array' ); // Loose checking -- return values are in comments // First three make sense, last four do not in_array(null, $array); // true in_array(false, $array); // true in_array(765, $array); // true in_array(763, $array); // true in_array('egg', $array); // true in_array('hhh', $array); // true in_array(array(), $array); // true // Strict checking in_array(null, $array, true); // true in_array(false, $array, true); // true in_array(765, $array, true); // true in_array(763, $array, true); // false in_array('egg', $array, true); // false in_array('hhh', $array, true); // false in_array(array(), $array, true); // false 

As you can see, without strict testing, in_array tests in_array not make sense.

We know from PHP.net that two objects are the same when strictly compared ( === ) if they belong to the same class + instance. Two objects are already the same in an arbitrary comparison ( == ) when they belong to the same class.

I wrote some tests with objects to see what happens.

 $a = new stdClass(); $a->egg = true; $b = new stdClass(); $b->cheese = false; $c = new stdClass(); $c->hair = 765; $d = new stdClass(); $d->goblins = null; $e = new stdClass(); $e->ogres = 'no ogres allowed in this array'; $array2 = array($a, $b, $c, $d, $e); $e = new stdClass(); $e->egg = null; $f = new stdClass(); $f->egg = false; $g = new stdClass(); $g->egg = 765; $h = new stdClass(); $h->egg = 763; $i = new stdClass(); $i->egg = 'egg'; $j = new stdClass(); $j->egg = 'hhh'; $k = new stdClass(); $k->egg = array(); in_array($e, $array2, false); // false in_array($f, $array2, false); // false in_array($g, $array2, false); // true in_array($h, $array2, false); // true in_array($i, $array2, false); // true in_array($j, $array2, false); // true in_array($k, $array2, false); // false in_array($e, $array2, true); // false in_array($f, $array2, true); // false in_array($g, $array2, true); // false in_array($h, $array2, true); // false in_array($i, $array2, true); // false in_array($j, $array2, true); // false in_array($k, $array2, true); // false 

In recent checks, in_array checks in_array results.

The reason is as follows. If you are trying to find an object with a specific value, you are forced to use arbitrary comparison (because when the class does not match, strict comparison always fails). But because of the types of PHP variables in recent tests, these checks are considered true, because the value is considered true. Also note that the key on the object is ignored during arbitrary comparisons.

0
source

All Articles