Is it normal to use parameters from .env file through $_ENV?

Viewed 122

Is it normal to use parameters in your own code from .env file through $_ENV variable? Of course in context of project using Symfony 4.

I have such code:

//WebhookUrlBuilder.php
class WebhookUrlBuilder
{

    private RouterInterface $router;

    public function __construct(RouterInterface $router)
    {
        $this->router = $router;
        if (PHP_SAPI === 'cli') {
            $this->router->getContext()->setHost($_ENV['HOST_URL'])->setScheme($_ENV['URL_SCHEME']);
        }
    }

    public function build(string $hash): string
    {
        return $this->router->generate(BotsController::WEBHOOK_URL_NAME, [
            'hash' => $hash
        ], UrlGeneratorInterface::ABSOLUTE_URL);
    }
}

There is an opinion that using an $_ENV variable is bad taste, and I have to deliver these parameters through ParameterBag, like this:

#services.yml
parameters:
    host: '%env(HOST_URL)'
    scheme: '%env(URL_SCHEME)'
//WebhookUrlBuilder.php
class WebhookUrlBuilder
{

    private RouterInterface $router;

    public function __construct(RouterInterface $router, ParameterBag $parameterBag)
    {
        $this->router = $router;
        if (PHP_SAPI === 'cli') {
            $this->router
                 ->getContext()
                 ->setHost($parameterBag->get('host'))
                 ->setScheme($parameterBag->get('scheme'));
        }
    }

    public function build(string $hash): string
    {
        return $this->router->generate(BotsController::WEBHOOK_URL_NAME, [
            'hash' => $hash
        ], UrlGeneratorInterface::ABSOLUTE_URL);
    }
}

But I consider that is useless extra action(copy values from .env variables to paramteres in services.yml) which doesn't bring any profit. What do u think?

1 Answers

It's better to decouple code from environmental variables, this make your code more portable and testable. You should rewrite contstructor of WebhookUrlBuilder like this:

//WebhookUrlBuilder.php
class WebhookUrlBuilder
{

    private RouterInterface $router;

    public function __construct(RouterInterface $router, $host, $scheme)
    {
        $this->router = $router;
        if (PHP_SAPI === 'cli') {
            $this->router
                 ->getContext()
                 ->setHost($host)
                 ->setScheme($scheme);
        }
    }

    public function build(string $hash): string
    {
        return $this->router->generate(BotsController::WEBHOOK_URL_NAME, [
            'hash' => $hash
        ], UrlGeneratorInterface::ABSOLUTE_URL);
    }
}

and inject $host and $scheme via services.yaml like this:

#services.yml
parameters:
    host: '%env(HOST_URL)'
    scheme: '%env(URL_SCHEME)'
services:
    WebhookUrlBuilder:
        autowire: true
        arguments: ['%host%', '%scheme%']

Now, thanks to autowire, your builder is correctly instantiated and you can create new instances passing directly $host and $scheme per example in a phpunit test

Related