# Symfony Patterns ## Dependency Injection ```php userRepository->save($user); $this->logger->info('User created', ['email' => $email]); return $user; } } ``` ## Service Configuration (services.yaml) ```yaml # config/services.yaml services: _defaults: autowire: true autoconfigure: true bind: string $projectDir: '%kernel.project_dir%' bool $isDebug: '%kernel.debug%' App\: resource: '../src/' exclude: - '../src/DependencyInjection/' - '../src/Entity/' - '../src/Kernel.php' # Interface binding App\Repository\UserRepositoryInterface: class: App\Repository\DoctrineUserRepository # Service with specific configuration App\Service\PaymentService: arguments: $apiKey: '%env(PAYMENT_API_KEY)%' $timeout: 30 # Tagged services App\EventSubscriber\: resource: '../src/EventSubscriber/' tags: ['kernel.event_subscriber'] ``` ## Controllers with Attributes ```php userService->getAllUsers(); return $this->json($users, Response::HTTP_OK, [], [ 'groups' => ['user:read'], ]); } #[Route('', name: 'create', methods: ['POST'])] #[IsGranted('ROLE_ADMIN')] public function create( #[MapRequestPayload] CreateUserRequest $request ): JsonResponse { $user = $this->userService->createUser( $request->email, $request->password ); return $this->json($user, Response::HTTP_CREATED, [], [ 'groups' => ['user:read'], ]); } #[Route('/{id}', name: 'show', methods: ['GET'])] public function show(User $user): JsonResponse { $this->denyAccessUnlessGranted('view', $user); return $this->json($user, context: ['groups' => ['user:detail']]); } } ``` ## DTOs with Validation ```php [ ['sendWelcomeEmail', 10], ['logRegistration', 5], ], ]; } public function sendWelcomeEmail(UserRegisteredEvent $event): void { $user = $event->getUser(); // Send email logic $this->logger->info('Welcome email sent', ['user_id' => $user->getId()]); } public function logRegistration(UserRegisteredEvent $event): void { $this->logger->info('User registered', [ 'user_id' => $event->getUser()->getId(), 'email' => $event->getUser()->getEmail(), ]); } } ``` ## Custom Events ```php user; } public function getOccurredAt(): \DateTimeImmutable { return $this->occurredAt; } } // Dispatching events use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; final readonly class UserService { public function __construct( private EventDispatcherInterface $eventDispatcher, ) {} public function registerUser(string $email, string $password): User { $user = new User($email, $password); // ... save user $this->eventDispatcher->dispatch(new UserRegisteredEvent($user)); return $user; } } ``` ## Console Commands ```php addArgument('email', InputArgument::REQUIRED, 'User email') ->addArgument('password', InputArgument::REQUIRED, 'User password') ->addOption('admin', 'a', InputOption::VALUE_NONE, 'Make user admin'); } protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); $email = $input->getArgument('email'); $password = $input->getArgument('password'); $isAdmin = $input->getOption('admin'); try { $user = $this->userService->createUser($email, $password, $isAdmin); $io->success(sprintf('User created with ID: %d', $user->getId())); return Command::SUCCESS; } catch (\Exception $e) { $io->error($e->getMessage()); return Command::FAILURE; } } } ``` ## Voters (Authorization) ```php getUser(); if (!$user instanceof User) { return false; } /** @var Post $post */ $post = $subject; return match ($attribute) { self::VIEW => $this->canView($post, $user), self::EDIT => $this->canEdit($post, $user), self::DELETE => $this->canDelete($post, $user), default => false, }; } private function canView(Post $post, User $user): bool { return $post->isPublished() || $this->isOwner($post, $user); } private function canEdit(Post $post, User $user): bool { return $this->isOwner($post, $user); } private function canDelete(Post $post, User $user): bool { return $this->isOwner($post, $user) || $user->hasRole('ROLE_ADMIN'); } private function isOwner(Post $post, User $user): bool { return $post->getAuthor()->getId() === $user->getId(); } } ``` ## Message Handler (Messenger) ```php userRepository->find($message->userId); if (!$user) { return; } // Send email logic } } // Dispatching messages use Symfony\Component\Messenger\MessageBusInterface; $this->messageBus->dispatch(new SendWelcomeEmail($user->getId())); ``` ## Quick Reference | Component | Purpose | File Location | |-----------|---------|---------------| | Controller | HTTP handlers | `src/Controller/` | | Service | Business logic | `src/Service/` | | Repository | Data access | `src/Repository/` | | Event | Domain events | `src/Event/` | | EventSubscriber | Event handlers | `src/EventSubscriber/` | | Command | CLI commands | `src/Command/` | | Voter | Authorization | `src/Security/Voter/` | | Message | Async messages | `src/Message/` | | MessageHandler | Message handlers | `src/MessageHandler/` | | DTO | Data transfer | `src/DTO/` |