整数のような名前のオブジェクトプロパティにアクセスする方法は?


87

私はjson_decode()次のようなものを使用しています:

$myVar = json_decode($data)

これは私にこのような出力を与えます:

[highlighting] => stdClass Object
        (
            [448364] => stdClass Object
                (
                    [Data] => Array
                        (
                            [0] => Tax amount liability is ....... 

キー[0]の文字列値にアクセスしたい。私が次のようなことをしようとすると:

print $myVar->highlighting->448364->Data->0;

私はこのエラーを受け取ります:

解析エラー:構文エラー、予期しないT_DNUMBER

2つの数字/整数に問題があるようです。



1
@FelixKling:私もCVを行いましたが、実際にはそれはだまされていないことがわかります:プロパティ名数字で始まるか、すべて数字であるかによって違いが生じます
Jon

@ジョン:うーん、面白い...私が推測する前にテストをするべきだった。知らせてくれてありがとうございます!
Felix Kling 2012

回答:


286

PHP 7.2用に更新

PHP 7.2では、オブジェクトおよび配列キャストの数値キーの変換に動作上の変更が導入されました。これにより、この特定の不整合が修正され、以下のすべての例が期待どおりに動作します。

混乱することは1つ少なくなります!


元の回答(7.2.0より前のバージョンに適用)

PHPには、あなた自分の中にいることを本当に望んでいない暗い路地があります。番号である名前を持つオブジェクトプロパティはその1つです...

彼らがあなたに言わなかったこと

事実#1:正当な変数名ではない名前のプロパティには簡単にアクセスできない

$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->123foo; // error

事実#2:あなたは、することができます {}括弧構文で、このようなプロパティにアクセス

$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // OK!

事実#3:しかし、プロパティ名がすべて数字の場合はそうではありません

$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // OK!
echo $o->{'123'}; // error!

ライブの例

事実#4:まあ、そもそもオブジェクトが配列からのものでない限り。

$a = array('123' => '123');
$o1 = (object)$a;
$o2 = new stdClass;
$o2->{'123'} = '123'; // setting property is OK

echo $o1->{'123'}; // error!
echo $o2->{'123'}; // works... WTF?

ライブの例

かなり直感的だと思いませんか?

あなたにできること

オプション#1:手動で行う

最も実用的な方法は、関心のあるオブジェクトを配列にキャストして、プロパティにアクセスできるようにすることです。

$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
$a = (array)$o;
echo $o->{'123'}; // error!
echo $a['123']; // OK!

残念ながら、これは再帰的に機能しません。したがって、あなたの場合は次のようなことをする必要があります:

$highlighting = (array)$myVar->highlighting;
$data = (array)$highlighting['448364']->Data;
$value = $data['0']; // at last!

オプション#2:核オプション

別のアプローチは、オブジェクトを配列に再帰的に変換する関数を書くことです:

function recursive_cast_to_array($o) {
    $a = (array)$o;
    foreach ($a as &$value) {
        if (is_object($value)) {
            $value = recursive_cast_to_array($value);
        }
    }

    return $a;
}

$arr = recursive_cast_to_array($myVar);
$value = $arr['highlighting']['448364']['Data']['0'];

ただし、これが全体的に優れたオプションであるとは確信していません。不要なプロパティだけでなく、興味のないプロパティもすべて配列に不必要にキャストするからです。

オプション#3:賢くプレイする

前のオプションの代替方法は、組み込みのJSON関数を使用することです。

$arr = json_decode(json_encode($myVar), true);
$value = $arr['highlighting']['448364']['Data']['0'];

JSON関数は、外部関数を定義する必要なく、配列への再帰的な変換を効果的に実行します。これがどのように見えても、オプション#2の「核」の欠点があり、さらにオブジェクト内に文字列がある場合、それらの文字列をUTF-8でエンコードする必要があるという欠点があります(これはの要件ですjson_encode)。


たまたま私の問題は解決しました!stackoverflow.com/questions/4643894/...
Bossliaw

ジョン、助けてくれてありがとう。私の問題は異なっていました(おそらく、「彼らがあなたに言わなかったこと」の部分にあると思います)。DBから取得したDateTimeオブジェクトは問題ないようですが、->dateまたはなどのプロパティにアクセスすると、返される->timezoneだけnullです。これらのプロパティを使用する前にオブジェクトをvar_dumpした場合、適切な値が返されることに気付きました。クローンはこれを修正しません、それでそれは本当にそれがするアクセスと何か関係があると思いvar_dumpます...それから私はあなたのオプション#1とvoiláを見て、配列($objCastAsArray['date'])としてアクセスすることは魅力のように機能しました。
アームフット2013

1
事実#0:配列をオブジェクトにキャストしても、そもそも臭いことはないはずです。事実#1から事実#3:不要。
Pacerier 2015年

4
@Pacerier:それはやや疑わしいと思いますが、状況によっては完全に理にかなっています。とにかく、このように動作するようにマニュアルに記載されているので、私たちの個人的な意見はそれほど重要ではありません。
Jon

UTF-8を必要としないオプション#3の代替案は$o = unserialize('O:8:"StdClass"' . substr(serialize($a),1));
OscarJ

10

ジョンの雄弁な説明に、これが失敗する理由を追加したかっただけです。配列を作成するときに、phpはキーを整数に変換します(可能な場合)。これは、数値キーが保持されているために、オブジェクトにキャストされた配列でルックアップの問題を引き起こします。すべてのプロパティアクセスオプションが文字列を予期するか、文字列に変換するため、これには問題があります。これを確認するには、次の手順を実行します。

$arr = array('123' => 'abc');
$obj = (object) $arr;
$obj->{'123'} = 'abc';
print_r( $obj );

どちらが出力されます:

stdClass Object ( 
  [123] => 'abc', 
  [123] => 'abc'
)

したがって、オブジェクトには2つのプロパティキーがあり、1つは数値(アクセスできません)と1つの文字列ベースです。これがJonが機能する理由#Fact 4です。中かっこを使用してプロパティを設定すると、数値ではなく常に文字列ベースのキーが定義されるためです。

Jonの解決策を採用しますが、その頭をオンにすると、次のようにして、常に文字列ベースのキーを持つ配列からオブジェクトを生成できます。

$obj = json_decode(json_encode($arr));

今後は、この方法でアクセスすると常に中括弧内の値が文字列に変換されるため、次のいずれかを使用できます。

$obj->{123};
$obj->{'123'};

古き良き非論理的なPHP ...


1

オブジェクトが次の@ように始まる場合:

SimpleXMLElement Object (
    [@attributes] => Array (
        [href] => qwertyuiop.html
        [id] => html21
        [media-type] => application/xhtml+xml
    )
)

使用する必要があります:

print_r($parent_object->attributes());

$parent_object->{'@attributes'}または$parent_object['@attributes']動作しませんので。


3年後、これはまだ人々を助けています、ありがとう!あなたの答えは私の問題を修正しますが、説明はありません。この背後にある理由を説明できる人はいますか?
アービター

1

この機能をネットからコピーしました。それが言うように機能する場合(「stdClassオブジェクトを多次元配列に変換する関数」)、以下を試してください。

<?php

    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;
        }
    }

?>
  • 最初に配列をobjectToArray関数に渡します
  • それから戻り値を取ります
  • エコー [highlighting][448364][Data][0]

ソース:PHP stdClass to ArrayおよびArray to stdClass


1

ジョンの包括的な答えの最後の選択肢:

2番目のパラメーターをtrueに設定してjson_decode()を使用するだけです

$array = json_decode($url, true);

これはオブジェクトではなく連想配列を返すため、事後に変換する必要はありません。

これはすべてのアプリケーションに適しているわけではありませんが、元のオブジェクトのプロパティを簡単に参照するのに役立ちました。

このチュートリアルで解決策が見つかりました-http://nitschinger.at/Handling-JSON-like-a-boss-in-PHP/

よろしく


1

PHP 7の場合

プロパティ名として数字を持つオブジェクトプロパティへのアクセス。ほとんどの場合、配列をオブジェクトにキャストした後に必要です。

    $arr = [2,3,7];
    $o = (object) $arr;

    $t = "1";
    $t2 = 1;
    $t3 = (1);

    echo $o->{1};      // 3
    echo $o->{'1'};   // 3
    echo $o->$t;        // 3
    echo $o->$t2;       // 3
    echo $o->$t3;       // 3

    echo $o->1;       // error
    echo $o->(1);      // error

0

数字で始まるオブジェクトに名前を付けることは許可されていません。文字で始まる最初の「448364」の名前を変更します。

2つ目は配列で、次のように角かっこでアクセスします。

print myVar->highlighting->test_448364->Data[0]

代わりに


変更できません。出力は、私が制御できないアプリケーションから返されます。
avinash shah 2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.