I have a library used by two Symfony apps, this library defines a set of services that I want to be public (I want to be able to retrieve them directly through the container. When I try to access one service I have this:
The "Library\Service\DerivedServices\OneSpecificImplementation" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.
The problem is that said service is declared public.
Basically there is:
Library\Service\BaseService
class that has two setters for the common dependencies (doctrine and a logger in this snippet);Library\Service\DerivedServices
namespace), each defines a new service (with its own constructor to handle DI directly).So here are my services definitions:
# Base: inject common dependencies
Library\Service\BaseService:
abstract: true
calls:
- [setDoctrine, ['@doctrine.orm.entity_manager']]
- [setLogger, ['@Library\Service\Logger']]
# These services are public to be retrieved directly by the container interface
Library\Service\DerivedServices\:
resource: '../vendor/company/library/src/Library/Service/DerivedServices'
public: true
autowire: true
autoconfigure: false
parent: Library\Service\BaseService
Then, the Symfony application retrieves one derived service like:
$this->get('Library\Service\DerivedServices\OneSpecificImplementation');
These didn't make any difference:
I think this is something trivial configuration-wise, but I can't pinpoint it (and after 2 hours trying to debug why the framework compiles my service as private, I thought that someone probably had this and could probably help me).
It turns out the order of declaration of the services matter a lot. As I thought so, the problem was configuration-wise.
I had:
Library\Service\BaseService:
...
Library\Service\DerivedServices\:
...
Library\Service\:
resource: '../vendor/company/library/src/Library/Service'
The last instruction redeclared all services as private (by default).
I changed this to:
Library\Service\:
resource: '../vendor/company/library/src/Library/Service'
Library\Service\BaseService:
...
Library\Service\DerivedServices\:
...
This declared all the services private first, then redeclared them with the new declaration: use of parent + public.