Вы пишете код, а PHP кричит: «Не трогай меня как массив!»
Представьте: вы получили данные от API. Всё красиво, JSON распарсен, вы уверены, что перед вами массив. Вы обращаетесь к элементу по ключу — и вместо результата видите Fatal error: Cannot use object of type stdClass as array. Знакомо? Эта ошибка — одна из самых частых ловушек для начинающих (и не только) PHP-разработчиков. На Stack Overflow её обсудили тысячи раз. Сегодня мы не просто объясним, почему она возникает, но и сравним 5 подходов, как её обойти или предотвратить. Вы узнаете, какой метод подходит для вашей задачи, и навсегда забудете о панике при виде stdClass.
Эта статья — для тех, кто пишет на PHP, работает с JSON, REST API или базами данных. Мы говорим на русском, но с живыми примерами кода. Поехали!
Почему возникает ошибка? Корень зла — stdClass
В PHP есть встроенный класс stdClass (standard class). Он используется как «пустой» объект, когда вы, например, вызываете json_decode() без второго параметра. По умолчанию json_decode возвращает объект, а не массив. И если вы затем пытаетесь обратиться к его свойству через квадратные скобки — PHP возмущается.
<?php
$json = '{"name": "Анна", "age": 25}';
$data = json_decode($json); // возвращает объект stdClass
echo $data['name']; // Fatal error: Cannot use object of type stdClass as array
?>
Объект и массив в PHP — разные типы. У объекта доступ к свойствам через ->, у массива — через []. Смешивать их нельзя. Но что делать, если вы не контролируете источник данных? Или если в коде legacy всё завязано на массивы? Давайте разбираться.
Подход 1: Приведение типа (array) — быстро, но с сюрпризами
Самый очевидный способ — явно привести объект к массиву с помощью (array). Это сработает, но не всегда так, как вы ожидаете.
<?php
$json = '{"name": "Анна", "age": 25}';
$data = (array) json_decode($json);
echo $data['name']; // Анна — работает!
?>
Всё хорошо? Не совсем. Если объект содержит вложенные объекты, они не преобразуются рекурсивно. Внутри останутся stdClass, и при попытке обратиться к ним как к массиву ошибка вернётся.
<?php
$json = '{"user": {"name": "Анна", "age": 25}}';
$data = (array) json_decode($json);
echo $data['user']['name']; // Снова ошибка! user — это объект
?>
Когда использовать: для плоских JSON-структур без вложенности. Быстро, но неглубоко.
Подход 2: json_decode с флагом true — золотой стандарт
Самый популярный и надёжный способ — передать true вторым аргументом в json_decode. Тогда функция вернёт ассоциативный массив, а не объект. И вложенные структуры тоже будут массивами.
<?php
$json = '{"user": {"name": "Анна", "age": 25}}';
$data = json_decode($json, true); // true — возвращаем массив
echo $data['user']['name']; // Анна — без ошибок
?>
Этот подход — рекомендуемый в документации PHP и в сообществе. Он решает проблему на корню, не требуя дополнительных преобразований.
Когда использовать: всегда, когда вы работаете с JSON и ожидаете массив. Единственный минус — если вы забыли поставить true.
Подход 3: Рекурсивное преобразование — для сложных структур
Иногда данные приходят не только из JSON, но и из других источников: базы данных, SOAP, XML-парсеров. И вы получаете готовый объект, который нужно превратить в массив любой ценой. Тут поможет рекурсивная функция.
<?php
function objectToArray($data) {
if (is_object($data)) {
$data = get_object_vars($data);
}
if (is_array($data)) {
return array_map(__FUNCTION__, $data);
}
return $data;
}
$obj = json_decode('{"a": {"b": {"c": "test"}}}');
$arr = objectToArray($obj);
echo $arr['a']['b']['c']; // test — работает!
?>
Функция get_object_vars получает все видимые свойства объекта. array_map с __FUNCTION__ применяет ту же функцию рекурсивно. Это полный и безопасный способ.
Когда использовать: если вы не знаете глубину вложенности или работаете с legacy-кодом, где объекты приходят «как есть». Но помните: рекурсия может быть ресурсоёмкой для очень глубоких структур.
Подход 4: Доступ через свойство объекта — не бойтесь ->
Альтернатива — не преобразовывать, а просто научиться работать с объектом. Вместо $data['name'] пишите $data->name. Для вложенных свойств — цепочка $data->user->name.
<?php
$json = '{"user": {"name": "Анна", "age": 25}}';
$data = json_decode($json);
echo $data->user->name; // Анна — никаких ошибок
?>
Этот подход особенно удобен, когда вы используете строгую типизацию или работаете с ORM, где объекты — основной формат данных.
Когда использовать: если вы контролируете код и готовы везде использовать синтаксис объекта. Минус — смешивание стилей (объекты и массивы) в одном проекте может запутать.
Подход 5: Строгая типизация и проверки — защита от дурака
Лучшая ошибка — та, которую вы не допустили. Используйте проверки типов с помощью is_object(), is_array() и gettype(). Это не решит проблему глобально, но убережёт от фатальных ошибок в рантайме.
<?php
$data = json_decode($json);
if (is_object($data)) {
$name = $data->name ?? 'default';
} elseif (is_array($data)) {
$name = $data['name'] ?? 'default';
} else {
$name = 'default';
}
echo $name;
?>
Или, если вы используете PHP 8+, можно применить match:
<?php
$name = match (true) {
is_object($data) => $data->name ?? 'default',
is_array($data) => $data['name'] ?? 'default',
default => 'default