दिलचस्प पोस्ट
इंटरनेट से एंड्रॉइड एमुलेटर कैसे कनेक्ट करें I फ़ोकस चोरी किए बिना एक फॉर्म दिखाएं? मुद्रित पृष्ठों पर Google Chrome दोहराने वाले टेबल हेडर होने पर PHP5 में सिंगलटन डिजाइन पैटर्न बनाना स्विंग एनीमेशन बहुत धीमा चल रहा है सत्यापन कैसे दबाए बटन पर निर्भर करते हैं? यदि शून्य है, तो json.net का उपयोग करके कक्षा में संपत्ति को अनदेखा कैसे करें क्या स्क्रिप्ट टैग के अंदर HTML टिप्पणियां एक सर्वोत्तम अभ्यास है? आकस्मिक चेकइन को वापस ले लें क्या "डिस्प्ले: कोई नहीं" लोड करने से कोई छवि रोकता है? मूल पृष्ठ से एक iframe में जावास्क्रिप्ट कोड को शामिल करना क्लोन कैसे करें या एक सूची कॉपी करें? साझा किए गए लाइब्रेरी लोड करते समय लिनक्स त्रुटि: साझा ऑब्जेक्ट फ़ाइल नहीं खोल सकता: ऐसी कोई फ़ाइल या निर्देशिका नहीं यूनिक्स पूल कमांड के बराबर विंडोज़ सी # में एक स्ट्रिंग एन्क्रिप्ट करना और डिक्रिप्ट करना

क्या मैं IN () स्थिति में एक सरणी बाँध सकता हूँ?

मुझे पता करने के लिए उत्सुक है कि क्या पीडीओ का इस्तेमाल करते हुए प्लेसहोल्डर को मूल्यों की सरणी बाँधना संभव है I उपयोग के मामले यहां IN() स्थिति के साथ उपयोग के लिए मानों की एक सरणी को पार करने का प्रयास कर रहे हैं।
मैं समझाने में बहुत अच्छा नहीं हूँ, इसलिए यहां कुछ दिखाए गए psuedocode हैं। मैं ऐसा कुछ करने में सक्षम होना चाहता हूं:

 <?php $ids=array(1,2,3,7,8,9); $db = new PDO(...); $stmt = $db->prepare( 'SELECT * FROM table WHERE id IN(:an_array)' ); $stmt->bindParam('an_array',$ids); $stmt->execute(); ?> 

और पीडीओ बाइंड करें और सरणी में सभी मानों का उद्धरण करें।

फिलहाल मैं कर रहा हूँ:

 <?php $ids = array(1,2,3,7,8,9); $db = new PDO(...); foreach($ids as &$val) $val=$db->quote($val); //iterate through array and quote $in = implode(',',$ids); //create comma separated list $stmt = $db->prepare( 'SELECT * FROM table WHERE id IN('.$in.')' ); $stmt->execute(); ?> 

जो निश्चित रूप से नौकरी करता है, लेकिन सिर्फ सोच रहा था कि क्या समाधान में बनाया गया कोई हल है?

वेब के समाधान से एकत्रित समाधान "क्या मैं IN () स्थिति में एक सरणी बाँध सकता हूँ?"

मुझे लगता है कि आत्मा सही है आपको क्वेरी स्ट्रिंग का निर्माण करना होगा

 <?php $ids = array(1, 2, 3, 7, 8, 9); $inQuery = implode(',', array_fill(0, count($ids), '?')); $db = new PDO(...); $stmt = $db->prepare( 'SELECT * FROM table WHERE id IN(' . $inQuery . ')' ); // bindvalue is 1-indexed, so $k+1 foreach ($ids as $k => $id) $stmt->bindValue(($k+1), $id); $stmt->execute(); ?> 

तय: डैन, आप सही थे। कोड तय किया (हालांकि यह परीक्षण नहीं किया था)

संपादित करें: दोनों क्रिस (टिप्पणियां) और किसी व्यक्ति को परेशानी का सुझाव दिया है कि foreach-loop …

 (...) // bindvalue is 1-indexed, so $k+1 foreach ($ids as $k => $id) $stmt->bindValue(($k+1), $id); $stmt->execute(); 

… बेमानी हो सकता है, इसलिए foreach पाश और $stmt->execute जा सकता है बस …

 <?php (...) $stmt->execute($ids); ?> 

(फिर से, मैंने इसका परीक्षण नहीं किया)

कुछ जल्दी के लिए:

 //$db = new PDO(...); //$ids = array(...); $qMarks = str_repeat('?,', count($ids) - 1) . '?'; $sth = $db->prepare("SELECT * FROM myTable WHERE id IN ($qMarks)"); $sth->execute($ids); 

क्या यह बयान IN इस्तेमाल करना बहुत महत्वपूर्ण है? FIND_IN_SET op का उपयोग करने का प्रयास करें

उदाहरण के लिए, पीडीओ में ऐसा प्रश्न है जैसे कि

 SELECT * FROM table WHERE FIND_IN_SET(id, :array) 

उसके बाद आपको केवल मूल्यों की एक सरणी बाँधनी पड़ेगी, जो अल्पविराम से समाहित हो, जैसे यह एक

 $ids_string = implode(',', $array_of_smth); // WITHOUT WHITESPACES BEFORE AND AFTER THE COMMA $stmt->bindParam('array', $ids_string); 

और यह किया है।

यूपीडी: जैसा कि कुछ लोगों ने इस जवाब पर टिप्पणियों में बताया, वहां कुछ ऐसे मुद्दे हैं जिन्हें स्पष्ट रूप से कहा जाना चाहिए।

  1. FIND_IN_SET तालिका में अनुक्रमणिका का उपयोग नहीं करता है, और यह अभी भी लागू नहीं है – यह रिकॉर्ड MySQL बग ट्रैकर में देखें नोटिस के लिए @ बिलकारविन के लिए धन्यवाद
  2. आप खोज के लिए एरे के मान के रूप में एक अल्पविराम के साथ एक स्ट्रिंग का उपयोग नहीं कर सकते। implode रूप में आप कॉमा के प्रतीक का उपयोग करते हुए implode बाद सही स्ट्रिंग को सही तरीके से पार्स करना असंभव है। नोट के लिए @ वीएएल के लिए धन्यवाद

ठीक है, यदि आप अनुक्रमित पर भारी निर्भर नहीं हैं और खोज के लिए अल्पविराम के साथ स्ट्रिंग का उपयोग नहीं करते हैं, तो मेरा समाधान अधिक आसान, सरल और उपरोक्त सूचीबद्ध समाधानों की तुलना में तेज़ी से होगा

चूंकि मैं बहुत सी गतिशील क्वेरी करता हूं, यह मैंने बनाया एक सुपर सरल सहायक फ़ंक्शन है I

 public static function bindParamArray($prefix, $values, &$bindArray) { $str = ""; foreach($values as $index => $value){ $str .= ":".$prefix.$index.","; $bindArray[$prefix.$index] = $value; } return rtrim($str,","); } 

इसे इस तरह प्रयोग करें:

 $bindString = helper::bindParamArray("id", $_GET['ids'], $bindArray); $userConditions .= " AND users.id IN($bindString)"; 

एक स्ट्रिंग लौटाता है :id1,:id2,:id3 और आपके $bindArray को बाइंडिंग भी अपडेट करता है, जब आपकी क्वेरी चलाने के लिए समय की आवश्यकता होगी। आसान!

ईविल रीजी से समाधान मेरे लिए काम नहीं किया। पोस्टग्रेज़ में आप एक और वैकल्पिक हल कर सकते हैं:

 $ids = array(1,2,3,7,8,9); $db = new PDO(...); $stmt = $db->prepare( 'SELECT * FROM table WHERE id = ANY (string_to_array(:an_array, ','))' ); $stmt->bindParam(':an_array', implode(',', $ids)); $stmt->execute(); 

मैंने पीडीओ को कुछ ऐसे ही करने के लिए विस्तारित किया जो स्टीफ्स के सुझावों के समान है, और यह लंबे समय तक मेरे लिए आसान था:

 class Array_Capable_PDO extends PDO { /** * Both prepare a statement and bind array values to it * @param string $statement mysql query with colon-prefixed tokens * @param array $arrays associatve array with string tokens as keys and integer-indexed data arrays as values * @param array $driver_options see php documention * @return PDOStatement with given array values already bound */ public function prepare_with_arrays($statement, array $arrays, $driver_options = array()) { $replace_strings = array(); $x = 0; foreach($arrays as $token => $data) { // just for testing... //// tokens should be legit //assert('is_string($token)'); //assert('$token !== ""'); //// a given token shouldn't appear more than once in the query //assert('substr_count($statement, $token) === 1'); //// there should be an array of values for each token //assert('is_array($data)'); //// empty data arrays aren't okay, they're a SQL syntax error //assert('count($data) > 0'); // replace array tokens with a list of value tokens $replace_string_pieces = array(); foreach($data as $y => $value) { //// the data arrays have to be integer-indexed //assert('is_int($y)'); $replace_string_pieces[] = ":{$x}_{$y}"; } $replace_strings[] = '('.implode(', ', $replace_string_pieces).')'; $x++; } $statement = str_replace(array_keys($arrays), $replace_strings, $statement); $prepared_statement = $this->prepare($statement, $driver_options); // bind values to the value tokens $x = 0; foreach($arrays as $token => $data) { foreach($data as $y => $value) { $prepared_statement->bindValue(":{$x}_{$y}", $value); } $x++; } return $prepared_statement; } } 

आप इसे इस तरह से उपयोग कर सकते हैं:

 $db_link = new Array_Capable_PDO($dsn, $username, $password); $query = ' SELECT * FROM test WHERE field1 IN :array1 OR field2 IN :array2 OR field3 = :value '; $pdo_query = $db_link->prepare_with_arrays( $query, array( ':array1' => array(1,2,3), ':array2' => array(7,8,9) ) ); $pdo_query->bindValue(':value', '10'); $pdo_query->execute(); 

पोस्टग्रेज़ के लिए बहुत साफ रास्ता पोस्टग्रेज़-एरे ("{}") का उपयोग कर रहा है:

 $ids = array(1,4,7,9,45); $param = "{".implode(', ',$ids)."}"; $cmd = $db->prepare("SELECT * FROM table WHERE id = ANY (?)"); $result = $cmd->execute(array($param)); 

यहां मेरा समाधान है:

 $total_items = count($array_of_items); $question_marks = array_fill(0, $total_items, '?'); $sql = 'SELECT * FROM foo WHERE bar IN (' . implode(',', $question_marks ). ')'; $stmt = $dbh->prepare($sql); $stmt->execute(array_values($array_of_items)); 

Array_values ​​के उपयोग को ध्यान दें यह महत्वपूर्ण ऑर्डरिंग मुद्दों को ठीक कर सकता है

मैं आईडी के सरणियों को मिला रहा था और फिर डुप्लिकेट आइटम निकाल रहा था। मुझे ऐसा कुछ था:

 $ids = array(0 => 23, 1 => 47, 3 => 17); 

और यह असफल रहा था

मुझे यह भी पता चलता है कि यह धागा पुराना है, लेकिन मुझे एक अनोखी समस्या थी, जहां से पीडीओ चालक को जल्द से जल्द पदावनत किए गए mysql चालक को परिवर्तित करने के लिए मुझे ऐसा फ़ंक्शन बनाना पड़ता था जो गतिशील रूप से सामान्य पैरामीटर और आईएनएस दोनों से बना सकता है परम सरणी तो मैंने इसे जल्दी बनाया:

 /** * mysql::pdo_query('SELECT * FROM TBL_WHOOP WHERE type_of_whoop IN :param AND siz_of_whoop = :size', array(':param' => array(1,2,3), ':size' => 3)) * * @param $query * @param $params */ function pdo_query($query, $params = array()){ if(!$query) trigger_error('Could not query nothing'); // Lets get our IN fields first $in_fields = array(); foreach($params as $field => $value){ if(is_array($value)){ for($i=0,$size=sizeof($value);$i<$size;$i++) $in_array[] = $field.$i; $query = str_replace($field, "(".implode(',', $in_array).")", $query); // Lets replace the position in the query string with the full version $in_fields[$field] = $value; // Lets add this field to an array for use later unset($params[$field]); // Lets unset so we don't bind the param later down the line } } $query_obj = $this->pdo_link->prepare($query); $query_obj->setFetchMode(PDO::FETCH_ASSOC); // Now lets bind normal params. foreach($params as $field => $value) $query_obj->bindValue($field, $value); // Now lets bind the IN params foreach($in_fields as $field => $value){ for($i=0,$size=sizeof($value);$i<$size;$i++) $query_obj->bindValue($field.$i, $value[$i]); // Both the named param index and this index are based off the array index which has not changed...hopefully } $query_obj->execute(); if($query_obj->rowCount() <= 0) return null; return $query_obj; } 

यह अभी भी अनुशंसित है, हालांकि तर्क वहां मौजूद है।

आशा है कि यह एक ही स्थिति में किसी को मदद करता है,

संपादित करें: कुछ परीक्षण के बाद मुझे पता चला:

  • PDO पसंद नहीं है '।' उनके नामों में (जो थोड़े बेवकूफी है अगर आप मुझसे पूछें)
  • बाँधपरम गलत कार्य है, बाइंड वैल्यू सही फ़ंक्शन है।

कार्य संस्करण को संपादित कोड

पीडीओ को देख रहे हैं : पूर्वनिर्धारित स्थिरांक कोई पीडीओ नहीं है :: पैरामा_रार्य जो आपको पीडीओएसटीएटमेंट-> बाइंडपरम में सूचीबद्ध की आवश्यकता होगी

bool PDOStatement :: bindParam (मिश्रित $ पैरामीटर, मिश्रित और $ चर [, int $ data_type [, int $ length [, मिश्रित $ driver_options]]])

इसलिए मुझे नहीं लगता कि यह संभव है।

Schnalle के कोड के बारे में थोड़ा सा संपादन

 <?php $ids = array(1, 2, 3, 7, 8, 9); $inQuery = implode(',', array_fill(0, count($ids)-1, '?')); $db = new PDO(...); $stmt = $db->prepare( 'SELECT * FROM table WHERE id IN(' . $inQuery . ')' ); foreach ($ids as $k => $id) $stmt->bindValue(($k+1), $id); $stmt->execute(); ?> //implode(',', array_fill(0, count($ids)-1), '?')); //'?' this should be inside the array_fill //$stmt->bindValue(($k+1), $in); // instead of $in, it should be $id 

जब आपके पास अन्य पैरामीटर है, तो आप ऐसा कर सकते हैं:

 $ids = array(1,2,3,7,8,9); $db = new PDO(...); $query = 'SELECT * FROM table WHERE X = :x AND id IN('; $comma = ''; for($i=0; $i<count($ids); $i++){ $query .= $comma.':p'.$i; // :p0, :p1, ... $comma = ','; } $query .= ')'; $stmt = $db->prepare($query); $stmt->bindValue(':x', 123); // some value for($i=0; $i<count($ids); $i++){ $stmt->bindValue(':p'.$i, $ids[$i]); } $stmt->execute(); 

आप किस डेटाबेस का उपयोग कर रहे हैं? PostgreSQL में मैं किसी भी (अरै) का उपयोग करना पसंद करता हूं तो अपने उदाहरण का पुन: उपयोग करने के लिए:

 <?php $ids=array(1,2,3,7,8,9); $db = new PDO(...); $stmt = $db->prepare( 'SELECT * FROM table WHERE id = ANY (:an_array)' ); $stmt->bindParam('an_array',$ids); $stmt->execute(); ?> 

दुर्भाग्य से यह बहुत ही गैर पोर्टेबल है

अन्य डेटाबेस पर आपको अपना खुद का जादू बनाने की आवश्यकता होगी क्योंकि अन्य का उल्लेख किया गया है। आप उस तर्क को एक वर्ग / फ़ंक्शन में रखना चाहते हैं ताकि वह अपने कार्यक्रम के पाठ्यक्रम में पुन: प्रयोज्य बना सके। विषय पर कुछ और विचारों और इस परिदृश्य के उदाहरणों के लिए PHP.NET पर mysql_query पृष्ठ पर टिप्पणियों को देखें।

एक ही समस्या से गुज़रने के बाद, मैं एक सरल समाधान पर गया (हालांकि अभी तक PDO::PARAM_ARRAY रूप में सुरुचिपूर्ण नहीं है PDO::PARAM_ARRAY होगा):

सरणी $ids = array(2, 4, 32) :

 $newparams = array(); foreach ($ids as $n => $val){ $newparams[] = ":id_$n"; } try { $stmt = $conn->prepare("DELETE FROM $table WHERE ($table.id IN (" . implode(", ",$newparams). "))"); foreach ($ids as $n => $val){ $stmt->bindParam(":id_$n", intval($val), PDO::PARAM_INT); } $stmt->execute(); 

… और इसी तरह

इसलिए यदि आप मिश्रित मानों का उपयोग कर रहे हैं, तो आपको टाइप परम को निर्दिष्ट करने से पहले अपने मानों का परीक्षण करने के लिए अधिक कोड की आवश्यकता होगी:

 // inside second foreach.. $valuevar = (is_float($val) ? floatval($val) : is_int($val) ? intval($val) : is_string($val) ? strval($val) : $val ); $stmt->bindParam(":id_$n", $valuevar, (is_int($val) ? PDO::PARAM_INT : is_string($val) ? PDO::PARAM_STR : NULL )); 

लेकिन मैंने इस एक का परीक्षण नहीं किया है।

जैसा कि मुझे पता है कि पीडीओ वक्तव्य में एक सरणी को बाँधने की कोई संभावना नहीं है।

लेकिन 2 सामान्य समाधान मौजूद हैं:

  1. स्थितिस्थ प्लेसहोल्डर (?,?,?,?) या नामधारी प्लेसहोल्डर (: id1,: id2,: id3) का उपयोग करें

    $ whereIn = implode (',', array_fill (0, गिनती ($ आईडी), '?'));

  2. उद्धरण पहले सरणी

    $ whereIn = array_map (ऐरे ($ db, 'quote'), $ आईडी);

दोनों विकल्प अच्छे और सुरक्षित हैं मैं दूसरे को पसंद करता हूं क्योंकि यह छोटा है और मैं var_dump पैरामीटर अगर मुझे इसकी आवश्यकता है प्लेसहोल्डर्स का उपयोग करना आपको मूल्यों को बंधाना होगा और अंत में आपका एसक्यूएल कोड समान होगा

 $sql = "SELECT * FROM table WHERE id IN ($whereIn)"; 

और मेरे लिए आखिरी और महत्वपूर्ण त्रुटि से बचना है "बाउंड वेरिएबल्स की संख्या टोकन की संख्या से मेल नहीं खाती"

सिद्धांत यह स्थलीय प्लेसहोल्डर्स का उपयोग करने का एक बढ़िया उदाहरण है, क्योंकि इसकी आने वाली मापदंडों पर आंतरिक नियंत्रण है।

यदि कॉलम में केवल पूर्णांक हो सकते हैं, तो आप शायद इसे प्लेसहोल्डर्स के बिना कर सकते हैं और सीधे आईडी में आईडी डाल सकते हैं। आपको सिर्फ सभी मानों को पूर्णांक में डालना होगा इस कदर:

 $listOfIds = implode(',',array_map('intval', $ids)); $stmt = $db->prepare( "SELECT * FROM table WHERE id IN($listOfIds)" ); $stmt->execute(); 

यह किसी भी एसक्यूएल इंजेक्शन के लिए कमजोर नहीं होना चाहिए।

यहाँ मेरा समाधान है मैंने पीडीओ कक्षा को भी बढ़ा दिया है:

 class Db extends PDO { /** * SELECT ... WHERE fieldName IN (:paramName) workaround * * @param array $array * @param string $prefix * * @return string */ public function CreateArrayBindParamNames(array $array, $prefix = 'id_') { $newparams = []; foreach ($array as $n => $val) { $newparams[] = ":".$prefix.$n; } return implode(", ", $newparams); } /** * Bind every array element to the proper named parameter * * @param PDOStatement $stmt * @param array $array * @param string $prefix */ public function BindArrayParam(PDOStatement &$stmt, array $array, $prefix = 'id_') { foreach($array as $n => $val) { $val = intval($val); $stmt -> bindParam(":".$prefix.$n, $val, PDO::PARAM_INT); } } } 

उपरोक्त कोड के लिए यहां एक नमूना उपयोग किया गया है:

 $idList = [1, 2, 3, 4]; $stmt = $this -> db -> prepare(" SELECT `Name` FROM `User` WHERE (`ID` IN (".$this -> db -> CreateArrayBindParamNames($idList)."))"); $this -> db -> BindArrayParam($stmt, $idList); $stmt -> execute(); foreach($stmt as $row) { echo $row['Name']; } 

आप क्या सोचते हैं मुझे बताओ

मेरे लिए कामुक समाधान एक गतिशील साहचर्य सरणी का निर्माण करना है और उसका उपयोग करना है

 // a dirty array sent by user $dirtyArray = ['Cecile', 'Gilles', 'Andre', 'Claude']; // we construct an associative array like this // [ ':name_0' => 'Cecile', ... , ':name_3' => 'Claude' ] $params = array_combine( array_map( // construct param name according to array index function ($v) {return ":name_{$v}";}, // get values of users array_keys($dirtyArray) ), $dirtyArray ); // construct the query like `.. WHERE name IN ( :name_1, .. , :name_3 )` $query = "SELECT * FROM user WHERE name IN( " . implode(",", array_keys($params)) . " )"; // here we go $stmt = $db->prepare($query); $stmt->execute($params); 

पैरामीटर बाँधने के लिए प्लेसहोल्डर्स का उपयोग करने के मूल प्रश्न के करीब जवाब पाने के लिए मैंने इसे थोड़ा आगे लिया।

इस उत्तर को क्वेरी में इस्तेमाल करने के लिए सरणी के माध्यम से दो छोरें बनाना होगा। लेकिन यह अधिक चुनिंदा प्रश्नों के लिए अन्य स्तंभ प्लेसहोल्डर्स होने के मुद्दे को हल करता है।

 //builds placeholders to insert in IN() foreach($array as $key=>$value) { $in_query = $in_query . ' :val_' . $key . ', '; } //gets rid of trailing comma and space $in_query = substr($in_query, 0, -2); $stmt = $db->prepare( "SELECT * WHERE id IN($in_query)"; //pind params for your placeholders. foreach ($array as $key=>$value) { $stmt->bindParam(":val_" . $key, $array[$key]) } $stmt->execute(); 

आप पहली बार "?" क्वेरी में और उसके बाद एक "के लिए" इस तरह पैरामीटर भेजें:

 require 'dbConnect.php'; $db=new dbConnect(); $array=[]; array_push($array,'value1'); array_push($array,'value2'); $query="SELECT * FROM sites WHERE kind IN ("; foreach ($array as $field){ $query.="?,"; } $query=substr($query,0,strlen($query)-1); $query.=")"; $tbl=$db->connection->prepare($query); for($i=1;$i<=count($array);$i++) $tbl->bindParam($i,$array[$i-1],PDO::PARAM_STR); $tbl->execute(); $row=$tbl->fetchAll(PDO::FETCH_OBJ); var_dump($row);