Pourquoi mon formulaire PHP ne vérifie pas si les checkbox sont cochées ?

Réponses rédigées par Antoine
Dernière mise à jour : 2022-03-25 23:26:41
Thèmes : php - checkbox - formulaire
Question

Bonsoir, J'ai un petit souci avec mon formulaire. Il est parfait dans l'ensemble. Lorsque je remplis rien (ni état civil ni checkbox) cela me renvoie bien aux 2 messages spécifiés mais si l'état civil est rempli mais aucune checkbox n'est cochée (au moins 1 doit être cochée), le message est validé et envoyé. Donc dans mon mail je reçois une commande sans aucun livre choisi. Je ne comprends pas où ça cloche : Mon formulaire :

<form action="traitement_commande.php" method="post" name="commande" id="formulaire">

<fieldset class="fieldset_commande">
<legend>Votre identité</legend>

<div class="champ">
<label for="prenom">Prénom<span class="requis">*</span></label>
<input type="text" name="prenom" id="prenom" pattern="[A-Za-zàéèêëîïôöûüÿ' -]+" value="<?= (empty($_POST['prenom'])) ? '' : $_POST['prenom']; ?>" placeholder="Votre prénom" />
<span class="error" title="Merci de ne saisir que des lettres, trait d'union, apostrophe et espace."></span>
</div>

<div class="champ">
<label for="nom">Nom<span class="requis">*</span></label>
    <input type="text" name="nom" id="nom" pattern="[A-Za-zàéèêëîïôöûüÿ' -]+" value="<?= (empty($_POST['nom'])) ? '' : $_POST['nom']; ?>" placeholder="Votre nom" />
 <span class="error" title="Merci de ne saisir que des lettres, trait d'union, apostrophe et espace."></span>
</div>

<div class="champ">
<label for="email">Email<span class="requis">*</span></label>
    <input type="text" name="email" id="email" pattern="^[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z]{2,4}$" value="<?= (empty($_POST['email'])) ? '' : $_POST['email']; ?>" placeholder="prenom.nom@site.com" />
<span class="error" title="Merci d'entrer une adresse email valide (prenom.nom@site.com)."></span>
</div>
</fieldset>

<fieldset class="fieldset_commande">
<legend>Vos coordonnées</legend>

<div class="champ">
<label for="adresse1">Adresse livraison<span class="requis">*</span></label>
<input class="error" type="text" name="adresse1" id="adresse1" value="<?= (empty($_POST['adresse1'])) ? '' : $_POST['adresse1']; ?>" placeholder="Adresse de livraison">
<span class="error" title="Merci d'indiquez l'adresse de livraison."></span>
</div>

<div class="champ">
<label for="adresse2">Complément d'adresse</label>
<input type="text" name="adresse2" id="adresse2" value="<?= (empty($_POST['adresse2'])) ? '' : $_POST['adresse2']; ?>" placeholder="Complément d'adresse">
</div>

<div class="champ">
<label for="cp">Code postal<span class="requis">*</span></label>
<input class="error" type="text" name="cp" id="cp" maxlength = "5" pattern="^[0-9]{5}$" value="<?= (empty($_POST['cp'])) ? '' : $_POST['cp']; ?>" placeholder="Code postal" >
<span class="error" title="Code postal composé de 5 chiffres."></span>
</div>

<div class="champ">
<label for="ville">Ville<span class="requis">*</span></label>
<input class="error" type="text" name="ville" id="ville" pattern="[A-Za-zàéèêëîïôöûüÿ' -]+" value="<?= (empty($_POST['ville'])) ? '' : $_POST['ville']; ?>" placeholder="Ville" >
<span class="error" title="Vous devez indiquer la ville (Lettres, trait d'union, apostrophe et lettres accentuées)."></span>
</div>
</fieldset>

<fieldset class="fieldset_commande">
<legend>Votre sélection</legend>

<p class="note">Vous devez choisir au moins un livre</p>

<!-- Le nombre total de livres -->
<h4>Il y a au total <?= $nb_livre; ?> livres. </h4>

<div class="align_check">

<!-- La requête pour afficher les livres -->

<?php
$sql = 'SELECT * FROM livre, collection WHERE livre.collectionID = collection.collectionID';

    $rs_select = $cnx->prepare($sql);
    $rs_select->execute();

while ($data = $rs_select->fetch(PDO::FETCH_ASSOC)) {
?>

<div class="checkbox">
<!--<span class="error" title="Attention ! Vous n'avez sélectionné aucun livre."></span>-->

<!-- La petite case à cocher -->
<input type="checkbox" id="choix_<?= $data['livreID']; ?>" name="choix[]" value="<?= strtoupper($data['nom_collection']); ?> - <?= $data['titre']; ?> (<?= $data['auteur']; ?>) - <?= $data['prix']; ?> € " />

<!-- Le détail des livres à sélectionner -->
<label class="livre" for="choix_<?= $data['livreID']; ?>">
<?= $data['nom_collection']; ?> <?= $data['vignette']; ?> <?= $data['prix']; ?> €
</label>

  </div>
<?php
}
?>
</div>

</fieldset>

<input class="bouton_commande" type="submit"  name="valider" value="J'envoie ma commande" />
</form>

et la page du script PHP :

<?php 
require_once('include/cnx.php');

// Si l'utilisateur a cliqué sur le bouton de validation
if(isset($_POST['valider'])) {

// strip_tags : Si l'utilisateur met des tags HTML, PHP ou autres, ils dégageront.
$prenom   = strip_tags($_POST['prenom']);
$nom      = strip_tags($_POST['nom']); 
$email    = strip_tags($_POST['email']);
$adresse1 = strip_tags($_POST['adresse1']);
$adresse2 = strip_tags($_POST['adresse2']);
$cp       = strip_tags($_POST['cp']);
$ville    = strip_tags($_POST['ville']);

if(empty($prenom) && empty($nom) && empty($email) && empty($adresse1) && empty($cp) && empty($ville)) {
$msg = 'Merci de remplir tous les champs comportant une *';

// Pour récupérer les checkbox cochées
if(!empty($_POST['choix'])) {
$commande = $_POST['choix'];
foreach($commande as $choixLivres) {
$selection .= $choixLivres.'<br />';
}
} else {
$msg2 = '<p style="text-align: center">Merci de cocher au moins un livre !</p>';
} 
// Fin pour les checkbox cochées
}

else {
$sql = 'INSERT INTO commande
(prenom, nom, email, adresse1, adresse2, cp, ville, selection) VALUE (:prenom, :nom, :email, :adresse1, :adresse2, :cp, :ville, :selection)';
$req = $cnx->prepare($sql);
$req->bindValue(':prenom', $prenom, PDO::PARAM_STR);
$req->bindValue(':nom', $nom, PDO::PARAM_STR);
$req->bindValue(':email', $email, PDO::PARAM_STR);
$req->bindValue(':adresse1', $adresse1, PDO::PARAM_STR);
$req->bindValue(':adresse2', $adresse2, PDO::PARAM_STR);
$req->bindValue(':cp', $cp, PDO::PARAM_INT);
$req->bindValue(':ville', $ville, PDO::PARAM_STR);
$req->bindValue(':selection', $selection, PDO::PARAM_STR);
$req->execute();

$expediteur    = 'no-reply_occasionsharlequin@mon-espace-detente.fr';
$destinataires = 'occasionsharlequin@mon-espace-detente.fr, v-arno@outlook.fr';
$sujet         = 'Commande de livres depuis votre site';

$contenu      = '<html>
<body>
<p class="form-contact">Vous avez reçu une commande de livres depuis votre site internet.</p>
<p class="form-contact">Prénom : '.$prenom.'</p>
<p class="form-contact">Nom : '.$nom.'</p>
<p class="form-contact">Email : '.$email.'</p>
<p class="form-contact">Adresse : '.$adresse1.'</p>
<p class="form-contact">Adresse complémentaire : '.$adresse2.'</p>
<p class="form-contact">Code postal : '.$cp.'</p>
<p class="form-contact">Ville : '.$ville.'</p>
<p class="form-contact">Commande :<br> '.$selection.'</p>
</body>
</html>';

$header = "MIME-Version: 1.0 \r\n";
$header.= 'From:' .$expediteur.' '."\n";
$header.= 'Content-Type:text/html; charset="utf-8"'."\n";
$header.= 'Content-transfert-Encoding: 8bit';

mail($destinataires, $sujet, $contenu, $header);

// Formulaire validé : Renvoi vers le message de remerciement.
header('Location: merci_commande.php');
}
}

// Si la réponse est un échec, on renvoie au formulaire
else {
//header('Location: bon_commande.php');
$msg = 'time out';
}
}
}
?>

<!DOCTYPE HTML>
<html lang="fr">
<head>
<title>Formulaire de contact</title>
<?php
include('include/meta.php');
?>
<?php
include('include/styles.php');
?>
</head>

<body>
<div id="conteneur">
<?php
include('include/header.php');
?>

<?php
include('include/nav.php');
?>

<section>
<div id="conteneur_contact">
<div id="contact">

<h2><?php
if(isset($msg)) {
echo $msg;
}
if(isset($msg2)) {
echo $msg2;
}
?></h2>

<i class="far fa-frown"></i>

<p><a class="lien" href="bon_commande.php">Retour au formulaire</a></p>

</div>
</div>

Merci pour votre aide Valérie

Réponse

Bonjour, pour vérifier les champs obligatoires, vous devriez plutôt utiliser l'opérateur logique || au lieu de &&.

Par ailleurs, votre insert en bdd et l'envoi du mail se faisaient car le else précédant la requête SQL venait en conséquence du if qui ne testait que les input du type text, et non les cases à cocher.

Vous pourriez par exemple procéder comme ceci :

if(empty($prenom) || empty($nom) || empty($email) || empty($adresse1) || empty($cp) || empty($ville)) 
{
$msg = 'Merci de remplir tous les champs comportant une  *';
}
else if(empty($_POST['choix']))
{
$msg2 = 'Merci de cocher au moins un livre !';
}
else
{
// tout est ok on récupère les checkbox cochées + insert bdd + envoi mail
}

La fonction strip_tags n'est par ailleurs pas suffisante pour sécuriser votre formulaire, référez vous à cette autre question pour le sécuriser d'avantage.