Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DependencyInjection] Prepending extension configs with file loaders #52843

Merged
merged 1 commit into from
Apr 3, 2024

Conversation

yceruto
Copy link
Member

@yceruto yceruto commented Dec 1, 2023

Q A
Branch? 7.1
Bug fix? no
New feature? yes
Deprecations? no
Issues Fix #52789
License MIT

#52636 continuation.

This is another try to simplify even more the prepending extension config strategy for Bundles and Extensions.

Feature: "Import and prepend an extension configuration from an external YAML, XML or PHP file"

Useful when you need to pre-configure some functionalities in your app, such as mapping some DBAL types provided by your bundle, or simply pre-configuring some default values automatically when your bundle is installed, without losing the ability to override them if desired in userland.

class AcmeFooBundle extends AbstractBundle
{
    public function prependExtension(ContainerConfigurator $container, ContainerBuilder $builder): void
    {
        // Before
        $config = Yaml::parse(file_get_contents(__DIR__.'/../config/doctrine.yaml'));
        $builder->prependExtensionConfig('doctrine', $config['doctrine']);

        // After
        $container->import('../config/doctrine.yaml');
    }
}

The "Before" section is limited to importing/parsing this kind of configuration by hand; it doesn't support features like when@env, recursive importing, or defining parameters/services in the same file. Further, you can't simply use ContainerConfigurator::import() or any *FileLoader::load() here, as they will append the extension config instead of prepending it, defeating the prepend method purpose and breaking your app's config strategy. Thus, you are forced to use $builder->prependExtensionConfig() as the only way.

This is because if you append any extension config using $container->import(), then you won't be able to change that config in your app as it's merged with priority. If anyone is doing that currently, it shouldn't be intentional.

Therefore, the "After" proposal changes that behavior for $container->import(). Now, all extension configurations encountered in your external file will be prepended instead. BUT, this will only happen here, at this moment, during the prependExtension() method.

Of course, this little behavior change is a "BC break". However, it is a behavior that makes more sense than the previous one, enabling the usage of ContainerConfigurator::import() here, which was previously ineffective.

This capability is also available for YamlFileLoader, XmlFileLoader and PhpFileLoader through a new boolean constructor argument:

class AcmeFooBundle extends AbstractBundle
{
    public function prependExtension(ContainerConfigurator $container, ContainerBuilder $builder): void
    {
        // Before
        // - It can't be used for prepending config purposes

        // After
        $loader = new YamlFileLoader($builder, new FileLocator(__DIR__.'/../config/'), prepend: true);
        $loader->load('doctrine.yaml'); // now it prepends extension configs as default behavior
        // or
        $loader->import('prepend/*.yaml');
    }
}

These changes only affect the loading strategy for extension configs; everything else keeps working as before.

Cheers!

@yceruto yceruto added this to the 7.1 milestone Dec 1, 2023
@carsonbot carsonbot changed the title [DependencyInjection] Prepending extension configs with file loaders Prepending extension configs with file loaders Dec 1, 2023
@carsonbot carsonbot changed the title Prepending extension configs with file loaders [DependencyInjection] Prepending extension configs with file loaders Dec 1, 2023
@yceruto yceruto added the DX DX = Developer eXperience (anything that improves the experience of using Symfony) label Dec 1, 2023
Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just wondering about recursive imports: are they also reversed?

src/Symfony/Component/DependencyInjection/CHANGELOG.md Outdated Show resolved Hide resolved
@yceruto
Copy link
Member Author

yceruto commented Dec 1, 2023

I'm just wondering about recursive imports: are they also reversed?

The behavior is set up for the whole process, so yes, all extension configs imported recursively will be prepended too. However, unless there are split configs of the same extension distributed into several files matching the same config key, it doesn't matter.

@yceruto
Copy link
Member Author

yceruto commented Dec 1, 2023

The behavior is set up for the whole process, so yes, all extension configs imported recursively will be prepended too.

Which is expected if you're importing from the prepend method.

@nicolas-grekas
Copy link
Member

Maybe you already answered but just to be sure: if I have a yaml file that imports two other files, I'd expect them to be loaded in top-down order, is that going to be the case?

@yceruto
Copy link
Member Author

yceruto commented Dec 4, 2023

Maybe you already answered but just to be sure: if I have a yaml file that imports two other files, I'd expect them to be loaded in top-down order, is that going to be the case?

I will confirm with a test case to ensure we know what the behavior will be.

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (small rebase needed)

@yceruto
Copy link
Member Author

yceruto commented Jan 2, 2024

Thanks Nicolas! rebased done.

@yceruto
Copy link
Member Author

yceruto commented Jan 14, 2024

Friendly ping @symfony/mergers, there is a BC behavior break on the table here; it would be great to have a double check in case we miss something.

@yceruto
Copy link
Member Author

yceruto commented Mar 16, 2024

Hey @nicolas-grekas, I rebased, rechecked, and updated another part where when@env wasn't working as expected. I added another test case to cover it. So, after a while, this looks ready to me. Wdyt?

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some minor CS things and 🚀

@nicolas-grekas
Copy link
Member

Anyone @symfony/mergers ? (after a small rebase)

@yceruto yceruto added the ❄️ Feature Freeze Important Pull Requests to finish before the next Symfony "feature freeze" label Apr 2, 2024
@nicolas-grekas
Copy link
Member

Thank you @yceruto.

@nicolas-grekas nicolas-grekas merged commit 4ce4e5e into symfony:7.1 Apr 3, 2024
4 of 10 checks passed
@yceruto yceruto deleted the prepend_extension_config branch April 3, 2024 20:57
fabpot added a commit that referenced this pull request Apr 5, 2024
…(OskarStark)

This PR was squashed before being merged into the 7.1 branch.

Discussion
----------

[DependencyInjection] Document BC break in UPGRADE file

| Q             | A
| ------------- | ---
| Branch?       | 7.1
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        | Follows #52843
| License       | MIT

Commits
-------

055892d [DependencyInjection] Document BC break in UPGRADE file
javiereguiluz added a commit to symfony/symfony-docs that referenced this pull request Apr 15, 2024
…ities (yceruto)

This PR was merged into the 7.1 branch.

Discussion
----------

[DependencyInjection] Updating prepend extension capabilities

Fixes #19735

I'm also suggesting removing the append example in the prepend extension method. As explained in PR symfony/symfony#52843 and related issues, it's flawed and should be discouraged from the official documentation.

I'll create a new PR to target the lower branch and remove it there too.

Commits
-------

25c5adf Updating prepend extension capabilities
@fabpot fabpot mentioned this pull request May 2, 2024
nicolas-grekas added a commit that referenced this pull request May 17, 2024
…nerConfigurator (MatTheCat)

This PR was merged into the 7.1 branch.

Discussion
----------

[DependencyInjection] Process PHP configs using the ContainerConfigurator

| Q             | A
| ------------- | ---
| Branch?       | 7.1
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Issues        | Fix #54852
| License       | MIT

Since #52843, `ContainerConfigurator::extension` is not called anymore which means `ParamConfigurator`s are no longer processed and converted to strings, and make nodes validation fail: e.g. `framework.secret` would receive an `EnvConfigurator` and throw because it is not a scalar.

Commits
-------

e6dc6be [DependencyInjection] Process PHP configs using the ContainerConfigurator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BC Break DependencyInjection DX DX = Developer eXperience (anything that improves the experience of using Symfony) Feature ❄️ Feature Freeze Important Pull Requests to finish before the next Symfony "feature freeze" Status: Reviewed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow prepending extension config in DI Loader (XML/YAML)
3 participants