Je fais un formulaire en me basant sur le tuto "systeme d'inscription avec validation par l'administrateur" or je rencontre un problème tel que" Fatal error in page 63 qui correspond à la requête préparée afin de savoir si le pseudo est déjà utilisé ou pas.
J'ai php 7.1.
<?php
// Je vérifie si tous les champs sont bien remplis et je récupère les variables
$nom=!empty($_POST['nom']) ? $_POST['nom']:NULL;
$prenom=!empty($_POST['prenom']) ? $_POST['prenom']:NULL;
$pseudo=!empty($_POST['pseudo']) ? $_POST['pseudo']:NULL;
$passe=!empty($_POST['passe']) ? $_POST['passe']:NULL;
$passe2=!empty($_POST['passe2']) ? $_POST['passe2']:NULL;
$email=!empty($_POST['email']) ? $_POST['email']:NULL;
try
{
// je me connecte à la BD
$bdd = new PDO('mysql:host=localhost;dbname=mzfs_albert', 'root','');
$bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e){
die('Erreur : Echec à la connexion' . $e->getMessage());
}
// je fais une requête préparée pour savoir si le pseudo proposé est déjà pris ou pas.
$sth=$bdd->prepare("SELECT COUNT(*) AS exist FROM validation WHERE pseudo=$pseudo");
$sth->execute();
$donnee=$sth->fetchALL(PDO::fetch_colum,3);
if($donnee['exist']!=0);//Si le pseudo existe
{
echo "Ce pseudo est déjà pris, choisissez un autre pseudo!";
}
if($passe===$passe2)
// je hache le mot de passe
{
$passe=password_hash($passe, PASSWORD_ARGON2ID);
}
else
{
echo "Vos 2 mots de passe ne correspondent pas, veuillez recommencer";
}
//je prépare à insérer les données du nouveau membre
$sth = $bdd->prepare('INSERT INTO validation (nom,prenom,pseudo,passe,email) VALUES ( :nom, :prenom, :pseudo, :passe, :email)');
$sth->bindParam(':nom',$nom);
$sth->bindParam(':prenom',$prenom);
$sth->bindParam(':pseudo', $pseudo);
$sth->bindParam(':passe', $passe);
$sth->bindParam(':email', $email);
$sth->execute();
?>
Je dois avoir omis quelque chose mais je ne vois,pas quoi! Merci d'avance!
ta requête ne renvoie pas 4 colonnes : d'où tu sors ce 3 ?
fetch_colum n'existe pas, c'est en majuscules (les constantes définies par PHP sont sensibles à la casse)
$donnee['exist'] n'existera pas en mode FETCH_COLUMN et encore moins avec un fetchAll, déjà que le fetchAll ne sert à rien puisque la requête n'aura (aurait vu qu'elle est fausse) qu'une ligne, idem pour l'alias
Effectivement j'ai donc changé le Fetch_column et mis en majuscule, pourtant j'ai lu dans le manuel PHP
PHP manuel:
Exemple #2 Récupération de toutes les valeurs d'une seule colonne depuis un jeu de résultats
L'exemple suivant montre comment retourner toutes les valeurs d'une seule colonne depuis un jeu de résultats, même si la requête SQL retourne plusieurs colonnes par lignes.
<?php $sth = $dbh->prepare("SELECT name, colour FROM fruit"); $sth->execute();
/* Récupération de toutes les valeurs de la première colonne */ $result = $sth->fetchAll(PDO::FETCH_COLUMN, 0); var_dump($result); ?>
Ou alors je lis mal (ce qui est très possible aussi)!
Après modification (mise en majuscule) il me signale maintenant que le champ "pseudo" n'existe pas, or je suis allé vérifié dans ma BD et ce champ existe bel et bien!
fetchAll c'est pour lire potentiellement plusieurs (= plus d'une) lignes (c'est le cas de la requête que tu reprends de la doc) et les retourne sous forme de tableau (comme doit le montrer ton var_dump). Or avec un SELECT COUNT sans clause GROUP BY tu n'as forcément qu'une ligne, c'est le principe d'une fonction d'agrégation quoi. Sachant cela, pourquoi ne pas utiliser directement un fetchColumn ?
Le fetchAll en mode PDO::FETCH_COLUMN va t'obliger à écrire inutilement $donnee[0] alors qu'avec un fetchColumn, tu obtiens directement un scalaire (ie tu peux utiliser directement $donnee).
Tu fais ce que tu veux, ce ne serait pas faux non plus, mais ce n'est pas utile ni vraiment naturel (ça risque éventuellement de prêter à confusion à quiconque reprendrait ton code). C'est encore plus "flagrant" avec les modes normaux (PDO::FETCH_ASSOC surtout), où tu te retrouves avec un tableau de tableaux et $row[0]['colonne'] quand tu sais n'avoir qu'une ligne à un $row['colonne'], tu te demandes un peu pourquoi tu te retrouves avec un tableau bidimensionnel et d'où sort ce 0.
> il me signale maintenant que le champ "pseudo" n'existe pas
> Donc si je comprends bien je dois changer ma requête:
Je ne sais même pas ce que tu cherches à faire ... Erreurs de syntaxe mises à part :
Select * from validation : la requête change tout à coup ?
Si ($donnee>0){ : parce que tu trouves que comparer un tableau à un entier a un sens ?
récupérer la valeur de la 4^ème colonne, ça d'accord, mais t'en fais quoi des autres ? Je veux dire que si le but est de n'utiliser qu'une des colonnes, ça ne sert à rien de demander à ta requête d'en renvoyer plus d'une ...
> Dans ma requête il ne reconnait pas le champ "pseudo", peut-être mal formulée?
Prépare (correctement) ta requête SELECT comme on te l'a déjà demandé ! (reprendre cours/doc si besoin) Là, il manque(manquait) les quotes pour le SQL mais de te façon, ça n'en serait pas correct, ça planterait si le pseudo contenait une quote et tu te retrouverais avec une injection SQL. Visiblement, tu t'es juste contenté de remplacer les " qui délimitaient la requête par des ', ce qui ne changera rien.
> Si tu utilises PHP dans sa version 7, autant utiliser les nouvelles fonctionnalités qui vont avec
Mouais :
tu ne serais pas en train de réécrire filter_input_array ?
de toute façon, est-ce qu'initialiser explicitement à NULL apporte quelque chose ? Je veux dire autant tester que le nécessaire existe au préalable, non ? Et j'imagine que la plupart de ces colonnes ne sont pas nullable pour autant ...
Si tu utilises PHP dans sa version 7, autant utiliser les nouvelles fonctionnalités qui vont avec sans oublier de préparer ta requête si tu attends un input utilisateur.
$data = array_map("strip_tags", [
"nom" => $_POST["nom"] ?? null,
"prenom" => $_POST["prenom"] ?? null
]);
// ...
$req = $sql->prepare("SELECT * FROM x WHERE y = :nom");
$req->bindValue(":nom", $data["nom"], PDO::PARAM_STR);
$req->execute();
La programmation, c'est avant tout un minimum de bon sens : même si la partie requête était correcte, tu aurais testé que le pseudo est déjà pris ou non mais tu as un if qui ne met pas fin au script ni de else pour autant donc quoi qu'il arrive, tu fais l'insertion ...
Et encore, avec le `;` derrière la condition de ton if, ça fait que ton if ne sert à rien et le echo est toujours affiché aussi.
Bref, on ne va pas y passer 15 ans :
$sth = $bdd->prepare('SELECT COUNT(*) FROM validation WHERE pseudo = :pseudo');
$sth->execute(['pseudo' => $_POST['pseudo']]);
if ($sth->fetchColumn()/* != 0*/) {
echo "Ce pseudo est déjà pris, choisissez un autre pseudo!";
} else {
// mettre l'insert/la suite du code ici
}
Encore que le mot de passe et sa confirmation, je le testerais avant, ça permettrait d'éviter de faire le SELECT COUNT pour rien si le mot de passe ne correspond pas.
EDIT : tu fais la même erreur avec le else de la confirmation du mot de passe justement : tu testes bien qu'ils correspondent mais le else ne met même pas fin au script (ce que je ne recommande pas, c'est le minimum syndical) mais l'INSERT est situé en dehors/après ce if/else donc, pareil, qu'importe le résultat de ce test, tu feras quand même l'insertion et avec, ô mon Dieu, le mot de passe en clair si tu passes par le else ... L'INSERT devrait être dans ce if, pas après (et ce sera l'occasion de virer cette variable intermédiaire $passe)
Voilà comment on pourrait faire un truc (bien plus) propre :
<?php
$bdd = new PDO('mysql:host=localhost;dbname=mzfs_albert', 'root','');
$bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$erreurs = [];
if (empty($_POST['pseudo'])) {
$erreurs[] = "Le champ pseudo a été omis";
} else {
$sth = $bdd->prepare('SELECT COUNT(*) FROM validation WHERE pseudo = :pseudo');
$sth->execute(['pseudo' => $_POST['pseudo']]);
if ($sth->fetchColumn()/* != 0*/) {
$erreurs[] = "Ce pseudo est déjà pris, choisissez un autre pseudo!";
}
}
if (empty($_POST['passe']) || empty($_POST['passe2'])) {
$erreurs[] = "Le champ mot de passe et/ou sa confirmation ont été omis";
} else if ($_POST['passe'] != $_POST['passe2']) {
$erreurs[] = "Vos 2 mots de passe ne correspondent pas, veuillez recommencer";
}
if ($erreurs) {
echo 'Veuillez corriger les erreurs suivantes :<br/>';
foreach ($erreurs as $erreur) {
echo $erreur, '<br/>';
}
} else {
$sth = $bdd->prepare('INSERT INTO validation (nom, prenom, pseudo, passe, email) VALUES (:nom, :prenom, :pseudo, :passe, :email)');
$sth->bindValue(':nom', $_POST['nom']);
$sth->bindValue(':prenom', $_POST['prenom']);
$sth->bindValue(':pseudo', $_POST['pseudo']);
$sth->bindValue(':passe', password_hash($_POST['passe'], PASSWORD_ARGON2ID));
$sth->bindValue(':email', $_POST['email']);
$sth->execute();
}
PS :
j'ai viré tout ce qui était inutile (le try/catch, les variables intermédiaires, etc)
<table width="518" height="833" border="5" align="center">
<tr>
<th width="528" height="819" bgcolor="#FFFF00" scope="col"><h2>INSCRIPTION
</h2><form action="inscription10.php" method="post">
<Label for="nom">Votre nom:</Label>
<input name="nom" type="text" placeholder="Indiquez votre nom:" id="nom" size="40">
<p>
<Label for="prenom">Votre prenom:</Label>
<input name="prenom" type="text" placeholder="Indiquez votre prenom:" id="prenom" size="40">
</p><p>
<label for="pseudo">Votre pseudo:</label>
<input name="pseudo" type="text" placeholder="Indiquez votre pseudo:" id="pseudo" size="40">
</p>
<p>
<label for="passe">Votre mot de passe</label>
<input name="passe" type="password" placeholder="Indiquez votre mot de passe:" id="passe" size="40">
</p>
<p>
<label for="passe2">Confirmez votre mot de passe</label>
<input name="passe2" type="password" placeholder="reintroduisez votre mot de passe:" id="passe2" size="40">
</p>
<p>
<label for="email">Votre e-mail:</label>
<input name="email" type="text" placeholder="Introduisez votre e-mail:" id="email" size="40">
</p>
<p>
<input type="submit" name="Enregistrer" id="Valider" value="Enregistrer">
</p>
<p>ATTENTION!!!!</p>
<p>1) les champs "nom" et "prenom" doivent être ceux du joueur ou de la licence récréative!</p>
<p>2) dès que vous êtes "enregistrer" envoyer un mail à l'administrateur <a href="mailto:af050943@gmail.com">af050943@gmail.com </a>demandant </p>
<p>la validation de votre inscription!</p>
<p>3) Dans ce mail, précisez:</p>
<p>-Je suis joueur du RTT ANS </p>
<p>- J'ai la licence récréative</p>
<p>Si mineur:</p>
<p>- Je suis le père du joueur</p>
<p>-Je suis la mère du joueur</p>
</form></th>
Voici le code
<?php
require_once('connect.php');
require_once('forminsc.php');
$erreurs = [];
if(isset($_POST['Enregistrer']))
{
if(empty($_POST['pseudo']))
{
$erreurs[] = "Le champ pseudo a été omis";
}
else
{
$sth = $bdd->prepare('SELECT COUNT(*) FROM validation WHERE pseudo = :pseudo');
$sth->execute(['pseudo' => $_POST['pseudo']]);
if ($sth->fetchColumn()/* != 0*/)
{
$erreurs[] = "Ce pseudo est déjà pris, choisissez un autre pseudo!";
}
}
if(empty($_POST['passe']) || empty($_POST['passe2']))
{
$erreurs[]= "Le champ mot de passe et/ou sa confirmation ont été omis";
}
else if ($_POST['passe'] != $_POST['passe2'])
{
$erreurs[] = "Vos 2 mots de passe ne correspondent pas, veuillez recommencer";
}
if($erreurs)
{
echo 'Veuillez corriger les erreurs suivantes :<br/>';
foreach ($erreurs as $erreur)
{
echo $erreur, '<br/>';
}
}
else
{
$sth = $bdd->prepare('INSERT INTO validation (nom, prenom, pseudo, passe, email) VALUES (:nom, :prenom, :pseudo, :passe, :email)');
$sth->bindValue(':nom', $_POST['nom']);
$sth->bindValue(':prenom', $_POST['prenom']);
$sth->bindValue(':pseudo', $_POST['pseudo']);
$sth->bindValue(':passe', password_hash($_POST['passe']PASSWORD_ARGON2ID));
$sth->bindValue(':email', $_POST['email']);
$sth->execute();
$sth->closeCursor();
}
}
?>
Et on peut avoir le contenu de connect.php (après avoir supprimé tes identifiants)
Soit les conditions sont fausses (le form ne serait pas en method="post") soit tu n'as pas gardé l'activation des erreurs PDO/SQL :/
EDIT :
> password_hash($_POST['passe']PASSWORD_ARGON2ID)
Elle est passée où la , pour séparer les paramètres ?
Si c'est le vrai code, ça vaut une erreur de syntaxe et pour ne pas le voir, c'est carrément que l'affichage des erreurs PHP n'est pas activé ! (display_errors à off au lieu de on)
J'ai corrigé l'erreur password et trouvé l'autre erreur car il tenait compte d'un champs non accessible à l'utilisateur, mais j'avais laissé ce champ à not null.
Au passage, vire-nous cette ligne 6 de connect.php et réfères-toi à la FAQ PHP de ce forum (ou celle de ma signature) pour voir comment faire correctement. A moins que tu ne codes une machine à remonter le temps avant PHP 5.3.6 ?
Keep It Simple Stupid - SF4 conf Swift - Cours 1/4 SF4 - Exceptions PDO - Formes Normales
julp.fr ~ PHP < 8.0.0 : activer les erreurs PDO/SQL ~ PHP < 8.1.0 : activer les erreurs mysqli
julp.fr ~ PHP < 8.0.0 : activer les erreurs PDO/SQL ~ PHP < 8.1.0 : activer les erreurs mysqli
Keep It Simple Stupid - SF4 conf Swift - Cours 1/4 SF4 - Exceptions PDO - Formes Normales
julp.fr ~ PHP < 8.0.0 : activer les erreurs PDO/SQL ~ PHP < 8.1.0 : activer les erreurs mysqli
julp.fr ~ PHP < 8.0.0 : activer les erreurs PDO/SQL ~ PHP < 8.1.0 : activer les erreurs mysqli
julp.fr ~ PHP < 8.0.0 : activer les erreurs PDO/SQL ~ PHP < 8.1.0 : activer les erreurs mysqli
julp.fr ~ PHP < 8.0.0 : activer les erreurs PDO/SQL ~ PHP < 8.1.0 : activer les erreurs mysqli
julp.fr ~ PHP < 8.0.0 : activer les erreurs PDO/SQL ~ PHP < 8.1.0 : activer les erreurs mysqli