Make private and removed service available in tests - php

I'm trying to make vatin-bundle compatible with Symfony 6.
But the tests fail
The "validator" 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.
It seems this is new in Symfony 6
The container in static::getContainer() is actually a special test container. It gives you access to both the public services and the non-removed private services services.
What is the preferred way to make validator available in tests again?
The only way I found is creating my own alias like
services:
myvalidator:
alias: validator
public: true
and use the new alias. Is there a better way?

If the service is removed, then it's no longer accessible no matter what. It's not a matter of visibility, the service is no longer there. So you need to prevent the service from being removed: creating an alias is the best and simplest way to go about it.
This has been confirmed by maintainers here.
You can create the alias only during testing, and still access the original service. (e.g. ->get('validator'). Once the alias is created, the original service is no longer removed.
I don't think this is something really new in Symfony 6, but it's bee a thing since Symfony 4.4. Although it's true that now on Symfony 6, since it's removes previously deprecated behaviour, things could have changed.

Related

How to use my own service definition for a security firewall guard in Symfony 4.2?

I have a service defined in services.yaml that has a calls entry since I don't want to specify my dependencies in it's constructor so I use setters.
Now I am trying to point the security.firewalls.main.guard.authenticators.0 configuration entry to it, but if I try to reference it like this: '#App\Service\Authentication\Guard' I get The service "security.authentication.provider.guard.main" has a dependency on a non-existent service "#App\Service\Authentication\Guard".
If I specify just the name of the class as per Symfony's docs: App\Service\Authentication\Guard then there's no exception and the guard works, however the calls section of my definition is completely ignored and thus my setters don't work.
My best guess would be that the security module uses it's own service locator that's somehow disconnected and ignores definitions in services.yaml, which is probably why you won't find examples of the above config entry using simple service names rather than canonical class names.

Systematic Symfony 4 lazy service loading or annotation?

It's possible to lazy-load a service in Symfony, but:
Is it possible to make it the default way to load services
without having to configure it for all service?
Is there a possibility to annotate a service for lazy-loading?
Regarding the lazy loading. There are multiple ways you can solve this:
For one there is the new Service Locator that was introduced in 3.3. The documentation explicitly says:
Sometimes, a service needs access to several other services without being sure that all of them will actually be used. In those cases, you may want the instantiation of the services to be lazy. However, that's not possible using the explicit dependency injection since services are not all meant to be lazy (see Lazy Services).
The referenced article on Lazy Service describes another way to solve this which requires an additional dependency ocramius/proxy-manager which will then make it possible to mark services as lazy: true in your DI config.
I don't know if I understand the first question correctly, but if you don't want to manually configure dependencies you can rely on the autowiring feature that also received major changes in Symfony 3.3 and 3.4. You can only make the autowring a default per configuration file, but using the PSR-4 autodiscovery can basically autowire your whol src directory if you want to with some manual intervention, e.g. for parameters.

Symfony4 migration: The "doctrine.database_create_command" service is private

I'm starting to migrate my application to symfony4 but I have the following deprecation notice in one of my third-party bundle ( tbbcmoneybundle . And I would like to know what to change in order to propose a PR
Currently the build is failing because of these errors (complete report here )
The "doctrine.database_create_command" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead: 25x
12x in ConfigTest::setUp from Tbbc\MoneyBundle\Tests\Config
6x in ConsoleTest::setUp from Tbbc\MoneyBundle\Tests\Console
3x in ConsoleTest::testRunRatioList from Tbbc\MoneyBundle\Tests\Console
2x in ConsoleTest::testRunRatioFetch from Tbbc\MoneyBundle\Tests\Console
1x in ConfigTest::testHistoryOfFetchedRatio from Tbbc\MoneyBundle\Tests\Config
1x in ConsoleTest::testRunSaveRatio from Tbbc\MoneyBundle\Tests\Console
I guess it's related to this code
$this->runCommand($this->client,'doctrine:database:create');
$this->runCommand($this->client,'doctrine:schema:update --force');
However I don't see see how to fix this and google seems unhelpful on this one.
The problem looks like it comes from the loss of container awareness (if that's a valid phrase) in Symfony 4, which started in Symfony 3.4. This blog talks about restricting container injection in 3.4 and how it will go away in 4.0.
It looks as though someone has opened a PR to upgrade to Symfony 4, but that is failing. (Looks like you're trying to help that along as well.)
According to this Travis integration test that is failing, the commands which extend "ContainerAwareCommand" are the source of the fail.
Which makes sense. The ContainerAwareCommand attempts to inject the Container, which is set to private in Symfony 4 (and deprecated since 3.4) as outlined in the blog post above. A fix, and I think you want to fix this in a PR to TBBC if I read your question correctly, seems to be to remove the extension of ContainerAwareCommand from those command classes and just inject the services necessary. See the new Symfony 4 doc on commands (and note that ContainerAware is no longer an option as it was in 2.8-ish.)
In short, get rid of the extension to ContainerAwareCommand and inject the services used by those commands. (Might need to do some extra configuration to ensure that the services are public.)

Symfony ServiceContainer removes service after compile

I read on the Symfony documentation for the ServiceContainer that any services that are not used before compiling the container are removed from the container.
Now, I compile the container on the request if the container isn't cached.
How would I stop unused services from being removed, especially if they're required after the container has been compiled?
I'm aware Drupal does it by essentially re-writing the the container (mostly code taken from the original Symfony container), but although this is an option I'm wondering if there's a more efficient method on doing this? Also, I'm relatively new to Symfony, so any related documentation links would be greatly appreciated.
By default, all unused private Symfony services are removed, simply because they are private and they are not defined to be called from outside.
If the private service is used only once, it will be inlined (and removed from the container).
But the public services are not removed from the container, even if you don't use them, so if you want keep your service in the DI container, make sure that it is public

Extending of Symfony container

is it possible overwrite/extend Symfony\Component\DependencyInjection\Container::get() method? I want automatic creating service, when it is not contain in container, but class of service exists.
For example:
Name of service is My.MyBundle.Model.FooRepository
Service with this name doesnt exists, but when i call:
$container->get('My.MyBundle.Model.FooRepository');
check class_exists for \My\MyBundle\Model\FooRepository and when its exists, add to container and return it. Dependencies of this new services will be resolve by kutny/autowiring-bundle.
This feature can be extended only for some namespaces or interfaces and in production enviroment can be cached, but for developing will be great helper.
Any idea?
This is not directly answering your question but maybe it's answering your need: if you want to have "auto-wiring" inside your Symfony project, you can use PHP-DI inside Symfony. PHP-DI is an alternative container that can do auto-wiring (which Symfony does not).
Have a look at the Symfony 2 integration documentation to see if it can fit your bill.

Categories