2010-05-28 6 views
5

मैं आज एक समस्या में भाग गया जहां मैं http_build_query() पर एक खाली सरणी के मान सेट के साथ एक कुंजी पास कर रहा था। उदा .:http_build_query कुंजी को अनदेखा करता है यदि मान एक खाली सरणी है। यह एक बग कैसे नहीं है?

$args = array("foo", "bar", array(), "baz"); 
$qs = http_build_query($args); 
echo $qs; // outputs 0=foo&1=bar&3=baz, I expected 0=foo&1=bar&2=&3=baz 

यह मेरे लिए एक समस्या प्रस्तुत करता है, के बाद से मैं HTTP पर एक आंतरिक एपीआई के लिए कुछ डेटा गुजर रही हूं और मैं दूसरी तरफ सभी तर्कों बाहर निकलने के लिए की जरूरत है।

ठीक है, मैंने इसे गुगल किया और निम्न बग रिपोर्ट के साथ आया: http://bugs.php.net/bug.php?id=50407। व्यवस्थापक से terse उत्तर है, "सेटिंग को खाली करने के समान नहीं है। कोई बग नहीं।"

क्या कोई मुझे समझा सकता है कि यह एक बग क्यों नहीं है? क्या किसी के पास कामकाज के लिए कोई विचार है, एक तरफ मनमानी मूल्य निर्धारित करने के लिए लंगड़ा हैक से और उस मूल्य को दूसरे पर खाली मूल्य के रूप में व्याख्या करना?

$args = array("foo", "bar", array(), "baz"); 
$qs = http_build_query($args); 
parse_str($qs, $query); 
echo ($args == $query); // false, I expect it to be true 

मुझे लगता है कि शायद यह एक दूसरे के parse_str() और http_build_query() प्रतिलोम होने के लिए विचार करने के लिए मुझे के अनुभवहीन है:

संपादित

यहाँ क्यों मुझे लगता है कि यह एक बग है।

मैं अपने वर्तमान "लंगड़ा हैक" समाधान को नीचे दिए गए उत्तर के रूप में पोस्ट कर रहा हूं।

+0

तो, क्या आप यह कहने जा रहे हैं कि आपका एपीआई बिना किसी सत्यापन के HTTP के माध्यम से डेटा पर भरोसा करेगा? दिलचस्प लगता है ... –

+2

ऐसा नहीं लगता है कि वह एपीआई के अंदर डेटा के साथ क्या होगा, उससे संबंधित कुछ भी कह रहा है। – Johrn

+3

@ कोल। Shrapnel: यह काफी कूद है। वह बस एक खाली मूल्य के साथ एक चर पारित करने में सक्षम होना चाहता है। – webbiedave

उत्तर

2

क्या कोई मुझे समझा सकता है कि यह क्यों नहीं है?

तकनीकी रूप से, मुझे नहीं लगता कि इसे एक बग लेबल किया जाना चाहिए। इसके बजाय, यह वैसे ही है कि उन्होंने कार्य करने के लिए फ़ंक्शन को कैसे डिजाइन किया है, चाहे अन्य उस निर्णय से असहमत हैं या नहीं।

आपका एपीआई सिर्फ if (empty($_POST['2']))

+0

मैंने अभी कुछ और विवरणों के साथ अपना प्रश्न संपादित किया है मुझे क्यों लगता है कि यह एक बग है। – jsdalton

+0

मुझे नहीं लगता कि आपका जोड़ा कोड इसे बग के रूप में कैसे परिभाषित करता है। यह एक व्यवहार निर्णय है जिसे आप, और कई अन्य, असहमत हैं। – webbiedave

+0

पर्याप्त मेला। "बग" शायद शब्दों की गलत पसंद है। यह एक खराब डिजाइन निर्णय आईएमओ है, क्योंकि मुझे लगता है कि डेटा को एन्कोड और डीकोड करने वाले कार्यों को उलटा होना चाहिए (जहां कम से कम संभव हो)। – jsdalton

0

यह मेरे वर्तमान "लंगड़ा हैक" समाधान है के साथ जांच कर सकता है। नोट मैं नेस्टेड सरणियों की संभावना के लिए खाते की थी, इसलिए मेरे उदाहरण मूल सरणी मैं क्या सवाल में तैनात से थोड़ा अलग है:

$args = array("foo", "bar", array("red", "blue", array(), "green"), "baz"); 
$original_array = $args; // save it to compare later 
function replace_empty_array_with_fake_string(&$value, $key) { 
    if (is_array($value)) { 
     if (empty($value)) { 
      $value = 'array()'; 
     } else { 
      array_walk($value, 'replace_empty_array_with_fake_string'); 
     } 

    } 
} 
array_walk($args, 'replace_empty_array_with_fake_string'); 
$qs = http_build_query($args); 

// convert the query string back to an array, this would happen on the "other side" 
parse_str($qs, $query); 
function replace_fake_string_with_empty_array(&$value, $key) { 
    if ($value == 'array()') { 
     $value = array(); 
    } 
    if (is_array($value)) { 
     array_walk($value, 'replace_fake_string_with_empty_array'); 
    } 
} 
array_walk($query, 'replace_fake_string_with_empty_array'); 
echo ($original_array == $query); // true 

मुमकिन है मैं "सरणी तुलना में एक अधिक मनमाना स्ट्रिंग के साथ आ सकता है() "प्लेसहोल्डर के रूप में उपयोग करने के लिए।

लंग, मुझे पता है।

+0

यह http_build_query को फिर से लागू करने के लिए छोटा होगा। मैं pecl_http एक्सटेंशन से http_build_str() की सिफारिश करने वाला था। लेकिन वह वहां भी काम नहीं करता है। – mario

+0

कोई भी शरीर http_build_query और http_build_str के बीच अंतर जानता है ?? –

1

मैंने लौटाए गए क्वेरी स्ट्रिंग में रिक्त ऑब्जेक्ट/सरणी छोड़ने के लिए http_build_query को फिर से कार्यान्वित किया है (एक '=' प्रतीक द्वारा प्रत्यय)। मैं इसे डिफ़ॉल्ट कार्यक्षमता से थोड़ा भी सुधार किया है और साथ ही, इसलिए ऑल-इन-सब:

  • रखता खाली वस्तुओं और सरणियों
  • (उम्र के लिए प्रासंगिक) RFC3986 करने के लिए डिफ़ॉल्ट enc_type बदल दिया
  • मुख्य-मान विभाजक तर्क (डिफ़ॉल्ट ओवरराइड करने की क्षमता '=') जोड़ा गया
  • संख्यानुसार अनुक्रमित कुंजी-मान जोड़ों

मैं एक उत्पादन वातावरण (के बारे में कोई जानकारी नहीं में इस परीक्षण नहीं किया के लिए संख्यात्मक सूचकांक निकालता है कामकाज मंस या बग), और यह अनुकूलित नहीं है, लेकिन बहुत अच्छी तरह से वर्तनी है।

function buildQuery($input,$numeric_prefix='', 
     $arg_separator='&',$enc_type=2, 
     $keyvalue_separator='=',$prefix='') { 
    if (is_array($input)) { 
     $arr = array(); 
     foreach ($input as $key => $value) { 
      $name = $prefix; 
      if (strlen($prefix)) { 
       $name .= '['; 
       if (!is_numeric($key)) { 
        $name .= $key; 
       } 
       $name .= ']'; 
      } else { 
       if (is_numeric($key)) { 
        $name .= $numeric_prefix; 
       } 
       $name .= $key; 
      } 
      if ((is_array($value) || is_object($value)) && count($value)) { 
       $arr[] = buildQuery($value,$numeric_prefix, 
         $arg_separator,$enc_type, 
         $keyvalue_separator,$name); 
      } else { 
       if ($enc_type === 2) { 
        $arr[] = rawurlencode($name) 
         .$keyvalue_separator 
         .rawurlencode($value?:''); 
       } else { 
        $arr[] = urlencode($name) 
         .$keyvalue_separator 
         .urlencode($value?:''); 
       } 
      } 
     } 
     return implode($arg_separator,$arr); 
    } else { 
     if ($enc_type === 2) { 
      return rawurlencode($input); 
     } else { 
      return urlencode($input); 
     } 
    } 
} 

उदाहरण:

$arr = array(
     'hello' => 'world', 
     'colors' => array('red','green','blue'), 
     'emptyArr' => array(), 
     'nested' => array(
      'empty' => array(), 
      'fruits' => array('orange','banana','apple'), 
      'curly' => 'sue', 
      'assoc' => array('a'=>'alpha','b'=>'bravo','c'=>'charlie') 
     ) 
    ); 

echo buildQuery($arr); 

आउटपुट: hello=world&colors%5B%5D=red&colors%5B%5D=green&colors%5B%5D=blue&emptyArr=&nested%5Bempty%5D=&nested%5Bfruits%5D%5B%5D=orange&nested%5Bfruits%5D%5B%5D=banana&nested%5Bfruits%5D%5B%5D=apple&nested%5Bcurly%5D=sue&nested%5Bassoc%5D%5Ba%5D=alpha&nested%5Bassoc%5D%5Bb%5D=bravo&nested%5Bassoc%5D%5Bc%5D=charlie मुझे आशा है कि यह किसी को अच्छी तरह से पाता है।

0

आप बस क्वेरी पैरामीटर, "[]" बजाय, इस तरह चल सकता है, तो खाली सरणी, का उपयोग करें:

function walkCriteria(&$criteria) { 
    array_walk($criteria, function (&$val) { 
     if ($val === []) { 
      $val = "[]"; 
     } else if (is_array($val)) { 
      walkCriteria($val); 
     } 
    }); 
} 

का प्रयोग न करें array_walk_recursive। क्योंकि यह खाली सरणी और कुछ भी नहीं करेगा।

संबंधित मुद्दे