⏱ Estimated reading time: 11 minutes

By Thomas Calvet, Senior PHP Developer @ Symfony

Table of Contents


Symfony is designed so that it is not necessary to rely on it as a framework; you can very much use isolated components at your convenience as would Drupal or Laravel do. This property is called “modularity” and is one of the main advantages of the ecosystem.

Symfony is stable, predictable and performant. Its update lifecycle is public and well known: one major version every two years and one minor every six months. This means that every two years one major and one minor versions release simultaneously.


There are multiple levels of contributions to Symfony:

  • Minor: No behavioral change to the components. Code style, comments, CI/CD, etc.;
  • Bug: Fixing behaviors, starts from the most relevant branch so that the fix reaches users of older maintained versions as well as the in-development one;
  • Feature: Symfony is used on many real-world applications. Features need to be justified with real-world reasons;
  • Security: Reserved to very specific cases, mostly used by the framework’s creator.

The plan with Symfony is that there is no plan. Everyone can contribute and there is always new stuff to do. Of course, even though every contribution is welcome there are rules to follow: core team validation, reviews, maintainability check and actual use cases for what you contribute.

The last six months of contributions, a.k.a. the path from Symfony 6.0 to 6.1 looked like this:

  • 930 open Pull Requests;
  • 230 Minor, 320 Bug and 130 Feature contributions merged.

The number of merges don’t add up to the number of open Pull Requests because not all of them are automatically accepted. Some require more work that gets them pushed back to the next version. Others did not pass the review process of were abandoned by their authors.

The last month before a release, the core team freezes the code in order to stabilize the next version. In addition, the blog editors contribute write-ups featuring next release highlights on the Living on the edge category of the official Symfony blog.

What’s new


Symfony 6.1 is a very special release: it requires an upgrade to PHP 8.1! Usually these kind of updates are required for major versions. Let’s explore some of the new features of PHP 8.1.

Starting with the First class callable syntax which changed a historical element of syntax relating to callables. This is purely syntactic sugar, yet code readability and thus maintainability gets better. Here is an example:

// Old syntax
[$this, "foo"];

// New syntax
$this->foo(...) // Yes, "..." is part of the syntax

A pet peeve of many developers was checking whether an array is associative or a list. A shorthand would be to check whether its keys range from zero to its length minus one:

function array_is_list(array $a): bool
  return $a === [] || (array_keys($a) === range(0, count($a) - 1));

For that matter specifically, the array_is_list function is now available!

Other changes include readonly properties, new in initializers and pure intersection types. These all help modernize Symfony’s code. This modernization effort is continuous and done with respect to retrocompatibility. Some of the last pushes in this regard concern the optional variable name for caught expressions and match control structures both introduced in PHP 8.0.

In Symfony

The only new component that ships with Symfony 6.1 is HtmlSanitizer, introduced in this blog post. The need to sanitize HTML input is extremely common. So much that Titouan Galopin implemented tgalopin/html-sanitizer, a library that solves this issue once and for all. The community followed suit and this work ended up in Symfony after some refactoring. The component works as a pattern builder to describe what is allowed in strings to sanitize. It integrates with other components such as symfony/ux and gets additional visibility thanks to the Symfony brand.

Switching locales will get easier with the new LocaleSwitcher introduced in this blog post. All the services tagged with kernel.locale_aware as well as your templates, emails and whatnot can now switch locales dynamically. You can even run specific pieces of code in a given locale without changing the locale for the rest of the application, which is handy when you want to generate multilingual previews for templates!

Enums have been supported in Symfony since version 5.4, notably in the Form and Serializer components. Thanks to some changes in the argument controller resolver, BackedEnums can now be used with Routes as RouteRequirements as described in this blog post! If the route parameter does not match any of the Enum values, Symfony will return an HTTP 404 error.

Decoration has been made simpler with the addition of three PHP Attributes:

  • #[AsDecorator] which declares that a given service decorates some other one from the code rather than a configuration file;
  • #[MapDecorated] which injects a decorated service;
  • #[Autowire] which should not be used and configures the autowiring behavior.

Serializer switches to a fluent interface instead of a configuration array. Autocompletion is now supported for this component, which improves developer exprerience. And the profiler gets an additional panel for this component!

Bundles were a massive pain point in terms of development experience that never changed since Symfony 2. Symfony 6.1 reduces the amount of boilerplate and conventions that come with bundles as described in this blog post.

Finally, Notifier includes a few additional integrations, TagAwareAdapter has been graeatly improved, ExpressionLanguage gets new syntax and operators

Preparing PHP 8.2

PHP 8.2 is due for the end of 2022. For the core team of Symfony, it is like a fix to apply to all maintained versions to ensure they support the newest version so that improvements to the language runtime benefit most framework users. Supporting new PHP features is considered a feature for Symfony as well.

Some of the highlights of PHP 8.2 include the deprecation of dynamic properties with their removal scheduled in PHP 9.0. Fortunately, this is already planned and tested thanks to the 40k tests run by the CI/CD. Tests like these run on all components at every level. Some of them require specific extension combinations or configurations but the team tries to run as many of them as possible at the same time.

Symfony 6.2 has tens of Pull Requests ready for review in addition to those that could not make it into 6.1.


There are a few ways to contribute to Symfony:

  • Testing beta and release candidates;
  • Reporting issues with a minimal reproducible case to ease the maintainers work. A GitHub project is an acceptable way to present this case if no simpler option exists;
  • Sponsor versions or components. Financial contributions can greatly help the project, especially if your business depends on the long-term well-being of the ecosystem.

Questions and Answers

How much time does it take before Rector supports a new Symfony release?

Rector is an independent project meant to automate upgrades and refactoring of PHP codebases so that developers can benefit from the latest language and major frameworks improvements with less amounts of effort. Indeed, Rector supports Symfony upgrades too!

Since no Symfony core team contributor works on Rector, upgrades are available a while after they are officially released on Symfony.

Which components is Thomas Calvet working on?

Contributors all have their preferences when it comes to working on components. Symfony does not impose anyone to work on a specific component.Thomas holds a preference for Dependency Injection, Routing, String and Uid. They recommend reading Cache and String and finds that Dependency Injection is an essential read to understand how Symfony clicks.

What did Thomas contribute for the 6.1 release?

They mostly worked on the support for Uid in the ArgumentResolver and the support of Enum for RouteRequirements. Contributions emanate from everyday needs. Many contributions get rejected but they are still valid learning experiences.

What is the contribution process like?

To avoid a Pull Request being rejected, talk with the other contributors on the different communication channels at your disposal. Avoid working in isolation too much. Finally issues are oriented while code is factual so when reporting an issue, always base it on a code example to base it on tangible and reproducible facts.

What are some features that have been laying around for a long time?

The best way to know that would be to check that on GitHub using issue filters. It happens that some features are left laying around for years before being taken care of by new contributors. This is the case for the migration from ParamConverter to ArgumentValueResolver which is in progress. At the same time, others may never see the light of day just like Encryption.

The way they are implemented in 6.1, aren’t decorators a risky practice?

The implementation goal for class decorators is to avoid maintaining code and configuration when the same semantic can be expressed from the code alone. Furthermore, the current Yaml syntax is still valid and fully supported: PHP Arguments are only supported as an alternate syntax to improve developer experience. It is certainly more magical and harder to understand but as efficient.

Post-meetup discoveries

Bref makes PHP application deployment simpler by removing servers and scaling from the equation and creating an environment that closely follows the load of the application. This practice is called “Serverless” and has been increasing in popularity over the last few years. Unfortunately, PHP has long been throught of as a runtime tied to servers. This project exists to contradict that line of thinking.

Pactflow is a platform made by Smartbear, a company who got extremely famous for their comprehensive work around APIs and testing. If you ever heard about OpenAPI and Cucumber, well that’s them! Pactflow is to be used when multiple teams need to integrate their systems. This is contract testing at scale and made serious.

The Mikado Method explains, just like in the game of the same name, how to carefully remove debt hidden deep inside a legacy system by taking a scratching the surface approach that is reminiscent of Martin Fowler’s Strangler Pattern. This approach is meant for legacy systems, where engineers are looking for absolute stability and is lightweight to help teams cope with the complexity of the system itself.