Léo has struck again. He listed his old broken bike in the classified ads, at a price of -€5: “I'll pay you to take it away!” Madame Lou did not laugh. A price must never be negative, whatever is written in new Annonce(...). And ads at €0 should show “Free” rather than “€0”.
Since PHP 8.4, a property can do this job itself, with hooks: code that runs when the property is read (get) or written (set).
Your mission
- In the constructor of
Annonce, the price becomespublic private(set) int $prix { set => max(0, $value); }. It can be read anywhere, changed only inside the class, and thesethook replaces a negative price with 0:max(0, $value)returns the larger of the two numbers, so 0 when$valueis negative. - Add to
Annoncea virtual propertypublic string $prixAffiche(displayed price), with agethook that returns'Free'for a price of 0, and otherwise “€” followed by the price:'€40'. - In
versHtml(), display$this->prixAffichein<p class="prix">.
The front page does not change: Madame Lou's bike still costs €40. The tests, on the other hand, will try Léo's ad.
Why not readonly anymore?
A hook cannot be put on a readonly property. private(set) plays a similar role: everyone can read the property (public), but only the class can write it (private(set)). That is asymmetric visibility, which also arrived with PHP 8.4.
Reminder
A set hook receives the value someone is trying to store in $value, and decides what actually gets stored. Written in the short form set => expression;, it stores the result of the expression. A get hook computes what you get when you read the property. A property that only has a get and never uses its own value stores nothing: it is virtual, recomputed on every read, like a method you read without parentheses. Before PHP 8.4, you wrote getPrix() and setPrix() methods for this.