Custom Bundles were long the standard for reusable Symfony modules. With PHP config classes, Symfony Flex and modern DI patterns, there are lighter-weight paths today, but for public packages, complex container manipulation and Compiler Passes, bundles are still the right tool.
Testing Doctrine repositories with pure mocks rarely exercises the actual query. An in-memory SQLite database runs DQL and query builder calls for real, without any database server, and makes repository tests run in milliseconds instead of seconds.
Autowiring makes Symfony development convenient, but used carelessly it creates unnecessary objects on every single request. With lazy services, ghost objects and service subscribers, kernel boot performance can be noticeably improved without giving up autowiring entirely.
Order processes, approval workflows, content publishing and ticket systems all have one thing in common: objects change their state according to defined rules. Implementing these transitions with if-constructs scattered across services builds up technical debt. The Symfony Workflow Component turns state machines into declarative configuration with full event support and visualization.
The Symfony Configuration Tree Builder is the tool a bundle uses to define which configuration is allowed, which values are mandatory and how invalid input is caught. This article walks through node types, default values, normalization and custom validation rules using a complete example.
The hexagonal architecture, also known as Ports and Adapters, frees the domain logic from coupling to frameworks, databases, and external services. In Symfony it can be implemented precisely with PHP interfaces as Ports and Symfony services as Adapters: fully testable domain code without a single framework import in the core logic.
A migration that spontaneously renames a column or locks a table can bring a running Symfony application to its knees right in the middle of rush hour. Zero downtime database migrations with Doctrine instead follow the expand contract pattern: schema and application grow through small, always backward compatible steps. This article walks through every step in detail, from the first new column to safely removing the old one.
The choice between EasyAdmin 4 and Sonata Admin determines how much configuration effort, customizing freedom and learning curve your team needs to plan for the backend. Both solutions are built for Symfony, but with fundamentally different philosophies and target audiences.
Anyone who thinks API Platform only works with Doctrine entities has not yet met the State Provider and the State Processor. These two interfaces fully decouple reading and writing from the persistence layer and let you expose REST endpoints, legacy systems, or purely computed values as first class API resources.
In Symfony, registering event listeners, voters, commands and Twig extensions long meant: implement an interface and separately write a tag entry in services.yaml. The autoconfigure feature recognizes well-known interfaces automatically and assigns the necessary DI tags without a single tag ever having to be written by hand.