जब मैं AJAX से निपटता हूं, कि मैं JSON के रूप में वापस आता हूं, तो एक चाल जिसका मैं उपयोग करता हूं वह है आउटपुट बफरिंग का लाभ उठाना। आप जो कुछ भी चाहते हैं उसे केवल प्रतिध्वनि या आउटपुट नहीं कर सकते क्योंकि यह JSON डेटा को गड़बड़ कर देगा, उदाहरण के लिए,
ob_start(); //turn on buffering at beginning of script.
.... other code ...
print_r($somevar);
.... other code ...
$debug = ob_get_clean(); //put output in a var
$data['debug'] = $debug;
header('Content-Type: application/json');
echo json_encode($data); //echo JSON data.
यह क्या करता है, आप स्क्रिप्ट से किसी भी आउटपुट को अपने JSON डेटा में लपेटते हैं ताकि इसका प्रारूप गड़बड़ न हो।
फिर जावास्क्रिप्ट पक्ष पर आप कंसोल.लॉग का उपयोग कर सकते हैं
$.post(url, input, function(data){
if(data.debug) console.log(data.debug);
});
यदि आप console.log()
. के साथ डिबगिंग के अभ्यस्त नहीं हैं , आप आमतौर पर F12
. दबा सकते हैं और अधिकांश ब्राउज़रों में डीबगर खोलें। फिर वहां आउटपुट "कंसोल" पर भेजा जाएगा। IE9 में console.log()
. के साथ कुछ समस्या थी अगर मुझे याद है, लेकिन मैं दूर के रास्ते पर नहीं जाना चाहता।
नोट: बस यह सुनिश्चित करें कि जब आप इसे उत्पादन में ले जाते हैं तो इस सामान को कोड में न छोड़ें, इस लाइन पर टिप्पणी करना बहुत आसान है,
//$data['debug'] = $debug;
और फिर आपकी डीबग जानकारी उत्पादन में उजागर नहीं होगी। इसे स्वचालित रूप से करने के अन्य तरीके हैं, लेकिन यह इस बात पर निर्भर करता है कि यदि आप स्थानीय विकास करते हैं तो सर्वर पर प्रकाशित करें। उदाहरण के लिए आप इसे $_SERVER['SERVER_ADDR'];
पर स्विच कर सकते हैं जो होगा ::1
या 127.0.0.1
जब यह स्थानीय हो। इसमें कुछ कमियां हैं, मुख्य रूप से कमांड लाइन इंटरफेस (सीएलआई) से सर्वर एड्रेस उपलब्ध नहीं है। तो आम तौर पर मैं इसे वैश्विक स्थिरांक में जोड़ दूंगा जो कहता है कि साइट किस "मोड" में है (सामान्य प्रवेश बिंदु में शामिल है, आमतौर पर index.php)।
if(!defined('ENV_DEVELOPMENT')) define('ENV_DEVELOPMENT','DEVELOPMENT');
if(!defined('ENV_PRODUCTION')) define('ENV_PRODUCTION','PRODUCTION');
if(!defined('ENVIRONMENT')) define('ENVIRONMENT',ENV_DEVELOPMENT);
//site is in Development mode, uncomment for production
//if(!defined('ENVIRONMENT')) define('ENVIRONMENT',ENV_DEVELOPMENT);
फिर इसे जांचना एक साधारण बात है:
if(ENVIRONMENT == ENV_PRODUCTION ) $data['debug'] = $debug;
यदि आप जानते हैं कि त्रुटि रिपोर्टिंग का उपयोग कैसे किया जाता है, तो आप
. का उपयोग करके उससे भी जुड़ सकते हैं if(ini_get('display_errors') == 1) $data['debug'] = $debug;
जो डिस्प्ले एरर चालू होने पर ही डिबग दिखाएगा।
आशा है कि यह मदद करता है।
अपडेट करें
क्योंकि मैंने टिप्पणियों में इसका उल्लेख किया है, यहाँ इसका एक उदाहरण एक वर्ग में लिपटा हुआ है (यह एक सरलीकृत संस्करण है, इसलिए मैंने इसका परीक्षण नहीं किया)
class LibAjax{
public static function respond($callback, $options=0, $depth=32){
$result = ['userdata' => [
'debug' => false,
'error' => false
]];
ob_start();
try{
if(!is_callable($callback)){
//I have better exception in mine, this is just more portable
throw new Exception('Callback is not callable');
}
$callback($result);
}catch(\Exception $e){
//example 'Exception[code:401]'
$result['userdata']['error'] = get_class($e).'[code:'.$e->getCode().']';
//if(ENVIRONMENT == ENV_DEVELOPMENT){
//prevents leaking data in production
$result['userdata']['error'] .= ' '.$e->getMessage();
$result['userdata']['error'] .= PHP_EOL.$e->getTraceAsString();
//}
}
$debug = '';
for($i=0; $i < ob_get_level(); $i++){
//clear any nested output buffers
$debug .= ob_get_clean();
}
//if(ENVIRONMENT == ENV_DEVELPMENT){
//prevents leaking data in production
$result['userdata']['debug'] = $debug;
//}
header('Content-Type: application/json');
echo self::jsonEncode($result, $options, $depth);
}
public static function jsonEncode($result, $options=0, $depth=32){
$json = json_encode($result, $options, $depth);
if(JSON_ERROR_NONE !== json_last_error()){
//debug is not passed in this case, because you cannot be sure that, that was not what caused the error. Such as non-valid UTF-8 in the debug string, depth limit, etc...
$json = json_encode(['userdata' => [
'debug' => false,
'error' => json_last_error_msg()
]],$options);
}
return $json;
}
}
फिर जब आप AJAX प्रतिक्रिया करते हैं तो आप इसे इस तरह लपेटते हैं (नोट $result संदर्भ द्वारा पास किया जाता है, इस तरह हमें वापसी करने की आवश्यकता नहीं होती है, और अपवाद के मामले में हम $result को "वास्तविक समय" में अपडेट करते हैं पूरा होने पर)
LibAjax::respond( function(&$result){
$result['data'] = 'foo';
});
यदि आपको क्लोजर में अतिरिक्त डेटा पास करने की आवश्यकता है, तो यह न भूलें कि आप use
. का उपयोग कर सकते हैं बयान, इस तरह।
$otherdata = 'bar';
LibAjax::respond( function(&$result) use($otherdata){
$result['data'][] = 'foo';
$result['data'][] = $otherdata;
});
यह किसी भी आउटपुट को पकड़ने में संभालता है और इसे डीबग में डालता है, अगर पर्यावरण सही है (टिप्पणी की गई)। कृपया किसी प्रकार की सुरक्षा को लागू करना सुनिश्चित करें ताकि उत्पादन ग्राहकों को उत्पादन पर न भेजा जाए, मैं उस पर पर्याप्त जोर नहीं दे सकता। यह किसी भी अपवाद को भी पकड़ता है जो इसे त्रुटि में डालता है। और यह हेडर और एन्कोडिंग को भी हैंडल करता है।
इसका एक बड़ा लाभ आपके JSON के अनुरूप संरचना है, आपको पता होगा (ग्राहक पक्ष पर) कि यदि if(data.userdata.error)
तो आपके पास बैक एंड पर अपवाद है। यह आपको अपने हेडर, JSON एन्कोडिंग आदि में बदलाव करने के लिए एक जगह देता है...
PHP7 में एक नोट आपको थ्रोएबल इंटरफ़ेस (अपवाद के बजाय) जोड़ना होगा या जोड़ना चाहिए। अगर आप एरर और एक्सेप्शन क्लासेस को पकड़ना चाहते हैं या दो कैच ब्लॉक करना चाहते हैं।
मान लीजिए कि मैं बहुत सारे AJAX करता हूं और हर समय इसे फिर से लिखने से बीमार हो जाता हूं, मेरी वास्तविक कक्षा इससे कहीं अधिक व्यापक है, लेकिन इसका सार यही है।
चीयर्स।
अद्यतन1
ऐसा आमतौर पर इसलिए होता है क्योंकि आप ब्राउज़र पर सही हेडर वापस नहीं भेज रहे हैं। अगर आप भेजते हैं (json_encode को कॉल करने से ठीक पहले)
header('Content-Type: application/json');
यह ब्राउज़र को यह जानने देता है कि वह किस प्रकार का डेटा वापस प्राप्त कर रहा है। एक बात ज्यादातर लोग भूल जाते हैं कि वेब पर सभी प्रतिक्रियाएं टेक्स्ट में की जाती हैं। यहां तक कि इमेज या फाइल डाउनलोड और वेब पेज भी। यह सब सिर्फ टेक्स्ट है, जो उस टेक्स्ट को कुछ खास बनाता है वह है Content-Type
ब्राउज़र को लगता है कि यह है।
header
के बारे में एक बात ध्यान देने योग्य है क्या आप हेडर भेजने से पहले कुछ भी आउटपुट नहीं कर सकते हैं। हालाँकि यह मेरे द्वारा पोस्ट किए गए कोड के साथ अच्छा खेलता है क्योंकि वह कोड सभी आउटपुट को कैप्चर करेगा और हेडर भेजे जाने के बाद भेज देगा।
मैंने हेडर रखने के लिए मूल कोड अपडेट किया, मेरे पास बाद में पोस्ट किए गए अधिक जटिल वर्ग में था। लेकिन अगर आप इसे जोड़ते हैं तो JSON को मैन्युअल रूप से पार्स करने की आवश्यकता से छुटकारा पाना चाहिए।
एक आखिरी चीज जिसका मुझे उल्लेख करना चाहिए, मैं यह जांचना चाहता हूं कि क्या मुझे JSON बैक या टेक्स्ट मिला है, आप अभी भी टेक्स्ट प्राप्त कर सकते हैं यदि आउटपुट बफरिंग शुरू होने से पहले कुछ त्रुटि होती है।
ऐसा करने के 2 तरीके हैं।
यदि डेटा एक स्ट्रिंग है जिसे पार्स करने की आवश्यकता है
$.post(url, {}, function(data){
if( typeof data == 'string'){
try{
data = $.parseJSON(data);
}catch(err){
data = {userdata : {error : data}};
}
}
if(data.userdata){
if( data.userdata.error){
//...etc.
}
}
//....
}
या यदि आपके पास हेडर और उसका हमेशा JSON है, तो यह थोड़ा आसान है
$.post(url, {}, function(data){
if( typeof data == 'string'){
data = {userdata : {error : data}};
}
if(data.userdata){
if( data.userdata.error){
//...etc.
}
}
//....
}
आशा है कि इससे मदद मिलेगी!
अद्यतन2
चूंकि यह विषय बहुत ऊपर आता है, मैंने उपरोक्त कोड का एक संशोधित संस्करण अपने गिटहब पर रखा है, आप इसे यहां पा सकते हैं।
https://github.com/ArtisticPhoenix/MISC/blob/master /AjaxWrapper/AjaxWrapper.php