Skip to Content

Terrain 1 — PHP moderne

Micro-défis sur le langage. 🔍 Renfort : Partie 2.

1. Enum de statut ⭐

🎯 But : créer une backed enum. 🕹️ Mission : une enum Priority: int avec Low=1, Medium=2, High=3 et une méthode label(): string. 🔍 Où chercher : 2.3.

✅ Solution

enum Priority: int { case Low = 1; case Medium = 2; case High = 3; public function label(): string { return match($this) { self::Low => 'Basse', self::Medium => 'Moyenne', self::High => 'Haute' }; } }

🔁 Variante : ajoutez Priority::fromLabel('Haute') (statique) qui retrouve le cas.

2. DTO immuable ⭐

🎯 But : promotion + readonly. 🕹️ Mission : un final readonly class Money avec amountCents:int et currency:string, plus withAmount(int): self. 🔍 : 2.5.

✅ Solution

final readonly class Money { public function __construct(public int $amountCents, public string $currency) {} public function withAmount(int $amountCents): self { return new self($amountCents, $this->currency); } }

🔁 Variante : ajoutez add(Money $o): self qui refuse (exception) deux devises différentes.

3. Chasse aux faux-amis ⭐⭐

🎯 But : corriger le code d’un dev JS. 🕹️ Mission : corrigez echo "Total: " + $n; if ($u.role == "admin") {}. 🔍 : 2.8.

✅ Solution

echo "Total: " . $n; // . et non + if ($u->role === 'admin') {} // -> et === strict

4. match exhaustif ⭐⭐

🎯 But : remplacer un switch. 🕹️ Mission : convertissez un switch($role) renvoyant un niveau en match. 🔍 : 2.5.

✅ Solution

$level = match($role) { 'admin' => 3, 'provider' => 2, default => 1 };

🔁 Variante : faites-le sur une enum Role (sans default, pour l’exhaustivité vérifiée).

5. Nullsafe ⭐⭐

🎯 But : chaîner sans if. 🕹️ Mission : extraire l’email du client d’une réservation possiblement nulle, en une ligne. 🔍 : 2.5.

✅ Solution

$email = $booking?->getCustomer()?->getEmail();

6. Générateur paresseux ⭐⭐⭐

🎯 But : mémoire constante. 🕹️ Mission : un générateur readLines(string $path) qui yield chaque ligne d’un fichier. 🔍 : 2.7.

✅ Solution

function readLines(string $path): \Generator { $h = fopen($path, 'r'); try { while (($l = fgets($h)) !== false) yield rtrim($l); } finally { fclose($h); } }

7. Attribut personnalisé ⭐⭐⭐

🎯 But : écrire + lire un attribut. 🕹️ Mission : un #[AuditLog(string $action)] applicable aux méthodes, puis le lire par réflexion. 🔍 : 2.4.

✅ Solution

#[Attribute(Attribute::TARGET_METHOD)] final class AuditLog { public function __construct(public string $action) {} } $m = new ReflectionMethod(Ctrl::class, 'cancel'); foreach ($m->getAttributes(AuditLog::class) as $a) echo $a->newInstance()->action;

8. Enum + interface ⭐⭐⭐

🎯 But : polymorphisme sur enum. 🕹️ Mission : BookingStatus implémente HasColor { color():string }. 🔍 : 2.3.

✅ Solution

interface HasColor { public function color(): string; } enum BookingStatus: string implements HasColor { case Pending='pending'; case Confirmed='confirmed'; case Cancelled='cancelled'; public function color(): string { return match($this){ self::Pending=>'orange', self::Confirmed=>'green', self::Cancelled=>'red' }; } }

9. Traduire du TS ⭐⭐

🎯 But : TS → PHP. 🕹️ Mission : traduisez const active = bookings.filter(b => b.status === 'confirmed').map(b => b.email);. 🔍 : 2.8.

✅ Solution

$confirmed = array_filter($bookings, fn(Booking $b) => $b->status === BookingStatus::Confirmed); $active = array_map(fn(Booking $b) => $b->email, $confirmed);

10. throw comme expression ⭐⭐

🎯 But : concision. 🕹️ Mission : convertir $data['email'] en variable, ou lever si absent, en une ligne. 🔍 : 2.7.

✅ Solution

$email = $data['email'] ?? throw new \InvalidArgumentException('Email requis');

Terrain suivant : Console & commandes.