PHP

Le while en PHP : bloqueur, condition d’arrêt et break

Le while en PHP : sécurité, structure classique et avancée.

→ Corrigé du Challenge : Vegeta combat ses ennemis

Dans ce challenge, on ne sait pas d’avance de combien de niveau il faudra augmenter Vegeta pour qu’il puisse combattre l’ennemi courant. On a donc des opérations à répéter (=> boucle) mais on ne sait pas combien de fois (=> tant que…), le while est donc la bonne structure à utiliser.

Intégrer un bloqueur pour sécuriser son while

Mal utilisé, le while peut entraîner une « boucle infinie », c’est-à-dire que rien ne va arrêter le « tant que ». Le script va donc s’exécuter jusqu’à rencontrer le « max_execution_time » du serveur.

Quand on code un while, et qu’on n’est pas sûr du code qu’il contient, on peut intégrer un bloqueur. C’est-à-dire une variable qui va forcément « casser » le while à un moment donné pour éviter de se retrouver dans le cas de figure de la boucle infinie.

Exemple :

// Initialisation de mon bloqueur
$stop = 0;

while (/* Condition d'arrêt à écrire */) {

	// Mon code spécifique

	// Le code de mon bloqueur
	$stop++;
	if ($stop > 1000) {
		break;
	}
}

Le 1000 est ici arbitraire, à ajuster selon ton code. De cette façon, même si je mets plusieurs tentatives à bien structurer ma condition d’arrêt et ou le code à l’intérieur de mon while, je suis sûr de ne jamais enclencher de boucle infinie !

While classique

J’ai appris le while de cette façon, c’est à dire en mettant la condition d’arrêt dans les ( ) du while.

Dans le challenge DBZ_1, je parcours chaque ennemi, et j’augmente le niveau de Végéta tant que sa puissance n’est pas suffisante pour battre l’ennemi. Voici le code avec un while classique : (je garde volontairement le bloqueur)

// Une fonction pour calculer la puissance
function puissance(int $niveau, int $force): int
{
	return $niveau * $force;
}

// Code du challenge
$niveau = 1;

foreach ($ennemis as $ennemi) {

	$stop = 0;

	// La condition d'arrêt est ici :
	while (puissance($niveau, $force_vegeta) < $ennemi) {
		$niveau++;

		$stop++;
		if ($stop > 1000) {
			break;
		}
	}

	$force_vegeta += floor($ennemi / 10);
}

Pour s’assurer de ne pas enclencher une boucle infinie, il faut absolument qu’au moins 1 élément présent dans la condition d’arrêt soit altéré dans le bloc d’instructions du while { }. Sinon la condition d’arrêt ne change pas. Ici, $niveau est incrémenté à chaque itération, donc la valeur retournée par la fonction puissance va bien changer, donc la condition d’arrêt évolue.

While true

Une autre façon d’écrire son while consiste à déplacer la condition d’arrêt dans le bloc d’instructions. On aura donc un while(true) { … } et obligatoirement une instruction break dans le while (différente de celle du bloqueur bien sûr).

Le bloqueur prend encore + d’importance dans la construction du while ici, car un while true sans break va forcément enclencher une boucle infinie.

Voici le code précédent, ajusté avec un while true : (volontairement sans le bloqueur)

$niveau = 1;

foreach ($ennemis as $ennemi) {

	while (true) {

		if (puissance($niveau, $force_vegeta) >= $ennemi) {
			break;
		}

		$niveau++;
	}

	$force_vegeta += floor($ennemi / 10);
}

Avec l’expérience, je préfère cette écriture, elle permet de voir explicitement ce qui va interrompre la boucle while. Et ça prend tout son sens quand on a plusieurs façons d’interrompre la boucle. Avec le while classique, on cumulerait les conditions avec des && alors que ces conditions peuvent n’avoir que peu de lien. Avec cette façon de faire, tout est structuré et clarifié.


Qui a codé ce superbe contenu ?


Ta newsletter chaque mois

Corrigés, challenges, actualités, veille technique... aucun spam.