All Projects → mnapoli → Fluent Symfony

mnapoli / Fluent Symfony

Licence: mit
Fluent configuration for Symfony

Projects that are alternatives of or similar to Fluent Symfony

Dependency Injection
The DependencyInjection component allows you to standardize and centralize the way objects are constructed in your application.
Stars: ✭ 3,635 (+4443.75%)
Mutual labels:  symfony, dependency-injection
Package Builder
[READ-ONLY] Speed up your package DI containers integration and console apps to Symfony and Nette
Stars: ✭ 152 (+90%)
Mutual labels:  symfony, dependency-injection
Http Client
The HttpClient component provides powerful methods to fetch HTTP resources synchronously or asynchronously.
Stars: ✭ 1,186 (+1382.5%)
Mutual labels:  symfony
Marinator
Delicious Dependency Injection
Stars: ✭ 79 (-1.25%)
Mutual labels:  dependency-injection
Symfonystarter
[DEPRECATED] Please use the new version here https://github.com/Monofony/Monofony
Stars: ✭ 77 (-3.75%)
Mutual labels:  symfony
Dms Filter Bundle
Provides a FilterService for Symfony to allow users to implement input filtering in entities using Annotations
Stars: ✭ 74 (-7.5%)
Mutual labels:  symfony
Python Dependency Injector
Dependency injection framework for Python
Stars: ✭ 1,203 (+1403.75%)
Mutual labels:  dependency-injection
Cronos Bundle
Easy update your crontab by using @cron annotations in Symfony commands.
Stars: ✭ 73 (-8.75%)
Mutual labels:  symfony
Go Web
A new Golang MVC Framework. Like Laravel... but faster!
Stars: ✭ 79 (-1.25%)
Mutual labels:  dependency-injection
Sonataclassificationbundle
Symfony SonataClassificationBundle
Stars: ✭ 76 (-5%)
Mutual labels:  symfony
Docker Symfony
Run a Symfony application using Docker & docker-compose
Stars: ✭ 1,217 (+1421.25%)
Mutual labels:  symfony
Dihedral
Compile-time dependency injection for Go
Stars: ✭ 76 (-5%)
Mutual labels:  dependency-injection
Security
The Security component provides a complete security system for your web application.
Stars: ✭ 1,195 (+1393.75%)
Mutual labels:  symfony
Symfony Ddd Edition
Symfony standard edition with DDD architecture.
Stars: ✭ 78 (-2.5%)
Mutual labels:  symfony
Console
The Console component eases the creation of beautiful and testable command line interfaces.
Stars: ✭ 8,988 (+11135%)
Mutual labels:  symfony
Dictionarybundle
Are you often tired to repeat static choices like gender or civility in your apps ?
Stars: ✭ 79 (-1.25%)
Mutual labels:  symfony
Insight
SymfonyInsight Official SDK
Stars: ✭ 73 (-8.75%)
Mutual labels:  symfony
Twigextensionsbundle
Useful Twig extensions for your Symfony project.
Stars: ✭ 75 (-6.25%)
Mutual labels:  symfony
Dikit
Dependency Injection Framework for Swift, inspired by KOIN.
Stars: ✭ 77 (-3.75%)
Mutual labels:  dependency-injection
Price Tracker
Price Tracking Application - An experimental Kotlin Android project with complex android app requirements.
Stars: ✭ 80 (+0%)
Mutual labels:  dependency-injection

Fluent configuration for Symfony

Build Status

This package offers an alternative configuration syntax for Symfony's container, inspired by PHP-DI's configuration.

Why?

The 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.

  • auto-completion on classes or constants:

  • auto-completion when writing configuration:

  • real time validation in IDEs:

  • constant support:

  • better refactoring support

Comparison with existing formats

Currently, in Symfony, you can configure the container using:

  • YAML

    parameters:
        mailer.transport: sendmail
    
    services:
        mailer:
            class:     Mailer
            arguments: ['%mailer.transport%']
    
  • XML

    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <parameters>
            <parameter key="mailer.transport">sendmail</parameter>
        </parameters>
    
        <services>
            <service id="mailer" class="Mailer">
                <argument>%mailer.transport%</argument>
            </service>
        </services>
    </container>
    
  • PHP code

    $container->setParameter('mailer.transport', 'sendmail');
    $container
        ->register('mailer', 'Mailer')
        ->addArgument('%mailer.transport%');
    

With this package, you can now use a 4th alternative:

return [
    'mailer.transport' => 'sendmail',

    'mailer' => create(Mailer::class)
        ->arguments('%mailer.transport%'),
];

Installation

composer require mnapoli/fluent-symfony

To enable the new format in a Symfony fullstack application, simply import the EnableFluentConfig trait in app/AppKernel.php, for example:

<?php

use Fluent\EnableFluentConfig;
use Symfony\Component\HttpKernel\Kernel;
// ...

class AppKernel extends Kernel
{
    use EnableFluentConfig;

    // ...
}

You can now either:

  • write all your config in "fluent" syntax, to do that change your AppKernel to load .php files instead of .yml:

    class AppKernel extends Kernel
    {
        use EnableFluentConfig;
    
        // ...
    
        public function registerContainerConfiguration(LoaderInterface $loader)
        {
            $loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.php');
        }
    }
    
  • or import PHP config files from YAML config files:

    imports:
        - services.php
        
    # ...
    

Be advised that PHP config files in the "traditional" form (see the documentation) are still supported and will continue to work.

Syntax

A configuration file must return a PHP array. In that array, parameters, services and imports are defined altogether:

<?php
# app/config/config.php

return [
    // ...
];

Parameters

Parameters are declared as simple values:

return [
    'foo' => 'bar',
];

This is the same as:

parameters:
    foo: 'bar'

Parameters and services can be mixed in the same array.

Services

Services can be declared simply using the create() function helper:

use function Fluent\create;

return [
    'mailer' => create(Mailer::class),
];

When calling $container->get('mailer') an instance of the Mailer class will be created and returned.

This is the same as:

services:
    mailer:
        class: Mailer

Using the class name as the entry ID

If the container entry ID is a class name, you can skip it when calling create().

return [
    Mailer::class => create(),
];

Autowiring

Services can also be automatically wired using the autowire() function helper in place of create():

use function Fluent\autowire;
 
return [
    Mailer::class => autowire(),
];

This is the same as:

services:
    Mailer:
        class: Mailer
        autowire: true

Constructor arguments

return [
    'mailer' => create(Mailer::class)
        ->arguments('smtp.google.com', 2525),
];

This is the same as:

services:
    mailer:
        class: Mailer
        arguments: ['smtp.google.com', 2525]

Dependencies

Parameters can be injected using the '%foo%' syntax:

return [
    'mailer' => create(Mailer::class)
        ->arguments('%mailer.transport%'),
];

This is the same as:

services:
    mailer:
        class:     Mailer
        arguments: ['%mailer.transport%']

Services can be injected using the get() function helper:

use function Fluent\get;

return [
    'newsletter_manager' => create(NewsletterManager::class)
        ->arguments(get('mailer')),
];

This is the same as:

services:
    newsletter_manager:
        class: NewsletterManager
        arguments: ['@mailer']

Setter injection

return [
    'mailer' => create(Mailer::class)
        ->method('setHostAndPort', 'smtp.google.com', 2525),
];

This is the same as:

services:
    mailer:
        class: Mailer
        calls:
            - [setHostAndPort, ['smtp.google.com', 2525]]

Property injection

return [
    'mailer' => create(Mailer::class)
        ->property('host', 'smtp.google.com'),
];

This is the same as:

services:
    mailer:
        class: Mailer
        properties:
            host: smtp.google.com

Optional service references

Services can have optional dependencies, so that the dependency is not required for it to work.

Setting missing dependencies to null
use function Fluent\create;
use function Fluent\get;

return [
    'newsletter_manager' => create(NewsletterManager::class)
        ->arguments(get('mailer')->nullIfMissing()),
];

This is the same as :

<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services
        http://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>
        <service id="newsletter_manager" class="NewsletterManager">
            <argument type="service" id="mailer" on-invalid="null" />
        </service>
    </services>
</container>
Ignore missing dependencies

When used with setter injection, it's possible to remove the method call using ignoreIfMissing() :

use function Fluent\create;
use function Fluent\get;

return [
    'newsletter_manager' => create(NewsletterManager::class)
        ->method('setMailer', get('mailer')->ignoreIfMissing()),
];

This is the same as :

services:
    app.newsletter_manager:
        class:     AppBundle\Newsletter\NewsletterManager
        calls:
            - [setMailer, ['@?app.mailer']]

Private Services

return [
    Mailer::class => create()
        ->private(),
];

This is the same as:

services:
    mailer:
        class: Mailer
        public: false

Decorated services

Services can be decorated with the decorate() method

return [
    'decorating_mailer' => create(MailerDecorator::class)
        ->decorate('mailer')
        ->argument(get('decorating_mailer.inner')),
];

This is the same as:

services:
    decorating_mailer:
        class: 'MailerDecorator'
        decorates: 'mailer'
        arguments: ['@decorating_mailer.inner']

If 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 :

return [
    'foo' => create(Foo::class),
    'bar' => create(Bar::class)
        ->decorate('foo', 'bar.foo', 5)
        ->arguments(get('bar.foo'))
    ,
    'baz': create(Baz::class)
        ->decorate('foo', 'baz.foo', 1),
        ->arguments(get('baz.foo'))
];

This is the same as:

foo:
    class: Foo

bar:
    class: Bar
    decorates: foo
    decoration_inner_name: 'bar.foo'
    decoration_priority: 5
    arguments: ['@bar.foo']

baz:
    class: Baz
    decorates: foo
    decoration_inner_name: 'baz.foo'
    decoration_priority: 1
    arguments: ['@baz.inner']

Non shared services

All services are shared by default. You can force the container to always create a new instance using the unshared() function helper:

return [
    'app.phpmailer' => create(PhpMailer::class)
        ->unshared(),
];

This is the same as:

services:
    app.phpmailer:
        class: AppBundle\Mail\PhpMailer
        shared: false

Synthetic services

Services can be injected at runtime. You can inject a class instance as service, instead of configuring the container to create a new instance using the synthetic() function helper:

return [
    'app.phpmailer' => create(PhpMailer::class)
        ->synthetic(),
];

This is the same as:

services:
    app.phpmailer:
        class: AppBundle\Mail\PhpMailer
        synthetic: true

Factories

Services can be created by factories using the factory() function helper:

use function Fluent\factory;

return [
    'newsletter_manager' => factory([NewsletterManager::class, 'create'], NewsletterManager::class)
        ->arguments('foo', 'bar'),
];

When calling $container->get('newsletter_manager') the result of NewsletterManager::create('foo', 'bar') will be returned.

This is the same as:

services:
    newsletter_manager:
        factory: ['AppBundle\Email\NewsletterManager', 'create']
        class: 'AppBundle\Email\NewsletterManager'
        arguments: ['foo', 'bar']

When using the class name as service ID, you don't have to explicitly state the class name of the service:

return [
    // you can write:
    NewsletterManager::class => factory([NewsletterManager::class, 'create']),
    // instead of:
    NewsletterManager::class => factory([NewsletterManager::class, 'create'], NewsletterManager::class),
];

Aliases

Services can be aliased using the alias() function helper:

use function Fluent\create;
use function Fluent\alias;

return [
    'app.phpmailer' => create(PhpMailer::class),
    'app.mailer' => alias('app.phpmailer'),
];

When calling $container->get('app.mailer') the app.phpmailer entry will be returned.

This is the same as:

services:
    app.phpmailer:
        class: AppBundle\Mail\PhpMailer
    app.mailer:
        alias: app.phpmailer

Private Aliases

return [
    'app.phpmailer' => create(PhpMailer::class),
    'app.mailer' => alias('app.phpmailer')
        ->private(),
];

This is the same as:

services:
    app.phpmailer:
        class: AppBundle\Mail\PhpMailer
    app.mailer:
        alias: app.phpmailer
        public: false

Tags

Services can be tagged :

return [
    'mailer' => create(Mailer::class)
        ->tag('foo', ['fizz' => 'buzz', 'bar' => 'baz'])
        ->tag('bar'),
];

This is the same as:

services:
    mailer:
        class: Mailer
        tags:
            - {name: foo, fizz: buzz, bar: baz}
            - {name: bar}

Imports

Other configuration files can be imported using the import() function helper:

use function Fluent\import;

return [
    import('services/mailer.php'),
];

You will notice that the array item is not indexed by an entry ID.

This is the same as:

imports:
    - { resource: services/mailer.yml }

Extensions

Extensions (like the framework configuration for example) can be configured using the extension() function helper:

use function Fluent\extension;

return [
    extension('framework', [
        'http_method_override' => true,
        'trusted_proxies' => ['192.0.0.1', '10.0.0.0/8'],
    ]),
];

This is the same as:

framework:
    http_method_override: true
    trusted_proxies: [192.0.0.1, 10.0.0.0/8]
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].