परिचय: "PDO मेरे ऐरे को क्यों नहीं समझता?"
\nडेटाबेस के साथ काम करने वाला हर PHP डेवलपर कभी न कभी IN() ऑपरेटर के साथ क्वेरी चलाने की स्थिति में आता है। लगता है कि इससे आसान क्या हो सकता है: वैल्यू का एक ऐरे पास करें और फ़िल्टर किया गया डेटा प्राप्त करें। लेकिन यहीं पर असली पेच है।
यहाँ एक क्लासिक उदाहरण है जो शुरुआती के दिमाग में आता है:
\n<?php\n$ids = [1, 2, 3, 5];\n$stmt = $pdo->prepare("SELECT * FROM users WHERE id IN (:ids)");\n$stmt->execute([':ids' => $ids]); // गलती!\n?>\nऔर PDO एक एरर फेंकता है: "Array to string conversion" या बस खाली परिणाम लौटाता है। ऐसा क्यों होता है? PDO SQL क्वेरी में ऐरे को "विस्तारित" नहीं कर सकता। यह प्रत्येक नामित प्लेसहोल्डर के लिए एक स्केलर वैल्यू की अपेक्षा करता है, पूरे ऐरे की नहीं।
\nइस लेख में हम शीर्ष गलतियों पर चर्चा करेंगे जो डेवलपर्स IN() में ऐरे को बांधने की कोशिश में करते हैं, और सही, सुरक्षित और प्रभावी समाधान दिखाएंगे।
गलती #1: execute() में ऐरे को सीधे पास करना
\nयह सबसे आम गलती है। डेवलपर सोचता है कि PDO खुद ही ऐरे के प्रत्येक मान को IN() शर्त में डाल देगा। लेकिन, जैसा कि हमने पाया, PDO ऐसे काम नहीं करता।
कोड में यह कैसा दिखता है
\n<?php\n$ids = [10, 20, 30];\n$stmt = $pdo->prepare("SELECT * FROM products WHERE id IN (:ids)");\n$stmt->execute([':ids' => $ids]); // Fatal error\n?>\nपरिणाम: ऐरे को स्ट्रिंग में बदलने पर एरर या चेतावनी। भले ही कोड "चल जाए", PDO क्वेरी में "Array" शब्द डाल देगा — और आपको WHERE id IN ('Array') मिलेगा, जो बेमानी है।
ऐसा क्यों होता है? PDO चाहता है कि प्रत्येक प्लेसहोल्डर के लिए एक ही मान हो। ऐरे एक मान नहीं है, बल्कि मानों का एक सेट है। PDO यह अनुमान नहीं लगा सकता कि आप क्या करना चाहते हैं।
\n\nगलती #2: bindValue() का ऐरे के साथ उपयोग
\nकभी-कभी डेवलपर्स bindValue() का उपयोग करके PDO को धोखा देने की कोशिश करते हैं:
<?php\n$ids = [1, 2, 3];\n$stmt = $pdo->prepare("SELECT * FROM users WHERE id IN (:ids)");\n$stmt->bindValue(':ids', $ids, PDO::PARAM_STR); // गलती!\n$stmt->execute();\n?>\nसमस्या वही है: bindValue() एक स्केलर वैल्यू की अपेक्षा करता है। ऐरे को स्ट्रिंग "Array" में बदल दिया जाएगा, और क्वेरी सही ढंग से नहीं चलेगी। तीसरा पैरामीटर (PDO::PARAM_STR) मदद नहीं करता — यह केवल डेटा प्रकार बताता है, ऐरे के साथ काम करने का तर्क नहीं बदलता।
गलती #3: सीधी कॉन्केटनेशन (SQL इंजेक्शन)
\nनिराश होकर, कुछ डेवलपर्स सबसे आसान रास्ता अपनाते हैं — implode() के माध्यम से ऐरे को सीधे क्वेरी में डालते हैं:
<?php\n$ids = [1, 2, 3];\n$ids_str = implode(',', $ids);\n$stmt = $pdo->query("SELECT * FROM users WHERE id IN ($ids_str)"); // खतरनाक!\n?>\nयह खतरनाक क्यों है? अगर ऐरे के मान उपयोगकर्ता से आते हैं (जैसे GET पैरामीटर या फॉर्म से), तो एक हमलावर 1; DROP TABLE users; -- पास कर सकता है। क्वेरी IN (1; DROP TABLE users; --) बन जाएगी, और आपका डेटाबेस नष्ट हो जाएगा। यह एक क्लासिक SQL इंजेक्शन है।
भले ही आपको लगे कि डेटा सुरक्षित है, यह अभ्यास खराब तरीका है। एक दिन आप डेटा स्रोत की जाँच करना भूल जाएंगे, और परिणाम विनाशकारी होंगे।
\n\nसही समाधान: डायनामिक प्लेसहोल्डर
\nअब अच्छी खबर पर आते हैं। PDO आपको डायनामिक रूप से प्लेसहोल्डर बनाने की अनुमति देता है। आपको आवश्यक संख्या में ? या :id1, :id2, ... के साथ एक स्ट्रिंग उत्पन्न करनी होगी और मानों का ऐरे अलग से पास करना होगा।
तरीका 1: पोजीशनल प्लेसहोल्डर (?) का उपयोग
\nयह सबसे सरल और लोकप्रिय तरीका है:
\n<?php\n