Symfony4 使用外部类库作为服务

Posted

技术标签:

【中文标题】Symfony4 使用外部类库作为服务【英文标题】:Symfony4 use external class library as a service 【发布时间】:2019-02-09 09:08:06 【问题描述】:

我有一个小的外部库,它公开了许多类。

在我的 symfony4 项目中,我想从供应商处声明我的类,作为具有 autowire 和 public 的服务。 所以我已经将我的库包含在 composer 中,并将这样的 psr 配置添加到 composer.json 中:

"autoload": 
        "psr-4": 
            "App\\": "src/",
            "ExternalLibrary\\": "vendor/external-library/api/src/"
        
    

之后我尝试将我的 services.yaml 更改为 symfony,如下所示:

ExternalLibrary\:
    resource: '../vendor/external-library/api/src/*'
    public: true
    autowire: true

如果我启动测试或运行应用程序返回此错误:

Cannot autowire service "App\Domain\Service\MyService": argument "$repository" of method "__construct()" references interface "ExternalLibrary\Domain\Model\Repository" but no such service exists. You should maybe alias this interface to the existing "App\Infrastructure\Domain\Model\mysqlRepository" service.

如果我在 services.yaml 中声明该接口,它可以正常工作:

ExternalLibrary\Domain\Model\Lotto\Repository:
    class: '../vendor/external-library/api/src/Domain/Model/Repository.php'
    public: true
    autowire: true

但是我有很多类并且我不想声明每个类,如何在不声明每个服务的情况下修复 services.yaml?

谢谢

【问题讨论】:

不确定加载整个目录是否是个好主意。这可能会对容器构建过程产生影响。无论如何,对于构造函数参数中的每个接口,您都需要手动声明一个类或别名。 好的,你能举一个你认为应该解决的例子吗?谢谢@FabienPapet 似乎您的第一种方法应该有效。回到它然后运行“bin/console debug:container”,看看你是否有任何 ExternalLibrary 服务。您可能必须注释掉 App 命名空间的行,才能克服原来的错误。 @Cerad 问题是我正在自动装配一个接口,并且应该使用别名声明例如 我很确定您需要将接口 ExternalLibrary\Domain\Model\Repository 设为 ExternalLibrary\Domain\Model\Lotto\Repository 的别名。我们的cmets越过了。 autowire 对接口没有多大帮助。以下面答案的最后一部分为例。 【参考方案1】:

我遇到了同样的问题,有人给了我这个解决方案,对我来说效果很好:

Use an external repository with symfony4 trouble with autoload and parameters

我在这里复制用户@DasBen的另一个解决方案以防万一:

我认为您不必单独导入每个服务。您已经在使用“Puc\SapClient”部分这样做了。

问题可能是您正在导入不应导入的模型。

在 symfony 示例项目中有这部分 vor "services.yaml":

# makes classes in src/ available to be used as services
  # this creates a service per class whose id is the fully-qualified class name
  App\:
    resource: '../src/*'
    exclude: '../src/Bundle,DependencyInjection,Entity,Model,Migrations,Tests,Kernel.php'

那么你的角色是:

# makes classes in src/ available to be used as services
  # this creates a service per class whose id is the fully-qualified class name
  Puc\SapClient\:
    resource: '../vendor/puc/sap-client/src/*'
    exclude: ''../vendor/puc/sap-client/src/Entity,Model,"etc."'

“等等”将是所有不需要的服务。

【讨论】:

【参考方案2】:

我们以 Dompdf 为例:

当您尝试在动作控制器或服务方法中添加 type-hint Dompdf 时,将发生错误,指出无法自动连接,因为 Dompdf是一个外部 PHP库

所以为了解决这个问题,我们将通过添加这个简短的配置对我们的 services.yaml 文件进行一些更改

Dompdf\: #Add the global namespace
   resource: '../vendor/dompdf/dompdf/src/*' #Where can we find your external lib ?
   autowire: true  #Turn autowire to true

将上述示例应用到所有外部 PHP 库:)

就是这样!

【讨论】:

【参考方案3】:

您需要手动创建服务: 我没有测试它,但它应该是这样的

services.yaml

Some\Vendor\:
    resource: '../vendor/external-library/api/src/*'
    public: true # should be false

Some\Vendor\FooInterface:
    alias: Some\Vendor\Foo # Interface implementation

Some\Vendor\Bar:
    class: Some\Vendor\Bar
    autowire: true

php

<?php

namespace Some\Vendor;

class Foo implements FooInterface




class Bar

    public function __construct(FooInterface $foo)
    

    

更准确地说,你应该有类似的东西

ExternalLibrary\Domain\Model\Repository:
    alias: App\Infrastructure\Domain\Model\MysqlRepository

【讨论】:

以上是关于Symfony4 使用外部类库作为服务的主要内容,如果未能解决你的问题,请参考以下文章

Thinkphp导入外部类的方法

JAVA关于引用外部jar包的问题

使用Visual Studio将类库项目附加到外部应用程序

Java运行外部程序(Apache Commons Exec)

winform如何全局调用一个外部的类?

生成类库chm帮助文档