PHP "php: // input" बनाम $ _POST


243

मुझे JQuery से अजाक्स अनुरोधों के साथ बातचीत करने के php://inputबजाय विधि का उपयोग करने के लिए निर्देशित किया गया है $_POST। जो मुझे समझ में नहीं आता है वह यह है कि वैश्विक बनाम इस का उपयोग करने के फायदे हैं $_POSTया $_GET


2
मैं इस पोस्ट पर ठोकर खाने और इसके भयानक जवाब पढ़ने से पहले PHP की तरफ ajax कॉल प्राप्त करने के लिए "हैक्स" का उपयोग करता था! भविष्य में एक ही मुद्दे वाले अन्य लोगों के लिए, मुझे आशा है कि खोज इंजन मेरी टिप्पणी को भी पढ़ेंगे! :)
एड्रॉक्स

जवाबों:


484

कारण यह है कि php://inputHTTP-हेडर के बाद सभी कच्चे डेटा को रिटर्न करता है, भले ही सामग्री प्रकार की परवाह किए बिना।

PHP सुपरग्लोबल $_POST, केवल उस डेटा को रैप करने वाला है जो या तो है

  • application/x-www-form-urlencoded (साधारण फॉर्म-पोस्ट के लिए मानक सामग्री प्रकार) या
  • multipart/form-data (ज्यादातर फ़ाइल अपलोड के लिए उपयोग किया जाता है)

ऐसा इसलिए है क्योंकि ये केवल सामग्री प्रकार हैं जो उपयोगकर्ता एजेंटों द्वारा समर्थित होने चाहिए । इसलिए सर्वर और PHP परंपरागत रूप से किसी अन्य सामग्री प्रकार (जिसका अर्थ यह नहीं है कि वे नहीं कर सकते थे) प्राप्त करने की उम्मीद नहीं करते हैं।

इसलिए, यदि आप एक अच्छे पुराने HTML को बस पोस्ट करते हैं form, तो अनुरोध कुछ इस तरह दिखता है:

POST /page.php HTTP/1.1

key1=value1&key2=value2&key3=value3

लेकिन अगर आप अजाक्स के साथ बहुत काम कर रहे हैं, तो इस प्रोबाईबी में प्रकारों (स्ट्रिंग, इंट, बूल) और संरचनाओं (सरणियों, वस्तुओं) के साथ अधिक जटिल डेटा का आदान-प्रदान भी शामिल है, इसलिए ज्यादातर मामलों में JSON सबसे अच्छा विकल्प है। लेकिन JSON-पेलोड के साथ एक अनुरोध कुछ इस तरह दिखाई देगा:

POST /page.php HTTP/1.1

{"key1":"value1","key2":"value2","key3":"value3"}

सामग्री अब application/json(या कम से कम उपरोक्त में से कोई भी नहीं) होगी, इसलिए PHP का $_POST-wrapper नहीं जानता कि उसे (अभी तक) कैसे संभालना है।

डेटा अभी भी वहाँ है, आप बस इसे आवरण के माध्यम से उपयोग नहीं कर सकते। इसलिए आपको इसे कच्चे प्रारूप में खुद के साथ लाने की जरूरत है file_get_contents('php://input')( जब तक कि यह multipart/form-data-कोड नहीं है )।

यह भी है कि आप एक्सएमएल-डेटा या किसी अन्य गैर-मानक सामग्री प्रकार का उपयोग कैसे करेंगे।


40
+1 के लिए "यह वह भी है कि आप XML-डेटा या किसी अन्य गैर-मानक सामग्री प्रकार तक कैसे
पहुंचेंगे

@Quasdank मैं क्लाउड ( stackoverflow.com/questions/36558261/… ) में JSON को एंड्रॉइड ऐप से php xampp सर्वर पर भेज रहा हूं लेकिन जब मैंने file_get_contents ('php: // input') की कोशिश की, तो मुझे यह काम नहीं मिला। जो बस स्ट्रिंग (0) देता है। यह मेरी स्थानीय मशीन में काम करता था लेकिन जब मैं इसे क्लाउड पर तैनात करता हूं तो यह काम नहीं करता है। क्या आप कृपया मेरी मदद कर सकते हैं?
the_Martian

1
यह ध्यान देने योग्य है कि PHP में एक AJAX अनुरोध में XMLHttpRequest ऑब्जेक्ट का उपयोग करने का मतलब यह नहीं है कि किसी को JSON पोस्ट करना चाहिए। यह अतिरिक्त उपरि है, लेकिन आपका क्लाइंट-साइड जावास्क्रिप्ट एप्लिकेशन / x-www-form-urlencoded प्रारूप में बदल सकता है। हालाँकि, अनुवाद डेटाटाइप शुद्ध नहीं हो सकता है ।
एंथोनी रुतलेज 23

यह कहना आवश्यक है कि दो मान्यता प्राप्त सामग्री-प्रकारों की सीमा काफी हद तक ऐतिहासिक है। PHP को सरणी के application/jsonलिए मान्य डेटा स्रोत के रूप में पहचानने से कुछ भी नहीं रोकता है $_POST। और विशेष रूप से उस समर्थन के लिए भी प्रकाशित अनुरोध हैं।
अरादमन

हाय @quasdunk क्या आप मुझे इस magento.stackexchange.com/questions/296960/…
के

53

php://inputआप डेटा के कच्चे बाइट्स दे सकते हैं। यह तब उपयोगी है जब POSTed डेटा एक JSON एनकोडेड संरचना है, जो अक्सर AJAX POST अनुरोध के लिए होता है।

यहाँ एक ऐसा करने का कार्य है:

  /**
   * Returns the JSON encoded POST data, if any, as an object.
   * 
   * @return Object|null
   */
  private function retrieveJsonPostData()
  {
    // get the raw POST data
    $rawData = file_get_contents("php://input");

    // this returns null if not valid json
    return json_decode($rawData);
  }

$_POSTजब आप एक रूप है, एक पारंपरिक पोस्ट द्वारा प्रस्तुत से मुख्य मान डेटा संभाल रहे सरणी अधिक उपयोगी है। यह केवल तभी काम करता है जब POSTed डेटा किसी मान्यता प्राप्त प्रारूप में होता है, आमतौर पर application/x-www-form-urlencoded( विवरण के लिए http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 देखें)।


7
यह ध्यान देने योग्य है कि यदि आप trueदूसरे पैरामीटर के रूप में पास करते हैं json_decode, तो यह एक सहयोगी सरणी लौटाएगा।
वाहिद अमीरी

28

यदि पोस्ट डेटा विकृत है, तो $ _POST में कुछ भी नहीं होगा। फिर भी, php: // इनपुट में विकृत स्ट्रिंग होगा।

उदाहरण के लिए कुछ अजाक्स अनुप्रयोग हैं, जो किसी फ़ाइल को अपलोड करने के लिए सही पोस्ट की-वैल्यू अनुक्रम नहीं बनाते हैं, और बस सभी डेटा को पोस्ट डेटा के रूप में डंप करते हैं, बिना चर नाम या कुछ भी। $ _POST खाली होगा, $ _FILES खाली भी होगा, और php: // इनपुट में एक स्ट्रिंग के रूप में लिखी गई सटीक फ़ाइल होगी।


22

सबसे पहले, PHP के बारे में एक बुनियादी सच्चाई।

PHP स्पष्ट रूप से आपको HTTP अनुरोधों को संभालने के लिए एक शुद्ध REST (GET, POST, PUT, PATCH, DELETE) जैसा इंटरफ़ेस देने के लिए नहीं बनाया गया था

हालांकि, $_POST, $_GET, और $_FILES superglobals , और समारोह filter_input_array()औसत व्यक्ति के / आम आदमी की जरूरतों के लिए बहुत उपयोगी हैं।

$_POST(और $_GET) का एक छिपा हुआ लाभ यह है कि आपके इनपुट डेटा को PHP द्वारा स्वचालित रूप से urldecoded किया जाता है । आप कभी भी ऐसा करने के बारे में नहीं सोचते हैं, विशेष रूप से एक मानक GET अनुरोध के भीतर क्वेरी स्ट्रिंग मापदंडों के लिए।

हालाँकि, फिर आप अधिक जानें ...

यह कहा जा रहा है, जैसा कि आप अपने प्रोग्रामिंग ज्ञान में आगे बढ़ते हैं और जावास्क्रिप्ट का उपयोग करना चाहते हैं XmlHttpRequest(कुछ के लिए jQuery), आप इस योजना की सीमा को देखने के लिए आते हैं।

$_POSTHTTP Content-Typeहेडर में दो मीडिया प्रकारों के उपयोग के लिए आपको सीमित करता है :

  1. application/x-www-form-urlencoded, तथा
  2. multipart/form-data

इस प्रकार, यदि आप सर्वर पर PHP में डेटा मान भेजना चाहते हैं, और यह $_POSTसुपरग्लोबल में दिखाई देता है , तो आपको इसे क्लाइंट-साइड पर urlencode करना होगा और उक्त डेटा को कुंजी / मान युग्म के रूप में भेजना होगा - नौसिखियों के लिए असुविधाजनक कदम। (विशेष रूप से यह पता लगाने की कोशिश करते हुए कि URL के विभिन्न हिस्सों को urlencoding के विभिन्न रूपों की आवश्यकता है: सामान्य, कच्चा, आदि)।

आप सभी jQuery के उपयोगकर्ताओं के लिए, $.ajax()विधि आपके JSON को सर्वर पर भेजने से पहले URL एन्कोडेड कुंजी / मान जोड़े में परिवर्तित कर रही है। आप सेटिंग करके इस व्यवहार को ओवरराइड कर सकते हैं processData: false। बस $ .ajax () प्रलेखन पढ़ें , और सामग्री प्रकार हेडर में सही मीडिया प्रकार भेजने के लिए मत भूलना।

URL एन्कोडिंग? क्या बिल्ली है!!!???

आमतौर पर, यदि आप एक सामान्य, सिंक्रोनस (जब पूरा पृष्ठ फिर से करता है) HTTP एक HTML फॉर्म के साथ अनुरोध करता है, तो उपयोगकर्ता-एजेंट (वेब ​​ब्राउज़र) आपके फॉर्म डेटा को आपके लिए urlencode करेगा। यदि आप XmlHttpRequestऑब्जेक्ट का उपयोग करके एक एसिंक्रोनस HTTP अनुरोध करना चाहते हैं , तो आपको एक urlencoded स्ट्रिंग को फ़ैशन करना होगा और इसे भेजना होगा, यदि आप चाहते हैं कि डेटा $_POSTसुपरग्लोबल में दिखाई दे

आप जावास्क्रिप्ट के साथ कैसे संपर्क में हैं? :-)

जावास्क्रिप्ट सरणी या ऑब्जेक्ट से एक urlencoded स्ट्रिंग में परिवर्तित करना कई डेवलपर्स को परेशान करता है (यहां तक ​​कि फॉर्म डेटा जैसे नए एपीआई के साथ )। वे बहुत अधिक सिर्फ JSON भेजने में सक्षम होंगे, और ऐसा करने के लिए क्लाइंट कोड के लिए अधिक कुशल होगा ।

याद रखें (wink, wink), औसत वेब डेवलपर XmlHttpRequestऑब्जेक्ट को सीधे उपयोग करना नहीं सीखता है , वैश्विक फ़ंक्शन, स्ट्रिंग फ़ंक्शन, सरणी फ़ंक्शंस, और आपके और I ;-) जैसे नियमित अभिव्यक्ति। उनके लिए उरलकोडिंग एक बुरा सपना है। ;-)

PHP, क्या देता है?

PHP की सहज XML और JSON हैंडलिंग की कमी कई लोगों को बंद कर देती है। आपको लगता है कि यह अब तक (sigh) PHP का हिस्सा होगा।

इतने सारे मीडिया प्रकार (अतीत में MIME प्रकार)

XML, JSON और YAML सभी में मीडिया प्रकार हैं जिन्हें HTTP Content-Typeहेडर में रखा जा सकता है ।

  • application / xml
  • applicaiton / json
  • आवेदन / यमल (हालांकि इना का कोई आधिकारिक पदनाम सूचीबद्ध नहीं है)

देखो कितने मीडिया प्रकार (पूर्व में, MIME प्रकार) IANA द्वारा परिभाषित किए गए हैं।

देखो कि कितने HTTP हेडर हैं।

php: // इनपुट या बस्ट

php://inputस्ट्रीम का उपयोग करने से आप शिशु-बैठे / हाथ पकड़े हुए स्तर को दरकिनार कर सकते हैं जिसे PHP ने दुनिया पर मजबूर कर दिया है। :-) महान शक्ति के साथ महान जिम्मेदारी आती है!

अब, इससे पहले कि आप डेटा मानों के साथ सौदा करें php://input, आपको कुछ चीजें करनी चाहिए।

  1. निर्धारित करें कि क्या सही HTTP विधि इंगित की गई है (GET, POST, PUT, PATCH, DELETE, ...)
  2. निर्धारित करें कि क्या HTTP कंटेंट-टाइप हेडर ट्रांसमिट हो गया है।
  3. निर्धारित करें कि सामग्री-प्रकार का मान वांछित मीडिया प्रकार है या नहीं।
  4. यह निर्धारित करें कि भेजा गया डेटा अच्छी तरह से XML / JSON / YMAL / आदि बना है या नहीं
  5. यदि आवश्यक हो, तो डेटा को PHP डेटाटाइप: सरणी या ऑब्जेक्ट में कनवर्ट करें
  6. अगर इनमें से कोई भी बुनियादी जाँच या रूपांतरण विफल रहता है, तो एक अपवाद फेंक दें !

चरित्र एन्कोडिंग के बारे में क्या?

आह, हा! हां, आप चाहते हैं कि आपके एप्लिकेशन में डेटा स्ट्रीम को UTF-8 इनकोड किया जाए, लेकिन आप यह कैसे जान सकते हैं कि यह है या नहीं?

दो गंभीर समस्याएं।

  1. आपको पता नहीं है कि कितना डेटा के माध्यम से आ रहा है php://input
  2. आप डेटा स्ट्रीम की वर्तमान एन्कोडिंग के लिए कुछ नहीं जानते हैं।

क्या आप यह जानने के बिना स्ट्रीम डेटा को संभालने का प्रयास करने जा रहे हैं कि पहले कितना है? यह एक भयानक विचार है । आप Content-Lengthस्ट्रीम किए गए इनपुट के आकार पर मार्गदर्शन के लिए HTTP हेडर पर विशेष रूप से भरोसा नहीं कर सकते क्योंकि यह स्पूफ हो सकता है।

आपको एक की जरूरत है:

  1. स्ट्रीम आकार का पता लगाने एल्गोरिथ्म।
  2. आवेदन परिभाषित धारा आकार सीमाएं (Apache / Nginx / PHP सीमाएं बहुत व्यापक हो सकती हैं)।

क्या आप धारा के एन्कोडिंग को जाने बिना धारा डेटा को यूटीएफ -8 में बदलने का प्रयास करने जा रहे हैं? कैसे? Iconv स्ट्रीम फ़िल्टर ( iconv स्ट्रीम फ़िल्टर उदाहरण ) ऐसा लगता है कि शुरू और अंत एन्कोडिंग चाहते हैं।

'convert.iconv.ISO-8859-1/UTF-8'

इस प्रकार, यदि आप कर्तव्यनिष्ठ हैं, तो आपको आवश्यकता होगी:

  1. स्ट्रीम एन्कोडिंग का पता लगाने एल्गोरिथ्म।
  2. डायनेमिक / रनटाइम स्ट्रीम फ़िल्टर डेफिनिशन एल्गोरिथ्म (क्योंकि आप प्रारंभिक एन्कोडिंग को प्राथमिकता नहीं जान सकते हैं)।

( अपडेट : 'convert.iconv.UTF-8/UTF-8'UTF-8 के लिए सब कुछ करने के लिए मजबूर करेगा, लेकिन आपको अभी भी वर्णों के लिए ध्यान रखना होगा कि iconv लाइब्रेरी अनुवाद करने का तरीका नहीं बता सकती है। दूसरे शब्दों में, आपको कुछ को परिभाषित करना है कि जब चरित्र का अनुवाद नहीं किया जा सकता है तो क्या कार्रवाई करें। : 1) एक डमी चरित्र डालें, 2) असफल / फेंक और अपवाद)।

आप विशेष रूप से HTTP Content-Encodingहेडर पर भरोसा नहीं कर सकते हैं , क्योंकि यह निम्नलिखित की तरह संपीड़न जैसा कुछ संकेत दे सकता है। यह वह नहीं है जो आप iconv के संबंध में निर्णय लेना चाहते हैं।

Content-Encoding: gzip

इसलिए, सामान्य कदम हो सकते हैं ...

भाग I: HTTP अनुरोध संबंधित

  1. निर्धारित करें कि क्या सही HTTP विधि इंगित की गई है (GET, POST, PUT, PATCH, DELETE, ...)
  2. निर्धारित करें कि क्या HTTP कंटेंट-टाइप हेडर ट्रांसमिट हो गया है।
  3. निर्धारित करें कि सामग्री-प्रकार का मान वांछित मीडिया प्रकार है या नहीं।

भाग II: स्ट्रीम डेटा संबंधित

  1. इनपुट स्ट्रीम का आकार निर्धारित करें (वैकल्पिक, लेकिन अनुशंसित)।
  2. इनपुट स्ट्रीम के एन्कोडिंग का निर्धारण करें।
  3. यदि आवश्यक हो, तो इनपुट स्ट्रीम को वांछित वर्ण एन्कोडिंग (UTF-8) में परिवर्तित करें।
  4. यदि आवश्यक हो, तो किसी भी एप्लिकेशन स्तर संपीड़न या एन्क्रिप्शन को उल्टा करें, और फिर चरण 4, 5 और 6 को दोहराएं।

भाग III: डेटा प्रकार संबंधित

  1. यह निर्धारित करें कि भेजा गया डेटा अच्छी तरह से XML / JSON / YMAL / आदि बना है या नहीं

(याद रखें, डेटा अभी भी एक URL एन्कोडेड स्ट्रिंग हो सकता है जिसे आपको तब पार्स और URL डीकोड करना होगा)।

  1. यदि आवश्यक हो, तो डेटा को PHP डेटाटाइप: सरणी या ऑब्जेक्ट में कनवर्ट करें

भाग IV: डेटा मूल्य संबंधित

  1. इनपुट डेटा फ़िल्टर करें।

  2. इनपुट डेटा को मान्य करें।

अब देखती हो?

$_POSTSuperglobal, इनपुट पर सीमा के लिए php.ini सेटिंग के साथ ही आम आदमी के लिए आसान कर रहे हैं। हालांकि, स्ट्रीम का उपयोग करते समय चरित्र एन्कोडिंग के साथ काम करना बहुत अधिक सहज और कुशल होता है क्योंकि उचित एन्कोडिंग के लिए इनपुट मूल्यों की जांच करने के लिए सुपरग्लोबल्स (या सरणियों) के माध्यम से लूप की आवश्यकता नहीं होती है।


1
अरे वाह! इस उत्तर की रेटिंग बहुत अधिक होनी चाहिए। अंधेरे में बाढ़ प्रकाश लाने के लिए बहुत बहुत धन्यवाद।
लोक्स

अंतिम विश्लेषण में, PHP बेस डिफॉल्ट्स को अपडेट करने के लिए अच्छा करेगा। हालाँकि, एक HTTP अनुरोध विधि को एक ही नाम ($ _GET, $ _POST) की डेटा संरचना के साथ जोड़े जाने की तार्किक रूप से गिरावट है। क्या मायने रखता है (1) वांछित HTTP अनुरोध विधि, और (2) उस अनुरोध (सामग्री-प्रकार) के साथ अनुरोध डेटा है। इसलिए, पर्ल के साथ के रूप में, आपको यह देखना होगा कि आप भाषा के रचनाकारों / अनुरक्षकों की राय का शिकार हो सकते हैं।
एंथनी रुटलेज ने

0

इसलिए मैंने एक फ़ंक्शन लिखा, जो php: // इनपुट स्ट्रीम से POST डेटा प्राप्त करेगा

तो यहाँ चुनौती PUT, DELETE या PATCH अनुरोध विधि पर स्विच हो रही थी, और अभी भी उस अनुरोध के साथ भेजा गया पोस्ट डेटा प्राप्त करें।

मैं इसे शायद इसी तरह की चुनौती वाले किसी व्यक्ति के लिए साझा कर रहा हूं। नीचे दिया गया कार्य वह है जिसके साथ मैं आया था और यह काम करता है। मुझे उम्मीद है यह मदद करेगा!

    /**
     * @method Post getPostData
     * @return array
     * 
     * Convert Content-Disposition to a post data
     */
    function getPostData() : array
    {
        // @var string $input
        $input = file_get_contents('php://input');

        // continue if $_POST is empty
        if (strlen($input) > 0 && count($_POST) == 0 || count($_POST) > 0) :

            $postsize = "---".sha1(strlen($input))."---";

            preg_match_all('/([-]{2,})([^\s]+)[\n|\s]{0,}/', $input, $match);

            // update input
            if (count($match) > 0) $input = preg_replace('/([-]{2,})([^\s]+)[\n|\s]{0,}/', '', $input);

            // extract the content-disposition
            preg_match_all("/(Content-Disposition: form-data; name=)+(.*)/m", $input, $matches);

            // let's get the keys
            if (count($matches) > 0 && count($matches[0]) > 0)
            {
                $keys = $matches[2];

                foreach ($keys as $index => $key) :
                    $key = trim($key);
                    $key = preg_replace('/^["]/','',$key);
                    $key = preg_replace('/["]$/','',$key);
                    $key = preg_replace('/[\s]/','',$key);
                    $keys[$index] = $key;
                endforeach;

                $input = preg_replace("/(Content-Disposition: form-data; name=)+(.*)/m", $postsize, $input);

                $input = preg_replace("/(Content-Length: )+([^\n]+)/im", '', $input);

                // now let's get key value
                $inputArr = explode($postsize, $input);

                // @var array $values
                $values = [];

                foreach ($inputArr as $index => $val) :
                    $val = preg_replace('/[\n]/','',$val);

                    if (preg_match('/[\S]/', $val)) $values[$index] = trim($val);

                endforeach;

                // now combine the key to the values
                $post = [];

                // @var array $value
                $value = [];

                // update value
                foreach ($values as $i => $val) $value[] = $val;

                // push to post
                foreach ($keys as $x => $key) $post[$key] = isset($value[$x]) ? $value[$x] : '';

                if (is_array($post)) :

                    $newPost = [];

                    foreach ($post as $key => $val) :

                        if (preg_match('/[\[]/', $key)) :

                            $k = substr($key, 0, strpos($key, '['));
                            $child = substr($key, strpos($key, '['));
                            $child = preg_replace('/[\[|\]]/','', $child);
                            $newPost[$k][$child] = $val;

                        else:

                            $newPost[$key] = $val;

                        endif;

                    endforeach;

                    $_POST = count($newPost) > 0 ? $newPost : $post;

                endif;
            }

        endif;

        // return post array
        return $_POST;
    }

-5

इसका उपयोग कैसे करें, इसका सरल उदाहरण

 <?php  
     if(!isset($_POST) || empty($_POST)) { 
     ?> 
        <form name="form1" method="post" action=""> 
          <input type="text" name="textfield"><br /> 
          <input type="submit" name="Submit" value="submit"> 
        </form> 
   <?php  
        } else { 
        $example = file_get_contents("php://input");
        echo $example;  }  
   ?>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.