В обход dependency injection symfony

323
27 августа 2021, 11:50

Потихоньку осваивая symfony 4 возникли недопонимания. Имеется абстрактный репозиторий в который inject-ица некий DriverManager объект-коннекшн к базе данных. От него отнаследованы конкретные репозитории, но в примере будет фигурировать один ConcreteRepository.

abstract class AbstractRepository {
   public function __construct(DriverManager $dm) {
      $this->driverManager = $dm;
   }
}
class ConcreteRepository extends AbstractRepository {
   public function save($object) {
      // use DriverManage and save $object
   }
}

Это использовалось примерно вот так(в console-команде как пример)

class ConcreteCommand extends Command {
   public function __construct(ConcreteRepository $cr) {
      $this->cr = $cr;
   }
   public function execute(InputInterface $input, OutputInterface $output) {
      ...
      $result = $this->cr->save($object);
   }
}

Далее возникла необходимость создать некую фабрику репозиториев и тут сталкиваюсь с проблемой. Мне нужно через все слои прокинуть DriverManager к конкретному репозиторию:

/**
 *
 */
class RepositoryFactory {
   public function __construct(DriverManager $dm) {
      $this->dm = $dm;
   }
   public function create($type) {
      if($type === 'concrete-repository') {
         return new ConcreteRepository($this->dm);
      }
   }
}
/**
 * 
 */
class ConcreteCommand extends Command {
   public function __construct(DriverManager $dm) {
      $this->dm = $dm;
   }
   public function execute(InputInterface $input, OutputInterface $output) {
      $repo = (new RepositoryFactory($this->dm))->create('concrete-repo');
   }
}

Выглядит как-то странно, как можно избежать данной проблемы с прокидыванием DriverManager через все слои?

PS: По ряду причин доктрину использовать нет возможности.

Answer 1

А что мешает сделать прямо так:

public function execute(InputInterface $input, OutputInterface $output, RepositoryFactory $factory) {
  $repo = $factory->create('concrete-repo');

}

я попробовал у себя только не на консольный команде а в контроллере:

/**
 * Ваш первый вариант с прямым вызовов репозитория
 * @Route("/concrete", name="concrete")
 */
public function concrete(ConcreteRepository $repo) {
    $repo->save(['test']);
    return new Response(
        '<html><body>concrete</body></html>'
    );
}
/**
 * Через фабрику
 * @Route("/factory", name="factory")
 */
public function factory(RepositoryFactory $factory) {
    $repo = $factory->create('concrete-repository');
    if ($repo) {
        $repo->save(['test']);
    }
    return new Response(
        '<html><body>factory</body></html>'
    );
}

Собсно фабрика и классы репозиториев ваши:

namespace App\Repository;
use App\Service\DriverManager;
class RepositoryFactory {
    /**
     * @var DriverManager
     */
    protected $dm;
    public function __construct(DriverManager $dm) {
        $this->dm = $dm;
    }
    public function create($type) {
        if($type === 'concrete-repository') {
            return new ConcreteRepository($this->dm);
        }
        throw new \Exception('Unknown type of Repo');
    }
}

Репы

use App\Service\DriverManager;
class AbstractRepository {
    /**
     * @var DriverManager
     */
    protected $driverManager;
    public function __construct(DriverManager $driverManager) {
        $this->driverManager = $driverManager;
    }
}
namespace App\Repository;
class ConcreteRepository extends AbstractRepository {
    public function save ($object) {
        $this->driverManager->anythingDo($object);
    }
}

и некий DriveManager

namespace App\Service;
class DriverManager {
    public function __construct() {
    }
    public function anythingDo($object) {
        echo self::class . ' anythingDo with: ' . print_r($object, true) . '<br>';
    }
}

я сам только изучаю и стало любопытно

READ ALSO
Map-merge при наличии List в качестве значений

Map-merge при наличии List в качестве значений

Задача следующая - есть мапа, которая хранит в себе Id и связанный с ним список значений

172
Почему программа работает медленно?

Почему программа работает медленно?

Написал программуПрограмма выполняет все поставленные задачи, кроме одной, она должна выполнятся за 1 секунду, но выполняется за 4, подскажите,...

128
Android, Refrofit. Как разобрать JSON с неизвестным ключом?

Android, Refrofit. Как разобрать JSON с неизвестным ключом?

У меня такой вопрос, как разобрать json с неизвестным ключом? https://acxio//api/v2/tickers

147
Что делает, означает аннотация @Stable?

Что делает, означает аннотация @Stable?

вот к примеру в классе String есть такое вот выражение

188