DEV Community

Andrew Markhai
Andrew Markhai

Posted on

4 1

How Symfony Flex Works

What is it?

Symfony Flex is a Composer plugin from Symfony that handles the configuration of installed packages. It adds configuration files, updates .gitignore and .env, registers bundles, and more.

For example, when installing PHPUnit, Flex will:

  • Add a default configuration file phpunit.dist.xml
  • Create tests/bootstrap.php
  • Add /phpunit.xml and /.phpunit.cache/ to .gitignore
  • Create .env.test with environment variables for tests

Where does Flex get its instructions?

In Flex terminology, these instructions are called recipes. They are stored in a GitHub repository. You can check out the recipes for the current version of PHPUnit here.

Is this a complete list of recipes?

No. The symfony/recipes repository is maintained by Symfony itself, while community-contributed recipes are stored in a separate repository. Anyone can contribute there.

To allow Flex to apply community recipes, you need to add the following to composer.json:

"extra": {
    "symfony": {
        "allow-contrib": true
    }
}
Enter fullscreen mode Exit fullscreen mode

How does it work under the hood?

When initialized, Flex loads links to all current recipes in Downloader::index. By default, it fetches them from two repositories described above:

private const DEFAULT_ENDPOINTS = [
'https://raw.githubusercontent.com/symfony/recipes/flex/main/index.json',
'https://raw.githubusercontent.com/symfony/recipes-contrib/flex/main/index.json',
];
Enter fullscreen mode Exit fullscreen mode

However, you can add your own repositories by specifying them in composer.json under extra.symfony.endpoint.

Since Flex is a Composer plugin, it listens for various events:

$events = [
    PackageEvents::POST_PACKAGE_UPDATE => 'enableThanksReminder',
    PackageEvents::POST_PACKAGE_INSTALL => 'recordFlexInstall',
    PackageEvents::POST_PACKAGE_UNINSTALL => 'record',
    InstallerEvents::PRE_OPERATIONS_EXEC => 'recordOperations',
    PluginEvents::PRE_POOL_CREATE => 'truncatePackages',
    ScriptEvents::POST_CREATE_PROJECT_CMD => 'configureProject',
    ScriptEvents::POST_INSTALL_CMD => 'install',
    ScriptEvents::PRE_UPDATE_CMD => 'configureInstaller',
    ScriptEvents::POST_UPDATE_CMD => 'update',
    'auto-scripts' => 'executeAutoScripts',
];
Enter fullscreen mode Exit fullscreen mode

During install and update commands, the Flex::install() method runs. It checks whether there are recipes for the current package by looking at both the package name and its version.

Recipe versioning is handled using subdirectories inside the package directory. For example, looking at PHPUnit’s recipes, you’ll see folders for versions 10.0, 9.6, 9.3, and 4.7. Flex selects the highest available recipe version that is less than or equal to the installed package version.

For example:

  • PHPUnit 12 will use the 10.0 recipe
  • PHPUnit 9.9 will use the 9.6 recipe

If a recipe is found, the instructions in its manifest are executed using various configurators. The console will display a message like:

Symfony operations: 1 recipe (13c8b05b36f03f13c596b688cb97d0da)
  - Configuring phpunit/phpunit (>=10.0): From github.com/symfony/recipes:main

Some files have been created and/or updated to configure your new packages.
Enter fullscreen mode Exit fullscreen mode

Useful commands

To check the current state of recipes:

composer symfony:recipes
Enter fullscreen mode Exit fullscreen mode

If a package has an updated recipe (marked as update available), you can update it with:

composer recipes:update vendor/package
Enter fullscreen mode Exit fullscreen mode

Top comments (0)

Image of Stellar post

How a Hackathon Win Led to My Startup Getting Funded

In this episode, you'll see:

  • The hackathon wins that sparked the journey.
  • The moment José and Joseph decided to go all-in.
  • Building a working prototype on Stellar.
  • Using the PassKeys feature of Soroban.
  • Getting funded via the Stellar Community Fund.

Watch the video

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, cherished by the supportive DEV Community. Coders of every background are encouraged to bring their perspectives and bolster our collective wisdom.

A sincere “thank you” often brightens someone’s day—share yours in the comments below!

On DEV, the act of sharing knowledge eases our journey and forges stronger community ties. Found value in this? A quick thank-you to the author can make a world of difference.

Okay