पूर्णांक जैसे नामों के साथ ऑब्जेक्ट गुणों तक कैसे पहुंचें?


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: मैं भी CVed हूं, लेकिन यह वास्तव में पता चला है कि यह कोई धोखा नहीं है: यह एक फर्क पड़ता है अगर संपत्ति का नाम एक नंबर से शुरू होता है या सभी संख्याएं हैं !
जॉन

@ जॉन: मम्म, दिलचस्प ... मुझे अनुमान लगाने से पहले एक परीक्षण करना चाहिए था। मुझे बताने के लिए धन्यवाद!
फेलिक्स क्लिंग

जवाबों:


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 का "परमाणु" नुकसान है और इसके अलावा नुकसान यह है कि यदि आपकी वस्तु के अंदर कोई तार है, तो उन तारों को UTF-8 (यह एक आवश्यकता है json_encode) में एन्कोड किया जाना चाहिए ।


यह मेरी समस्या को हल करने के लिए भी हुआ! stackoverflow.com/questions/4643894/…
Bossliaw

जॉन, मुझे बचाने के लिए धन्यवाद। हालांकि मेरी समस्या अलग थी (मुझे लगता है कि यह वास्तव में "जो उन्होंने आपको कभी नहीं बताया" भाग) है। DB से पुनर्प्राप्त डेटटाइम ऑब्जेक्ट ठीक लगता है, लेकिन अगर मैं इसके किसी भी गुण, जैसे ->dateया ->timezone, का उपयोग करता हूं , केवल nullवापस किया जाता है। मैंने देखा कि यदि मैं इन गुणों का उपयोग करने से पहले ऑब्जेक्ट को var_dumped करता हूं तो उचित मान वापस कर दिए जाते हैं। क्लोनिंग इसे ठीक नहीं करता है, इसलिए मुझे लगता है कि वास्तव में इसका उपयोग करने के साथ कुछ करना var_dumpहै ... तब मैंने आपके विकल्प # 1 और वॉइला को देखा, इसे एक सरणी के रूप में एक्सेस $objCastAsArray['date']किया ( ) एक आकर्षण की तरह काम किया।
आर्मफूट

1
तथ्य # 0 : वस्तुओं में कास्टिंग सरणियाँ पहली जगह में कोई बदबूदार अर्थ नहीं होना चाहिए। तथ्य # 1 से तथ्य # 3: अनावश्यक।
पचेरियर

4
@ स्पेसर: मैं मानता हूं कि यह कुछ हद तक संदिग्ध है, लेकिन यह कुछ स्थितियों में पूरी तरह से समझ में आ सकता है। वैसे भी, चूंकि यह मैनुअल में इस तरह से काम करने के लिए प्रलेखित है, इसलिए हमारे व्यक्तिगत विचार वास्तव में मायने नहीं रखते हैं।
जॉन

विकल्प # 3 का विकल्प जिसे UTF-8 की आवश्यकता नहीं है$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'
)

इसलिए ऑब्जेक्ट में दो प्रॉपर्टी कीज़, एक न्यूमेरिक (जिसे एक्सेस नहीं किया जा सकता) और एक स्ट्रिंग आधारित है। यही कारण है कि जॉन का #Fact 4काम करता है, क्योंकि घुंघराले ब्रेसिज़ का उपयोग करके संपत्ति सेट करने का मतलब है कि आप हमेशा एक स्ट्रिंग-आधारित कुंजी को परिभाषित करते हैं, न कि संख्यात्मक।

जॉन के समाधान को लेते हुए, लेकिन इसे अपने सिर पर मोड़कर, आप अपने एरे से एक ऐसी वस्तु उत्पन्न कर सकते हैं जिसमें हमेशा निम्न करके स्ट्रिंग-आधारित कुंजियाँ होती हैं:

$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

मैंने इस फंक्शन को नेट से कॉपी किया था। यदि यह कहता है कि यह काम करता है ("फंक्शन को स्टडक्लास ऑब्जेक्ट्स को बहुआयामी एरर्स में बदलने के लिए"), तो निम्न प्रयास करें:

<?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

जॉन के व्यापक उत्तर का अंतिम विकल्प:

बस दूसरे पैरामीटर के साथ 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]

बजाय


मैं इसे बदल नहीं सकता। आउटपुट एक ऐसे एप्लिकेशन से लौटा है जिसका मेरे पास कोई नियंत्रण नहीं है।
अविनाश शाह
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.