Відповіді:
Просто наберіть це
$array = (array) $yourObject;
З масивів :
Якщо об'єкт перетворений у масив, результат - це масив, елементи якого є властивостями об'єкта. Ключі - імена змінних членів, за кількома помітними винятками: цілі властивості недоступні; приватні змінні мають ім'я класу, що додається до імені змінної; захищені змінні мають ім'я '*', вказане на ім'я змінної. Ці заздалегідь задані значення мають нульові байти з обох сторін.
Приклад: Простий об’єкт
$object = new StdClass;
$object->foo = 1;
$object->bar = 2;
var_dump( (array) $object );
Вихід:
array(2) {
'foo' => int(1)
'bar' => int(2)
}
Приклад: Складний об’єкт
class Foo
{
private $foo;
protected $bar;
public $baz;
public function __construct()
{
$this->foo = 1;
$this->bar = 2;
$this->baz = new StdClass;
}
}
var_dump( (array) new Foo );
Вихід (з \ 0s відредагований для наочності):
array(3) {
'\0Foo\0foo' => int(1)
'\0*\0bar' => int(2)
'baz' => class stdClass#2 (0) {}
}
Вихід з var_export
замість var_dump
:
array (
'' . "\0" . 'Foo' . "\0" . 'foo' => 1,
'' . "\0" . '*' . "\0" . 'bar' => 2,
'baz' =>
stdClass::__set_state(array(
)),
)
Цей тип клавіатури не призведе до глибокого викидання об'єктного графіка, і вам потрібно застосувати нульові байти (як пояснено в ручній цитаті) для доступу до будь-яких непублічних атрибутів. Тож це найкраще спрацьовує під час передавання StdClass об'єктів або об'єктів, що мають лише загальнодоступні властивості. Для швидкого та брудного (про що ви просили) це добре.
Також дивіться цю поглиблену публікацію в блозі:
[1 => "one"]
стає["1" => "one"]
(array)
і (object)
працює надійно та однаково для всіх версій з PHP 4.3. Дивіться 3v4l.org/X6lhm . Якщо ви отримаєте синтаксичну помилку, ви зробили щось не так.
empty
журналу для . Ви не можете використовувати вираз до empty
рівня 5.5. Це абсолютно не пов’язано з набіркою;)
Ви можете швидко перетворити глибоко вкладені об'єкти в асоціативні масиви, спираючись на поведінку функцій кодування / декодування JSON:
$array = json_decode(json_encode($nested_object), true);
З першого хіта Google для " PHP-об'єкта до масиву assoc " ми маємо це:
function object_to_array($data)
{
if (is_array($data) || is_object($data))
{
$result = array();
foreach ($data as $key => $value)
{
$result[$key] = object_to_array($value);
}
return $result;
}
return $data;
}
Джерело знаходиться на сайті codenippets.joyent.com .
function objectToArray($o) { $a = array(); foreach ($o as $k => $v) $a[$k] = (is_array($v) || is_object($v)) ? objectToArray($v): $v; return $a; }
Це просто встановлює все, що не є об'єктом або масивом, і продовжується без повторного виклику методу, якщо це не потрібно.
Якщо ваші властивості об'єкта є загальнодоступними, ви можете зробити:
$array = (array) $object;
Якщо вони приватні або захищені, вони матимуть дивні імена ключів у масиві. Отже, у цьому випадку вам знадобиться така функція:
function dismount($object) {
$reflectionClass = new ReflectionClass(get_class($object));
$array = array();
foreach ($reflectionClass->getProperties() as $property) {
$property->setAccessible(true);
$array[$property->getName()] = $property->getValue($object);
$property->setAccessible(false);
}
return $array;
}
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"
}
Ось код:
function object_to_array($data) {
if ((! is_array($data)) and (! is_object($data)))
return 'xxx'; // $data;
$result = array();
$data = (array) $data;
foreach ($data as $key => $value) {
if (is_object($value))
$value = (array) $value;
if (is_array($value))
$result[$key] = object_to_array($value);
else
$result[$key] = $value;
}
return $result;
}
Усі інші відповіді, розміщені тут, працюють лише з публічними атрибутами. Ось одне рішення, яке працює з об’єктами, схожими на JavaBeans , використовуючи роздуми та геттери:
function entity2array($entity, $recursionDepth = 2) {
$result = array();
$class = new ReflectionClass(get_class($entity));
foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
$methodName = $method->name;
if (strpos($methodName, "get") === 0 && strlen($methodName) > 3) {
$propertyName = lcfirst(substr($methodName, 3));
$value = $method->invoke($entity);
if (is_object($value)) {
if ($recursionDepth > 0) {
$result[$propertyName] = $this->entity2array($value, $recursionDepth - 1);
}
else {
$result[$propertyName] = "***"; // Stop recursion
}
}
else {
$result[$propertyName] = $value;
}
}
}
return $result;
}
public
властивостей?
Про що get_object_vars($obj)
? Це здається корисним, якщо ви хочете отримати доступ лише до публічних властивостей об'єкта.
Дивіться get_object_vars .
Перш за все, якщо вам потрібен масив з об'єкта, ви, ймовірно, слід сформувати дані спочатку як масив. Подумай над цим.
Не використовуйте foreach
оператор або перетворення JSON. Якщо ви плануєте це, знову працюєте зі структурою даних, а не з об'єктом.
Якщо вам це справді потрібно, використовуйте об'єктно-орієнтований підхід, щоб мати чистий і доступний код. Наприклад:
Об'єкт як масив
class PersonArray implements \ArrayAccess, \IteratorAggregate
{
public function __construct(Person $person) {
$this->person = $person;
}
// ...
}
Якщо вам потрібні всі властивості, використовуйте об’єкт передачі:
class PersonTransferObject
{
private $person;
public function __construct(Person $person) {
$this->person = $person;
}
public function toArray() {
return [
// 'name' => $this->person->getName();
];
}
}
Ви можете легко використовувати цю функцію, щоб отримати результат:
function objetToArray($adminBar){
$reflector = new ReflectionObject($adminBar);
$nodes = $reflector->getProperties();
$out = [];
foreach ($nodes as $node) {
$nod = $reflector->getProperty($node->getName());
$nod->setAccessible(true);
$out[$node->getName()] = $nod->getValue($adminBar);
}
return $out;
}
Використовуйте PHP 5 або новішої версії.
Ось моя рекурсивна функція PHP для перетворення об'єктів PHP в асоціативний масив:
// ---------------------------------------------------------
// ----- object_to_array_recursive --- function (PHP) ------
// ---------------------------------------------------------
// --- arg1: -- $object = PHP Object - required --
// --- arg2: -- $assoc = TRUE or FALSE - optional --
// --- arg3: -- $empty = '' (Empty String) - optional --
// ---------------------------------------------------------
// ----- Return: Array from Object --- (associative) -------
// ---------------------------------------------------------
function object_to_array_recursive($object, $assoc=TRUE, $empty='')
{
$res_arr = array();
if (!empty($object)) {
$arrObj = is_object($object) ? get_object_vars($object) : $object;
$i=0;
foreach ($arrObj as $key => $val) {
$akey = ($assoc !== FALSE) ? $key : $i;
if (is_array($val) || is_object($val)) {
$res_arr[$akey] = (empty($val)) ? $empty : object_to_array_recursive($val);
}
else {
$res_arr[$akey] = (empty($val)) ? $empty : (string)$val;
}
$i++;
}
}
return $res_arr;
}
// ---------------------------------------------------------
// ---------------------------------------------------------
Приклад використання:
// ---- Return associative array from object, ... use:
$new_arr1 = object_to_array_recursive($my_object);
// -- or --
// $new_arr1 = object_to_array_recursive($my_object, TRUE);
// -- or --
// $new_arr1 = object_to_array_recursive($my_object, 1);
// ---- Return numeric array from object, ... use:
$new_arr2 = object_to_array_recursive($my_object, FALSE);
$new_arr1 = (array) $my_object;
Щоб перетворити об'єкт у масив, просто викладіть його явно:
$name_of_array = (array) $name_of_object;
Ви також можете створити функцію в PHP для перетворення масиву об'єктів:
function object_to_array($object) {
return (array) $object;
}
Ви можете зробити це, коли ви отримуєте дані як об’єкти з баз даних:
// Suppose 'result' is the end product from some query $query
$result = $mysqli->query($query);
$result = db_result_to_array($result);
function db_result_to_array($result)
{
$res_array = array();
for ($count=0; $row = $result->fetch_assoc(); $count++)
$res_array[$count] = $row;
return $res_array;
}
Спеціальна функція для перетворення stdClass в масив:
function objectToArray($d) {
if (is_object($d)) {
// Gets the properties of the given object
// with get_object_vars function
$d = get_object_vars($d);
}
if (is_array($d)) {
/*
* Return array converted to object
* Using __FUNCTION__ (Magic constant)
* for recursive call
*/
return array_map(__FUNCTION__, $d);
} else {
// Return array
return $d;
}
}
Ще одна спеціальна функція для перетворення масиву в stdClass:
function arrayToObject($d) {
if (is_array($d)) {
/*
* Return array converted to object
* Using __FUNCTION__ (Magic constant)
* for recursive call
*/
return (object) array_map(__FUNCTION__, $d);
} else {
// Return object
return $d;
}
}
Приклад використання:
// Create new stdClass Object
$init = new stdClass;
// Add some test data
$init->foo = "Test data";
$init->bar = new stdClass;
$init->bar->baaz = "Testing";
$init->bar->fooz = new stdClass;
$init->bar->fooz->baz = "Testing again";
$init->foox = "Just test";
// Convert array to object and then object back to array
$array = objectToArray($init);
$object = arrayToObject($array);
// Print objects and array
print_r($init);
echo "\n";
print_r($array);
echo "\n";
print_r($object);
Використання:
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;
}
Він повертає масив без спеціальних символів та імен класів.
Ця відповідь є лише об'єднанням різних відповідей цієї публікації, але це рішення для перетворення об’єкта PHP з публічними або приватними властивостями з простими значеннями або масивами в асоціативний масив ...
function object_to_array($obj)
{
if (is_object($obj))
$obj = (array)$this->dismount($obj);
if (is_array($obj)) {
$new = array();
foreach ($obj as $key => $val) {
$new[$key] = $this->object_to_array($val);
}
}
else
$new = $obj;
return $new;
}
function dismount($object)
{
$reflectionClass = new \ReflectionClass(get_class($object));
$array = array();
foreach ($reflectionClass->getProperties() as $property) {
$property->setAccessible(true);
$array[$property->getName()] = $property->getValue($object);
$property->setAccessible(false);
}
return $array;
}
Деякі збіднення до коду "добре-knwon"
/*** mixed Obj2Array(mixed Obj)***************************************/
static public function Obj2Array($_Obj) {
if (is_object($_Obj))
$_Obj = get_object_vars($_Obj);
return(is_array($_Obj) ? array_map(__METHOD__, $_Obj) : $_Obj);
} // BW_Conv::Obj2Array
Зауважте, що якщо функція є членом класу (як і вище), ви повинні змінити __FUNCTION__
її__METHOD__
Також ви можете використовувати компонент серіалізатора Symfony
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);
Для вашого випадку було правильним / прекрасним, якщо ви використовуєте шаблони "декоратор" або "трансформація моделі дати". Наприклад:
Ваша модель
class Car {
/** @var int */
private $color;
/** @var string */
private $model;
/** @var string */
private $type;
/**
* @return int
*/
public function getColor(): int
{
return $this->color;
}
/**
* @param int $color
* @return Car
*/
public function setColor(int $color): Car
{
$this->color = $color;
return $this;
}
/**
* @return string
*/
public function getModel(): string
{
return $this->model;
}
/**
* @param string $model
* @return Car
*/
public function setModel(string $model): Car
{
$this->model = $model;
return $this;
}
/**
* @return string
*/
public function getType(): string
{
return $this->type;
}
/**
* @param string $type
* @return Car
*/
public function setType(string $type): Car
{
$this->type = $type;
return $this;
}
}
Декоратор
class CarArrayDecorator
{
/** @var Car */
private $car;
/**
* CarArrayDecorator constructor.
* @param Car $car
*/
public function __construct(Car $car)
{
$this->car = $car;
}
/**
* @return array
*/
public function getArray(): array
{
return [
'color' => $this->car->getColor(),
'type' => $this->car->getType(),
'model' => $this->car->getModel(),
];
}
}
Використання
$car = new Car();
$car->setType('type#');
$car->setModel('model#1');
$car->setColor(255);
$carDecorator = new CarArrayDecorator($car);
$carResponseData = $carDecorator->getArray();
Так буде красивіший і правильніший код.
Перетворення та видалення дратівливих зірок:
$array = (array) $object;
foreach($array as $key => $val)
{
$new_array[str_replace('*_', '', $key)] = $val;
}
Напевно, це буде дешевше, ніж використання роздумів.
Оскільки у багатьох людей виникає це питання через проблеми з атрибутами динамічного доступу до об'єкта, я просто зазначу, що це можна зробити в PHP: $valueRow->{"valueName"}
У контексті (видалено вихід HTML для читабельності):
$valueRows = json_decode("{...}"); // Rows of unordered values decoded from a JSON object
foreach ($valueRows as $valueRow) {
foreach ($references as $reference) {
if (isset($valueRow->{$reference->valueName})) {
$tableHtml .= $valueRow->{$reference->valueName};
}
else {
$tableHtml .= " ";
}
}
}
Використовуючи набір даних, ви можете вирішити свою проблему. Просто додайте наступні рядки до об'єкту повернення:
$arrObj = array(yourReturnedObject);
Ви можете також додати до нього новий ключ і пару значень, використовуючи:
$arrObj['key'] = value;
Я думаю, що це гарна ідея використовувати риси для зберігання логіки перетворення об'єкта в масив. Простий приклад:
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());
$Menu = new Admin_Model_DbTable_Menu();
$row = $Menu->fetchRow($Menu->select()->where('id = ?', $id));
$Addmenu = new Admin_Form_Addmenu();
$Addmenu->populate($row->toArray());
Тут я створив метод objectToArray () , який також працює з рекурсивними об'єктами, наприклад, коли $objectA
містить, $objectB
які вказує знову на$objectA
.
Крім того, я обмежив вихід публічними властивостями за допомогою ReflectionClass. Позбавтеся від нього, якщо вам це не потрібно.
/**
* Converts given object to array, recursively.
* Just outputs public properties.
*
* @param object|array $object
* @return array|string
*/
protected function objectToArray($object) {
if (in_array($object, $this->usedObjects, TRUE)) {
return '**recursive**';
}
if (is_array($object) || is_object($object)) {
if (is_object($object)) {
$this->usedObjects[] = $object;
}
$result = array();
$reflectorClass = new \ReflectionClass(get_class($this));
foreach ($object as $key => $value) {
if ($reflectorClass->hasProperty($key) && $reflectorClass->getProperty($key)->isPublic()) {
$result[$key] = $this->objectToArray($value);
}
}
return $result;
}
return $object;
}
Для ідентифікації вже використаних об'єктів я використовую захищений властивість у цьому (абстрактному) класі, названому $this->usedObjects
. Якщо знайдений рекурсивний вкладений об'єкт, він буде замінений рядком **recursive**
. В іншому випадку це не вдасться через нескінченну петлю.
$usedObjects
не ініціалізується на початку, тому виклик цього декількох разів дасть неправильні результати в пізніших викликах. Крім того, ви не звільняєте його в кінці, тому ваші об'єкти ніколи не будуть вилучені з пам'яті.
Є моя пропозиція, якщо у вас є об’єкти в об’єктах, які мають навіть приватні члени:
public function dismount($object) {
$reflectionClass = new \ReflectionClass(get_class($object));
$array = array();
foreach ($reflectionClass->getProperties() as $property) {
$property->setAccessible(true);
if (is_object($property->getValue($object))) {
$array[$property->getName()] = $this->dismount($property->getValue($object));
} else {
$array[$property->getName()] = $property->getValue($object);
}
$property->setAccessible(false);
}
return $array;
}
Я використовую це (потрібне рекурсивне рішення з належними клавішами):
/**
* This method returns the array corresponding to an object, including non public members.
*
* If the deep flag is true, is will operate recursively, otherwise (if false) just at the first level.
*
* @param object $obj
* @param bool $deep = true
* @return array
* @throws \Exception
*/
public static function objectToArray(object $obj, bool $deep = true)
{
$reflectionClass = new \ReflectionClass(get_class($obj));
$array = [];
foreach ($reflectionClass->getProperties() as $property) {
$property->setAccessible(true);
$val = $property->getValue($obj);
if (true === $deep && is_object($val)) {
$val = self::objectToArray($val);
}
$array[$property->getName()] = $val;
$property->setAccessible(false);
}
return $array;
}
Приклад використання, наступний код:
class AA{
public $bb = null;
protected $one = 11;
}
class BB{
protected $two = 22;
}
$a = new AA();
$b = new BB();
$a->bb = $b;
var_dump($a)
Буде надруковано це:
array(2) {
["bb"] => array(1) {
["two"] => int(22)
}
["one"] => int(11)
}
ArrayAccess
інтерфейс, можливо в поєднанні з цим рішенням. php.net/manual/en/class.arrayaccess.php