Skip to content

FactoryInterface::make with parameters on reference definitions #771

Open
@hultberg

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. :)

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions