symfony-knowledge
Symfony Knowledge Base
Quick reference for Symfony framework patterns, DDD integration, and PHP implementation guidelines for auditing and generating Symfony-based applications.
Core Principles
- Bundle System — Symfony's plugin mechanism. Third-party code is installed as bundles; application code lives outside bundles in
src/. - Symfony Flex — Automates bundle installation via recipes. Standard dirs:
config/,src/,public/,var/,migrations/,tests/,templates/. - Kernel — Entry point that boots the container, registers bundles, loads configuration. Must remain thin — no business logic.
Quick Checklists
DDD-Compatible Symfony Project
- Domain layer has zero Symfony imports
- Doctrine mapping uses XML or PHP config (not entity attributes)
- Controllers are invokable (single action per class)
- Messenger handles commands and queries via separate buses
- Value Objects use custom Doctrine types
- Repository interfaces in Domain, implementations in Infrastructure
-
services.yamlbinds interfaces to implementations - Domain events are dispatched, not Doctrine lifecycle events
- Authorization uses Voters delegating to domain Specifications
- Workflow guards delegate to domain Specifications (no inline business logic)
- Domain defines its own
EventDispatcherInterface(not Symfony's) - Infrastructure components (Cache, HTTP Client) accessed via domain ports
Clean Architecture in Symfony
- No
use Symfony\in Domain or Application layers - No
use Doctrine\in Domain layer - Use Cases accept Command/Query DTOs, not Request objects
- Controllers only map HTTP to Use Case calls
- EventSubscribers do not contain business logic
- Compiler passes do not encode domain rules
Common Violations Quick Reference
| Violation | Where to Look | Severity |
|---|---|---|
| Doctrine attributes in Domain entities | Domain/**/*.php with #[ORM\ |
Critical |
| Symfony Request/Response in Application layer | Application/**/*.php |
Critical |
| Business logic in Controller | Controllers with if/switch on domain state |
Warning |
| Fat Controller (multiple actions) | Controllers with 2+ public methods | Warning |
| Entity used as DTO across layers | Entity passed to templates/serializers directly | Warning |
| Service Locator via ContainerInterface | $container->get() in services |
Critical |
| Doctrine EventListener with domain logic | EventListener classes with business rules |
Warning |
| Hard-coded service IDs | $container->get('service.id') |
Warning |
| UserInterface in Domain | Domain/**/*.php with implements UserInterface |
Critical |
| Missing Messenger retry strategy | messenger.yaml without retry_strategy |
Warning |
| Business logic in Workflow listener | Guard/transition listeners with domain rules | Warning |
| Symfony EventDispatcher in Domain | Domain/**/*.php with use Symfony\Contracts\EventDispatcher |
Critical |
| Direct infrastructure in Application | Application/**/*.php with CacheInterface, LockFactory |
Warning |
PHP 8.4 Symfony Patterns
Invokable Controller (Single Action)
<?php
declare(strict_types=1);
namespace App\Order\Presentation\Api;
use App\Order\Application\Command\CreateOrderCommand;
use App\Order\Application\UseCase\CreateOrderUseCase;
use Symfony\Component\HttpFoundation\{JsonResponse, Request, Response};
use Symfony\Component\Routing\Attribute\Route;
#[Route('/api/orders', methods: ['POST'])]
final readonly class CreateOrderAction
{
public function __construct(private CreateOrderUseCase $createOrder) {}
public function __invoke(Request $request): JsonResponse
{
$data = $request->toArray();
$orderId = $this->createOrder->execute(new CreateOrderCommand(
customerId: $data['customer_id'],
items: $data['items'],
));
return new JsonResponse(['id' => $orderId->value], Response::HTTP_CREATED);
}
}
Use Case (Application Service)
<?php
declare(strict_types=1);
namespace App\Order\Application\UseCase;
use App\Order\Domain\Entity\Order;
use App\Order\Domain\Repository\OrderRepositoryInterface;
use App\Shared\Domain\EventDispatcherInterface;
final readonly class CreateOrderUseCase
{
public function __construct(
private OrderRepositoryInterface $orders,
private EventDispatcherInterface $events,
) {}
public function execute(CreateOrderCommand $command): OrderId
{
$order = Order::create($command->customerId, $command->items);
$this->orders->save($order);
foreach ($order->releaseEvents() as $event) {
$this->events->dispatch($event);
}
return $order->id();
}
}
Messenger Command Handler
<?php
declare(strict_types=1);
namespace App\Order\Application\Handler;
use App\Order\Application\Command\ConfirmOrderCommand;
use App\Order\Domain\Repository\OrderRepositoryInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
#[AsMessageHandler(bus: 'command.bus')]
final readonly class ConfirmOrderHandler
{
public function __construct(private OrderRepositoryInterface $orders) {}
public function __invoke(ConfirmOrderCommand $command): void
{
$order = $this->orders->findById($command->orderId);
$order->confirm();
$this->orders->save($order);
}
}
References
For detailed information, load these reference files:
references/architecture.md— Bundle system, Flex recipes, standard vs DDD-aligned directory layoutreferences/ddd-integration.md— Domain purity, Messenger CQRS, Domain Events, Value Objects with Doctrinereferences/routing-http.md— Invokable controllers, EventSubscribers, attribute routing, validationreferences/persistence.md— Doctrine ORM mapping, repositories, migrations, keeping Doctrine out of Domainreferences/dependency-injection.md— services.yaml, auto-wiring, tagged services, compiler passes, interface bindingreferences/testing.md— WebTestCase, KernelTestCase, functional tests, fixtures, Messenger handler testingreferences/security.md— UserInterface adapter, Voters with Specifications, firewalls, password hashing, auth eventsreferences/messenger-advanced.md— Multiple buses, transports, retry strategy, DLQ, middleware, workers, serializationreferences/workflow.md— StateMachine for aggregates, enum places, guards with Specifications, audit trailreferences/event-system.md— EventDispatcher patterns, kernel events, domain event dispatching, PSR-14references/infrastructure-components.md— Cache, Lock, RateLimiter, HTTP Client, Serializer, Scheduler with DDD portsreferences/antipatterns.md— Fat controllers, entity as DTO, Doctrine in Domain, Service Locator, detection patterns
More from dykyi-roman/awesome-claude-code
psr-overview-knowledge
PHP Standards Recommendations (PSR) overview knowledge base. Provides comprehensive reference for all accepted PSRs including PSR-1,3,4,6,7,11,12,13,14,15,16,17,18,20. Use for PSR selection decisions and compliance audits.
22detect-code-smells
Detects code smells in PHP codebases. Identifies God Class, Feature Envy, Data Clumps, Long Parameter List, Long Method, Primitive Obsession, Message Chains, Inappropriate Intimacy. Generates actionable reports with refactoring recommendations.
15clean-arch-knowledge
Clean Architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Clean Architecture and Hexagonal Architecture audits.
15ddd-knowledge
DDD architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Domain-Driven Design audits.
14testing-knowledge
Testing knowledge base for PHP 8.4 projects. Provides testing pyramid, AAA pattern, naming conventions, isolation principles, DDD testing guidelines, and PHPUnit patterns.
12bug-root-cause-finder
Root cause analysis methods for PHP bugs. Provides 5 Whys technique, fault tree analysis, git bisect guidance, and stack trace parsing.
12