FactoryInterface::make with parameters on reference definitions #771
Description
I noticed that when you call FactoryInterface::make() with a definition and parameters that is a reference to another definition FactoryInterface::make will end up calling ContainerInterface::get() on the target entry name since \DI\Definition\Reference::resolve is called.
Consider the following example.
<?php
declare(strict_types=1);
namespace TestApp {
require './vendor/autoload.php';
interface ConnectionInterface
{
}
class Connection implements ConnectionInterface
{
public string $host;
public function __construct(string $host)
{
$this->host = $host;
}
}
$containerBuilder = new \DI\ContainerBuilder();
$containerBuilder->addDefinitions([
\TestApp\ConnectionInterface::class => \DI\get(\TestApp\Connection::class),
\TestApp\Connection::class => \DI\factory(static function () {
return new \TestApp\Connection('localhost.master');
}),
]);
$container = $containerBuilder->build();
$container->get(\TestApp\ConnectionInterface::class);
$container->get(\TestApp\Connection::class);
echo $container->make(\TestApp\ConnectionInterface::class, ['host' => 'localhost.read'])->host . PHP_EOL; // localhost.master
echo $container->make(\TestApp\Connection::class, ['host' => 'localhost.read'])->host; // localhost.read
}
Is this intentional? FactoryInterface::make is documented to always resolve the definition which always lead to a new instance to be created (if the definition creates objects) except for Reference definition.
One fix is to call make with the abstract class. In my real world example I use FactoryInterface::make in my custom RepositoryFasctory for doctrine entities and I use interfaces for my custom repositories. The repositories using interfaces then get the wrong EntityManager instance since I send the correct EntityManagerInterface as a parameter to FactoryInterface::make.
Thanks in advance for help and guidance. :)