如何将供应商类注入服务?

时间:2018-03-27 17:25:20

标签: php symfony solid-principles symfony-3.4

我有示例服务:

<?php

namespace AppBundle\Service;

use AppBundle\Entity\Article;
use CompanyName\Utils\ClassFromVendor;

class DecorateArticle
{
    private $customDecorator;
    private $article;

    public function __construct(CustomDecorator $customDecorator)
    {
        $this->customDecorator = $customDecorator;
    }

    public function setNews(Article $article)
    {
        $this->article = $article;
    }

    public function decorate() : string
    {
         $text = strip_tags($this->article->getBody());

         $text = $this->customDecorator->doIt($text);

         $classFromVendor = new ClassFromVendor();
         $text = $classFromVendor->doIt($text);

         return $text;
    }
}

//controller:

public function showToApiAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();
    $news = $em->getRepository('AppBundle:News')->find($request->get('id'));

    $decorateArticle = $this->get('AppBundle\Service\DecorateArticle');
    $decorateArticle->setNews($news);

    return $decorateArticle->decorate();
}

//services.yml:

AppBundle\Service\DecorateArticle:
    arguments:
        $decorateArticle: '@AppBundle\Service\DecorateArticle'
    public: true

此代码中的一切都运行良好,但我的团队负责人告诉我,它违反了SOLID原则。

这就是我做的原因:

<?php

namespace AppBundle\Service;

use AppBundle\Entity\Article;
use CompanyName\Utils\ClassFromVendor;

class DecorateArticle
{
    private $customDecorator;
    private $classFromVendor;
    private $article;

    public function __construct(CustomDecorator $customDecorator, ClassFromVendor $classFromVendor)
    {
        $this->customDecorator = $customDecorator;
        $this->classFromVendor = $classFromVendor;
    }

    public function setNews(Article $article)
    {
        $this->article = $article;
    }

    public function decorate() : string
    {
         $text = strip_tags($this->article->getBody());

         $text = $this->customDecorator->doIt($text);

         $text = $this->classFromVendor->doIt($text);

         return $text;
    }
}

//controller:

public function showToApiAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();
    $news = $em->getRepository('AppBundle:News')->find($request->get('id'));

    $decorateArticle = $this->get('AppBundle\Service\DecorateArticle');
    $decorateArticle->setNews($news);

    return $decorateArticle->decorate();
}

//services.yml:

AppBundle\Service\DecorateArticle:
    arguments:
        $decorateArticle: '@AppBundle\Service\DecorateArticle'
        $classFromVendor: 'CompanyName\Utils\ClassFromVendor'
    public: true

但是这个抛出错误:

  

类型错误:参数2传递给   AppBundle \ Service \ DecorateArticle :: __ construct()必须是一个实例   of CompanyName \ Utils \ ClassFromVendor或null,给定字符串

如何将供应商类注入服务?

也许有更好的方法来做我做的事情? 我不确定我是否可以在一个类中使用services.yml和setter(setNews)中的注入。

2 个答案:

答案 0 :(得分:0)

试试这个。

AppBundle\Service\DecorateArticle:
        arguments:
            decorateArticle: '@AppBundle\Service\DecorateArticle'
            classFromVendor: companyName.utils.ClassFromVendor
        public: true


companyName.utils.ClassFromVendor:
    class: CompanyName\Utils\ClassFromVendor
    public: false

我不知道decorateArticle是否有效,因为你使用相同的服务作为参数.. 我认为这是将类作为参数传递给服务的正确方法。

答案 1 :(得分:0)

在Symfony 4中,我需要将供应商类注入我的一项服务中:

 jiraRestApi.ClassFromVendor:
    class: JiraRestApi\Issue\IssueService
    public: false

CM\Infrastructure\IssueJira\IssueJiraDbRepository:
    arguments: ['@jiraRestApi.ClassFromVendor', '@parameter_bag']
    public: false

您可能认为jiraRestApi.ClassFromVendor在哪里是供应商类。

我的IssueJiraDbRepository.php具有一个构造函数:

public function __construct(JiraRestApi Issue, ParameterBagInterface $params){ ...

因此,在您的情况下,我认为您必须进行service.yaml:

CompanyName.ClassFromVendor:
    class: CompanyName\Utils\ClassFromVendor
    public: false

AppBundle\Service\DecorateArticle:
    arguments:['@CompanyName.ClassFromVendor']
    public: true

记住参数中的“ @”。控制器中的构造函数应保持不变:

public function __construct(CustomDecorator $customDecorator)
{
    $this->customDecorator = $customDecorator;
}

将services.yaml处理为控制器的构造函数。在那里放置的参数将用于创建控制器的实例。您说的错误是您传递了字符串而不是对象。如果您有问题,可以随时使用自动装配,在大多数情况下就足够了。请记住,service.yaml中的新条目将替换以前的条目。