8000 Nullable environment variable processor by bpolaszek · Pull Request #29767 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Nullable environment variable processor #29767

New is 8000 sue

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
Feb 13, 2019
Merged

Nullable environment variable processor #29767

merged 1 commit into from
Feb 13, 2019

Conversation

bpolaszek
Copy link
Contributor
@bpolaszek bpolaszek commented Jan 3, 2019
Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets
License MIT
Doc PR todo

Hey there,

Because environment variables are strings by design, empty environment variables are evaluated to "" by default.
In the same way, MY_ENV_VAR=null will be evaluated to "null", as a string.

What I suggest is to allow some environment variables to be evaluated to null (the real one) when their strings are blank or equal null, Null or NULL.

This can be easily done through a new nullable processor:

# .env
API_KEY=
# config/services.yaml
services:
    FooService:
        arguments:
            $apiKey: %env(nullable:API_KEY)%
# src/Services/FooService
namespace App\Services;

final class FooService
{
    /**
     * @var string|null
     */
    private $apiKey;

    /**
     * FooService constructor.
     */
    public function __construct(?string $apiKey)
    {
        $this->apiKey = $apiKey;
    }

    public function doSomething()
    {
        // Free plan
        if (null === $this->apiKey) {
            // ...
        }
    }

}

That's an example that comes to my mind but there can be many others.
This can also help in using null coalesce operators in constructors instead of checking if a string equals "" (which is very PHP4 style).

Of course it can be used in conjunction with other types, i.e. %env(float:nullable:SOME_OPTIONAL_FLOAT_ENV_VAR)%.

What do you think?

Copy link
Contributor
@OskarStark OskarStark 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 the PR

@bpolaszek
Copy link
Contributor Author

Related tickets: #22151 #28618 #25129 #20434

@bpolaszek
< 8000 /summary> Copy link
Contributor Author

Appveyor randomly fails on Symfony\Component\Process\Tests\ProcessTest::testWaitUntilSpecificOutput though this PR isn't related to this 😕

@OskarStark
Copy link
Contributor

You can have a look here: #29760

@bpolaszek
Copy link
Contributor Author

Reworded commit message and force pushed, everything's fine now 🎉

@@ -195,6 +196,10 @@ public function getEnv($prefix, $name, \Closure $getEnv)
return str_getcsv($env);
}

if ('nullable' === $prefix) {
return '' === $env ? null : $env;
Copy link
Contributor

Choose a reason for hiding this comment

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

What if the env var is not defined at all? To me, not providing the env var means null.

Currently, you can already get a null behavior for FOO env var by setting a env(FOO) parameter:

parameters:
    env(FOO): null

so null is used as default value if FOO env var is not set.

Don't we just need this allowing an env var not to be set to get null, without defining a parameter as default?

Copy link
Contributor
@ro0NL ro0NL Jan 8, 2019

Choose a reason for hiding this comment

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

i think we should avoid

env(DEFAULT_NULL): null
%env(DEFAULT_NULL)%

competing with

%env(nullable:RUNTIME_ARBITRARY_NULL)%

to take this further we could also deprecate setting null defaults, in favor of always using nullable: + string values (related to #27808)

Copy link
Contributor
@ogizanagi ogizanagi Jan 8, 2019

Choose a reason for hiding this comment

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

Yes, my point is %env(nullable:FOO)% should be accepted even if FOO is not set and no env(FOO) parameter exists => injected value will be null.

Second point: not sure we need the empty string to be considered null.

Copy link
Contributor
@ro0NL ro0NL Jan 8, 2019

Choose a reason for hiding this comment

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

My worry is RUNTIME_ENV= can only be nulled by removing it or move it to config.

Currently there's only one source where null can come from, and it's: env(DEFAULT): ~

Adding nullable creates 2 scenarios. Hence my suggestion to deprecate env(DEFAULT): ~ in favor of

RUNTIME=
env(DEFAULT): ""

%env(nullable:DEFAULT)%
%env(nullable:RUNTIME)%

IMHO that's the easiest to reason about.

Copy link
Member
@nicolas-grekas nicolas-grekas Jan 27, 2019

Choose a reason for hiding this comment

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

When the env var is not defined, we already added the "default" processor in #28976. I think this processor should do one thing, turn empty strings to null - what it does currently - and "default" covers the other use cases.
I also don't agree deprecating env(FOO): ~ is a good idea: we shouldn't deprecate for the sake of it.

Copy link
Member
@nicolas-grekas nicolas-grekas Jan 27, 2019

Choose a reason for hiding this comment

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

Note that "default" has not been released yet so we can also alter its behavior.
But each processor should have one responsibility - we shouldn't have many processors doing the same in slightly different ways.

@nicolas-grekas nicolas-grekas added this to the next milestone Jan 25, 2019
@nicolas-grekas
Copy link
Member

please rebase

@bpolaszek
Copy link
Contributor Author

@nicolas-grekas Done.

Copy link
Member
@xabbuh xabbuh left a comment

Choose a reason for hiding this comment

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

Can you also add an entry to the component's changelog file please?

@bpolaszek
Copy link
Contributor Author

Sure.

@fabpot
Copy link
Member
fabpot commented Feb 13, 2019

Thank you @bpolaszek.

@fabpot fabpot merged commit 3a604ac into symfony:master Feb 13, 2019
fabpot added a commit that referenced this pull request Feb 13, 2019
This PR was merged into the 4.3-dev branch.

Discussion
----------

Nullable environment variable processor

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        | todo

Hey there,

Because environment variables are strings by design, empty environment variables are evaluated to `""` by default.
In the same way, `MY_ENV_VAR=null` will be evaluated to `"null"`, as a string.

What I suggest is to allow some environment variables to be evaluated to `null` (the real one) when their strings are _blank_ or equal _null_, _Null_ or _NULL_.

This can be easily done through a new `nullable` processor:

```bash
# .env
API_KEY=
```

```yaml
# config/services.yaml
services:
    FooService:
        arguments:
            $apiKey: %env(nullable:API_KEY)%
```
```php
# src/Services/FooService
namespace App\Services;

final class FooService
{
    /**
     * @var string|null
     */
    private $apiKey;

    /**
     * FooService constructor.
     */
    public function __construct(?string $apiKey)
    {
        $this->apiKey = $apiKey;
    }

    public function doSomething()
    {
        // Free plan
        if (null === $this->apiKey) {
            // ...
        }
    }

}
```
That's an example that comes to my mind but there can be many others.
This can also help in using null coalesce operators in constructors instead of checking if a string equals `""` (which is very PHP4 style).

Of course it can be used in conjunction with other types, i.e. `%env(float:nullable:SOME_OPTIONAL_FLOAT_ENV_VAR)%`.

What do you think?

Commits
-------

3a604ac Nullable environment variable processor
@bpolaszek bpolaszek deleted the nullable-env-processor branch February 13, 2019 09:00
fabpot added a commit that referenced this pull request Mar 10, 2019
… "default" one (nicolas-grekas)

This PR was merged into the 4.3-dev branch.

Discussion
----------

[DI] replace "nullable" env processor by improving the "default" one

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

Neither `nullable` nor `default` are released yet.
I propose to replace the `nullable` processor (see #29767) with an improved `default` one (from #28976).
`%env(default::FOO)%` now defaults to `null` when the env var doesn't exist or compares to false".

ping @jderusse @bpolaszek

Commits
-------

c50aad2 [DI] replace "nullable" env processor by improving the "default" one
@nicolas-grekas nicolas-grekas removed this from the next milestone Apr 30, 2019
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
0