Un prix qui se tient

Exercice 7 sur 9 du chapitre 2 · 150 XP · 5 objectifs vérifiés par des tests

Notions abordées : Property hookgetsetprivate(set)Propriété virtuelle

Léo a encore frappé. Il a proposé son vieux vélo cassé dans les petites annonces, au prix de -5 € : « Je vous paie pour l'emporter ! » Madame Lou n'a pas ri. Un prix ne doit jamais être négatif, quoi qu'on écrive dans new Annonce(...). Et les annonces à 0 € doivent afficher « Gratuit » plutôt que « 0 € ».

Depuis PHP 8.4, une propriété peut faire elle-même ce travail, avec des hooks : du code qui s'exécute quand on lit (get) ou quand on écrit (set) la propriété.

Votre mission

  1. Dans le constructeur d'Annonce, le prix devient public private(set) int $prix { set => max(0, $value); }. Il se lit partout, ne se change que dans la classe, et le hook set remplace un prix négatif par 0 : max(0, $value) renvoie le plus grand des deux nombres, donc 0 quand $value est négatif.
  2. Ajoutez à Annonce une propriété virtuelle public string $prixAffiche, avec un hook get qui renvoie 'Gratuit' pour un prix de 0, et sinon le prix suivi d'une espace et de « € » : '40 €'.
  3. Dans versHtml(), affichez $this->prixAffiche dans <p class="prix">.

La une ne change pas : le vélo de Madame Lou coûte toujours 40 €. Les tests, eux, essaieront l'annonce de Léo.

Pourquoi plus readonly ?

Un hook ne peut pas se poser sur une propriété readonly. private(set) joue un rôle voisin : tout le monde peut lire la propriété (public), mais seule la classe peut l'écrire (private(set)). C'est la visibilité asymétrique, arrivée elle aussi avec PHP 8.4.

Rappel

Un hook set reçoit la valeur qu'on essaie de ranger dans $value, et décide de ce qui est vraiment stocké. Écrit sous la forme courte set => expression;, il range le résultat de l'expression. Un hook get calcule ce qu'on obtient en lisant la propriété. Une propriété qui n'a qu'un get et ne se sert pas d'elle-même ne stocke rien : elle est virtuelle, recalculée à chaque lecture, comme une méthode qu'on lirait sans parenthèses. Avant PHP 8.4, on écrivait pour cela des méthodes getPrix() et setPrix().