New in Symplify 5: 3 New Cool Features of PackageBuilder

PackageBuilder was always sort of meta package with all the cool and shiny features anyone can use. After all, it's the most downloaded Symplify package hitting almost 1000 downloads a day.

In Symplify 5 now it allows you to drop manual binds from Symfony configs, separate files from directories in one method and merge nested YAML parameters with 1 service.

You don't have this package installed yet?

composer require symplify/package-builder

Now enjoy the news ↓

1. Drop Manual Binds in Symfony configs

See pull-request #998

You can add parameter binding since Symfony 3.4:

services:
    _defaults:
        bind:
            $meetupComApiKey: '%meetup_com_api_key%'

That's nice. But what if you have multiple configs that use multiple parameters?

services:
    _defaults:
        bind:
            $meetupComApiKey: '%meetup_com_api_key%'
            $facebookApiKey: '%facebook_api_key%'
            $maxPostOnHomepage: '%max_post_on_homepage%'

    App\FirstPackage\:
        resource: ..
services:
    _defaults:
        bind:
            $facebookApiKey: '%facebook_api_key%'
            $maxPostOnHomepage: '%max_post_on_homepage%'

    App\SecondPackage\:
        resource: ..

Not for Lazy Programmer

This way you'll be writing more bindings than there are parameters. And there is more! When you remove autodiscovered service that depends on a bound parameter, you'll get this "nice" exception:

Unused binding "maxPostOnHomepage" in service "App\SomeUnterlatedService"

You can solve this all by having a huge config with all parameters, binding and services. Even if the config would be shorter than 100 lines, you still have to maintain parameters, bindings and services and it teaches other programmers to put-everything-to-one-place instead of SOLID principles.


Would you like to get rid of this all extra maintenance, and just code cleanly instead? I would!

So, have you noticed the pattern?

And exactly this can be automated! Just add Symplify\PackageBuilder\DependencyInjection\CompilerPass\AutoBindParametersCompilerPass compiler pass:

<?php

    // ...

 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\HttpKernel\Kernel;
+use Symplify\PackageBuilder\DependencyInjection\CompilerPass\AutoBindParametersCompilerPass;

 final class YourAppKernel extends Kernel
 {
     // ...

+    protected function build(ContainerBuilder $containerBuilder): void
+    {
+        $containerBuilder->addCompilerPass(new AutoBindParametersCompilerPass());
+    }
 }

And if you keep this convention, you can keep yours configs clear and minimalistic:

 services:
-    _defaults:
-        bind:
-            $meetupComApiKey: '%meetup_com_api_key%'
-            $facebookApiKey: '%facebook_api_key%'
-            $maxPostOnHomepage: '%max_post_on_homepage%'

Of course you can bind your parameters manually:

services:
    _defaults:
        bind:
            $anotherName: '%non_standard_parameter_naming%'

    SomeClass:
        arguments:
            - '%very_specfici_meetup_com_api_key%'

2. Separate Files from Directories

See pull-request #963

Do you need to work multiple file/directories arguments?

vendor/bin/ecs check src tests/ThisFile.php

Just use Symplify\PackageBuilder\FileSystem\FileSystem:

<?php

$sources = [
   __DIR__ . '/SomeDirectory',
   __DIR__ . '/SomeFile.php'
];

$symplifyFileSystem = new Symplify\PackageBuilder\FileSystem\FileSystem;
[$files, $directories] = $symplifyFileSystem->separateFilesAndDirectories($sources);

// ...

3. Merge Parameters without Leaving Any Behind

See pull-request #989

At the moment, Symfony is unable to merge nested parameters for historical and other reasons:

# config.yml
imports:
    - { resource: 'imported-file.yml' }

parameters:
    festivals:
        - three
# imported-file.yml
parameters:
    festivals:
        - one
        - two

This will end up with just 1 festival in classic Symfony Applicatoin. Do you want to use the full power of YAML, glob and imports and still keep all the parameters?

Use Symplify\PackageBuilder\Yaml\ParameterMergingYamlLoader:

<?php

$parametersMergingYamlLoader = new Symplify\PackageBuilder\Yaml\ParameterMergingYamlLoader;
$parameterBag = $parametersMergingYamlLoader->loadParameterBagFromFile(
    __DIR__ . '/config.yml'
);

var_dump($parameterBag->get('festivals'));
// ['one', 'two', 'three']

And that's all folks!


Happy tuning of your code!




Do you learn from my contents or use open-souce packages like Rector every day?
Consider supporting it on GitHub Sponsors. I'd really appreciate it!