정수와 같은 이름으로 개체 속성에 액세스하는 방법은 무엇입니까?


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

두 개의 숫자 / 정수에 문제가있는 것 같습니다.



1
@FelixKling : 저도 이력서를 작성했지만 실제로 속임수는 아닙니다. 속성 이름 숫자로 시작 하거나 모두 숫자 이면 차이 가 있습니다 !
Jon

@Jon : 음, 흥미 롭군요 ... 제가 추측하기 전에 테스트를 했어야했습니다. 알려 줘서 고마워!
Felix Kling

답변:


286

PHP 7.2 용으로 업데이트 됨

PHP 7.2는 객체 및 배열 캐스트의 숫자 키 변환에 대한 동작 변경을 도입하여 이러한 특정 불일치를 수정하고 다음 예제가 모두 예상대로 동작하도록합니다.

혼란 스러울 것이 하나 줄었습니다!


원래 답변 (7.2.0 이전 버전에 적용)

PHP는 당신이 실제로 자신을 찾고 싶지 않은 어두운 골목을 가지고 있습니다 . 이름이 숫자 인 개체 속성도 그중 하나입니다.

그들이 당신에게 말하지 않은 것

사실 # 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의 "nuke"단점 과 추가로 객체 내부에 문자열이있는 경우 해당 문자열 이 UTF-8로 인코딩 되어야 한다는 단점이 있습니다 (이는의 요구 사항입니다 json_encode).


내 문제도 해결되었습니다! stackoverflow.com/questions/4643894/...
Bossliaw

존, 구해줘 서 고마워. 하지만 내 문제는 달랐습니다 (정말 "그들이 말하지 않은"부분에있는 것 같습니다). DB에서 검색 한 DateTime 개체가 확인을 보인다하지만 같은 속성의 액세스하는 경우 ->date또는 ->timezonenull반환됩니다. 이러한 속성을 사용하기 전에 개체를 var_dumped하면 적절한 값이 반환됩니다. 복제는이 문제를 해결하지 못하므로 실제로 액세스와 관련이있는 것 같습니다 var_dump. 그런 다음 옵션 # 1과 voilá를 보았습니다. 배열 ( $objCastAsArray['date']) 로 액세스하는 것이 매력처럼 작동했습니다.
Armfoot

1
사실 # 0 : 배열을 객체로 캐스팅하는 것은 애초에 악취가 나는 것이 아닙니다. 사실 # 1에서 사실 # 3 : 불필요.
Pacerier 2015 년

4
@Pacerier : 다소 의문의 여지가 있다는 데 동의하지만 일부 상황에서는 완전히 이해할 수 있습니다. 어쨌든 이렇게 작동하는 것이 매뉴얼에 문서화 되어 있기 때문에 우리의 개인적인 의견은별로 중요하지 않습니다.
Jon

UTF-8이 될 필요하지 않습니다 옵션 # 3의 대안$o = unserialize('O:8:"StdClass"' . substr(serialize($a),1));
OscarJ

10

이것이 실패하는 이유를 Jon의 웅변적인 설명에 추가하고 싶었습니다. 배열을 만들 때 php가 키를 정수로 변환하기 때문입니다. 가능하다면 숫자 키가 보존되어 있기 때문에 객체로 캐스트 된 배열에서 조회 문제가 발생합니다. 모든 속성 액세스 옵션이 문자열로 예상되거나 변환되기 때문에 이는 문제가됩니다. 다음을 수행하여이를 확인할 수 있습니다.

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

다음과 같이 출력됩니다.

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

따라서 객체에는 두 개의 속성 키가 있습니다. 하나는 숫자 (액세스 할 수 없음)이고 하나는 문자열 기반입니다. 이것이 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 년 후에도 여전히 사람들을 돕고 있습니다. 감사합니다! 귀하의 답변은 내 문제를 해결하지만 설명이 부족합니다. 누구든지 그 이유를 설명 할 수 있습니까?
중재인 dec

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에서 Array로, Array에서 stdClass로


1

Jon의 포괄적 인 답변에 대한 최종 대안 :

두 번째 매개 변수를 true로 설정하여 json_decode ()를 사용하면 됩니다.

$array = json_decode($url, true);

그런 다음 객체가 아닌 연관 배열을 반환하므로 사실 이후에 변환 할 필요가 없습니다.

이것은 모든 응용 프로그램에 적합하지 않을 수 있지만 oroginal 객체의 속성을 쉽게 참조하는 데 도움이되었습니다.

이 튜토리얼에서 해결책을 찾았습니다 -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"의 이름을 바꿉니다.

두 번째는 배열이며 다음과 같이 대괄호로 액세스됩니다.

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

대신


변경할 수 없습니다. 출력은 내가 제어 할 수없는 응용 프로그램에서 반환됩니다.
avinash shah 2012
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.