autowire Predis Interface in symfony - php

i wanna use ClientInterface in my class constructor and i give an error :
Cannot autowire service "App\Service\DelayReportService": argument "$client" of method "__construct()" references interface "Predis\ClientInterface" but no such service exists. Did you create a class that implements this interface?
seems to be i should add it manually to services.yml i added it like :
Predis\ClientInterface: '#Predis\Client'
and now i give this error:
You have requested a non-existent service "Predis\Client".
what is the solution and why symfony itself dont handle it?

you seem to be confused about how to define a service... which isn't surprising tbh
look here
https://symfony.com/doc/5.4/service_container.html#explicitly-configuring-services-and-arguments
for example
services:
App\Service\Concerns\IDevJobService:
class: App\Tests\Service\TestDevJobService
autowire: true
public: true
where
IDevJobService is an INTERFACE
and
TestDevJobService
is the actual implementation that will be auto injected
using # inside the yaml files is done to reference a service that has already been defined ELSEWHERE
https://symfony.com/doc/5.4/service_container.html#service-parameters
you probably want to watch symfonycasts services tutorial (I am not affiliated and I havent watched it myself yet (sure wish I did)).
EDIT
Predis\Client is a 3rd party class. It isn't in your App namespace or in your src folder. Symfony checks the src folder for class that it will then make to a service. See services.yaml there is a comment there, look for exclude and resource. And I'm not sure, even if you autoload it, that you can then just do #Predis\Client to reference an existing service.
be sure as well to debug your config using
php bin/console debug:autowiring
under linux you could do as well php bin/console debug:autowiring | grep Predis to find it more quickly (if it is there at all)

Related

How to separate Symfony (6.x) service and its configuration (using ContainerConfigurator)?

I have a service (it is not a bundle but might be in the future) which is using complex array as configuration - I would like to create a separate config file for that array in config/packages, let`s say "config/packages/my_service.php".
Example which I think is valid from Documentation (https://symfony.com/doc/current/configuration.html#accessing-configuration-parameters) (see below) does not work with error "You have requested a non-existent service ...". My service is available via debug:container and works otherwise. Using Symfony 6.1.
I am not sure why this service is not available during config compile time.
<?php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use App\Services\MyService;
return static function(ContainerConfigurator $container) {
$container->services()->get(MyService::class)
->arg('$foo','bar');
};
where 'foo' => 'bar' would be my complex config.
Another way to separate service from configuration is by using configurator service which Symfony offers (I have used it in different cases) but I am reluctant because I wanted to have all config under config folder.
Any other ways to do it?

The definition for "security.user_password_hasher" has no class, during Symfony 5.3 phpunit tests?

The question is somehow related to: How to access a private service in Symfony 5.3 phpunit tests?. I set up env services_test.yaml by:
services:
security.user_password_hasher:
public: true
When I try retrieve security.user_password_hasher I get exception:
$encoded = static::getContainer()->get('security.user_password_hasher')->hashPassword($user, $password);
Symfony\Component\DependencyInjection\Exception\RuntimeException: The definition for "security.user_password_hasher" has no class. If you intend to inject this service dynamically at runtime, please mark it as synthetic=true. If this is an abstract definition solely used by child definitions, please add abstract=true, otherwise specify a class to get rid of this error.
Why I getting this exception? In the same test suite I retrieve EntityManagerInterface::class and everything is okay.
When I access UserPasswordHasherInterface (it's alias for security.user_password_hasher) in dev env by injecting it in controller public function homepage(UserPasswordHasherInterface $hash) no error is thrown. Why changing it settings to public: true crashing tests? It's that this service is special, and need special care in test env? Or maybe because test env change some defaults settings?
I'm newbie to Symfony. My guess is that container do some hidden magic. Someone can reveal the secret?
What does mean: [NOTE] The "security.user_password_hasher" service or alias has been removed or inlined when the container was compiled?

Resolving Controller Services in Sylius/Symfony

Hoes does Symfony resolve the Sylius service sylius.controller.shop_user service to the controller class file Sylius\Bundle\UserBundle\Controller\UserController.
My understanding is that sylius.controller.shop_user is a service, and that in Symfony there will be a corresponding service configuration. This service configuration will tell Symfony which class to use when it needs to instantiate the service.
However, I can't seem to find a sylius.controller.shop_user configuration in the Sylius source configuration anywhere. There's just references to this service in routing files
#File: src/Sylius/Bundle/ShopBundle/Resources/config/routing/ajax/user.yml
sylius_shop_ajax_user_check_action:
path: /check
methods: [GET]
defaults:
_controller: sylius.controller.shop_user:showAction
_format: json
_sylius:
repository:
method: findOneByEmail
arguments:
email: $email
serialization_groups: [Secured]
or in on-disk container cache files.
var/cache/dev/srcKernelDevDebugContainer.xml
1798: <parameter key="sylius.controller.shop_user.class">Sylius\Bundle\UserBundle\Controller\UserController</parameter>
15230: <service id="sylius.controller.shop_user" class="Sylius\Bundle\UserBundle\Controller\UserController" public="true">
So how does Symfony know to instantiate the right class for this service?
Is there configuration I'm not seeing? Some Symfony magic that auto-generates the class? Some other mysterious third thing where I don't know what I don't know?
I don't have any specific task in mind, I'm just trying to get a feel for how Sylius and Symfony work under the hood.
The controller service is defined based on ResourceBundle's configuration in Sylius\Bundle\ResourceBundle\DependencyInjection\Driver\AbstractDriver::addController. This driver is called when loading a bundle.
Services with the name sylius.controller.[entity-name] are part of the
Sylius
entity resource system. As best I can tell, when you define your new doctrine entities
in a specific way and
register them as a Sylius resource, Sylius will
automatically generate these controller services based on your
configuration.
The actual line of code that defines these services
is here.
#File: src/Sylius/Bundle/ResourceBundle/DependencyInjection/Driver/AbstractDriver.php
/* ... */
$container->setDefinition($metadata->getServiceId('controller'), $definition);
/* ... */
The
Sylius\Bundle\ResourceBundle\DependencyInjection\Driver\AbstractDriver
class is a (as of 1.3) a base class for the
Sylius\Bundle\ResourceBundle\DependencyInjection\Driver\Doctrine\DoctrineORMDriver
class. How this class ends up being used is by Symfony is unclear, but is
fortunately beyond the scope of this answer.

Symfony2 LiipFunctionalTestBundle overriding #validator service

I am trying to inject #validator into my service but LiipFunctionalTestBundle is overriding that service when it gets injected.
admin.image_service:
class: AdminBundle\Service\ImageService
arguments: ["#validator", "#doctrine.orm.admin_entity_manager", "#image_storage_filesystem"]
Which results in the error
must be an instance of Symfony\Component\Validator\Validator\RecursiveValidator, instance of Liip\FunctionalTestBundle\Validator\DataCollectingValidator given
running php bin/console debug:container results in
liip_functional_test.validator: Liip\FunctionalTestBundle\Validator\DataCollectingValidator
validator: alias for "liip_functional_test.validator"
Is there a way to get around this over than remove liip and refactor all of my tests?
In Your service you should typehint Interface not exact class.
Instdead Symfony\Component\Validator\Validator\RecursiveValidator use Symfony\Component\Validator\Validator\ValidatorInterface - which is implemented by both classes (Symfony and Liip).

logging in symfony 2.3

I am trying to write my own messages to the log in Symfony 2.3, from anywhere, and not just the Controller (which I realize you can just do a "$this->get('logger')".
I've seen that in Symfony 1 you can use sfContext, but that class no longer seems to be a viable choice in 2.3.
Any help is appreciated.
Symfony2 has Service-oriented architecture (http://en.wikipedia.org/wiki/Service-oriented_architecture) and logger is one of service (by default Monolog). In controller you have access to service via $this->get('service_name'). Here is more info about service container: http://symfony.com/doc/current/book/service_container.html#what-is-a-service-container. If you wanna use logger in another service you have to define service and inject logger service. Example:
# section with defined service in your config.yml file (by default in config.yml)
services:
# your service name
my_service:
# your class name
class: Fully\Qualified\Loader\Class\Name
# arguments passed to service constructor. In this case #logger
arguments: ["#logger"]
# tags, info: http://symfony.com/doc/current/components/dependency_injection/tags.html
tags:
- { name: monolog.logger, channel: acme }
Additionally you should familiarize with dependency injection docs: http://symfony.com/doc/current/components/dependency_injection/index.html
I hope that helped. If not, please let me know where exactly you want to use logger.

Categories