Named service in service.yml gives me autowire error - symfony

In symfony5 (it happened with me in symfony4 too, I just forgot the solution) I have strange behivor.
Here is the service.yml related part:
app.service.media.mediaresolve:
class: Vaso123\Service\Media\MediaResolve
arguments:
[
'%incomingPdf%',
'%processedPdf%',
'%workDir%',
]
If I am using like this, I am getting error:
Cannot autowire service "Vaso123\Service\Media\MediaResolve": argument
"$incomingPdf" of method "__construct()" is type-hinted "array", you
should configure its value explicitly.
Here comes the magic. If I remove the name and give exactly the class, it works:
Vaso123\Service\Media\MediaResolve:
arguments:
[
'%incomingPdf%',
'%processedPdf%',
'%workDir%',
]
Why is it happens? The name does not matter, it could be a.b, xxxxx, anything.

Related

Symfony serializer with GetSetMethodNormalizer returns an empty arrays instead of dates

I configured service for using GetSetMethodNormalizer
services:
Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer:
arguments: [ '#Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface', '#serializer.name_converter.camel_case_to_snake_case' ]
tags: [serializer.normalizer]
And when I call $serializer->serialize() I got an empty array as a value for serialized date variable.
Could you please advise how it can be fixed?
The problem was in the priority of normalizers. Here is a solution:
services:
Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer:
arguments: ['#Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface', '#serializer.name_converter.camel_case_to_snake_case']
tags:
- { name: 'serializer.normalizer', priority: -1100 }
The new priority will put this normalizer right after all standard ones and serialization will works as expected.

Symfony 3.4 - Autowire not working for bind values?

I am working on migrating an existing Symfony 2.8 project to Symfony 3.4 and would like to autowire / auto inject the value of the %kernel.environment% parameter into a controller action.
However binding the parameter to a argument name does not work:
// app/config/services.yml
services:
_defaults:
autowire: true
autoconfigure: true
public: false
bind:
$kernelEnvironment: '%kernel.environment%'
MyBundle\:
resource: '../../src/MyBundle/*'
exclude: '../../src/MyBundle/{Entity,Repository,Tests}'
MyBundle\Controller\:
resource: '../../src/MyBundle/Controller'
tags: ['controller.service_arguments']
// src/MyBundle/SomeController.php
public function showPostAction($kernelEnvironment, $post_id) {
...
}
Uncaught PHP Exception RuntimeException: "Controller "MyBundle\Controller\SomeController::showPostAction()" requires that you provide a value for the "$kernelEnvironment" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one."
Why does this not work?
I know that I could specify MyBundle\Controller\SomeController directly within in the services.yml and set the value of $kernelEnvironment in the arguments list. However this solution would mean that I would have to specify the argument for every controller that uses this parameter. This is is not what autorwire is good for. Binding the argument should work, shouldn't it?

Configuring LiipImagineBundle Symfony to work with Flysystem

I've been trying to configure a CDN (S3) to work with LiipImagineBundle, but keep getting stuck when it is asking for a non-existent service.
What does this mean?
The value of the filesystem_service property must be a service that returns an instance of League\Flysystem\Filesystem.
From here: http://symfony.com/doc/current/bundles/LiipImagineBundle/cache-resolver/flysystem.html
and here: http://symfony.com/doc/current/bundles/LiipImagineBundle/data-loader/flysystem.html
I have tried to create a service that returns an instance of League\Flysystem\Filesystem as follows:
league.flysystem.s3adaptor:
class: League\Flysystem\AwsS3v3\AwsS3Adapter
arguments: ['#acme.s3_client', '%amazon.s3.bucket%', 's3_fs', '#?']
league.flysystem.filesystem:
class: League\Flysystem\Filesystem
arguments: ['#league.flysystem.s3adaptor', '#?']
calls:
- [addPlugin, ['#oneup_flysystem.plugin.list_with']]
I'm not sure if this is along the right lines or not, but I can't get this working.
Any help or advice will be greatly appreciated.
I was on the right lines, I had just misconfigured my LiipImagineBundle slightly.
To return an instance of League\Flysystem\Filesystem you first need to create a service for the adaptor that you want to use, in this case league.flysystem.s3adaptor does this. Then pass that as an argument to league.flysystem.filesystem.
league.flysystem.s3adaptor:
class: League\Flysystem\AwsS3v3\AwsS3Adapter
arguments: ['#acme.s3_client', '%amazon.s3.bucket%']
league.flysystem.filesystem:
class: League\Flysystem\Filesystem
arguments: ['#league.flysystem.s3adaptor']
calls:
- [addPlugin, ['#oneup_flysystem.plugin.list_with']]
LiipImagineBundle config:
liip_imagine:
resolvers:
profile_photos:
flysystem:
filesystem_service: league.flysystem.filesystem
root_url: "https://s3.eu-west-2.amazonaws.com/nameofthebucket/"
cache_prefix: media/cache
visibility: public
loaders:
profile_photos:
flysystem:
filesystem_service: league.flysystem.filesystem
data_loader: profile_photos
cache: profile_photos

Create config collector for exposing config settings accross application

I'm looking for way of exposing config settings across application, where I can in any bundle add what I want. Purpose of this is to expose several things to HTML, parse it and use in JS.
Base part is ConfigService to which can be added ConfigUnit with own logic.
ConfigServiceInterface:
public function getConfig();
public function addUnit(ConfigUnitInterface $unit);
ConfigUnitInterface:
public function getName();
public function getConfig();
best would be to add units in service.yml like this:
services:
service.config:
class: ConfigService
calls:
- [ addUnit, [ "#unit" ] ]
- [ addUnit, [ "#unit2" ] ]
but config service should be declared in some bundle and developer can't change it's declaration.
second thing which comes to my mind was declare units with calling register method which would get ConfigService as parameter.
config_unit:
class: ConfigUnit
arguments: [...]
calls:
- [ register, [ "#service.config" ] ]
but this isn't nice and I must get this service to init calls, so I must get it from container each time.
Is there way to do this automatically? And separate as possible?
Maybe event would be nice for this, but I don't want to allow developer to modify config array directly.
Well I found out how to do it.
documentation helps:
tags, compiler pass
Each my unit has now tag: 'config.unit'
config_unit:
class: ConfigUnit
arguments: [...]
tags:
- { name: config.unit }
these are processed by CompilerPass and injected to ConfigService

Symfony service container injecting string not object

I'm trying to inject an object into one of my services, as well as another service. The second argument is just an object, however when declaring it in the services.yml file, I receive an exception staying that its expecting an object, but a string was given.
services.yml
parameters:
app.my_class.class: AppBundle\MyClass
app.object_to_inject.class: AppBundle\InjectObject
services:
app.my_service:
class: %app.my_class.class%
arguments: [#app.another_service, %app.object_to_inject.class%]
Which results in:
Catchable Fatal Error: Argument 2 passed to
AppBundle\MyClass::__construct() must be an instance
of AppBundle\InjectObject, string given
I've tried quoting, unquoting and using new lines instead of square brackets:
arguments
- #app.another_service
- %app.object_to_inject.class%
Parameters are just strings, so you you trying to inject the string of your class name, not the actual class.
You need to define AppBundle\InjectObject as a service, then inject that.
Example:
parameters:
app.my_class.class: AppBundle\MyClass
app.object_to_inject.class: AppBundle\InjectObject
services:
app.my_object:
class: "%app.object_to_inject.class%"
app.my_service:
class: %app.my_class.class%
arguments: [#app.another_service, #app.my_object]

Resources