PHP + MYSQLI :Liaison paramètre/résultat variable avec des instructions préparées
Question
Dans un projet que je suis sur le point de terminer, j'ai écrit et implémenté une solution de mappage objet-relationnel pour PHP.Avant que les sceptiques et les rêveurs ne s'écrient "Comment diable ?", détendez-vous -- je n'ai pas trouvé de moyen de faire fonctionner la reliure statique tardive -- je travaille simplement autour de ce problème de la meilleure façon possible.
Quoi qu'il en soit, je n'utilise pas actuellement d'instructions préparées pour les requêtes, car je n'ai pas trouvé de moyen de transmettre un nombre variable d'arguments au bind_params()
ou bind_result()
méthodes.
Pourquoi dois-je soutenir un nombre variable d’arguments, demandez-vous ?Parce que la superclasse de mes modèles (considérez ma solution comme un aspirant à PHP ActiveRecord piraté) est l'endroit où la requête est définie, et donc la méthode find(), par exemple, ne sait pas combien de paramètres elle aurait besoin de lier .
Maintenant, j'ai déjà pensé à créer une liste d'arguments et à transmettre une chaîne à eval(), mais je n'aime pas beaucoup cette solution : je préfère simplement implémenter mes propres contrôles de sécurité et transmettre les instructions.
Quelqu'un a-t-il des suggestions (ou des histoires de réussite) sur la façon d'y parvenir ?Si vous pouvez m'aider à résoudre ce premier problème, nous pourrions peut-être nous attaquer à la liaison du jeu de résultats (quelque chose, je suppose, sera plus difficile, ou du moins plus gourmand en ressources s'il implique une requête initiale pour déterminer la structure de la table).
La solution
En PHP, vous pouvez transmettre un nombre variable d'arguments à une fonction ou une méthode en utilisant call_user_func_array
.Un exemple de méthode serait :
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);
La fonction sera appelée avec chaque membre du tableau passé comme son propre argument.
Autres conseils
Vous devez vous assurer que $array_of_params est un tableau de liens vers des variables, pas se valorise.Devrait être:
$array_of_params[0] = &$param_string; //link to variable that stores types
Et puis...
$param_string .= "i";
$user_id_var = $_GET['user_id'];//
$array_of_params[] = &$user_id_var; //link to variable that stores value
Sinon (s'il s'agit d'un tableau de valeurs), vous obtiendrez :
Avertissement PHP :Le paramètre 2 de mysqli_stmt::bind_param() devrait être une référence
Encore un exemple :
$bind_names[] = implode($types); //putting types of parameters in a string
for ($i = 0; $i < count($params); $i++)
{
$bind_name = 'bind'.$i; //generate a name for variable bind1, bind2, bind3...
$$bind_name = $params[$i]; //create a variable with this name and put value in it
$bind_names[] = & $$bind_name; //put a link to this variable in array
}
et BOUOOOM :
call_user_func_array( array ($stmt, 'bind_param'), $bind_names);
Je n'ai pas le droit de modifier, mais je crois au code
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);
La référence devant $stmt n’est pas nécessaire.Depuis $stmt
est l'objet et bindparams
est la méthode dans cet objet, la référence n'est pas nécessaire.Ça devrait être:
call_user_func_array(array($stmt, 'bindparams'), $array_of_params);
Pour plus d'informations, consultez le manuel PHP sur Fonctions de rappel."
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);
Cela n'a pas fonctionné pour moi dans mon environnement mais cette réponse m'a mis sur la bonne voie.Ce qui a réellement fonctionné, c'est :
$sitesql = '';
$array_of_params = array();
foreach($_POST['multiselect'] as $value){
if($sitesql!=''){
$sitesql .= "OR siteID=? ";
$array_of_params[0] .= 'i';
$array_of_params[] = $value;
}else{
$sitesql = " siteID=? ";
$array_of_params[0] .= 'i';
$array_of_params[] = $value;
}
}
$stmt = $linki->prepare("SELECT IFNULL(SUM(hours),0) FROM table WHERE ".$sitesql." AND week!='0000-00-00'");
call_user_func_array(array(&$stmt, 'bind_param'), $array_of_params);
$stmt->execute();