Je suis occupé par une fonction qui obtient les paramètres d'une base de données, et soudainement, j'ai rencontré cette erreur:
Fatal error: Call to a member function bind_param() on boolean in C:\xampp2\htdocs\application\classes\class.functions.php on line 16
Normalement, cela signifie que je sélectionne des éléments dans des tables et des éléments non existants. Mais dans ce cas, je ne suis pas ...
Voici la fonction getSetting
:
public function getSetting($setting)
{
$query = $this->db->conn->prepare('SELECT value, param FROM ws_settings WHERE name = ?');
$query->bind_param('s', $setting);
$query->execute();
$query->bind_result($value, $param);
$query->store_result();
if ($query->num_rows() > 0)
{
while ($query->fetch())
{
return $value;
if ($param === '1')
{
$this->tpl->createParameter($setting, $value);
}
}
}
else
{
__('invalid.setting.request', $setting);
}
}
La variable $this->db
est transmise par un constructeur. En cas de besoin, le voici:
public function __construct($db, $data, $tpl)
{
$this->db = $db;
$this->tpl = $tpl;
$this->data = $data;
$this->data->setData('global', 'theme', $this->getSetting('theme'));
}
De plus, comme je me sers d'une base de données, ma connexion à la base de données:
class Database
{
private $data;
public function __construct($data)
{
$this->data = $data;
$this->conn = new MySQLi(
$this->data->getData('database', 'hostname'),
$this->data->getData('database', 'username'),
$this->data->getData('database', 'password'),
$this->data->getData('database', 'database')
);
if ($this->conn->errno)
{
__('failed.db.connection', $this->conn->errno);
}
date_default_timezone_set('Europe/Amsterdam');
}
J'ai déjà testé la connexion, 100% positif, cela fonctionne comme prévu . Je configure la connexion à la base de données dans un fichier de configuration:
'database' => array(
'hostname' => '127.0.0.1',
'username' => 'root',
'password' => ******,
'database' => 'wscript'
)
Maintenant, la chose étrange est; la table existe, le paramètre demandé existe, la base de données existe, mais cette erreur ne disparaîtra pas. Voici quelques preuves que la base de données est correcte:
Le problème réside dans:
$query = $this->db->conn->prepare('SELECT value, param FROM ws_settings WHERE name = ?');
$query->bind_param('s', $setting);
La méthode prepare()
peut renvoyer false
et vous devriez le vérifier. Pourquoi renvoie-t-il false
? Peut-être que le nom de la table ou les noms des colonnes (dans la clause SELECT
ou WHERE
) ne sont pas corrects?
En outre, envisagez d'utiliser quelque chose comme $this->db->conn->error_list
pour examiner les erreurs survenues lors de l'analyse syntaxique du code SQL. (Je vais de temps en temps faire écho aux chaînes d'instructions SQL réelles et les coller dans phpMyAdmin pour les tester, mais il y a certainement quelque chose qui ne fonctionne pas.)
Chaque fois que vous obtenez le ...
"Erreur fatale: appel d'un fonction membre bind_param () sur un booléen"
... c'est probablement parce qu'il y a un problème avec votre requête. La prepare()
peut renvoyer FALSE
(un booléen), mais ce message d'échec générique ne vous laisse pas beaucoup d'indices. Comment trouvez-vous ce qui ne va pas avec votre requête? Vous demandez!
Tout d’abord, assurez-vous que le rapport d’erreur est activé et visible: ajoutez ces deux lignes en haut de vos fichiers juste après votre balise <?php
d’ouverture:
error_reporting(E_ALL);
ini_set('display_errors', 1);
Si votre rapport d'erreur a été défini dans le fichier php.ini, vous n'aurez pas à vous en préoccuper. Assurez-vous simplement de gérer les erreurs avec élégance et de ne jamais révéler la véritable cause de tout problème à vos utilisateurs. Révéler la véritable cause au public peut être une invitation gravée dans l’or pour ceux qui veulent nuire à vos sites et à vos serveurs. Si vous ne souhaitez pas envoyer d'erreurs au navigateur, vous pouvez toujours surveiller les journaux d'erreurs de votre serveur Web. L'emplacement des journaux varie d'un serveur à l'autre. Par exemple, sous Ubuntu, le journal des erreurs se trouve généralement à /var/log/Apache2/error.log
. Si vous examinez les journaux d'erreurs dans un environnement Linux, vous pouvez utiliser tail -f /path/to/log
dans une fenêtre de console pour voir les erreurs lorsqu'elles se produisent en temps réel .... ou au fur et à mesure que vous les créez.
Une fois que vous êtes prêt à signaler les erreurs standard, ajouter une vérification des erreurs sur votre connexion à la base de données et des requêtes vous donnera beaucoup plus de détails sur les problèmes rencontrés. Jetez un oeil à cet exemple où le nom de colonne est incorrect. Tout d’abord, le code qui renvoie le message d’erreur fatale générique:
$sql = "SELECT `foo` FROM `weird_words` WHERE `definition` = ?";
$query = $mysqli->prepare($sql)); // assuming $mysqli is the connection
$query->bind_param('s', $definition);
$query->execute();
L'erreur est générique et ne vous aide pas beaucoup à résoudre ce qui se passe.
Avec quelques lignes de code supplémentaires, vous pouvez obtenir des informations très détaillées que vous pouvez utiliser pour résoudre le problème immédiatement. Vérifiez l'exactitude de la déclaration prepare()
et, si elle est bonne, vous pouvez procéder à la liaison et à l'exécution.
$sql = "SELECT `foo` FROM `weird_words` WHERE `definition` = ?";
if($query = $mysqli->prepare($sql)) { // assuming $mysqli is the connection
$query->bind_param('s', $definition);
$query->execute();
// any additional code you need would go here.
} else {
$error = $mysqli->errno . ' ' . $mysqli->error;
echo $error; // 1054 Unknown column 'foo' in 'field list'
}
Si quelque chose ne va pas, vous pouvez cracher un message d'erreur qui vous amène directement au problème. Dans ce cas, il n'y a pas de colonne foo
dans la table, la résolution du problème est triviale.
Si vous le souhaitez, vous pouvez inclure cette vérification dans une fonction ou une classe et l'étendre en corrigeant les erreurs comme mentionné précédemment.
prepare
renvoie un booléen uniquement quand il échoue donc FALSE
, pour éviter l'erreur, vous devez d'abord vérifier si c'est True
avant d'exécuter:
$sql = 'SELECT value, param FROM ws_settings WHERE name = ?';
if($query = $this->db->conn->prepare($sql)){
$query->bind_param('s', $setting);
$query->execute();
//rest of code here
}else{
//error !! don't go further
var_dump($this->db->error);
}
Même si la syntaxe de la requête est correcte, prepare pourrait renvoyer false, s'il existait une instruction précédente et qu'elle n'était pas fermée . Fermez toujours votre instruction précédente avec
$statement->close();
Si la syntaxe est correcte, la requête suivante fonctionnera également correctement.
Une autre situation pouvant provoquer ce problème est une incorporation incorrecte dans vos requêtes.
Je sais que cela peut sembler évident, mais je me suis heurté à cela en utilisant tablename
au lieu de Tablename
. Vérifiez vos requêtes et assurez-vous que vous utilisez le même casse que les noms réels des colonnes de votre table.
Vous devriez toujours essayer autant que possible de toujours mettre vos déclarations dans un bloc catch try ... cela aidera toujours dans des situations comme celle-ci et vous permettra de savoir ce qui ne va pas. Peut-être que le nom de la table ou de la colonne est incorrect.
Cette erreur particulière a très peu à voir avec l'erreur réelle. Voici mon expérience similaire et la solution ... J'avais une table que j'utilise dans ma déclaration avec le nom composite "| database-name | .login". Je pensais que ce ne serait pas un problème. C'était le problème en effet. Le placer entre crochets a résolu mon problème ("[| nom-base-de-données |]. [Login]"). Donc, le problème, ce sont les mots préservés dans MySQL (autrement inverse;)) ... assurez-vous que vos colonnes ne manquent pas non plus de ce type d'erreur scdenario ...
Parfois, cela est également dû à un table incorrectenom ou nom de colonnedans l'instruction de préparation.
Regarde ça:
Les deux causes les plus probables de ce problème sont les suivantes:
$stmt->close(); // <<<-----This fixed the issue for me
$stmt = $conn->prepare("Insert statement");
Parfois, il peut être utile d'indiquer explicitement les noms de colonne de votre table (en particulier dans une requête d'insertion). Par exemple, la requête: INSERT INTO tableName(param1,param2,param3) VALUES(?,?,?)
peut mieux fonctionner que: INSERT INTO tableName VALUES(?,?,?)