Не можете использовать объект типа stdClass в качестве массива?

541

Я получаю странную ошибку, используя json_decode(). Он правильно декодирует данные (я видел это с помощью print_r), но когда я пытаюсь получить доступ к информации внутри массива, я получаю:

Fatal error: Cannot use object of type stdClass as array in
C:\Users\Dail\software\abs.php on line 108

Я только попытался сделать: $result['context']где $resultданные, возвращенныеjson_decode()

Как я могу прочитать значения внутри этого массива?

нижняя палата парламента Ирландии
источник
15
$ result = json_decode ('the string', true); Добавление true возвращает результат в виде массива, а не stdClass.
Непалуз

Ответы:

790

Используйте второй параметр, json_decodeчтобы он возвращал массив:

$result = json_decode($data, true);
Джон
источник
209

Функция json_decode()возвращает объект по умолчанию.

Вы можете получить доступ к данным, как это:

var_dump($result->context);

Если у вас есть идентификаторы типа from-date(дефис может вызвать ошибку PHP при использовании вышеуказанного метода), вы должны написать:

var_dump($result->{'from-date'});

Если вы хотите массив, вы можете сделать что-то вроде этого:

$result = json_decode($json, true);

Или приведите объект к массиву:

$result = (array) json_decode($json);
Svens
источник
2
Мне понадобилось некоторое время, чтобы найти это, когда я пытался найти способ обратиться к значению _destroy в php, установленному knockoutjs, так что +1
deltree
2
Этот ответ гораздо более квалифицирован, чем первый (самый рейтинговый) ответ!
Мойтаба Резаян
149

Вы должны получить к нему доступ, используя ->его как объект.

Измените свой код с:

$result['context'];

Для того, чтобы:

$result->context;
JiNexus
источник
Проблема, которую я имею, пытается использовать свойство в условном if ($result->context = $var) выражении. Это приводит к тому, что для свойства устанавливается значение var, и возвращается значение true, независимо от того,
STWilson
3
@STWilson вы должны использовать двойное равенство ==, в текущем состоянии вы присваиваете $varзначение $result->contextс помощью одного равенства =. И он if statementбудет читать его так, как если бы он был пустым или нет, а если он $varимеет значение, то это означает, что он не пустой и всегда будет возвращать true.
JiNexus
89

Есть сегодня та же проблема, решаемая так:

Если вы позвоните, json_decode($somestring)вы получите объект, и вам нужно получить доступ к как $object->key, но если вы позвоните, json_decode($somestring, true)вы получите словарь и можете получить доступ к как$array['key']

Алексей Лысенко
источник
2
Это сэкономило мне ооочень много времени! Я не
вводил
87

Используйте trueв качестве второго параметра для json_decode. Это будет декодировать JSON в ассоциативный массив вместо stdObjectэкземпляров:

$my_array = json_decode($my_json, true);

Смотрите документацию для более подробной информации.

Сандер Марешаль
источник
61

Это не массив, это объект типа stdClass.

Вы можете получить к нему доступ следующим образом:

echo $oResult->context;

Больше информации здесь: Что такое stdClass в PHP?

Уэсли ван Опдорп
источник
28

Как сказано в руководстве Php ,

print_r - печатает удобочитаемую информацию о переменной

Когда мы используем json_decode();, мы получаем объект типа stdClass в качестве возвращаемого типа. Аргументы, которые должны передаваться внутри, print_r()должны быть либо массивом, либо строкой. Следовательно, мы не можем передать объект внутрь print_r(). Я нашел 2 способа справиться с этим.

  1. Приведите объект к массиву.
    Это может быть достигнуто следующим образом.

    $a = (array)$object;
  2. Получая доступ к ключу Object
    Как упоминалось ранее, когда вы используете json_decode();функцию, она возвращает Object из stdClass. Вы можете получить доступ к элементам объекта с помощью ->оператора.

    $value = $object->key;

Во-первых, можно также использовать несколько ключей для извлечения вложенных элементов в случае, если у объекта есть вложенные массивы.

$value = $object->key1->key2->key3...;

Есть и другие варианты, print_r()как, например, var_dump();иvar_export();

PS : Кроме того, если вы установите второй параметр json_decode();для true, он автоматически преобразует объект в array();
Вот некоторые ссылки:
http://php.net/manual/en/function.print-r.php
http: // php.net/manual/en/function.var-dump.php
http://php.net/manual/en/function.var-export.php

Панда
источник
12

Чтобы получить массив как результат из строки json, вы должны установить второй параметр как логическое значение true.

$result = json_decode($json_string, true);
$context = $result['context'];

В противном случае $ result будет объектом std. но вы можете получить доступ к значениям как объект.

  $result = json_decode($json_string);
 $context = $result->context;
infomasud
источник
8

Когда вы пытаетесь обратиться к нему как $result['context'], вы рассматриваете его как массив, ошибка говорит вам, что вы на самом деле имеете дело с объектом, тогда вы должны получить к нему доступ как$result->context

Мидас Мтилени
источник
4

Вот подпись функции:

mixed json_decode ( string $json [, bool $assoc = false [, int $depth = 512 [, int $options = 0 ]]] )

Когда param равен false, что по умолчанию, он вернет соответствующий тип php. Вы получаете значение этого типа, используя парадигму object.method.

Когда параметр равен true, он возвращает ассоциативные массивы.

Он вернет NULL в случае ошибки.

Если вы хотите получить значение через массив, установите для Assoc значение true.

Роберт
источник
3

Иногда при работе с API вы просто хотите сохранить объект объектом. Чтобы получить доступ к объекту, который имеет вложенные объекты, вы можете сделать следующее:

Мы предполагаем, что когда вы печатаете объект, вы можете увидеть это:

print_r($response);

stdClass object
(
    [status] => success
    [message] => Some message from the data
    [0] => stdClass object
        (
            [first] => Robert
            [last] => Saylor
            [title] => Symfony Developer
        )
    [1] => stdClass object
        (
            [country] => USA
        )
)

Для доступа к первой части объекта:

print $response->{'status'};

И это приведет к «успеху»

Теперь давайте напишем другие части:

$first = $response->{0}->{'first'};
print "First name: {$first}<br>";

Ожидаемый результат будет "Роберт" с разрывом строки.

Вы также можете переназначить часть объекта другому объекту.

$contact = $response->{0};
print "First Name: " . $contact->{'first'} . "<br>";

Ожидаемый результат будет "Роберт" с разрывом строки.

Для доступа к следующей клавише «1» процесс такой же.

print "Country: " . $response->{1}->{'country'} . "<br>";

Ожидаемый результат будет "США"

Надеюсь, это поможет вам понять объекты и почему мы хотим, чтобы объект был объектом. Вам не нужно преобразовывать объект в массив для доступа к его свойствам.

Роберт Сэйлор
источник
2

вместо использования скобок используйте оператор объекта, например, мой массив, основанный на объекте базы данных, создается следующим образом в классе DB:

class DB {
private static $_instance = null;
private $_pdo,
        $_query, 
        $_error = false,
        $_results,
        $_count = 0;



private function __construct() {
    try{
        $this->_pdo = new PDO('mysql:host=' . Config::get('mysql/host') .';dbname=' . Config::get('mysql/db') , Config::get('mysql/username') ,Config::get('mysql/password') );


    } catch(PDOException $e) {
        $this->_error = true;
        $newsMessage = 'Sorry.  Database is off line';
        $pagetitle = 'Teknikal Tim - Database Error';
        $pagedescription = 'Teknikal Tim Database Error page';
        include_once 'dbdown.html.php';
        exit;
    }
    $headerinc = 'header.html.php';
}

public static function getInstance() {
    if(!isset(self::$_instance)) {
        self::$_instance = new DB();
    }

    return self::$_instance;

}


    public function query($sql, $params = array()) {
    $this->_error = false;
    if($this->_query = $this->_pdo->prepare($sql)) {
    $x = 1;
        if(count($params)) {
        foreach($params as $param){
            $this->_query->bindValue($x, $param);
            $x++;
            }
        }
    }
    if($this->_query->execute()) {

        $this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
        $this->_count = $this->_query->rowCount();

    }

    else{
        $this->_error = true;
    }

    return $this;
}

public function action($action, $table, $where = array()) {
    if(count($where) ===3) {
        $operators = array('=', '>', '<', '>=', '<=');

        $field      = $where[0];
        $operator   = $where[1];
        $value      = $where[2];

        if(in_array($operator, $operators)) {
            $sql = "{$action} FROM {$table} WHERE {$field} = ?";

            if(!$this->query($sql, array($value))->error()) {
            return $this;
            }
        }

    }
    return false;
}

    public function get($table, $where) {
    return $this->action('SELECT *', $table, $where);

public function results() {
    return $this->_results;
}

public function first() {
    return $this->_results[0];
}

public function count() {
    return $this->_count;
}

}

для доступа к информации я использую этот код на скрипте контроллера:

<?php
$pagetitle = 'Teknikal Tim - Service Call Reservation';
$pagedescription = 'Teknikal Tim Sevice Call Reservation Page';
require_once $_SERVER['DOCUMENT_ROOT'] .'/core/init.php';
$newsMessage = 'temp message';

$servicecallsdb = DB::getInstance()->get('tt_service_calls', array('UserID',
 '=','$_SESSION['UserID']));

if(!$servicecallsdb) {
// $servicecalls[] = array('ID'=>'','ServiceCallDescription'=>'No Service Calls');
} else {
$servicecalls = $servicecallsdb->results();
}
include 'servicecalls.html.php';



?>

затем, чтобы отобразить информацию, которую я проверяю, чтобы увидеть, установлены ли servicecalls и имеет ли счет больше 0, помните, что это не массив, на который я ссылаюсь, поэтому я обращаюсь к записям с помощью оператора объекта "->" следующим образом:

<?php include $_SERVER['DOCUMENT_ROOT'] .'/includes/header.html.php';?>
<!--Main content-->
<div id="mainholder"> <!-- div so that page footer can have a minum height from the
  header -->
<h1><?php if(isset($pagetitle)) htmlout($pagetitle);?></h1>
<br>
<br>
<article>
    <h2></h2>
</article>
<?php
if (isset($servicecalls)) {
if (count ($servicecalls) > 0){
     foreach ($servicecalls as $servicecall) {
        echo '<a href="https://stackoverflow.com/servicecalls/?servicecall=' .$servicecall->ID .'">'
  .$servicecall->ServiceCallDescription .'</a>';
    }
}else echo 'No service Calls';

}

?>
<a href="/servicecalls/?new=true">Raise New Service Call</a>
</div> <!-- Main content end-->
<?php include $_SERVER['DOCUMENT_ROOT'] .'/includes/footer.html.php'; ?>
timmac15
источник
2

Я получил эту ошибку на ровном месте, потому что мой логин на facebook неожиданно перестал работать (я также сменил хостов) и выкинул эту ошибку. Исправить это действительно легко

Проблема была в этом коде

  $response = (new FacebookRequest(
    FacebookSession::newAppSession($this->appId, $this->appSecret),
    'GET',
    '/oauth/access_token',
    $params
  ))->execute()->getResponse(true);

  if (isset($response['access_token'])) {       <---- this line gave error
    return new FacebookSession($response['access_token']);
  }

В основном функция isset () ожидает массив, но вместо этого находит объект. Простое решение - преобразовать объект PHP в массив, используя квантификатор (массив) . Ниже приведен фиксированный код.

  $response = (array) (new FacebookRequest(
    FacebookSession::newAppSession($this->appId, $this->appSecret),
    'GET',
    '/oauth/access_token',
    $params
  ))->execute()->getResponse(true);

Обратите внимание на использование квантификатора off array () в первой строке.

Хаммад хан
источник
1

Поменяй это на

$results->fetch_array()
Дэн Падилья
источник