2009-12-16 24 views
8

Lütfen koduma bakın. Hazırlamamdaki ifadeye bir dizi paramenter bağlamayı deniyorum. Web’de etrafa bakıyorum ve call_user_func_array’ı kullanmak zorunda olduğumu görebiliyorum ama işe yaramıyor. Aldığım hata: "İlk argümanın geçerli bir geri arama olması bekleniyor, 'Array' verildi" Yanlış olabilirim ama ilk argümanın bir dizi olabileceğini ve belki de bu hata mesajının yanıltıcı olduğunu varsayıyorum. Mesele şu ki, dizim hata yaptığında. Neyi yanlış yaptığımı gören var mı? Teşekkürler.MySQLI bağlanma paramlarını kullanarak call_user_func_array

$type = array("s", "s"); 
$param = array("string1","anotherstring"); 

$stmt = $SQLConnection->prepare("INSERT INTO mytable (comp, addl) VALUES (?,?)"); 

$params = array_merge($type, $param); 

call_user_func_array(array(&$stmt, 'bind_param'), $params); 
$SQLConnection->execute(); 
+0

: $ type = array ("ss İşte

/* create a database connection */ $db = new mysqli($host, $user, $password, $db_name); /* setup the sql, values, and types */ $sql="SELECT * FROM languages WHERE language_code = ? AND charset = ? ORDER BY native_name"; $values = array($langCode, $charset); $types = "ss"; /* pass those variables to the execute() function defined below */ if ($rows = execute($sql, $values, $types)) { return $rows[0]; } function execute($sql, $values='', $types='') { /* prepare the sql before binding values and types */ $stmt = $db->prepare($sql); /*combine the values and types into $inputArray */ $inputArray[] = &$types; $j = count($values); for($i=0;$i<$j;$i++){ $inputArray[] = &$values[$i]; } /* add the combined values and types to call_user_func_array() for binding */ call_user_func_array(array($stmt, 'bind_param'), $inputArray); $result = $stmt->execute(); return $result; } 

bu örnek dayanır tam açıklama bir referans var "); – Columbo

+0

Mysqli üzerinden PDO'yu tercih etmemi sağlayan bu gibi durumlar. –

cevap

9

Eğer kullanım call_user_func_array zorunda Bilmiyorum neden, ama bu başka bir hikaye.

Gözlerimde yanlış olabilecek tek şey, nesneye bir başvuru kullandığınızdır. PHP 5. * kullandığınız varsayarak, bu gerekli değildir:

call_user_func_array(array($stmt, 'bind_param'), $params); 
+0

Teşekkürler Franz, call_user_func_array kullanıyorum çünkü bağlanılacak parametrelerin sayısı değişiyor. PHP5 kullanıyorum ama referans adımı kaldırmak aynı sonucu veriyor. – Columbo

+0

O zaman bu, nesnenizle ilgili bir sorun olduğu anlamına gelmelidir. Bu PHP "bug" raporuna bakın: http://bugs.php.net/bug.php?id=46229. 'Var_dump ($ stmt)' size o yerde ne veriyor? – Franz

+0

Evet, sadece ifade yerine bool (true) alıyorum. Neden bir göz atmayacağınıza emin olun. Sanırım hazırlık ifadesinin başarılı olduğunu söylemek bana bir TRUe veriyor. Ama birkaç örnekte yaptığım şeyleri yapan insanlar gördüm. – Columbo

16

Böyle olmak gerekir: call_user_func_array (array ($ deyimi aramak isteyeyim Neden

//connect 
$mysqli = new mysqli($host, $user, $password, $db_name); 

//prepare 
$stmt = $mysqli->prepare("SELECT * FROM the_table WHERE field1= ? AND Field2= ?"); 

//Binding parameters. Types: s = string, i = integer, d = double, b = blob 
$params= array("ss","string_1","string_2"); 

//now we need to add references 
$tmp = array(); 
foreach($params as $key => $value) $tmp[$key] = &$params[$key]; 
// now us the new array 
call_user_func_array(array($stmt, 'bind_param'), $tmp); 

$stmt->execute(); 

/* Fetch result to array */ 
$res = $stmt->get_result(); 
while($row = $res->fetch_array(MYSQLI_ASSOC)) { 
    $a_data[]=$row; 
} 
print_r($a_data); 

$stmt->close(); 
+0

Son olarak, bu örnekten yardım alarak sorunumu çözebiliyordum. Sorun, çoğu örnekte hard code 'params dizisi 'gibi gözüküyordu, fakat bunu dinamik olarak API'mdaki bir gönderiye dayalı olarak üretmem gerekiyor. Değerleri alan ve daha sonra 'call_user_function_array' ile kullandığım params dizisini oluşturan bir işlev oluşturmam gerekiyordu. Çözümümü asıl soruma burada koydum: [virgülle nasıl bağlanır ... NOT IN ...] (https://stackoverflow.com/questions/47821201/how-to-bind-comma-separated -ids kullanan-mysqli-stmt--bağlama-param-sonuçlar değil-in-stateme? noredirect = 1 # comment82605027_47821201). –

0

, 'bind_param '), $ bind_arguments)? Çünkü $ bind_arguments bir dizidir. Ne kadar parametreye sahip olursanız olun, sorgulanan parametrelerine bir ifadeyi bağlayan bir fonksiyona sahip olursunuz. İyi kod

Örnek ... kötü kod

<?php 
      # link 
     $dblink = new mysqli('HOSTNAME','USERNAME','PASSWORD','DATABASENAME'); 

      # example data 
     $statement = $dblink->prepare("SELECT * from Person WHERE FirstName = ? AND MiddleName = ? AND LastName = ? and Age = ?"); 
     $recordvalues = ['John', 'H.', 'Smith', 25]; 
     $sqlbindstring = "sssi"; # String, String, String, Integer example 

      # make the references 
     $bind_arguments = []; 
     $bind_arguments[] = $sqlbindstring; 
     foreach ($recordvalues as $recordkey => $recordvalue) 
     { 
      $bind_arguments[] = & $recordvalues[$recordkey]; # bind to array ref, not to the temporary $recordvalue 
     } 

      # query the db 
     call_user_func_array(array($statement, 'bind_param'), $bind_arguments);  # bind arguments 
     $statement->execute(); # run statement 
     $result = $statement->get_result(); # get results 

      # get the results 
     if($result) { 
      while ($row = $result->fetch_assoc()) { 
       print("\n\nMy row is..."); 
       print_r($row); 
      } 
     } 
    ?> 

Örnek ... İlk örnekte

<?php 

      # Same setup as above.. 

     $statement->prepare("SELECT * from Person WHERE FirstName = ? AND MiddleName = ? AND LastName = ? and Age = ?"); 
     $statement->bind('John', 'H.", 'Smith', 25); 

    ?> 

: Sen olarak çok veya az bağlayıcı olması için geçebilir bittiğinde, tüm uygulamada bind() sadece bir satırda çağrılabilir. Bu iyi ölçeklendirir.

İkinci örnekte: Veritabanınızdaki her olası kayıt için olası tüm ekleme grupları için bir bind() deyimi yazmalısınız. Bu zayıf ölçeklendirir. Eğer bir hata alırsanız

+0

Cevabınız, başka bir cevaba bir cevaptır ... –

0

, bunu denemelisiniz:

call_user_func_array(array($stmt, 'bind_param'), refValues($params)); 

function refValues($arr){ 
    if (strnatcmp(phpversion(),'5.3') >= 0) { 
     $refs = array(); 
     foreach($arr as $key => $value) 
      $refs[$key] = &$arr[$key]; 
     return $refs; 
    } 
    return $arr; 
} 
1

kendi soru üzerine bu cevap vermek mümkün değildi o dupe olarak işaretlenmiş var çünkü: here. Ama sanırım bu sorudaki cevapları kullanan son çözümüm, kullanım durumumda çalışıyor, birisi için yararlı olabilir.

Hedeflerim, postalanmış bir kimlik seti almak ve bunları bir NOT IN MYSQL deyiminde kullanmaktı. 5 ID dizisinin yayınlandığı varsayılmaktadır.

  1. sayısını kimlikleri NOT IN deyimi için ? yer tutucular oluşturmak için yayınlanmıştır. $params_count = substr(str_repeat(',?', count($array_of_ids)), 1);'u kullanarak, SQL deyiminde kullanılacak (?,?,?,?,?) sonucunu verir. Benim için kimlikleri ve yazın i veya s vb alır

  2. Yap fonksiyonu, hepsi i yani benim işlevi basittir idi.Bu $params= array("iiiii",1,2,3,4,5) gibi görünen döndürme dizisi, burada ilk değer i 'lerdir ve sonraki değerler, işleve geçirilen toplam kimliğe bağlı olarak kimliklerdir.

$params = build_bind_params($array_of_ids, "i");

function build_bind_params($values, $bind_type) { 
    $s = substr(str_repeat($bind_type, count($values)), 0); 
    $bind_array = array(); 
    $bind_array[] = $s; 
    foreach($values as $value) { 
     $bind_array[] = $value; 
    } 
    return $bind_array; 
} 

  1. Sonra foreach ($params as $key => $value) $tmp[$key] = &$params[$key]; yeni $params oluşturulan bağlanma için düzgün biçimlendirilmiş almak için kullanın. Diziyi düzgün şekilde bağlamak için call_user_func_array(array($stmt , 'bind_param') , $tmp); öğesini kullanın.

  2. sonra bunları call_user_func_array eklemeden önce değerleri ile birlikte türleri entegre olmadan $stmt