91

Is it possible to pass in array_column an array of objects?
I have implemented ArrayAccess interface, but it has no effect.
Should I implement another one?

class Foo implements ArrayAccess {

    public $Id, $Title;

    public function offsetExists($offset)
    {
        return isset($this->{$offset});
    }    

    public function offsetGet($offset)
    {
        return $this->{$offset};
    }

    public function offsetSet($offset, $value)
    {
        $this->{$offset} = $value;
    }

    public function offsetUnset($offset)
    {
        unset($this->{$offset});
    }
}

$object = new \Foo();
$object->Id = 1;
$object->Title = 'Test';

$records = array(
    $object, 
    array(
        'Id' => 2,
        'Title' => 'John'
    )
);

var_dump(array_column($records, 'Title')); // array (size=1) 0 => string 'John' (length=4)
4
  • 1
    How about creating a custom function to do this for you? Array_column is targeted just for arrays and while ArrayAccess is implemented, array_column is a built in function of php so it is difficult to ascertain exactly how the function works. Commented Apr 28, 2014 at 8:18
  • 1
    What are you expecting to be returned? Commented Apr 28, 2014 at 8:19
  • 1
    @Anthony, I expect the same result as if it was simply an array instead of object. In other words, I want property "Title" to be returned. Commented Apr 28, 2014 at 8:40
  • can convert array of objects to array of column by $array = json_decode(json_encode($array), TRUE); Commented Nov 16, 2017 at 10:37

6 Answers 6

176

PHP 5

array_column doesn't work with an array of objects. Use array_map instead:

$titles = array_map(function($e) {
    return is_object($e) ? $e->Title : $e['Title'];
}, $records);

PHP 7

array_column()

The function now supports an array of objects as well as two-dimensional arrays. Only public properties are considered, and objects that make use of __get() for dynamic properties must also implement __isset().

See https://github.com/php/php-src/blob/PHP-7.0.0/UPGRADING#L629 - Thanks to Bell for the hint!

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

10 Comments

You won't gain any better performance if you need it to work with arrays and objects.
PHP 7.0 will support objects in array_column: github.com/php/php-src/blob/PHP-7.0.0/UPGRADING#L629
For anyone interested in the actual code change, the original pull request can be found here; disclaimer, it's mine :D
@StanislavBelichenko The type assertion is quite strict in this case, and only accepts true arrays. It would tell you this when your error reporting is configured properly :)
@StanislavBelichenko i’ll see what i can do :)
|
17

Is it possible to pass in array_column an array of objects?

PHP 7

Yes, see http://php.net/manual/en/function.array-column.php

PHP 5 >= 5.5.0

In PHP 5 array_column does not work with an array of objects. You can try with:

// object 1
$a = new stdClass();
$a->my_string = 'ciao';
$a->my_number = 10;

// object 2
$b = new stdClass();
$b->my_string = 'ciao b';
$b->my_number = 100;

// array of objects
$arr_o = array($a,$b);

// using array_column with an array of objects
$result = array_column(array_map(function($o){return (array)$o;},$arr_o),'my_string');

PS: for clarity I prefer to not use array_column and use array_map with an anonymous function

$result = array_map(function($o){ return $o->my_string; }, $arr_o);

or a simple foreach

$result = array();
foreach($arr_o as $o) {
    $result[] = $o->my_string;
}

Comments

4

Here is a function that will work on both php7 and php5

function array_column_portable($array, $key) {
    return array_map(function($e) use ($key) {
        return is_object($e) ? $e->$key : $e[$key];
    }, $array);
}

You can then use it as you use array_column in php7

Comments

1

While it's not possible to use array_column on child-objects, you can cast them to arrays. This is of course not the way to go, but it's a way.

Using array_map/get_object_vars (doesn't not work in your case, due the containing array)

array_column(array_map('get_object_vars', $thingy), 'property');

Using json_decode/json_encode

array_column(json_decode(json_encode($thingy), true), 'property');

https://eval.in/597950

Note: Using json brings not the same result as using a true recursive function. You’ll lose protected and private properties of the object. But in some situations its fine.

function object_to_array($object) {
  if (is_object($object)) $object = get_object_vars($object);
  return is_array($object) ? array_map(__FUNCTION__, $object) : $object;
}

Comments

1

Just so there's an explicit answer using array_column(): the code as given in the question will work with modern PHP versions since 7.0. array_column() will happily work with public object properties and/or array keys in the array elements:

$object = new \stdClass();
$object->Id = 1;
$object->Title = 'Test';
$records = [$object, ['Id' => 2, 'Title' => 'John']];
print_r(array_column($records, 'Title'));

Output:

Array
(
    [0] => Test
    [1] => John
)

Comments

0

Possible solution is prepare that array of objects:

$objectsList = [];

foreach ($objs as $obj) {        
    $objectsList[] = (array)$obj;
}

$propList = array_column($objectsList, 'prop');

2 Comments

Be aware of casting objects to arrays: php.net/manual/en/…
So, you are recommending that the entire array of objects structure be fully iterated to cast the objects to arrays, then iterate the entire data set again with array_column()? I wouldn't.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.