PROJET AUTOBLOG


Tiger-222

Archivé

Site original : Tiger-222

⇐ retour index

Comment gérer les checkbox multiple non envoyées en POST ?

vendredi 21 février 2014 à 12:05
C'est un cas qui revient assez souvent sur la toile : dans votre formulaire HTML, les cases à cocher ne sont accessibles avec PHP — dans le tableau $_POST — que si elles sont cochées. Il existe des astuces comme ajouté un champ caché, mais dans le cas suivant, ça ne fonctionnera pas (ou la mise en place serait trop fastidieuse).


Le formulaire


Imaginons une todolist toute simple en HTML, avec quelques contrôles en JS et le stockage en PHP.
<form action="." method="post">
	<table summary="Liste des choses à faire">
<tr>
<th>Tâche</th>
<th>Priorité</th>
<th>Urgent ?</th>
</tr>
<tr>
<td><input type="text" name="tache[]"></td>
<td><input type="number" name="priorite[]" step="1" min="1" max="5"></td>
<td><input type="checkbox" name="urgent[]"></td>
</tr>
<!-- (...) plusieurs autres lignes telles que la précédente -->
</table>
<input type="submit" value="Mettre à jour !">
</form>

Dans ce cas là, si j'ajoute 3 choses à faire non urgentes, le tableau $_POST sera rempli tel que :
array(2) {
["tache"]=> array(3) {
[0]=>
string(17) "Faire les courses"
[1]=>
string(28) "Corriger bug #2 Shaarlimages"
[2]=>
string(1) "S'abonner à MISC"
}
["priorite"]=>
array(3) {
[0]=>
string(1) "1"
[1]=>
string(1) "4"
[2]=>
string(1) "2"
}
}

Maintenant, je coche urgent pour la tâche n° 2, soit « Corriger bug #2 Shaarlimages ». Voyons ce que ça donne :
array(3) {
["urgent"]=> array(1) {
[0]=>
string(2) "on"
}
["tache"]=>
array(3) {
[0]=>
string(17) "Faire les courses"
[1]=>
string(28) "Corriger bug #2 Shaarlimages"
[2]=>
string(1) "S'abonner à MISC"
}
["priorite"]=>
array(3) {
[0]=>
string(1) "1"
[1]=>
string(1) "4"
[2]=>
string(1) "2"
}
}
DOH ! La tâche n° 1 se retrouve urgente, c'est n'importe quoi !


La solution


Lorsque l'on utilise name="tache[]" à la place de name="tache", le tableau $_POST est peuplé d'un tableau contenant les différentes valeurs de tous les champs ayant comme name tache. La premère occurrence sera en tête du tableau. Il y a donc un indice, un curseur, ou appelez ça comme vous voudrez, qui est incrémenté.
Utilisons ce système à notre avantage alors !

Lorsque l'utilisateur (dé)chochera une case à cocher, on lui affectera la valeur de sont index dans le tableau. Facile :
<form action="." method="post">
	<table summary="Liste des choses à faire">
<tr>
<th>Tâche</th>
<th>Priorité</th>
<th>Urgent ?</th>
</tr>
<tr>
<td><input type="text" name="tache[]"></td>
<td><input type="number" name="priorite[]" step="1" min="1" max="5"></td>
<td>
<input type="checkbox" name="urgent[]"
onChange="this.value = this.parentNode.parentNode.rowIndex;">
</td>
</tr>
<!-- (...) plusieurs autres lignes telles que la précédente -->
</table>
<input type="submit" value="Mettre à jour !">
</form>
La fonction rowIndex retourne l'indice de la ligne dans le tableau.

Dorénavant, voici le contenu du tableau $_POST avec la tâche n° 2 urgente :
array(3) {
["urgent"]=> array(1) {
[0]=>
string(1) "1"
}
["tache"]=>
array(3) {
[0]=>
string(17) "Faire les courses"
[1]=>
string(28) "Corriger bug #2 Shaarlimages"
[2]=>
string(1) "S'abonner à MISC"
}
["priorite"]=>
array(3) {
[0]=>
string(1) "1"
[1]=>
string(1) "4"
[2]=>
string(1) "2"
}
}
L'ordre du tableau urgent ne compte plus, il contient seulement les indices des caces cochées.

Et du côté de PHP, pour savoir si une tâche est urgente ou non :
for ( $i = 0, $len = count($_POST['tache']); $i < $len; ++$i ) {
$infos[] = array(
'tache' => $_POST['tache'][$i],
'priorite' => min(max(1, $_POST['priorite'][$i]+0), 5),
'urgent' => isset($_POST['urgent']) ? in_array($i, $_POST['urgent']) : false,
);
}