{"id":13821815,"url":"https://github.com/mnapoli/fluent-symfony","last_synced_at":"2025-08-20T16:30:55.616Z","repository":{"id":57018488,"uuid":"80359021","full_name":"mnapoli/fluent-symfony","owner":"mnapoli","description":"Fluent configuration for Symfony","archived":false,"fork":false,"pushed_at":"2017-04-22T11:25:22.000Z","size":69,"stargazers_count":78,"open_issues_count":2,"forks_count":3,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-12-08T23:34:37.189Z","etag":null,"topics":["dependency-injection","php","symfony"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mnapoli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-29T17:08:08.000Z","updated_at":"2022-10-30T12:48:23.000Z","dependencies_parsed_at":"2022-08-22T11:10:06.515Z","dependency_job_id":null,"html_url":"https://github.com/mnapoli/fluent-symfony","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnapoli%2Ffluent-symfony","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnapoli%2Ffluent-symfony/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnapoli%2Ffluent-symfony/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnapoli%2Ffluent-symfony/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mnapoli","download_url":"https://codeload.github.com/mnapoli/fluent-symfony/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230438185,"owners_count":18225870,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dependency-injection","php","symfony"],"created_at":"2024-08-04T08:01:29.370Z","updated_at":"2024-12-19T13:06:55.386Z","avatar_url":"https://github.com/mnapoli.png","language":"PHP","readme":"# Fluent configuration for Symfony\n\n[![Build Status](https://img.shields.io/travis/mnapoli/fluent-symfony/master.svg?style=flat-square)](https://travis-ci.org/mnapoli/fluent-symfony)\n\nThis package offers an alternative configuration syntax for Symfony's container, inspired by [PHP-DI's configuration](http://php-di.org/doc/php-definitions.html).\n\n- [Why?](#why)\n- [Comparison with existing formats](#comparison-with-existing-formats)\n- [Installation](#installation)\n- [Syntax](#syntax)\n- [Parameters](#parameters)\n- [Services](#services)\n    - [Using the class name as the entry ID](#using-the-class-name-as-the-entry-id)\n    - [Autowiring](#autowiring)\n    - [Constructor arguments](#constructor-arguments)\n    - [Dependencies](#dependencies)\n    - [Setter injection](#setter-injection)\n    - [Property injection](#property-injection)\n    - [Optional service references](#optional-service-references)\n    - [Decorated services](#decorated-services)\n    - [Non shared services](#non-shared-services)\n- [Factories](#factories)\n- [Aliases](#aliases)\n- [Tags](#tags)\n- [Imports](#imports)\n- [Extensions](#extensions)\n\n## Why?\n\nThe main goal is to benefit from stricter analysis from the PHP engine and IDEs. If you are interested you can also read [why YAML was replaced by a similar syntax in PHP-DI 5](http://php-di.org/news/06-php-di-4-0-new-definitions.html).\n\n- auto-completion on classes or constants:\n\n    ![](https://i.imgur.com/t65dZ9l.png)\n\n- auto-completion when writing configuration:\n\n    ![](http://i.imgur.com/0w0or7S.gif)\n\n- real time validation in IDEs:\n\n    ![](http://i.imgur.com/28wO3Oa.png)\n    \n- constant support:\n\n    ![](https://i.imgur.com/LsRXbJx.png)\n\n- better refactoring support\n\n## Comparison with existing formats\n\nCurrently, in Symfony, you can configure the container using:\n\n- YAML\n\n    ```yaml\n    parameters:\n        mailer.transport: sendmail\n    \n    services:\n        mailer:\n            class:     Mailer\n            arguments: ['%mailer.transport%']\n    ```\n\n- XML\n\n    ```xml\n    \u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e\n    \u003ccontainer xmlns=\"http://symfony.com/schema/dic/services\"\n        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n        xsi:schemaLocation=\"http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd\"\u003e\n    \n        \u003cparameters\u003e\n            \u003cparameter key=\"mailer.transport\"\u003esendmail\u003c/parameter\u003e\n        \u003c/parameters\u003e\n    \n        \u003cservices\u003e\n            \u003cservice id=\"mailer\" class=\"Mailer\"\u003e\n                \u003cargument\u003e%mailer.transport%\u003c/argument\u003e\n            \u003c/service\u003e\n        \u003c/services\u003e\n    \u003c/container\u003e\n    ```\n\n- PHP code\n\n    ```php\n    $container-\u003esetParameter('mailer.transport', 'sendmail');\n    $container\n        -\u003eregister('mailer', 'Mailer')\n        -\u003eaddArgument('%mailer.transport%');\n    ```\n\nWith this package, you can now use a 4th alternative:\n\n```php\nreturn [\n    'mailer.transport' =\u003e 'sendmail',\n\n    'mailer' =\u003e create(Mailer::class)\n        -\u003earguments('%mailer.transport%'),\n];\n```\n\n## Installation\n\n```\ncomposer require mnapoli/fluent-symfony\n```\n\nTo enable the new format in a Symfony fullstack application, simply import the `EnableFluentConfig` trait in `app/AppKernel.php`, for example:\n\n```php\n\u003c?php\n\nuse Fluent\\EnableFluentConfig;\nuse Symfony\\Component\\HttpKernel\\Kernel;\n// ...\n\nclass AppKernel extends Kernel\n{\n    use EnableFluentConfig;\n\n    // ...\n}\n```\n\nYou can now either:\n\n- write all your config in \"fluent\" syntax, to do that change your `AppKernel` to load `.php` files instead of `.yml`:\n\n    ```php\n    class AppKernel extends Kernel\n    {\n        use EnableFluentConfig;\n    \n        // ...\n    \n        public function registerContainerConfiguration(LoaderInterface $loader)\n        {\n            $loader-\u003eload($this-\u003egetRootDir().'/config/config_'.$this-\u003egetEnvironment().'.php');\n        }\n    }\n    ```\n\n- or import PHP config files from YAML config files:\n\n    ```yaml\n    imports:\n        - services.php\n        \n    # ...\n    ```\n\nBe advised that PHP config files in the \"traditional\" form ([see the documentation](http://symfony.com/doc/current/components/dependency_injection.html#setting-up-the-container-with-configuration-files)) *are still supported* and will continue to work.\n\n## Syntax\n\nA configuration file must `return` a PHP array. In that array, parameters, services and imports are defined altogether:\n\n```php\n\u003c?php\n# app/config/config.php\n\nreturn [\n    // ...\n];\n```\n\n## Parameters\n\nParameters are declared as simple values:\n\n```php\nreturn [\n    'foo' =\u003e 'bar',\n];\n```\n\nThis is the same as:\n\n```yaml\nparameters:\n    foo: 'bar'\n```\n\nParameters and services can be mixed in the same array.\n\n## Services\n\nServices can be declared simply using the `create()` function helper:\n\n```php\nuse function Fluent\\create;\n\nreturn [\n    'mailer' =\u003e create(Mailer::class),\n];\n```\n\nWhen calling `$container-\u003eget('mailer')` an instance of the `Mailer` class will be created and returned.\n\nThis is the same as:\n\n```yaml\nservices:\n    mailer:\n        class: Mailer\n```\n\n#### Using the class name as the entry ID\n\nIf the container entry ID is a class name, you can skip it when calling `create()`.\n\n```php\nreturn [\n    Mailer::class =\u003e create(),\n];\n```\n\n#### Autowiring\n\nServices can also be [automatically wired](http://symfony.com/doc/current/components/dependency_injection/autowiring.html) using the `autowire()` function helper in place of `create()`:\n \n```php\nuse function Fluent\\autowire;\n \nreturn [\n    Mailer::class =\u003e autowire(),\n];\n```\n \nThis is the same as:\n\n```yaml\nservices:\n    Mailer:\n        class: Mailer\n        autowire: true\n```\n\n#### Constructor arguments\n\n```php\nreturn [\n    'mailer' =\u003e create(Mailer::class)\n        -\u003earguments('smtp.google.com', 2525),\n];\n```\n\nThis is the same as:\n\n```yaml\nservices:\n    mailer:\n        class: Mailer\n        arguments: ['smtp.google.com', 2525]\n```\n\n#### Dependencies\n\nParameters can be injected using the `'%foo%'` syntax:\n\n```php\nreturn [\n    'mailer' =\u003e create(Mailer::class)\n        -\u003earguments('%mailer.transport%'),\n];\n```\n\nThis is the same as:\n\n```yaml\nservices:\n    mailer:\n        class:     Mailer\n        arguments: ['%mailer.transport%']\n```\n\nServices can be injected using the `get()` function helper:\n\n```php\nuse function Fluent\\get;\n\nreturn [\n    'newsletter_manager' =\u003e create(NewsletterManager::class)\n        -\u003earguments(get('mailer')),\n];\n```\n\nThis is the same as:\n\n```yaml\nservices:\n    newsletter_manager:\n        class: NewsletterManager\n        arguments: ['@mailer']\n```\n\n#### Setter injection\n\n```php\nreturn [\n    'mailer' =\u003e create(Mailer::class)\n        -\u003emethod('setHostAndPort', 'smtp.google.com', 2525),\n];\n```\n\nThis is the same as:\n\n```yaml\nservices:\n    mailer:\n        class: Mailer\n        calls:\n            - [setHostAndPort, ['smtp.google.com', 2525]]\n```\n\n#### Property injection\n\n```php\nreturn [\n    'mailer' =\u003e create(Mailer::class)\n        -\u003eproperty('host', 'smtp.google.com'),\n];\n```\n\nThis is the same as:\n\n```yaml\nservices:\n    mailer:\n        class: Mailer\n        properties:\n            host: smtp.google.com\n```\n\n#### Optional service references\n\nServices can have [optional dependencies](https://symfony.com/doc/current/service_container/optional_dependencies.html), so that the dependency is not required for it to work.\n\n##### Setting missing dependencies to null\n\n```php\nuse function Fluent\\create;\nuse function Fluent\\get;\n\nreturn [\n    'newsletter_manager' =\u003e create(NewsletterManager::class)\n        -\u003earguments(get('mailer')-\u003enullIfMissing()),\n];\n```\n\nThis is the same as :\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e\n\u003ccontainer xmlns=\"http://symfony.com/schema/dic/services\"\n    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n    xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n        http://symfony.com/schema/dic/services/services-1.0.xsd\"\u003e\n\n    \u003cservices\u003e\n        \u003cservice id=\"newsletter_manager\" class=\"NewsletterManager\"\u003e\n            \u003cargument type=\"service\" id=\"mailer\" on-invalid=\"null\" /\u003e\n        \u003c/service\u003e\n    \u003c/services\u003e\n\u003c/container\u003e\n```\n\n##### Ignore missing dependencies\n\nWhen used with setter injection, it's possible to remove the method call using `ignoreIfMissing()` :\n\n```php\nuse function Fluent\\create;\nuse function Fluent\\get;\n\nreturn [\n    'newsletter_manager' =\u003e create(NewsletterManager::class)\n        -\u003emethod('setMailer', get('mailer')-\u003eignoreIfMissing()),\n];\n```\n\nThis is the same as :\n\n```yaml\nservices:\n    app.newsletter_manager:\n        class:     AppBundle\\Newsletter\\NewsletterManager\n        calls:\n            - [setMailer, ['@?app.mailer']]\n```\n\n#### Private Services\n\n```php\nreturn [\n    Mailer::class =\u003e create()\n        -\u003eprivate(),\n];\n```\n\nThis is the same as:\n\n```yaml\nservices:\n    mailer:\n        class: Mailer\n        public: false\n```\n\n#### Decorated services\n\nServices can be [decorated](https://symfony.com/doc/current/service_container/service_decoration.html) with the `decorate()` method\n\n```php\nreturn [\n    'decorating_mailer' =\u003e create(MailerDecorator::class)\n        -\u003edecorate('mailer')\n        -\u003eargument(get('decorating_mailer.inner')),\n];\n```\n\nThis is the same as:\n\n```yaml\nservices:\n    decorating_mailer:\n        class: 'MailerDecorator'\n        decorates: 'mailer'\n        arguments: ['@decorating_mailer.inner']\n```\n\nIf you want to apply more than one decorator to a service, you can change the inner service name (IE the decorated service) and configure the priority of decoration :\n\n```php\nreturn [\n    'foo' =\u003e create(Foo::class),\n    'bar' =\u003e create(Bar::class)\n        -\u003edecorate('foo', 'bar.foo', 5)\n        -\u003earguments(get('bar.foo'))\n    ,\n    'baz': create(Baz::class)\n        -\u003edecorate('foo', 'baz.foo', 1),\n        -\u003earguments(get('baz.foo'))\n];\n```\n\nThis is the same as:\n\n```yaml\nfoo:\n    class: Foo\n\nbar:\n    class: Bar\n    decorates: foo\n    decoration_inner_name: 'bar.foo'\n    decoration_priority: 5\n    arguments: ['@bar.foo']\n\nbaz:\n    class: Baz\n    decorates: foo\n    decoration_inner_name: 'baz.foo'\n    decoration_priority: 1\n    arguments: ['@baz.inner']\n```\n\n#### Non shared services\n\nAll services [are shared by default](http://symfony.com/doc/current/service_container/shared.html). You can force the container to always create a new instance using the `unshared()` function helper:\n\n```php\nreturn [\n    'app.phpmailer' =\u003e create(PhpMailer::class)\n        -\u003eunshared(),\n];\n```\n\nThis is the same as:\n\n```yaml\n\nservices:\n    app.phpmailer:\n        class: AppBundle\\Mail\\PhpMailer\n        shared: false\n``````\n\n#### Synthetic services\n\nServices can be injected [at runtime](http://symfony.com/doc/current/service_container/synthetic_services.html). You can inject a class instance as service, instead of configuring the container to create a new instance using the `synthetic()` function helper:\n\n```php\nreturn [\n    'app.phpmailer' =\u003e create(PhpMailer::class)\n        -\u003esynthetic(),\n];\n```\n\nThis is the same as:\n\n```yaml\n\nservices:\n    app.phpmailer:\n        class: AppBundle\\Mail\\PhpMailer\n        synthetic: true\n```\n\n## Factories\n\nServices can be created by [factories](https://symfony.com/doc/current/service_container/factories.html) using the `factory()` function helper:\n\n```php\nuse function Fluent\\factory;\n\nreturn [\n    'newsletter_manager' =\u003e factory([NewsletterManager::class, 'create'], NewsletterManager::class)\n        -\u003earguments('foo', 'bar'),\n];\n```\n\nWhen calling `$container-\u003eget('newsletter_manager')` the result of `NewsletterManager::create('foo', 'bar')` will be returned.\n\nThis is the same as:\n\n```yaml\nservices:\n    newsletter_manager:\n        factory: ['AppBundle\\Email\\NewsletterManager', 'create']\n        class: 'AppBundle\\Email\\NewsletterManager'\n        arguments: ['foo', 'bar']\n```\n\nWhen using the class name as service ID, you don't have to explicitly state the class name of the service:\n\n```php\nreturn [\n    // you can write:\n    NewsletterManager::class =\u003e factory([NewsletterManager::class, 'create']),\n    // instead of:\n    NewsletterManager::class =\u003e factory([NewsletterManager::class, 'create'], NewsletterManager::class),\n];\n```\n\n## Aliases\n\nServices can be aliased using the `alias()` function helper:\n\n```php\nuse function Fluent\\create;\nuse function Fluent\\alias;\n\nreturn [\n    'app.phpmailer' =\u003e create(PhpMailer::class),\n    'app.mailer' =\u003e alias('app.phpmailer'),\n];\n```\n\nWhen calling `$container-\u003eget('app.mailer')` the `app.phpmailer` entry will be returned.\n\nThis is the same as:\n\n```yaml\nservices:\n    app.phpmailer:\n        class: AppBundle\\Mail\\PhpMailer\n    app.mailer:\n        alias: app.phpmailer\n```\n\n#### Private Aliases\n\n```php\nreturn [\n    'app.phpmailer' =\u003e create(PhpMailer::class),\n    'app.mailer' =\u003e alias('app.phpmailer')\n        -\u003eprivate(),\n];\n```\n\nThis is the same as:\n\n```yaml\n\nservices:\n    app.phpmailer:\n        class: AppBundle\\Mail\\PhpMailer\n    app.mailer:\n        alias: app.phpmailer\n        public: false\n```\n\n## Tags\n\nServices can be tagged :\n\n```php\nreturn [\n    'mailer' =\u003e create(Mailer::class)\n        -\u003etag('foo', ['fizz' =\u003e 'buzz', 'bar' =\u003e 'baz'])\n        -\u003etag('bar'),\n];\n```\n\nThis is the same as:\n\n```yaml\nservices:\n    mailer:\n        class: Mailer\n        tags:\n            - {name: foo, fizz: buzz, bar: baz}\n            - {name: bar}\n```\n\n## Imports\n\nOther configuration files can be imported using the `import()` function helper:\n\n```php\nuse function Fluent\\import;\n\nreturn [\n    import('services/mailer.php'),\n];\n```\n\nYou will notice that the array item is not indexed by an entry ID.\n\nThis is the same as:\n\n```yaml\nimports:\n    - { resource: services/mailer.yml }\n```\n\n## Extensions\n\nExtensions (like the framework configuration for example) can be configured using the `extension()` function helper:\n\n```php\nuse function Fluent\\extension;\n\nreturn [\n    extension('framework', [\n        'http_method_override' =\u003e true,\n        'trusted_proxies' =\u003e ['192.0.0.1', '10.0.0.0/8'],\n    ]),\n];\n```\n\nThis is the same as:\n\n```yaml\nframework:\n    http_method_override: true\n    trusted_proxies: [192.0.0.1, 10.0.0.0/8]\n```\n","funding_links":[],"categories":["PHP"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmnapoli%2Ffluent-symfony","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmnapoli%2Ffluent-symfony","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmnapoli%2Ffluent-symfony/lists"}