【问题标题】:Inject EntityManager in a service from another service将 EntityManager 从另一个服务注入到一个服务中
【发布时间】:2023-03-11 23:38:01
【问题描述】:

我正在将代码从 Controller 提取到 Symfony 3.4 应用程序中的一种 ApplicationService。

我有一个用于抓取数据的具体类和另一个用于更改一些数据的具体转换器。

src\App\Service 

class CompanyScraping implements ScrapingInterface
{
    private $crawler;

    public function __construct(CrawlerInterface $crawler)
    {
        $this->crawler = $crawler;

    }

    public function extract()
    {
        ...
    }

    public function transform()
    {
        $transformer = new concreteTransformer();

    }
}

class concreteTransformer
{
    private $em;

    public __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }
}

如果没有在 CompanyScraping 类中调用 EntityManager,我如何将 EntityManager 传递给具体的Transformer 类?我不能用新的实例化concreteTransformer。

我正在考虑这两个选项:

  • 将 EntityManager 传递给 CompanyScraping,但我认为这是一个错误的想法,因为 CompanyScraping 不需要此依赖项。

  • 将转换方法提取到另一个类并从控制器/控制台传递 em

$crawler =  new CompanyScraping(new GoutteClient());
$rawData = $crawler->extract(...);
$data = new concreteTransformer($em, $rawData);

还有什么想法吗?

谢谢。

【问题讨论】:

  • 为什么不直接将 ConcreteTransformer 注入到 CompanyScraping 类中?

标签: php symfony private


【解决方案1】:

我想到的第一个解决方案是将 Transformer(不是 EM,而是)注入到 Scraper 类中,如 cmets 中所述。

但是,这种解决方案无法解决根本问题:Scraper 是在抓取、转换还是两者兼而有之?在后一种情况下,它不遵循单一职责原则,因为它同时负责抓取转换。

decorator pattern 是一种可以非常有效地解决这个问题的设计模式。 在这种情况下,想法是通过转换来“装饰”抓取的结果。

结果看起来有点像这样:

class Transformer implements ScrapingInterface
{
    private $scraper;
    private $em;

    public __construct(ScrapingInterface $scraper, EntityManagerInterface $em)
    {
        $this->scraper = $scraper;
        $this->em = $em;
    }

    public function extract()
    {
        return $this->transform($this->scraper->extract());
    }

    private function transform() {...}
}

可以这样构造:

$crawler = new Transformer(new CompanyScraping(new GoutteClient()), $em);

如果你有多个转换器实现,你可以让装饰器更通用:

class TransformingScraper implements Scraper
{
    private $scraper;
    private $transformer;

    public __construct(Scraper $scraper, Transformer $transformer)
    {
        $this->scraper = $scraper;
        $this->transformer = $transformer;
    }

    public function extract()
    {
        return $this->transformer->transform($this->scraper->extract());
    }
}

$crawler = new TransformingScraper(
    new CompanyScraping(new GoutteClient()),
    new ConcreteTransformer($em)
);

【讨论】:

  • 你说得对,你评论的最坏的情况是正确的......刮板类有两个职责:(我已经实现了你的装饰器解决方案。非常感谢!
猜你喜欢
  • 2013-12-22
  • 1970-01-01
  • 2014-01-27
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 2012-08-01
相关资源
最近更新 更多