Как преобразовать PHP объект в ассоциативный массив
Я интегрирую API на свой сайт, который работает с данными, хранящимися в объектах, в то время как мой код написан с использованием массивов. Мне нужна функция для преобразования PHP объектов в ассоциативные массивы.
Постановка проблемы
- API возвращает данные в виде PHP объектов
- Мой существующий код использует массивы для обработки данных
- Необходимо преобразовывать объекты в массивы для совместимости
Требования
- Ищу простую функцию для преобразования объектов в массивы
- Решение должно обрабатывать вложенные объекты, если это возможно
- Нужно сохранять отношения ключ-значение при преобразовании
Какой самый эффективный способ преобразовать PHP объект в ассоциативный массив в PHP?
Проще всего преобразовать PHP объект в ассоциативный массив (php to array) — привести объект к (array) для простых случаев; для вложенных структур лучше рекурсивная функция, сохраняющая отношения ключ‑значение. Быстрый хак — json_decode(json_encode($obj), true), но он теряет типы (DateTime, ресурсы), ломается на циклах и чувствителен к кодировке. Ниже — практичные примеры, готовая рекурсивная функция и рекомендации по выбору метода.
Содержание
- Быстрый способ: приведение (array)
- Рекурсивная функция — преобразовать объект в массив рекурсивно
- JSON-подход (json_encode → json_decode)
- Краевые случаи: DateTime, приватные свойства, циклы, ресурсы
- Полный пример: безопасная рекурсивная функция
- Советы по производительности и выбору метода
- Источники
- Заключение
Быстрый способ: приведение (array) — преобразовать объект в массив
Если вам нужно быстро преобразовать верхний уровень объекта в массив — используйте приведение (array). Просто, быстро, но поверхностно: вложенные объекты останутся объектами.
Пример:
$obj = (object) ['id' => 1, 'meta' => (object) ['author' => 'Ivan']];
$arr = (array) $obj;
// $arr['meta'] всё ещё stdClass
var_dump($arr);
Когда подходит
- Простые ответы API без вложенных объектов.
- Нужна скорость и минимум кода.
Ограничения
- Не рекурсивно: вложенные stdClass останутся объектами.
- Приватные/защищённые свойства кодируются с нулевыми байтами (см. ниже).
- Для поверхностного описания приведения см. объяснение в блоге: https://medium.com/@mavelar/convert-array-to-object-object-to-array-in-php-e430ae492951
Рекурсивная функция — преобразовать объект в массив рекурсивно
Нужно сохранить вложенные структуры и ключ‑значение? Тогда рекурсивная функция — стандартный путь. Вот короткая и понятная реализация (на основе практик с StackOverflow и php.net):
function object_to_array_recursive($input, &$visited = []) {
if (is_object($input)) {
// Обрабатываем распространённые специальные объекты
if ($input instanceof \DateTimeInterface) {
return $input->format(\DateTime::ATOM);
}
if ($input instanceof \JsonSerializable) {
$input = $input->jsonSerialize();
} else {
$oid = spl_object_hash($input);
if (isset($visited[$oid])) {
return null; // отметка рекурсии
}
$visited[$oid] = true;
$input = get_object_vars($input); // возвращает массив свойств объекта
}
}
if (is_array($input)) {
$result = [];
foreach ($input as $key => $val) {
// убираем кодировку приватных/защищённых ключей "\0ClassName\0prop"
$cleanKey = is_string($key) ? preg_replace('/^\0.*\0/', '', $key) : $key;
$result[$cleanKey] = object_to_array_recursive($val, $visited);
}
return $result;
}
return $input; // скаляр, null или ресурс (можно обрабатывать отдельно)
}
Пояснения и ссылки:
- Функция
get_object_varsвозвращает доступные свойства объекта; формат ключей описан в официальной документации: https://www.php.net/manual/en/function.get-object-vars.php - Примеры рекурсивных реализаций — обсуждение на StackOverflow: https://stackoverflow.com/questions/22676150/php-recursively-convert-object-to-array и https://stackoverflow.com/questions/4345554/convert-a-php-object-to-an-associative-array
JSON-подход (json_encode → json_decode)
Самый короткий код для глубокой конверсии:
$arr = json_decode(json_encode($obj), true);
Плюсы
- Очень простая запись; рекурсивно переводит структуру.
- Часто быстрее, чем простая рекурсия для больших массивов (но зависит от данных).
Минусы
- Потеря типов: DateTime и объекты станут строками или массивами; ресурсы не кодируются.
- Циклические ссылки приведут к ошибке или потере данных.
- Требует UTF‑8: при другой кодировке
json_encodeможет вернуть false (см. предупреждение в gist): https://gist.github.com/victorbstan/744478 - Обзор метода с предупреждениями: https://www.geeksforgeeks.org/php/convert-an-object-to-associative-array-in-php/
Когда использовать
- Когда структура простая и данные — чисто JSON‑совместимые (API обычно возвращают JSON‑совместимые объекты).
- Быстрое прототипирование.
Краевые случаи: DateTime, приватные свойства, циклы, ресурсы
DateTime и похожие объекты
- DateTime лучше явно форматировать:
$dt->format(DATE_ATOM)или обрабатывать в рекурсии черезinstanceof \DateTimeInterface.
Приватные и защищённые свойства
get_object_vars(и приведение(array)) вернут ключи вида “\0ClassName\0property” для приватных/protected. Очищайте ключи регулярным выражением:preg_replace('/^\0.*\0/', '', $key).
Циклические ссылки
- Чтобы не попасть в бесконечную рекурсию, отслеживайте посещённые объекты через
spl_object_hash(см. пример выше). Альтернатива —SplObjectStorage.
Ресурсы и нестандартные типы
- Ресурсы нельзя корректно сериализовать в массив; обычно возвращают
nullили идентификатор ресурса в строковом виде. - JSON‑метод ломается при не‑UTF8. Подробный разбор: https://gist.github.com/victorbstan/744478
Дополнительная обработка
- После конверсии можно пройтись по массиву и преобразовать значения (например, привести числа, распарсить даты) с помощью
array_walk_recursive: https://www.php.net/manual/en/function.array-walk-recursive.php
Полный пример: безопасная рекурсивная функция
Вот более полный вариант с защитой от рекурсии и обработкой распространённых случаев:
function obj_to_array_safe($input, &$visited = [], $depth = 0, $maxDepth = 512) {
if ($depth > $maxDepth) {
return null; // защита от слишком глубокой рекурсии
}
if (is_object($input)) {
if ($input instanceof \DateTimeInterface) {
return $input->format(\DateTime::ATOM);
}
if ($input instanceof \JsonSerializable) {
$input = $input->jsonSerialize();
} else {
$oid = spl_object_hash($input);
if (isset($visited[$oid])) {
return ['__recursion' => true];
}
$visited[$oid] = true;
$input = get_object_vars($input);
}
}
if (is_array($input)) {
$out = [];
foreach ($input as $k => $v) {
$cleanKey = is_string($k) ? preg_replace('/^\0.*\0/', '', $k) : $k;
$out[$cleanKey] = obj_to_array_safe($v, $visited, $depth + 1, $maxDepth);
}
return $out;
}
if (is_resource($input)) {
return null;
}
return $input;
}
// Использование:
$array = obj_to_array_safe($apiResponse);
Ещё вариант: сначала проверить, есть ли у объекта метод toArray (часто в библиотеках и моделях):
if (method_exists($obj, 'toArray')) {
$array = $obj->toArray();
} else {
$array = obj_to_array_safe($obj);
}
Советы по производительности и выбору метода
Какой способ выбрать?
- Нужна скорость и структура неглубока —
(array)(приведение). - Нужна корректная обработка вложенных структур и особых типов — рекурсивная функция (предпочтительно).
- Быстро и удобно для JSON‑совместимых данных —
json_decode(json_encode(...), true)(но помните про потерю типов и кодировку).
Дополнительные рекомендации
- Для больших ответов API сравните по производительности:
jsonvs рекурсия — всё зависит от структуры данных; блог и Gist обсуждают производительность и ограничения (см. https://ben.lobaugh.net/blog/567/php-recursively-convert-an-object-to-an-array и https://gist.github.com/victorbstan/744478). - Если используете фреймворк — проверьте стандартные методы (
toArray,getArrayCopyдля ArrayObject). - После конверсии применяйте
array_walk_recursiveдля финальной нормализации значений, если нужно.
Источники
- https://stackoverflow.com/questions/4345554/convert-a-php-object-to-an-associative-array
- https://stackoverflow.com/questions/22676150/php-recursively-convert-object-to-array
- https://www.php.net/manual/en/function.get-object-vars.php
- https://www.php.net/manual/en/function.array-walk-recursive.php
- https://www.geeksforgeeks.org/php/convert-an-object-to-associative-array-in-php/
- https://ben.lobaugh.net/blog/567/php-recursively-convert-an-object-to-an-array
- https://gist.github.com/victorbstan/744478
- https://jsontophp.com/
- https://medium.com/@mavelar/convert-array-to-object-object-to-array-in-php-e430ae492951
Заключение
Если цель — просто и быстро преобразовать объект в массив, начните с (array); для надёжной конверсии вложенных структур используйте рекурсивную функцию (или финальный пример выше). Быстрый способ через json_decode(json_encode(...), true) удобен, но он не сохраняет типы и чувствителен к циклам и кодировке. В большинстве интеграций API оптимальным будет рекурсивный подход, который корректно преобразует stdClass в ассоциативные массивы и сохраняет отношения ключ‑значение.