Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[DependencyInjection] Add #[When(env: 'foo')] to skip autoregistering a class when the env doesn't match #40782

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

Merged
merged 1 commit into from
Apr 17, 2021

Conversation

nicolas-grekas
Copy link
Member

@nicolas-grekas nicolas-grekas commented Apr 12, 2021

Q A
Branch? 5.x
Bug fix? no
New feature? yes
Deprecations? no
Tickets -
License MIT
Doc PR -

This is a follow up of #40214, in order to conditionally auto-register classes.

By adding a #[When(env: prod)] annotation on a class, one can tell that a class should be skipped when the current env doesn't match the one declared in the attribute.

This saves from writing similar conditional configuration by using the per-env services_prod.yaml convention (+corresponding exclusion from services.yaml), or some logic in the Kernel.

@nicolas-grekas nicolas-grekas added this to the 5.x milestone Apr 12, 2021
@carsonbot carsonbot changed the title [DI] add #[When(env: 'foo')] to disable autoconfiguring a class during autodiscovery when the env doesn't match [DependencyInjection] add #[When(env: 'foo')] to disable autoconfiguring a class during autodiscovery when the env doesn't match Apr 12, 2021
@derrabus
Copy link
Member

Would it make sense to also take the debug flag into account?

#[When(debug: true)]
class When
{
    public function __construct(
        public ?string $environment = null,
        public ?bool $debug = null,
    ) {
    }
}

@nicolas-grekas
Copy link
Member Author

nicolas-grekas commented Apr 12, 2021

I considered adding debug when working on #40214 but in the end, this I decided against. The reason is that we have no use case for loading configuration conditionally based on debug/non-debug without corresponding complex logic. debug is useful for two things: logic in DI extensions, and runtime logic of services. Adding it here would increase complexity by a lot for no practical benefit.

About environment vs env, #40214 uses env (see examples in the description, also #[Route(env: 'foo')]. We could change, but this PR at least is consistent :)

@derrabus
Copy link
Member

About environment vs env, #40214 uses env (see examples in the description, also #[Route(env: 'foo')]. We could change, but this PR at least is consistent :)

Oh, that slipped me. Yes, I would be very much in favor of changing the property to environment for Route as well. 🙂

@nicolas-grekas
Copy link
Member Author

Argh, I very much prefer env on my side :)

@yceruto
Copy link
Member

yceruto commented Apr 14, 2021

I'm also prefer env for short.

@ogizanagi
Copy link
Contributor

👍🏻 env for me as well

@nicolas-grekas nicolas-grekas changed the title [DependencyInjection] add #[When(env: 'foo')] to disable autoconfiguring a class during autodiscovery when the env doesn't match [DependencyInjection] Add #[When(env: 'foo')] to skip autoregistering a class when the env doesn't match Apr 15, 2021
Copy link
Member

@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

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

I like this now! But... one last question :). Can we (someone) put out a concrete use case for this? I checked our codebase, and we don't do this very often. But I also might be neglecting a nice thing that "conditionally registering a service in an environment" allows me to do.

Thanks!

@nicolas-grekas
Copy link
Member Author

nicolas-grekas commented Apr 16, 2021

We do this very often actually, but we do this through bundles, which are the parts that are conditionally loaded by env. In apps, there are no bundles usually, and ppl have to resort to writing explicit config, by 1. excluding the corresponding classes from discovery and 2. loading them only in the appropriate env. I've talked to several ppl that do this.

A typical example is an event listener that should be enabled only for prod/dev/etc.

@fancyweb
Copy link
Contributor

@weaverryan Here is a real use case from a real project, defining a command only for the dev env:

I define my services in PHP files in config/services. When I want something for a particular env, I define it in a sub directory, eg: config/services/dev.

// Kernel.php
$container->import(__DIR__.'/../config/services/*.php');
$container->import(__DIR__.'/../config/{services}/'.$this->environment.'/*.php');

Before:

// config/services/commands.php
$services
    ->load(
        'App\\Command\\',
        '../../src/Command'
    )
    ->exclude([
        '../../src/Command/Dev',
    ]);
//config/services/dev/commands.php
$services
    ->load(
        'App\\Command\\Dev\\',
        '../../../src/Command/Dev'
    );

After:

// config/services/commands.php
$services
    ->load(
        'App\\Command\\',
        '../../src/Command'
    );
// src/Command/Dev/MyDevCommand.php
#[When(env: 'dev')]
final class MyDevCommand extends Command

Logically, I won't need those env sub directories anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.