/recipes

Symfony Recipes Repository

Primary LanguagePHPMIT LicenseMIT

Symfony Flex Recipes

Symfony Flex is the new way to manage dependencies in Symfony applications. One of its main features is the automatic installation, configuration and removal of dependencies. This automation is possible thanks to the Symfony Flex Recipes.

Creating Flex Recipes

Symfony Flex recipes consist of a manifest.json config file and, optionally, any number of files and directories. Recipes must be stored on their own repositories, outside of your Composer package repository. They must follow the vendor/package/version/ directory structure, where version is the minimum version supported by the recipe.

The following example shows the real directory structure of some Symfony recipes:

symfony/
    console/
        3.3/
            bin/
            manifest.json
    framework-bundle/
        3.3/
            etc/
            src/
            web/
            manifest.json
    requirements-checker/
        1.0/
            manifest.json

All the manifest.json file contents are optional and they are divided into options and configurators.

Options

aliases option

This option defines one or more alternative names that can be used to install the dependency. Its value is an array of strings. For example, if a dependency is published as acme-inc/acme-log-monolog-handler, it can define one or more aliases to make it easier to install:

{
    "aliases": ["acme-log", "acmelog"]
}

Developers can now install this dependency with composer require acme-log.

version_aliases option

This option lists all the additional dependency versions (using the x.y format) that work with this very same recipe. This avoids duplicating recipes when a new version of the package is released:

// vendor/package-name/3.2/manifest.json
{
    "version_aliases": ["3.3", "3.4", "4.0"]
}

Note

When using version_aliases, the directory where the recipe is defined must be the oldest supported version (3.2 in the previous example).

Configurators

Recipes define the different tasks executed when installing a dependency, such as running commands, copying files or adding new environment variables. Recipes only contain the tasks needed to install and configure the dependency because Symfony Flex is smart enough to reverse those tasks when uninstalling and unconfiguring the dependencies.

Symfony Flex provides eight types of tasks, which are called configurators: copy-from-recipe, copy-from-package, bundles, env, makefile, composer-scripts, gitignore, and post-install-output.

bundles Configurator

Enables one or more bundles in the Symfony application by appending them to the bundles.php file. Its value is an associative array where the key is the bundle class name and the value is an array of environments where it must be enabled. The supported environments are dev, prod, test and all (which enables the bundle in all environments):

{
    "bundles": {
        "Symfony\\Bundle\\DebugBundle\\DebugBundle": ["dev", "test"],
        "Symfony\\Bundle\\MonologBundle\\MonologBundle": ["all"]
    }
}

The previous recipe is transformed by Symfony Flex into the following PHP code:

// etc/bundles.php
return [
    'Symfony\Bundle\DebugBundle\DebugBundle' => ['dev' => true, 'test' => true],
    'Symfony\Bundle\MonologBundle\MonologBundle' => ['all' => true],
];

copy-from-package Configurator

Copies files or directories from the Composer package contents to the Symfony application. It's defined as an associative array where the key is the original file/directory and the value is the target file/directory.

This example copies the bin/check.php script of the package into the binary directory of the application:

{
    "copy-from-package": {
        "bin/check.php": "%BIN_DIR%/check.php"
    }
}

The %BIN_DIR% string is a special value that it's turned into the absolute path of the binaries directory of the Symfony application. These are the special variables available: %BIN_DIR%, %CONF_DIR%, %ETC_DIR%, %SRC_DIR% and %WEB_DIR%. You can also access to any variable defined in the extra section of your composer.json file:

// composer.json
{
    "...": "...",

    "extra": {
        "my-special-dir": "..."
    }
}

Now you can use %MY_SPECIAL_DIR% in your Symfony Flex recipes.

copy-from-recipe Configurator

It's identical to copy-from-package but contents are copied from the recipe itself instead of from the Composer package contents. It's useful to copy the initial configuration of the dependency and even a simple initial structure of files and directories:

"copy-from-recipe": {
    "etc/": "%ETC_DIR%/",
    "src/": "%SRC_DIR%/"
}

env Configurator

Adds the given list of environment variables to the .env and .env.dist files stored in the root of the Symfony project:

{
    "env": {
        "APP_ENV": "dev",
        "APP_DEBUG": "1"
    }
}

Symfony Flex turns that recipe into the following content appended to the .env and .env.dist files:

###> your-recipe-name-here ###
APP_ENV=dev
APP_DEBUG=1
###< your-recipe-name-here ###

The ###> your-recipe-name-here ### section separators are needed by Symfony Flex to detect the contents added by this dependency in case you uninstall it later. Don't remove or modify these separators.

makefile Configurator

Adds new tasks to the Makefile file stored in the root of the Symfony project. Unlike other configurators, there is no specific entry in the manifest file. Define tasks by creating a Makefile file at the root of the recipe directory (Symfony Flex adds a PHP_EOL character after each line).

Similar to the env configurator, the contents are copied into the Makefile file and wrapped with section separators (###> your-recipe-name-here ###) that must not be removed or modified.

composer-scripts Configurator

Registers scripts in the auto-scripts section of the composer.json file to execute them automatically when running composer install and composer update. The value is an associative array where the key is the script to execute (including all its arguments and options) and the value is the type of script (php-script for PHP scripts, script for any shell script and symfony-cmd for Symfony commands):

{
    "composer-scripts": {
        "vendor/bin/security-checker security:check": "php-script",
        "make cache-warmup": "script",
        "assets:install --symlink --relative %WEB_DIR%": "symfony-cmd"
    }
}

gitignore Configurator

Adds patterns to the .gitignore file of the Symfony project. Define those patterns as a simple array of strings (Symfony Flex adds a PHP_EOL character after each line):

{
    "gitignore": [
        ".env",
        "/var/",
        "/vendor/",
        "/web/bundles/"
    ]
}

Similar to other configurators, the contents are copied into the .gitignore file and wrapped with section separators (###> your-recipe-name-here ###) that must not be removed or modified.

post-install-output Configurator

Displays contents in the command console after the package has been installed. Avoid outputting meaningless information and use it only when you need to show help messages or the next step actions.

The contents must be defined in a file named post-install.txt (Symfony Flex adds a PHP_EOL character after each line). Symfony Console styles and colors are supported too:

<bg=blue;fg=white>              </>
<bg=blue;fg=white> What's next? </>
<bg=blue;fg=white>              </>

  * <fg=blue>Run</> your application:
    1. Change to the project directory
    2. Execute the <comment>make serve</> command;
    3. Browse to the <comment>http://localhost:8000/</> URL.

  * <fg=blue>Read</> the documentation at <comment>https://symfony.com/doc</>

Full Example

Combining all the above configurators you can define powerful recipes, like the one used by symfony/framework-bundle:

{
    "bundles": {
        "Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle": ["all"]
    },
    "copy-from-recipe": {
        "etc/": "%ETC_DIR%/",
        "src/": "%SRC_DIR%/",
        "web/": "%WEB_DIR%/"
    },
    "composer-scripts": {
        "make cache-warmup": "script",
        "assets:install --symlink --relative %WEB_DIR%": "symfony-cmd"
    },
    "env": {
        "APP_ENV": "dev",
        "APP_DEBUG": "1",
        "APP_SECRET": "Ju$tChang3it!"
    },
    "gitignore": [
        ".env",
        "/var/",
        "/vendor/",
        "/web/bundles/"
    ]
}