Terrain 4 — Services & DI
🔍 Renfort : Partie 5.
1. Service autowiré ⭐
🕹️ Mission : créez un SlotAvailabilityChecker dépendant de BookingRepository, injectable sans config.
✅ Solution
final class SlotAvailabilityChecker {
public function __construct(private BookingRepository $bookings) {}
public function isAvailable(int $slotId, int $seats): bool { /* ... */ return true; }
}(Auto-enregistré via App\ dans services.yaml.)
2. Injecter un paramètre ⭐⭐
🕹️ Mission : injectez %kernel.project_dir% dans un service. 🔍 5.2.
✅ Solution
public function __construct(#[Autowire('%kernel.project_dir%')] private string $dir) {}3. Injecter une variable d’env ⭐⭐
🕹️ Mission : injectez STRIPE_KEY.
✅ Solution
public function __construct(#[Autowire(env: 'STRIPE_KEY')] private string $stripeKey) {}4. Interface ambiguë ⭐⭐⭐
🕹️ Mission : StorageInterface a deux implémentations ; ciblez S3Storage. 🔍 5.2.
✅ Solution
public function __construct(#[Autowire(service: S3Storage::class)] private StorageInterface $storage) {}5. Collecter une famille ⭐⭐⭐
🕹️ Mission : collectez tous les NotificationChannelInterface dans un Notifier. 🔍 5.3.
✅ Solution
#[AutoconfigureTag('app.notification_channel')]
interface NotificationChannelInterface {}
final class Notifier {
public function __construct(#[AutowireIterator('app.notification_channel')] private iterable $channels) {}
}6. Priorité de tag ⭐⭐⭐
🕹️ Mission : faites passer SlackChannel en premier dans l’itération.
✅ Solution
#[AsTaggedItem(priority: 10)]
final class SlackChannel implements NotificationChannelInterface {}7. Locator paresseux ⭐⭐⭐⭐
🕹️ Mission : choisissez un exporteur par clé sans instancier les autres. 🔍 5.3.
✅ Solution
public function __construct(#[AutowireLocator('app.exporter')] private ContainerInterface $exporters) {}
// $this->exporters->get($format)->export($data);8. EventSubscriber ⭐⭐⭐
🕹️ Mission : journalisez chaque BookingCreated via un listener. 🔍 5.5.
✅ Solution
#[AsEventListener]
final class LogBookingCreated {
public function __construct(private LoggerInterface $logger) {}
public function __invoke(BookingCreated $e): void { $this->logger->info('Booking créée', ['id' => $e->booking->getId()]); }
}9. Diagnostiquer l’injection ⭐⭐
🕹️ Mission : trouvez quel service sera injecté pour MailerInterface.
✅ Solution
php bin/console debug:autowiring mailer (liste les types injectables et l’implémentation retenue).
10. Service par environnement ⭐⭐⭐⭐
🕹️ Mission : un faux PaymentGateway en dev, Stripe en prod.
✅ Solution
#[When(env: 'dev')] final class FakePaymentGateway implements PaymentGatewayInterface {}
#[When(env: 'prod')] final class StripePaymentGateway implements PaymentGatewayInterface {}Terrain suivant : Doctrine : entités & relations.