क्या PHP एक अनुरोध में प्रतिक्रिया हेडर और बॉडी को पुनः प्राप्त कर सकता है?


314

क्या PHP का उपयोग करके CURL अनुरोध के लिए हेडर और बॉडी दोनों प्राप्त करने का कोई तरीका है? मैंने पाया कि यह विकल्प:

curl_setopt($ch, CURLOPT_HEADER, true);

शरीर के शीर्षकों को वापस करने जा रहा है , लेकिन फिर मुझे शरीर प्राप्त करने के लिए इसे पार्स करने की आवश्यकता है। क्या दोनों को अधिक उपयोगी (और सुरक्षित) तरीके से प्राप्त करने का कोई तरीका है?

ध्यान दें कि "एकल अनुरोध" के लिए मेरा मतलब है कि GET / POST से पहले HEAD अनुरोध जारी करने से बचें।


3
इसके लिए एक समाधान बनाया गया है, इस उत्तर को देखें: stackoverflow.com/a/25118032/1334485 (इस टिप्पणी को शामिल किया गया 'इस पोस्ट को अभी भी कई विचार मिलते हैं)
Skacc

इस अच्छी टिप्पणी को देखें: secure.php.net/manual/en/book.curl.php#117138
user956584


मुझे बताया गया कि मेरा प्रश्न इस प्रश्न का दोहराव था। यदि यह डुप्लिकेट नहीं है, तो क्या कोई इसे फिर से खोल सकता है? stackoverflow.com/questions/43770246/… मेरे सवाल में मुझे एक ऐसी विधि का उपयोग करने की ठोस आवश्यकता है जो किसी वस्तु को हेडर और बॉडी के साथ लौटा दे और एक स्ट्रिंग न हो।
1.21 गीगावाट

जवाबों:


466

इसका एक समाधान PHP प्रलेखन टिप्पणियों में पोस्ट किया गया था: http://www.php.net/manual/en/function.curl-exec.php#80442

कोड उदाहरण:

$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
// ...

$response = curl_exec($ch);

// Then, after your curl_exec call:
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);

चेतावनी: जैसा कि नीचे टिप्पणी में कहा गया है, यह विश्वसनीय नहीं हो सकता है जब प्रॉक्सी सर्वर के साथ उपयोग किया जाता है या जब कुछ प्रकार के रीडायरेक्ट को संभालते हैं। @ ज्यॉफ्रे का जवाब इनको अधिक भरोसेमंद रूप से संभाल सकता है।


22
आप भी कर सकते हैं list($header, $body) = explode("\r\n\r\n", $response, 2), लेकिन आपके अनुरोध के आकार के आधार पर इसमें थोड़ा अधिक समय लग सकता है।
21

43
यह खराब समाधान है क्योंकि यदि आप प्रॉक्सी सर्वर और अपने प्रॉक्सी सर्वर (उदाहरण के लिए list($header, $body) = explode("\r\n\r\n", $response, 2)
फ़िडलर) का

5
@msangel आपका समाधान तब काम नहीं करता है जब प्रतिक्रिया में कई हेडर हों, जैसे कि जब सर्वर 302 रीडायरेक्ट करता है। कोई सुझाव?
नैट

4
@ नहीं, हाँ, मुझे यह पता है। AFAIK, लेकिन कोड के साथ 100(जारी) - केवल एक ही संभव अतिरिक्त हेडर है । इस हेडर के लिए आप सही ढंग से परिभाषित अनुरोध विकल्प के साथ चारों ओर जा सकते हैं:, curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); इस हेडर प्रतिक्रिया को भेजने में अक्षम। के रूप में 302, यह नहीं होना चाहिए, क्योंकि 302 हैडर पुनर्निर्देशित है, यह शरीर की उम्मीद नहीं करता है, हालांकि मुझे पता है, कभी-कभी सर्वर 302प्रतिक्रिया के साथ कुछ शरीर भेजते हैं , लेकिन इसे वैसे भी ब्राउज़रों द्वारा अनदेखा किया जाएगा, अब तक, कर्ल को क्यों संभालना चाहिए? )
मस्तेंगल

5
CURLOPT_VERBOSESTDERR(सीएलआई में परेशान हो सकता है) के लिए उत्पादन प्रक्रिया की जानकारी के लिए इरादा है और चर्चा की समस्या के लिए बेकार है।
हेजदव

205

इस धागे की पेशकश की कई अन्य समाधान सही ढंग से नहीं कर रहे हैं ।

  • जब सर्वर चालू होता है या जब सर्वर 100 कोड के साथ प्रतिक्रिया करता है, तो विभाजित करना \r\n\r\nविश्वसनीय नहीं होता CURLOPT_FOLLOWLOCATIONहै।
  • सभी सर्वर मानक के अनुरूप नहीं होते हैं और \nनई लाइनों के लिए संचारित होते हैं।
  • के माध्यम से हेडर के आकार का पता लगाना CURLINFO_HEADER_SIZEभी हमेशा विश्वसनीय नहीं होता है, खासकर जब प्रॉक्सी का उपयोग किया जाता है या कुछ एक ही पुनर्निर्देशित परिदृश्यों में।

सबसे सही विधि का उपयोग कर रहा है CURLOPT_HEADERFUNCTION

यहाँ PHP क्लोजर का उपयोग करके प्रदर्शन करने का एक बहुत ही साफ तरीका है। यह सभी हेडर को सर्वर और एचटीटीपी संस्करणों में निरंतर हैंडलिंग के लिए लोअरकेस में कनवर्ट करता है।

यह संस्करण डुप्लिकेट हेडर को बनाए रखेगा

यह RFC822 और RFC2616 का अनुपालन करता है, कृपया mb_स्ट्रिंग कार्यों का उपयोग करने के लिए संपादन का सुझाव न दें , यह गलत है!

$ch = curl_init();
$headers = [];
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// this function is called by curl for each header received
curl_setopt($ch, CURLOPT_HEADERFUNCTION,
  function($curl, $header) use (&$headers)
  {
    $len = strlen($header);
    $header = explode(':', $header, 2);
    if (count($header) < 2) // ignore invalid headers
      return $len;

    $headers[strtolower(trim($header[0]))][] = trim($header[1]);

    return $len;
  }
);

$data = curl_exec($ch);
print_r($headers);

12
IMO इस थ्रेड में सबसे अच्छा उत्तर है और अन्य उत्तरों के साथ हुई रीडायरेक्ट के साथ समस्याओं को हल करता है। CURLOPT_HEADERFUNCTION के लिए प्रलेखन पढ़ने के लिए सबसे अच्छा यह समझने के लिए कि यह कैसे काम करता है और संभावित गोच । मैंने दूसरों को मदद करने के लिए उत्तर में कुछ सुधार किए हैं।
साइमन ईस्ट

महान, मैंने डुप्लिकेट हेडर के लिए पूरा करने के लिए उत्तर अपडेट किया है। भविष्य में आप जो मानते हैं, उसे कोड को फिर से प्रारूपित नहीं करना चाहिए। यह एक तरह से यह स्पष्ट करने के लिए लिखा गया है कि क्लोजर फ़ंक्शन सीमाएं कहां हैं।
ज्योफ्री

@Geoffrey $headers = [];वैध php है?
थिएलेक्सबारन

6
@thealexbaron हाँ यह PHP 5.4 के रूप में है, देखें: php.net/manual/en/migration54.new-features.php
ज्योफ्री

4
इस तरह के नीट और RFC के अनुरूप दृष्टिकोण के लिए यह जवाब बेहद कम है। यह चिपचिपा उत्तर बनाया जाना चाहिए और शीर्ष पर ले जाया जाना चाहिए। मैं बस चाहता हूं कि पहले सभी हेडर को पार्स करने के बजाय एक वांछित हेडर का मूल्य प्राप्त करने के लिए एक तेज़ दृष्टिकोण था।
Fr0zenFyr

114

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

function HandleHeaderLine( $curl, $header_line ) {
    echo "<br>YEAH: ".$header_line; // or do whatever
    return strlen($header_line);
}


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.google.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADERFUNCTION, "HandleHeaderLine");
$body = curl_exec($ch); 

ऊपर सब कुछ के साथ काम करता है, विभिन्न प्रोटोकॉल और परदे के पीछे भी, और आपको हेडर के आकार के बारे में चिंता करने की ज़रूरत नहीं है, या बहुत सारे अलग-अलग कर्ल विकल्प सेट करें।

पुनश्च: किसी ऑब्जेक्ट विधि के साथ हेडर लाइनों को संभालने के लिए, यह करें:

curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$object, 'methodName'))

नोट के रूप में, कॉलबैक फ़ंक्शन को प्रत्येक हेडर के लिए कॉल किया जाता है और ऐसा लगता है कि वे ट्रिम नहीं किए गए हैं। आप सभी शीर्ष लेखों को रखने के लिए एक वैश्विक चर का उपयोग कर सकते हैं या आप कॉलबैक के लिए एक अनाम फ़ंक्शन का उपयोग कर सकते हैं और स्थानीय चर का उपयोग कर सकते हैं (मूल कार्यक्षेत्र के लिए स्थानीय, अनाम फ़ंक्शन नहीं)।
एम.वी.

2
@MV धन्यवाद, हां, "लाइन-बाय-लाइन" से मेरा मतलब था "प्रत्येक हेडर"। मैंने अपना उत्तर स्पष्टता के लिए संपादित किया। पूरे हेडर सेक्शन (aka। सभी हेडर) को प्राप्त करने के लिए, आप कॉलबैक के लिए ऑब्जेक्ट विधि का उपयोग भी कर सकते हैं ताकि ऑब्जेक्ट प्रॉपर्टी उन सभी को पकड़ सके।
Skacc

8
यह सबसे अच्छा जवाब है IMO। CURLOPT_FOLLOWLOCATION का उपयोग करते समय यह एकाधिक "\ r \ n \ r \ n" के साथ समस्या पैदा नहीं करता है और मुझे लगता है कि यह प्रॉक्सी से अतिरिक्त हेडर से प्रभावित नहीं होगा।
राफेल जी।

मेरे लिए बहुत अच्छी तरह से काम किया, यह भी देखना stackoverflow.com/questions/6482068/... मुद्दों के मामले में
RHH

1
हां, यह सबसे अच्छा तरीका है, हालांकि @ जियोफ्रे का जवाब एक गुमनाम फ़ंक्शन का उपयोग करके इस क्लीनर को बनाता है जिसकी वैश्विक चर और ज़रूरत नहीं है।
साइमन ईस्ट

39

क्या यह आप देख रहे हैं?

curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
$response = curl_exec($ch); 
list($header, $body) = explode("\r\n\r\n", $response, 2);

8
यह सामान्य रूप से काम करता है सिवाय इसके कि जब HTTP / 1.1 100 जारी रहे तो उसके बाद HTTP / 1.1 200 ठीक है। मैं दूसरी विधि के साथ जाऊँगा।
भूतकाल

1
कुछ इस तरह से लागू करने से पहले stackoverflow.com/questions/14459704/… के चयनित उत्तर पर एक नज़र डालें । w3.org/Protocols/rfc2616/rfc2616-sec14.html (14.20) A server that does not understand or is unable to comply with any of the expectation values in the Expect field of a request MUST respond with appropriate error status. The server MUST respond with a 417 (Expectation Failed) status if any of the expectations cannot be met or, if there are other problems with the request, some other 4xx status.
Alrik


यह विधि 302 रीडायरेक्ट पर भी विफल हो जाती है जब कर्ल को स्थान हेडर का पालन करने के लिए सेट किया जाता है।
साइमन ईस्ट

10

बस विकल्प सेट करें:

  • CURLOPT_HEADER, 0

  • CURLOPT_RETURNTRANSFER, 1

और CURLINFO_HTTP_CODE के साथ curl_getinfo का उपयोग करें (या कोई विकल्प नहीं है और आप चाहते हैं कि सभी informations के साथ एक सहयोगी सरणी होगा)

अतिरिक्त जानकारी का संपर्क : http://php.net/manual/fr/function.curl-getinfo.php


5
यह प्रतिक्रिया शीर्षकों को आपको वापस लौटाने के लिए प्रतीत नहीं होता है। या कम से कम उन्हें उपयोग करने का कोई तरीका नहीं है curl_getinfo()
साइमन ईस्ट

8

यदि आप विशेष रूप से चाहते हैं Content-Type, तो इसे पुनः प्राप्त करने के लिए एक विशेष cURL विकल्प है:

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
$content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);

ओपी ने पूछा कि क्या हेडर प्राप्त करने का एक तरीका है, एक विशिष्ट हेडर नहीं है, यह ओपी के सवाल का जवाब नहीं देता है।
ज्योफ्री

2
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);

$parts = explode("\r\n\r\nHTTP/", $response);
$parts = (count($parts) > 1 ? 'HTTP/' : '').array_pop($parts);
list($headers, $body) = explode("\r\n\r\n", $parts, 2);

HTTP/1.1 100 Continueअन्य हेडर से पहले काम करता है ।

यदि आपको बगली सर्वरों के साथ काम करने की आवश्यकता है जो सीआरएलएफ के बजाय केवल एलएफ भेजता है क्योंकि लाइन ब्रेक आप preg_splitनिम्नानुसार उपयोग कर सकते हैं :

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);

$parts = preg_split("@\r?\n\r?\nHTTP/@u", $response);
$parts = (count($parts) > 1 ? 'HTTP/' : '').array_pop($parts);
list($headers, $body) = preg_split("@\r?\n\r?\n@u", $parts, 2);

$parts = explode("\r\n\r\nHTTP/", $response);2 के रूप में विस्फोट के लिए 3 पैरामीटर नहीं होना चाहिए ?
user4271704

@ user4271704 नहीं। यह अंतिम HTTP संदेश खोजने की अनुमति देता है। HTTP/1.1 100 Continueकई बार दिखाई दे सकता है।
Enyby

लेकिन वह कुछ और कहता है: stackoverflow.com/questions/9183178/… आप में से कौन सा सही है?
user4271704

HTTP/1.1 100 Continueकई बार दिखाई दे सकता है। वह मामले को देखता है यदि यह केवल एक बार दिखाई देता है, लेकिन यह आम मामले में गलत है। उदाहरण के लिए HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK...\r\n\r\n...उनके कोड ठीक से काम नहीं करते
Enyby

1
\ R \ n पर विभाजन विश्वसनीय नहीं है, कुछ सर्वर HTTP विनिर्देशों के अनुरूप नहीं हैं और केवल एक \ n ही भेजेंगे। RFC मानक कहता है कि अनुप्रयोगों को \ r पर ध्यान नहीं देना चाहिए और सबसे बड़ी विश्वसनीयता के लिए \ n विभाजन करना चाहिए।
ज्योफ्री

1

मेरा रास्ता है

$response = curl_exec($ch);
$x = explode("\r\n\r\n", $v, 3);
$header=http_parse_headers($x[0]);
if ($header=['Response Code']==100){ //use the other "header"
    $header=http_parse_headers($x[1]);
    $body=$x[2];
}else{
    $body=$x[1];
}

यदि आवश्यक हो तो लूप के लिए आवेदन करें और विस्फोट सीमा को हटा दें।


1

यहां बहस में मेरा योगदान है ... यह डेटा अलग किए गए और हेडर सूचीबद्ध के साथ एक ही सरणी देता है। यह इस आधार पर काम करता है कि CURL एक हेडर चंक [रिक्त लाइन] डेटा लौटाएगा

curl_setopt($ch, CURLOPT_HEADER, 1); // we need this to get headers back
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, true);

// $output contains the output string
$output = curl_exec($ch);

$lines = explode("\n",$output);

$out = array();
$headers = true;

foreach ($lines as $l){
    $l = trim($l);

    if ($headers && !empty($l)){
        if (strpos($l,'HTTP') !== false){
            $p = explode(' ',$l);
            $out['Headers']['Status'] = trim($p[1]);
        } else {
            $p = explode(':',$l);
            $out['Headers'][$p[0]] = trim($p[1]);
        }
    } elseif (!empty($l)) {
        $out['Data'] = $l;
    }

    if (empty($l)){
        $headers = false;
    }
}

0

यहाँ कई उत्तरों के साथ समस्या यह है कि "\r\n\r\n"वैध रूप से html के शरीर में दिखाई दे सकता है, इसलिए आप सुनिश्चित नहीं हो सकते हैं कि आप हेडर को सही ढंग से विभाजित कर रहे हैं।

ऐसा लगता है कि हेडर को एक कॉल से अलग करने का एकमात्र तरीका curl_execकॉलबैक का उपयोग करना है जैसा कि ऊपर https://stackoverflow.com/a/25118032/3326494 में बताया गया है।

और फिर (मज़बूती से) बस अनुरोध के शरीर को प्राप्त करें, आपको Content-Lengthहेडर के मूल्य को substr()नकारात्मक प्रारंभ मान के रूप में पास करना होगा ।


1
यह वैध रूप से प्रकट हो सकता है, लेकिन आपका उत्तर गलत है। सामग्री-लंबाई HTTP प्रतिक्रिया में मौजूद नहीं है। हेडर को मैन्युअल रूप से पार्स करने की सही विधि \ _ \ n (या \ n \ n) का पहला उदाहरण देखना है। यह केवल दो तत्वों की वापसी के लिए विस्फोट करके सीमित किया जा सकता है, अर्थात: list($head, $body) = explode("\r\n\r\n", $response, 2);हालांकि, CURL पहले से ही आपके लिए यह करता है यदि आप उपयोग करते हैंcurl_setopt($ch, CURLOPT_HEADERFUNCTION, $myFunction);
ज्योफ्री

-1

बस अगर आप CURLOPT_HEADERFUNCTIONअन्य समाधानों का उपयोग नहीं कर सकते / कर सकते हैं;

$nextCheck = function($body) {
    return ($body && strpos($body, 'HTTP/') === 0);
};

[$headers, $body] = explode("\r\n\r\n", $result, 2);
if ($nextCheck($body)) {
    do {
        [$headers, $body] = explode("\r\n\r\n", $body, 2);
    } while ($nextCheck($body));
}

-2

एक संदर्भ पैरामीटर के साथ प्रतिक्रिया हेडर लौटें:

<?php
$data=array('device_token'=>'5641c5b10751c49c07ceb4',
            'content'=>'测试测试test'
           );
$rtn=curl_to_host('POST', 'http://test.com/send_by_device_token', array(), $data, $resp_headers);
echo $rtn;
var_export($resp_headers);

function curl_to_host($method, $url, $headers, $data, &$resp_headers)
         {$ch=curl_init($url);
          curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $GLOBALS['POST_TO_HOST.LINE_TIMEOUT']?$GLOBALS['POST_TO_HOST.LINE_TIMEOUT']:5);
          curl_setopt($ch, CURLOPT_TIMEOUT, $GLOBALS['POST_TO_HOST.TOTAL_TIMEOUT']?$GLOBALS['POST_TO_HOST.TOTAL_TIMEOUT']:20);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
          curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
          curl_setopt($ch, CURLOPT_HEADER, 1);

          if ($method=='POST')
             {curl_setopt($ch, CURLOPT_POST, true);
              curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
             }
          foreach ($headers as $k=>$v)
                  {$headers[$k]=str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $k)))).': '.$v;
                  }
          curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
          $rtn=curl_exec($ch);
          curl_close($ch);

          $rtn=explode("\r\n\r\nHTTP/", $rtn, 2);    //to deal with "HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK...\r\n\r\n..." header
          $rtn=(count($rtn)>1 ? 'HTTP/' : '').array_pop($rtn);
          list($str_resp_headers, $rtn)=explode("\r\n\r\n", $rtn, 2);

          $str_resp_headers=explode("\r\n", $str_resp_headers);
          array_shift($str_resp_headers);    //get rid of "HTTP/1.1 200 OK"
          $resp_headers=array();
          foreach ($str_resp_headers as $k=>$v)
                  {$v=explode(': ', $v, 2);
                   $resp_headers[$v[0]]=$v[1];
                  }

          return $rtn;
         }
?>

क्या आपको यकीन $rtn=explode("\r\n\r\nHTTP/", $rtn, 2);है कि सही है? क्या विस्फोट के तीसरे पैरामीटर को नहीं हटाया जाना चाहिए?
user4271704

@ user4271704, तीसरा पैराम "HTTP / 1.1 100 जारी रखें \ n \ r \ n \ r \ nHTTP / 1.1 200 ठीक है ... \ r \ n \ r \ n ..." शीर्ष लेख
अतिवाद

लेकिन उन्होंने कुछ और कहा: stackoverflow.com/questions/9183178/… आप में से कौन सा सही है?
user4271704

@ user4271704 जिस लिंक का आप उपयोग करने की बात कर रहे हैं: explode("\r\n\r\n", $parts, 2); तो दोनों सही हैं।
साइबोर्ग

-5

यदि आपको वास्तव में कर्ल का उपयोग करने की आवश्यकता नहीं है;

$body = file_get_contents('http://example.com');
var_export($http_response_header);
var_export($body);

जो आउटपुट देता है

array (
  0 => 'HTTP/1.0 200 OK',
  1 => 'Accept-Ranges: bytes',
  2 => 'Cache-Control: max-age=604800',
  3 => 'Content-Type: text/html',
  4 => 'Date: Tue, 24 Feb 2015 20:37:13 GMT',
  5 => 'Etag: "359670651"',
  6 => 'Expires: Tue, 03 Mar 2015 20:37:13 GMT',
  7 => 'Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT',
  8 => 'Server: ECS (cpm/F9D5)',
  9 => 'X-Cache: HIT',
  10 => 'x-ec-custom-error: 1',
  11 => 'Content-Length: 1270',
  12 => 'Connection: close',
)'<!doctype html>
<html>
<head>
    <title>Example Domain</title>...

Http://php.net/manual/en/reserved.variables.httpresponseheader.php देखें


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