【问题标题】:PHP. Is it possible to use array_column with an array of objectsphp。是否可以将 array_column 与对象数组一起使用
【发布时间】:2014-04-28 08:13:25
【问题描述】:

是否可以传入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)

【问题讨论】:

  • 如何创建一个自定义函数来为您执行此操作? Array_column 仅针对数组,虽然实现了 ArrayAccess,但 array_column 是 php 的内置函数,因此很难确定该函数的确切工作原理。
  • 您希望返回什么?
  • @Anthony,我希望得到相同的结果,就好像它只是一个数组而不是对象一样。换句话说,我希望返回属性“Title”。
  • 可以通过$array = json_decode(json_encode($array), TRUE);将对象数组转换为列数组

标签: php


【解决方案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 的提示!

【讨论】:

  • 如果你需要它来处理数组对象,你不会获得更好的性能。
  • PHP 7.0 将支持 array_column 中的对象:github.com/php/php-src/blob/PHP-7.0.0/UPGRADING#L629
  • 任何对实际代码更改感兴趣的人,可以找到原始拉取请求here;免责声明,这是我的:D
  • @StanislavBelichenko 在这种情况下,类型断言非常严格,并且只接受真正的数组。当您的错误报告配置正确时,它会告诉您这一点:)
  • @StanislavBelichenko 我会看看我能做什么:)
【解决方案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】:

    这是一个适用于 php7 和 php5 的函数

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

    然后你可以像在 php7 中使用 array_column 一样使用它

    【讨论】:

      【解决方案4】:

      可能的解决方案是准备对象数组:

      $objectsList = [];
      
      foreach ($objs as $obj) {        
          $objectsList[] = (array)$obj;
      }
      
      $propList = array_column($objectsList, 'prop');
      

      【讨论】:

      • 注意将对象转换为数组:php.net/manual/en/…
      • 那么,您是建议对整个对象结构数组进行完全迭代以将对象转换为数组,然后使用array_column() 再次迭代整个数据集?我不会。
      【解决方案5】:

      虽然不能在子对象上使用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;
      }

      【讨论】:

        猜你喜欢
        • 2013-09-03
        • 1970-01-01
        • 2022-12-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-26
        • 1970-01-01
        • 2021-05-26
        相关资源
        最近更新 更多