PHP - Retrieving a Property from an Array of Objects

I have an array of cats objects:

$cats = Array ( [0] => stdClass Object ( [id] => 15 ), [1] => stdClass Object ( [id] => 18 ), [2] => stdClass Object ( [id] => 23 ) ) 

and I want to extract an array of cat identifiers in 1 line (and not a function or loop).

I was thinking about using array_walk with create_function , but I don't know how to do this.

Any idea?

+73
php
Jul 13 '09 at 11:42
source share
8 answers

You can use the array_map() function.
This should do it:

 $catIds = array_map(create_function('$o', 'return $o->id;'), $objects); 
+111
Jul 13 '09 at 11:51
source share
β€” -

If you have PHP 5.5 or later , the best way is to use the built-in array_column() function:

 $idCats = array_column($cats, 'id'); 

But the son must be an array or converted to an array

+57
Aug 13 '14 at 12:24
source share

The decision depends on the version of PHP you are using. At least there are two solutions:

First (newer versions of PHP)

As @JosepAlsina said before the best as well as the shortest solution, you should use array_column as follows:

 $catIds = array_column($objects, 'id'); 

Note: For iterating an array containing \stdClass es, as used in the question, it is only possible with PHP versions >= 7.0 . But when using an array containing array , you can do the same with PHP >= 5.5 .

Second (older versions of PHP)

@Greg said in older versions of PHP that you can do the following:

 $catIds = array_map(create_function('$o', 'return $o->id;'), $objects); 

But be careful: in newer versions of PHP >= 5.3.0 it is better to use Closure s, for example follow:

 $catIds = array_map(function($o) { return $o->id; }, $objects); 


Difference

The first solution creates a new function and puts it in your RAM. For some reason, the garbage collector does not delete the already created and already called function instance from memory. And the next time this code is called, the same function will be created again. This behavior slowly fills your memory ...

Both examples with memory output for comparison:

Bad

 while (true) { $objects = array_map(create_function('$o', 'return $o->id;'), $objects); echo memory_get_usage() . "\n"; sleep(1); } 4235616 4236600 4237560 4238520 ... 

GOOD ONES

 while (true) { $objects = array_map(function($o) { return $o->id; }, $objects); echo memory_get_usage() . "\n"; sleep(1); } 4235136 4235168 4235168 4235168 ... 


It can also be discussed here.

Memory leak?! Is the garbage collector correct using 'create_function' in 'array_map'?

+45
Sep 12 '14 at 12:03 on
source share
 function extract_ids($cats){ $res = array(); foreach($cats as $k=>$v) { $res[]= $v->id; } return $res } 

and use it on one line:

 $ids = extract_ids($cats); 
+4
Jul 13 '09 at 11:48
source share

You can do it easily with ouzo goodies.

 $result = array_map(Functions::extract()->id, $arr); 

or with arrays (due to ugly freaks)

 $result = Arrays::map($arr, Functions::extract()->id); 

Check out: http://ouzo.readthedocs.org/en/latest/utils/functions.html#extract

See also functional programming with ouzo (I cannot post the link).

+3
Jan 07 '15 at 10:22
source share

Built-in loops in PHP interpret loops faster, so it actually makes sense to make this one-line:

 $result = array(); array_walk($cats, create_function('$value, $key, &$result', '$result[] = $value->id;'), $result) 
+2
Jul 13 '09 at 11:55
source share

CODE

 <?php # setup test array. $cats = array(); $cats[] = (object) array('id' => 15); $cats[] = (object) array('id' => 18); $cats[] = (object) array('id' => 23); function extract_ids($array = array()) { $ids = array(); foreach ($array as $object) { $ids[] = $object->id; } return $ids; } $cat_ids = extract_ids($cats); var_dump($cats); var_dump($cat_ids); ?> 

OUTPUT

 # var_dump($cats); array(3) { [0]=> object(stdClass)#1 (1) { ["id"]=> int(15) } [1]=> object(stdClass)#2 (1) { ["id"]=> int(18) } [2]=> object(stdClass)#3 (1) { ["id"]=> int(23) } } # var_dump($cat_ids); array(3) { [0]=> int(15) [1]=> int(18) [2]=> int(23) } 

I know that it uses a loop, but this is the easiest way to do it! And using the function, it ends on the same line anyway.

+1
Jul 13 '09 at 12:05
source share
  $object = new stdClass(); $object->id = 1; $object2 = new stdClass(); $object2->id = 2; $objects = [ $object, $object2 ]; $ids = array_map(function ($object) { /** @var YourEntity $object */ return $object->id; // Or even if you have public methods // return $object->getId() }, $objects); 

Output : [1, 2]

0
May 16 '17 at 17:30
source share



All Articles