Resolving Controller Services in Sylius/Symfony - php

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.

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)

Symfony 3.4: Correctly configured service is not found

I have an service class with the class name NewsService.
The service is configured as follows:
services:
portal.news:
class: xxx\NewsBundle\Service\NewsService
arguments: ["#doctrine.orm.entity_manager"]
I use Phpstorm with symfony plugin - The plugin finds the service, but Symfony itself does not.
I get the following error message:
An exception has been thrown during the rendering of a template ("You have requested a non-existent service "portal.news".").
How I use the service:
{{ render(controller('xxBundle:Widget:renderNews', {'slice_length': 250})) }}
in the Controller xxBundle:Widget:renderNews: $articles = $this->get('portal.news')->getNewestArticles($count);
cache is cleared
I checked everything (wrong service configuration, bundle is loaded, syntax is ok, ...)
You probably forgot to set public: true to your service, because since 3.4 all Symfony services are private by Default.
Also, you should avoid $this->get() functions and prefer fetching directly your service from your controller arguments
<?php
use xxx\NewsBundle\Service\NewsService
class MyController {
public function myAction(NewsService $service) {}
}
Using Service that needs an argument, you need to declare your service as an alias https://symfony.com/doc/current/service_container.html#explicitly-configuring-services-and-arguments

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

Retrieve service from one bundle in another bundle extension

I have a bundle I am working on. In the extension for configurations, I am dependant on a service defined in a different bundle, but I get messages that the service is not defined. What can I do to call the services from the other bundle?
EDIT: Here is how I am trying to get the session service.
This is the bundle extension (simplified)
class BundleExtension
{
function load()
{
$this->container->get('bundle.service');
}
}
And here is the services.yml that I am using (again, simplified)
services:
bundle.service:
class: ServiceClass
arguments: [ #session ]
The error I am getting is:
InvalidArgumentException: The service definition "session" does not exist.

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