PHP. Можно ли использовать array_column с массивом объектов

Можно ли передать в array_column массив объектов?
Я реализовал интерфейс ArrayAccess, но он не имеет никакого эффекта.
Должен ли я реализовать еще один?

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)

Ответ 1

PHP 5

array_column не работает с массивом объектов. Вместо этого используйте array_map:

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

PHP 7

array_column()

Теперь функция поддерживает массив объектов, а также двумерные массивы. Учитываются только публичные свойства и объекты, которые используют __get() для динамических свойств, также должны реализовать __isset().

См. https://github.com/php/php-src/blob/PHP-7.0.0/UPGRADING#L629 - Спасибо Bell за подсказку!

Ответ 2

Можно ли передать в array_column массив объектов?

PHP 7

Да, см. http://php.net/manual/en/function.array-column.php

PHP 5 >= 5.5.0

В PHP 5 array_column не работает с массивом объектов. Вы можете попробовать:

// 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: для ясности я предпочитаю не использовать array_column и использовать array_map с анонимной функцией

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

или простой foreach

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

Ответ 3

Возможное решение - подготовить массив массивов:

$objectsList = [];

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

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

Ответ 4

Пока невозможно использовать array_column для дочерних объектов, вы можете отнести их к массивам. Это, конечно, не путь, но это путь.

Использование array_map/get_object_vars (не работает в вашем случае из-за содержащего массива)

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

Использование json_decode/json_encode

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

https://eval.in/597950

Примечание. Использование json не приводит к тому же результату, что и при использовании истинной рекурсивной функции. Вы потеряете защищенные и частные свойства объекта. Но в некоторых ситуациях это прекрасно.

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

Ответ 5

Для будущего посетителя.

$arrayColumnData = array_map(function($e) {
    return is_object($e) ? $e->your_column : $e['your_column'];
}, $yourArray);

Спасибо.

Ответ 6

Если вы не хотите изменять каждый фрагмент кода, который вы уже писали, потому что ваш prod-сервер находится на php5, а не php7

Вот портативная функция

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

Затем вы можете использовать его при использовании array_column в php7

Это не самое лучшее в производительности из-за array_fill, но оно работает.

Примечание. вы можете переопределить собственный массив array_column php с этой функцией, поэтому вам не нужно ничего менять при переключении php7/php5