我正在集成一个API到我的网站,它与存储在对象中的数据一起工作,而我的代码是使用数组编写的。

我想要一个快速和肮脏的函数将对象转换为数组。


当前回答

我认为使用trait来存储对象到数组的转换逻辑是一个不错的想法。举个简单的例子:

trait ArrayAwareTrait
{
    /**
     * Return list of Entity's parameters
     * @return array
     */
    public function toArray()
    {
        $props = array_flip($this->getPropertiesList());
        return array_map(
            function ($item) {
                if ($item instanceof \DateTime) {
                    return $item->format(DATE_ATOM);
                }
                return $item;
            },
            array_filter(get_object_vars($this), function ($key) use ($props) {
                return array_key_exists($key, $props);
            }, ARRAY_FILTER_USE_KEY)
        );
    }


    /**
     * @return array
     */
    protected function getPropertiesList()
    {
        if (method_exists($this, '__sleep')) {
            return $this->__sleep();
        }
        if (defined('static::PROPERTIES')) {
            return static::PROPERTIES;
        }
        return [];
    }
}

class OrderResponse
{
    use ArrayAwareTrait;

    const PROP_ORDER_ID = 'orderId';
    const PROP_TITLE = 'title';
    const PROP_QUANTITY = 'quantity';
    const PROP_BUYER_USERNAME = 'buyerUsername';
    const PROP_COST_VALUE = 'costValue';
    const PROP_ADDRESS = 'address';

    private $orderId;
    private $title;
    private $quantity;
    private $buyerUsername;
    private $costValue;
    private $address;

    /**
     * @param $orderId
     * @param $title
     * @param $quantity
     * @param $buyerUsername
     * @param $costValue
     * @param $address
     */
    public function __construct(
        $orderId,
        $title,
        $quantity,
        $buyerUsername,
        $costValue,
        $address
    ) {
        $this->orderId = $orderId;
        $this->title = $title;
        $this->quantity = $quantity;
        $this->buyerUsername = $buyerUsername;
        $this->costValue = $costValue;
        $this->address = $address;
    }

    /**
     * @inheritDoc
     */
    public function __sleep()
    {
        return [
            static::PROP_ORDER_ID,
            static::PROP_TITLE,
            static::PROP_QUANTITY,
            static::PROP_BUYER_USERNAME,
            static::PROP_COST_VALUE,
            static::PROP_ADDRESS,
        ];
    }

    /**
     * @return mixed
     */
    public function getOrderId()
    {
        return $this->orderId;
    }

    /**
     * @return mixed
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * @return mixed
     */
    public function getQuantity()
    {
        return $this->quantity;
    }

    /**
     * @return mixed
     */
    public function getBuyerUsername()
    {
        return $this->buyerUsername;
    }

    /**
     * @return mixed
     */
    public function getCostValue()
    {
        return $this->costValue;
    }

    /**
     * @return string
     */
    public function getAddress()
    {
        return $this->address;
    }
}

$orderResponse = new OrderResponse(...);
var_dump($orderResponse->toArray());

其他回答

您还可以使用Symfony Serializer组件

use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

$serializer = new Serializer([new ObjectNormalizer()], [new JsonEncoder()]);
$array = json_decode($serializer->serialize($object, 'json'), true);

Use:

function readObject($object) {
    $name = get_class ($object);
    $name = str_replace('\\', "\\\\", $name); // Outcomment this line, if you don't use
                                              // class namespaces approach in your project
    $raw = (array)$object;

    $attributes = array();
    foreach ($raw as $attr => $val) {
        $attributes[preg_replace('('.$name.'|\*|)', '', $attr)] = $val;
    }
    return $attributes;
}

它返回一个没有特殊字符和类名的数组。

class Test{
    const A = 1;
    public $b = 'two';
    private $c = test::A;

    public function __toArray(){
        return call_user_func('get_object_vars', $this);
    }
}

$my_test = new Test();
var_dump((array)$my_test);
var_dump($my_test->__toArray());

输出

array(2) {
    ["b"]=>
    string(3) "two"
    ["Testc"]=>
    int(1)
}
array(1) {
    ["b"]=>
    string(3) "two"
}

要将对象转换为数组,只需显式强制转换:

$name_of_array = (array) $name_of_object;

这不是一个新的解决方案,但是在可用时包含了toArray方法转换

function objectToArray($r)
{
  if (is_object($r)) {
    if (method_exists($r, 'toArray')) {
      return $r->toArray(); // returns result directly
    } else {
      $r = get_object_vars($r);
    }
  }

  if (is_array($r)) {
    $r = array_map(__FUNCTION__, $r); // recursive function call
  }

  return $r;
}