TLDR
// The key is the "charset=utf8" part.
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';
$dbh = new PDO($dsn, 'user', 'pass');
इस उत्तर php के पीडीओ पुस्तकालय पर जोर देने के है।
एक संक्षिप्त अनुस्मारक - mysql क्लाइंट-सर्वर आर्किटेक्चर है। यह महत्वपूर्ण है क्योंकि न केवल MySQL सर्वर है जहां वास्तविक डेटाबेस है, लेकिन अलग-अलग mysql क्लाइंट ड्राइवर भी है, जो कि MySQL सर्वर से बात करता है (वे अलग-अलग इकाइयां हैं)। आप थोड़े से कह सकते हैं कि mysql क्लाइंट और pdo एक साथ मिश्रित हैं।
जब आप set names utf8
का उपयोग करते हैं, तो आप mysql पर मानक SQL क्वेरी जारी करते हैं।जबकि एसक्यूएल क्वेरी pdo के माध्यम से गुजरती है, और उसके बाद mysql क्लाइंट लाइब्रेरी के माध्यम से, और अंत में यह mysql सर्वर तक पहुंच जाती है, केवल mysql सर्वर पार्स और उस SQL क्वेरी को व्याख्या करता है। यह महत्वपूर्ण है क्योंकि MySQL सर्वर किसी भी संदेश को पीडीओ या MySQL क्लाइंट को वापस नहीं भेजता है, यह बताता है कि चरित्र सेट और एन्कोडिंग बदल गई है, और इसलिए पीडीओ पूरी तरह से अज्ञानी है कि यह हुआ।
ऐसा करना महत्वपूर्ण नहीं है क्योंकि क्लाइंट लाइब्रेरी तारों को सही ढंग से संभाल नहीं सकती है अगर यह वर्तमान चरित्र सेट से अवगत नहीं है। अधिकांश सामान्य ऑपरेशन सही चरित्र सेट को जानने वाले क्लाइंट के बिना सही तरीके से काम करेंगे, लेकिन एक ऐसा जो स्ट्रिंग से बच नहीं रहा है, जैसे कि PDO::quote। आपको लगता है कि आपको ऐसे मैन्युअल आदिम स्ट्रिंग से बचने की चिंता करने की आवश्यकता नहीं है क्योंकि आप तैयार कथन का उपयोग करते हैं, लेकिन सच्चाई पीडीओ का विशाल बहुमत है: mysql उपयोगकर्ता अनजाने में emulated prepared statements का उपयोग करते हैं क्योंकि यह pdo के लिए डिफ़ॉल्ट सेटिंग है: mysql ड्राइवर अब बहुत लंबा समय एक नकली तैयार कथन वास्तविक मूल mysql तैयार कथन का उपयोग नहीं करता है जैसा कि mysql api द्वारा प्रदान किया गया है; इसके बजाय, php आपके सभी मानों पर PDO::quote()
पर कॉल करने के बराबर है, और आपके सभी प्लेसहोल्डर्स को आपके लिए उद्धृत मूल्यों के साथ str_replacing कर रहा है।
चूंकि आप उस स्ट्रिंग से ठीक से नहीं बच सकते हैं जब तक कि आप उस चरित्र सेट को नहीं जानते हैं जिसका उपयोग आप कर रहे हैं, इन नकली तैयार कथन एसक्यूएल इंजेक्शन के लिए कमजोर हैं यदि आप सेट नामों के माध्यम से कुछ चरित्र सेट में बदल गए हैं। एसक्यूएल इंजेक्शन की संभावना के बावजूद, यदि आप एक अलग चरित्र सेट के लिए एक एस्केपिंग योजना का उपयोग करते हैं तो भी आप अपने तारों को तोड़ सकते हैं।
pdo mysql ड्राइवर के लिए, आप specifying it in the DSN द्वारा कनेक्ट करते समय वर्ण सेट निर्दिष्ट कर सकते हैं। यदि आप ऐसा करते हैं तो क्लाइंट लाइब्रेरी और सर्वर दोनों वर्ण सेट के बारे में अवगत होंगे।
// The key is the "charset=utf8" part.
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';
$dbh = new PDO($dsn, 'user', 'pass');
लेकिन अनुचित स्ट्रिंग से बचने में एकमात्र समस्या नहीं है। उदाहरण के लिए, आपको PDO::bindColumn का उपयोग करने में समस्याएं भी हो सकती हैं क्योंकि कॉलम नाम स्ट्रिंग के रूप में निर्दिष्ट होते हैं, और फिर एन्कोडिंग के मामले महत्वपूर्ण होते हैं। एक उदाहरण ütube
नामक कॉलम नाम हो सकता है (umlaut को नोट करें), और आप latin
से utf8
पर सेट नामों के माध्यम से स्विच करते हैं, और फिर आप $stmt->bindColumn('ütube', $var);
ütube
के साथ utf8 एन्कोडेड स्ट्रिंग होने की कोशिश करते हैं क्योंकि आपकी PHP फ़ाइल utf8 एन्कोडेड है। यह काम नहीं करेगा, आपको स्ट्रिंग को लैटिन 1 संस्करण के रूप में एन्कोड करने की आवश्यकता होगी ... और अब आपके पास सभी प्रकार की पागल चल रही है।
आपने किस तकनीक को कार्यान्वित करने का अंत किया? –