phpdependency-injectionautowiredsymfony5

How to inject env VARS into abstract class in a Symfony54 php81 app


I have recently undertaken upgrading an old Symfony 4.4 app (to 5.4 and PHP 8.1) and have been following the brilliant tutorials over at symfonycasts.com. I have come up to a point where I don't understand how to move forward.

class One extends AbstractClassTwo {}

abstract class AbstractClassTwo extends AbstractClassThree {
    public function __construct(array $arr = []){
    parent::__construct(); 
    $this->arr = $arr; 
    }
}

abstract class AbstractClassThree {

    public function __construct(protected string $injectedVar) {} 
    public function doSomething() { 
        echo $this->injectedVar; 
    }
}

services.yaml:


_defaults: autowire: true autoconfigure: true bind: 'string $injectedVar': '%env(TO_INJECT)%'

.env.local:

TO_INJECT=astringgoeshere

When I try to execute the code I get: Uncaught Error: Too few arguments to function App\AbstractClassThree::__construct(), 0 passed in /src/AbstractClassTwo on line 35 and exactly 1expected.

I'm really unsure as to why this doesn't work. Any help much appreciated!


Solution

  • So the only way I seem to be able to solve this is to inject the parameters into the child class as well thus becomming:

    abstract class AbstractClassTwo extends AbstractClassThree {
        public function __construct(protected string $injectedVar, array $arr = []){
        parent::__construct($injectedVar); 
        $this->arr = $arr; 
        }
    }
    

    The Symfony documentation itself does state:

    These advantages do mean that constructor injection is not suitable for working with optional dependencies. It is also more difficult to use in combination with class hierarchies: if a class uses constructor injection then extending it and overriding the constructor becomes problematic.

    Emphasis mine, this can be found just above the following link: https://symfony.com/doc/current/service_container/injection_types.html#immutable-setter-injection