DI or Abstract factory in this scenario?

Hello everyone!
Im struggling to find a solution for this type of situation:

use Symfony\Component\Console\Command\Command;
class ExCommand extends Command{
    protected $repo;
    function __construct(RepoInterface $repo){
       $this->repo = $repo;
    }
    function execute($in, $out){
       // this variable should determine which repo should call the method below
       $var = $in->getArgument('repo');
       $result = $this->repo->someMethod();
    }
}

class ExCommandFactory implements FactoryInterface{
   function __invoke(..){
      return new ExCommand($container->get(RepoInterface::class));
   }
}
interface RepoInterface{
   function someMethod() : string;
}
class RepoOne implements RepoInterface {
   function __construct( /*RepoOne Dependencies via factory class ..*/ ) { .. }
   function someMethod() : string {
      //work with the dependencies ..
      return $someVar;
   }
}

class RepoTwo implements RepoInterface{
   function __construct( /*RepoTwo Dependencies via factory class ..*/ ) { .. }
   function someMethod() : string {
      //work with the dependencies ..
      return $someOtherVar;
   }
}

And it obviously leads to the following configuration

'service_manager' => [
     'aliases' => [
        RepoInterface::class => ???
     ],
]

I’ve read about Laminas-di and Matthew’s analogy (cool blog tho) and i was like: “Yea that may be the solution(?)” but then i found out the Abstract Factory use case in the docs and those lines fitted too:

An abstract factory is often useful when you do not know in advance the name of the service (e.g. if the service name is generated dynamically at runtime), but know that the services share a common creation pattern.

In your opinion what should i use for my case?
And if it’s ok can i have little explanation and some code to understand?

Just to get a better idea… what determines (or should) which Repo (One/Two) to use?

Ah, I see what you are trying to do here.

Since you need to know what the parameter is within the factory, you could try something like this…

class ExCommandFactory
{
    function __invoke(...): RepoInterface
    {
        $argv = $argv ?? $_SERVER['argv'] ?? [];
        ...

One of the $argv values should get you closer to identify the repo you want to instantiate.

Thanks for the hint! Didnt notice about $_SERVER[‘argv’] :smiley:
i wrote something like:

public function __invoke( ... ) {
        $argv = $argv ?? $_SERVER['argv'] ?? [];
        //dont really know if it's always the 3rd param
        $repoRequested = isset($argv[2]) ? $argv[2] : null; 
        $repoRetrieved = $this->retrieveRepo($repoRequested, $container);
        return new ExCommand( $repoRetrieved );
    }

    private function retrieveRepo($requested, $container) {
        //temporary solution to map the command input to a class
        $repoAvaiables = [
            'One' => RepoOne::class
            'Two' => RepoTwo::class
        ];
        $repoToInstantiate = (array_key_exists($requested, $repoAvaiables)) ? $repoAvaiables[$requested] : null;
        return ($repoToInstantiate && $container->has($repoToInstantiate)) ? $container->get($repoToInstantiate) : null;
    }

And i can manage it in my command:

if (!$this->repo) {
    //exit or request again
}