Symfony2 LiipFunctionalTestBundle overriding #validator service - php

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

Related

autowire Predis Interface in symfony

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)

Unit testing services annotations without Symfony

I got a few bundles that are not installed in Symfony yet.
These bundles have a services.yml file in them:
mybundle/src/Bundle/Resources/config/services.yml
The services.yml contains classes and arguments from the bundle that are later used by Symfony, but not by the bundle itself:
mybundle.data.download.get:
class: mybundle\data\download\getinfo\get
arguments:
- "#bundle.myDepdendency.generate"
- "#bundle.myDepdendency.dosomething"
- "#bundle.helloThere"
I have working unit tests in Symfony for services.yml that checks that all classes are loaded correctly, however since I am developing the bundles independently outside of Symfony, I'd like to have a test to know if services.yml contains all the classes and their arguments.
So the question is:
Is there a way to test if services.yml contains given classes and their arguments without using Symfony?
I would start with this snippet:
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
$containerBuilder = new ContainerBuilder();
$loader = new YamlFileLoader($containerBuilder, new FileLocator(__DIR__.'/../BundlePath/Resources/config'));
$loader->load('services.yml');
$containerBuilder->compile();
Of course you need the symfony/dependency-injection and symfony/config components of symfony. But here you would test if any exception will thrown. If not, then every service was found and could be wired.
With
$containerBuilder->get('service_id') instanceof Bundle\Service\SomeService
you can even test if the service class was realy loaded.

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.

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.

How to share the \Mongo instance between Doctrine ODM and MongoDbSessionHandler?

I'm trying to use MongoDB to store my sessions, and I need to get a reference to the \Mongo instance.
But apparently it's not declared as a service. Instead, doctrine creates it from within the wrapper.
So what can I do about it? I tried this:
services:
mongo.connection:
class: MongoDoctrine\MongoDB\Connection
factory_service: doctrine.odm.mongodb.document_manager
factory_method: getConnection
mongo:
class: Mongo
factory_service: mongo.connection
factory_method: getMongo
But sometimes it returns null, and it also conflicts with my logger preprocessor that adds the request_id to the logs, which I think has something to do with the session.
Any ideas?
Looking at the source for Doctrine\MongoDB\Connection, the getMongo() method simply returns the $mongo class property, which may or may not be initialized. If possible, you can call initialize() manually before you inject the connection. Given that you're already defining a service for the Connection wrapper, you should be able to do this:
services:
mongo.connection:
class: Doctrine\MongoDB\Connection
factory_service: doctrine.odm.mongodb.document_manager
factory_method: getConnection
calls:
- [initialize, []]
mongo:
class: Mongo
factory_service: mongo.connection
factory_method: getMongo
That would invoke the initialize() method between the container constructing the mongo.connection service from its factory method and it being returned.
Some additional points to note:
If mongo.connection is only going to be used once (to injected into mongo), you may prefer using anonymous service definitions in lieu of defining another service.
The ODM bundle already defines each connection as doctrine_mongodb.odm.%s_connection, using its name from the configuration in place of %s; however, that's not helpful if you need to add a method invocation to the service definition.
The latest version of the ODM bundle (for Symfony 2.1+) changed its service prefix from doctrine.odm.mongodb to doctrine_mongodb.odm, although a BC alias exists for the default document manager. It'd be wise to switch over to the new prefix, though.

Categories