1

I am trying to use the Symfony Dependancy Injection component to make my PHP classes easier to unit test. However I am getting stuck when the class that I want has constructor arguments that are determined at runtime. The class must be instantiated with the arguments to make sense. So I don't want to use setter injection. I have a feeling that I will not be able to use Dependancy Injection for this situation and need to reorganize the way I am trying to do this, but I am not sure what I need to do...

I read that I should use abstract factory if I have runtime arguments, but my class will also have the $service argument which is not a runtime argument and I would like to inject this so that when I am running tests, I can inject a mock service.

If Abstract factory is the way to go I would like to know how to use Abstract Factory with DI so that I can inject my service.

Otherwise if not Abstract Factory, what are my other options?

class Foo
{
     public function myMethod()
     {
         $container = new ContainerBuilder();
         $loader = new PhpFileLoader($container, new FileLocator(__DIR__));
         $loader->load('services.php'); //Load the config
         $container->compile();

         //I don't know how to get a Bar because it has other runtime arguments.
         $bar = $container->get('bar');
         //...
    }
}

class Bar
{
    private $service;

    public function __construct($userId, $date, $service)
    {
        $this->service = $service
        //...
    }
}

service.php (DI container config):

$container->register('dao', 'Dao');

$container->register('service', 'Service')
        ->addArgument(new Reference('dao'));


$container->register('bar', 'Bar')
        ->addArgument(new Reference('service'));

1 Answer 1

3

You could create a factory like that:

class BarFactory 
{
    private $service;

    public function __construct($service)
    {
        $this->service = $service;
    }

    public function createBar($userId, $date)
    {
        return new Bar($userId, $date, $service);
    }
}

This way you could still pass the service via your dependency injection container.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.