Symfony4 use external class library as a service

Viewed 3181

I have a little external library that expose many classes.

Into my symfony4 project I would like to declare my class from vendor, as a service with autowire and public. So I have include my library with composer and add psr configuration like this into composer.json:

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

After that I have tried to change my services.yaml into symfony like this:

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

If I launch tests or run the application returns me this error:

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.

If I declare into services.yaml the interface this works fine:

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

But I have many classes and I don't want to declare each class, how can I fix services.yaml without declare every single service?

Thanks

3 Answers

You need to create services by hand: I did not test it but it should look like this

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)
    {

    }
}

To be more precise you should have something like

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

Let's take Dompdf as an example :

When you try to add type-hint Dompdf in your action controller or service method , an error will be occurred saying that auto-wiring isn't possible because Dompdf is an external PHP library

So to solve this problem we'll make a little change in our services.yaml file by adding this short config

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

Apply the above example to all external PHP libs :)

That's all !

I had the same problem and someone gave me this solution, which works fine for me:

Use an external repository with symfony4 trouble with autoload and parameters

I copy the other solution by user @DasBen here just in case:

I think that you don't have to import each service separately. Your are already doing that with the "Puc\SapClient" part.

The problem could be that you are importing your models, which should not be imported.

In the symfony example project there is this part 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}'

Then your part would be:

# 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."}'

"etc." Would be everything that is not needed as service.

Related