Share
Embed
20 years of Symfony, what's next?
20 years of Symfony, what's next?
Fabien Potencier
November 27, 2025
Transcript
56 slides
-
And of course, SymfonyCast since 2019 SymfonyCast is still alive
and very active -
A few months ago, Ryan Weaver passed away Ryan was
a pillar of the Symfony community -
Ryan gave so many great talks at conferences Ryan had
so much energy on stage Ryan had a passion for teaching and passing on knowledge -
In the early days, Ryan helped our community via a
symfony1 blog. Quickly, Ryan became instrumental in the success of Symfony. From documentation to the developer experience Ryan changed Symfony forever Thank you -
Thank you Upsun You saved my live release First time
in my life I restored from a backup! -
From fabpot/symfony sf_releaser prepare-release 8.0 | source git co -b
release-$VERSION sf_releaser update-changelog sf_releaser update-version sf_releaser create-pr From symfony/symfony export SPLITSH_PROJECT=symfony sf_releaser prepare-release 8.0 | source sf_releaser tag ⏳ splitsh check:create "*/$GITBRANCH" --watch splitsh tag:sync --tag v$VERSION 🐢 splitsh check:create "*/$GITBRANCH" --watch --tags sf_releaser update-version --dev git push sf_releaser release Our To Do list -
From fabpot/symfony sf_releaser prepare-release 8.0 | source git co -b
release-$VERSION sf_releaser update-changelog sf_releaser update-version sf_releaser create-pr From symfony/symfony export SPLITSH_PROJECT=symfony sf_releaser prepare-release 8.0 | source sf_releaser tag ⏳ splitsh check:create "*/$GITBRANCH" --watch splitsh tag:sync --tag v$VERSION 🐢 splitsh check:create "*/$GITBRANCH" --watch --tags sf_releaser update-version --dev git push sf_releaser release Our To Do list + Check the repo is not dirty + Checkout the branch + Sync code with upstream + Find the version to release + Set environment variables + Parse the Git logs, Update CHANGELOG-X-Y.md and commit + Update Kernel.php, and commit + Push the branch to Github + Create a pull request and merge it + Cleanup -
Symfony 2: 21 components Symfony 3: 11 new components -
Asset, Debug, ExpressionLanguage, Filesystem, Intl, Ldap, OptionsResolver, PropertyAccess, PropertyInfo, Stopwatch, VarDumper Symfony 4: 6 new components - Cache, Dotenv, Inflector, Lock, WebLink, Workflow Symfony 5: 8 new components - ErrorHandler, HttpClient, Mailer, Messenger, Mime, Notifier, String, VarExporter Symfony 6: 5 new components - PasswordHasher, RateLimiter, Runtime, Semaphore, Uid Symfony 7: 6 new components - AssetMapper, Clock, HtmlSanitizer, RemoteEvent, Scheduler, Webhook Symfony 8: 5 new components - Emoji, JsonPath, JsonStreamer, ObjectMapper, TypeInfo 57 components and counting -
Bridges to the external world Symfony 5: 10 new bridges
Symfony 6: 51 new bridges Symfony 7: 33 new bridges Symfony 8: 23 new bridges | Component | Bridge Count | |-------------|--------------| | Notifier | 81 | | Mailer | 20 | | Messenger | 5 | | Translation | 4 | | Lock | 1 | | Total | 111 | -
From fabpot/symfony 🔥 sf_releaser prepare-release 8.0 | source 🔥 git
co -b release-$VERSION 🔥 sf_releaser update-changelog 🔥 sf_releaser update-version 🔥 sf_releaser create-pr From symfony/symfony export SPLITSH_PROJECT=symfony sf_releaser prepare-release 8.0 | source sf_releaser tag ⏳ splitsh check:create "*/$GITBRANCH" --watch splitsh tag:sync --tag v$VERSION 🐢 splitsh check:create "*/$GITBRANCH" --watch --tags sf_releaser update-version --dev git push sf_releaser release Our To Do list -
▪ Several times a day ▪ Help with debugging problems
▪ Help me when I’m outside of my comfort zone ▪ Mostly using Claude Code and Cursor nowadays But I never keep much as I care deeply about code, its aesthetic and how it's organized LLMs for coding -
▪ More recently, I’ve also used them to automate boring
tasks ◦ Things that should be automated as no to little value ◦ I know exactly how they should be done ▪ But I want the generated code ◦ To be as deterministic as possible ◦ To feel like I’ve done it myself Boring tasks -
▪ Deterministic, no need for an LLM? ◦ Coding standards
◦ Scaffolding for web controllers, CLI commands, … ▪ Non-deterministic, LLMs shine ◦ Updating existing code ◦ Generating code where possibilities are huge Boring tasks? -
▪ Package the “logic” (prompt, context, …) as a specific
“agent” ▪ Control the generated code precisely ▪ Little human interaction ▪ Little code review needed ▪ Reach almost 100% accuracy ▪ Make it cheap ▪ Avoid vendor lock-in Packaging recurring tasks -
From fabpot/symfony 🔥 sf_releaser prepare-release 8.0 | source 🔥 git
co -b release-$VERSION 🔥 sf_releaser update-changelog 🔥 sf_releaser update-version 🔥 sf_releaser create-pr From symfony/symfony ⭐ export SPLITSH_PROJECT=symfony ⭐ sf_releaser prepare-release 8.0 | source ⭐ sf_releaser tag ⏳ splitsh check:create "*/$GITBRANCH" --watch splitsh tag:sync --tag v$VERSION 🐢 splitsh check:create "*/$GITBRANCH" --watch --tags sf_releaser update-version --dev git push sf_releaser release Our To Do list + Check that all package repositories are up-to-date with the mono-repository + Create tags for all packages Tag the same commit as the mono repo -
Upgrade code ▪ A new CLI command that updates code:
Help removing deprecations and using new features ▪ Carefully build the context with deterministic data: ◦ Facts about the code base: PHP version, Symfony version, ... ◦ Relevant upgrade guides only (with before/after examples), written and optimized for LLMS ◦ Determine files that need to be updated ◦ ... -
# Add support for `help` in `Symfony\Component\Console\Attribute\AsCommand` For all PHP
classes using the `AsCommand` PHP attribute, we must use the new `help` property instead of calling the `setHelp()` method in the `configure()` method. *Before* ```php #[AsCommand( name: 'app:add-user', description: 'Add a new user' )] class SomeCommand { protected function configure(): void { $this ->setHelp(<<<TXT The <info>%command.name%</info> command adds a new user with the username passed to it: <info>php %command.full_name% jane-doe</info> TXT); } } ``` -
*After* ```php #[AsCommand( name: 'app:add-user', description: 'Add a new user',
help: <<<TXT The <info>%command.name%</info> command adds a new user with the username passed to it: <info>php %command.full_name% jane-doe</info> // ... TXT, )] class SomeCommand { protected function configure(): void { $this ->setCommand('username', InputArgument::REQUIRED) ; } } ``` Remove the `configure()` method if it does not do anything anymore after the changes. -
▪ A new version of Maker bundle using LLMs to
better compose generated files and allow for updating existing ones more easily. ▪ We are already upgrading existing files (like Doctrine entities), but updating the default base template, which can diverge drastically from the default, is way more complicated. Maker Bundle -
▪ An enhanced version of the recipes:update command that would
automatically resolve conflicts when possible. ▪ It could also open the door to recipe composition (by assembling small snippets). Security configuration is a good example. recipes:update conflict resolver -
▪ Expose logs exception, profiler information, container and routes data
from cache ▪ Expose tools: give me all console command classes with their paths As a debugger -
▪ LLMs = HTTP APIs Frontier models (OpenAI, Anthropic) or
local ones (Ollama, vLLM), they all speak HTTP ▪ Symfony already solved this: Symfony HTTPClient powers 40+ Mailer/Notifier bridges. The same pattern works perfectly for LLMs ▪ Additional challenge: many LLM apps need streaming support Talking to AI? It's just HTTP Symfony HTTP Client component -
▪ Great prompts need dynamic context: RAG results, user data,
business rules ▪ Twig already solves this: filters, conditionals, inheritance for clean prompt assembly ▪ System prompts are just templates: version control, test, and iterate like any other code Build better prompts with Twig Twig -
▪ Control complexity with predictable workflows. When LLMs handle complex
workflows, outcomes become unpredictable. Use Symfony Workflow to: ◦ Define explicit states and transitions ◦ Set guardrails and business rules ◦ Let AI decide within boundaries you control ◦ Handle human-in-the-loop before proceeding to the next step Keep AI workflows deterministic Symfony Workflow component -
▪ LLMs can plan, but smaller models not so much
▪ Split the work ▪ Increase attention, also output quality/accuracy ▪ Reduce hallucination Avoid too many tasks in a single prompt -
▪ Define the task precisely to avoid implicit assumptions and
ambiguity ▪ Optimize the context to be short and straight to the point Narrow down the task -
▪ Optimize the size of the context by providing only
what's needed for the task ▪ Improve model accuracy ▪ Decrease costs (less tokens) ▪ Improve performance (less tokens) ▪ Rule of thumb: a human should enjoy reading the context Optimize the context -
▪ For structured output: Schema validation and semantic validation ▪
For code: Lint and run tests ▪ Auto-correct in a loop when errors ▪ Use LLM as judge ▪ A human in the loop is still needed Help improve accuracy -
▪ Expose specific project context: ◦ CLI commands: console list
--format=json ◦ Container information: var/cache/dev/App_KernelDevDebugContainer.* ◦ Routes info: var/cache/dev/url_*.php ◦ ... ▪ Expose profiler info for a specific request like logs, exception messages, configuration, ... ▪ Help answer questions like "give me all command classes" (avoiding the use of grep in a loop by LLMs) Tools via console commands/API? -
▪ CHANGELOG with better deprecation info (before, after, edge cases,
...), maybe split into many files ▪ Specialized guides that explain how to solve specific tasks (add authentication, ...) ▪ Great pull request descriptions Anything optimized for LLMs is great for human as well Better documentation -
From fabpot/symfony 🔥 sf_releaser prepare-release 8.0 | source 🔥 git
co -b release-$VERSION 🔥 sf_releaser update-changelog 🔥 sf_releaser update-version 🔥 sf_releaser create-pr From symfony/symfony ⭐ export SPLITSH_PROJECT=symfony ⭐ sf_releaser prepare-release 8.0 | source ⭐ sf_releaser tag ⏳ 🎉 splitsh check:create "*/$GITBRANCH" --watch 🎉 splitsh tag:sync --tag v$VERSION 🐢 splitsh check:create "*/$GITBRANCH" --watch --tags sf_releaser update-version --dev git push sf_releaser release Our To Do list + Check that all subtrees are up-to-date + Check that tags are consistent + Update version back to dev + Commit + Create the Github Release + Publish the blog post on symfony.com + Post on social media + Send notifications by email