Можно ли передать 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)
с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)
PHP 5
array_column
не работает с массивом объектов. array_map
этого используйте 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 – Спасибо Белу за подсказку!
Можно ли передать 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; }
Возможное решение – подготовить массив массивов:
$objectsList = []; foreach ($objs as $obj) { $objectsList[] = (array)$obj; } $propList = array_column($objectsList, 'prop');
Хотя нельзя использовать 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');
Примечание. Использование json не приводит к тому же результату, что и при использовании истинной рекурсивной функции. Вы потеряете защищенные и частные свойства объекта. Но в некоторых ситуациях это прекрасно.
function object_to_array($object) { if (is_object($object)) $object = get_object_vars($object); return is_array($object) ? array_map(__FUNCTION__, $object) : $object; }
Для будущего посетителя.
$arrayColumnData = array_map(function($e) { return is_object($e) ? $e->your_column : $e['your_column']; }, $yourArray);
Благодарю.
Если вы не хотите изменять каждый фрагмент кода, который вы уже писали, потому что ваш 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