Defining Memcache as Symfony service produces unhelpful error - php

I'm trying to define Memcache as a service in Symfony 3.4 and it doesn't appear to want to work.
This has previously worked correctly with a Symfony 2 build which is where the configuration is taken from.
I've got the following code in my services.yml:
memcache:
class: \Memcache
arguments:
persistent_id: elearn
calls:
- [ addServer, [ %memcached_host%, %memcached_port% ]]
However when attempting to clear the Symfony cache I'm getting the following error:
In AbstractRecursivePass.php line 126:
Invalid service "memcache": class "\Memcache" has no constructor.
This would make sense to me if we were trying to pass some constructor arguments in the service definition, as, like it says Memcache has no constructor but clearly we aren't doing that.
Am I missing something obvious?

Removing the
arguments
Option allowed me to get past the error. Not yet certain if memcache is behaving as expected.

Related

Method setSQLLogger deprecated - Doctrine\DBAL\Configuration

I am in the process of upgrading an application from Symfony 5.4 to Symfony 6.0. Along the way, I had to upgrade some doctrine libraries.
We are currently using setSQLLogger(null) to avoid having SQL logging enabled. By using the newer version of Doctrine, I am getting a warning:
The Doctrine\DBAL\Configuration::setSQLLogger method is deprecated (Use {#see setMiddlewares()} and {#see \Doctrine\DBAL\Logging\Middleware} instead.).
I could not figure out how can I replace setSQLLogger(null) with setMiddlewares so I could disable the SQL logging.
Did anyone have this issue and managed to fix it?
Thanks.
I replaced this code:
$em->getConnection()->getConfiguration()->setSQLLogger(null);
With:
$em->getConnection()->getConfiguration()->setMiddlewares([new \Doctrine\DBAL\Logging\Middleware(new \Psr\Log\NullLogger())]);
This puts the NullLogger as the only middleware.
You should configure a middleware in order to accept the NullLogger, then use it along with setMiddlewares method.
So from symfony standpoint, you can do something like
# configuration.yaml // or whatever name you have
services:
doctrine.logging.middleware.null: // or whatever name you prefer
class: Doctrine\DBAL\Logging\Middleware
autowire: false
arguments:
- #FQCN or service id of NullLogger
Then you can inject it where you were using setLogger and replace that method call with setMiddlewares.
I didn't tried it myself, as we're running on older version, but I'm pretty confident this should resolve your issue.

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)

set service class from .env or ENV in system

I have symfony 4 setup
in services.yml I have the following configured service
MyCompany\Interfaces\QueueProducerInterface:
class: MyCompany\Service\KafkaProducer
arguments:
$queueConfig: '#queue_config'
I want to change the setting dynamically in my .envfile, so I can inject it later, depending on the env (dev, production)....so I tried something like this:
in .env
QUEUE_DRIVER="MyCompany\Service\KafkaProducer"
and now in services.yaml
MyCompany\Interfaces\QueueProducerInterface:
# class: MyCompany\Service\KafkaProducer
class: '.%env(QUEUE_DRIVER)%'
arguments:
$queueConfig: '#queue_config'
but when I run for instance composer update I get a container error
Script cache:clear returned with error code 1
!!
!! In Compiler.php line 112:
!!
!! Incompatible use of dynamic environment variables "QUEUE_DRIVER" found in p
!! arameters.
!!
!!
!! In AbstractRecursivePass.php line 123:
!!
!! Invalid service "MyCompany\Interfaces\QueueProducerInterface": class ".%env(
!! QUEUE_DRIVER)%" does not exist.
!!
!!
how do I solve this problem? or better said, how can I set the value of this class dynamically depending on ENV.
I solved it, by creating a services.yaml inside the folder config/packages/dev/ and also `config/packages/prod/' with different settings.
In newer versions of symfony you can do that in a single services.yaml using the when#xxx syntax and use an interface, like this:
For example:
parameters:
my.nice.service.class: Some\NameSpace\RealServiceClass
when#dev:
parameters:
my.nice.service.class: Some\DevelHelper\RealServiceClass
Some\NameSpace\WorkerInterface:
class: '%my.nice.service.class%'
In your consuming class just typehint the Some\NameSpace\WorkerInterface interface in the constructor and it will be injected properly.
Of course the interface Some\NameSpace\WorkerInterface must exist in the code and both RealServiceClass and RealServiceClass must implement the interface.

symfony2 CLI [Symfony\Component\Debug\Exception\ContextErrorException]

I'm having a problem whilst trying to create a command with Symfony2's Console component, in a full Symfony stack app.
If i try to pass my services in via DI, the command throws the following error when i try to run it:
[Symfony\Component\Debug\Exception\ContextErrorException]
Notice: Trying to get property of non-object
If I create the command with ContainerAwareCommand and try to get my service with
$this->getContainer()->get('mtgu.api.card.list.response.data');
I get
[LogicException]
The container cannot be retrieved as the application instance is not yet set.
My service is defiantly being loaded, as its used in a front end controller. This problem gets stranger, as if I pass a repository service - I don't get this problem!
Is there some trick to setting up a service to be passible by this? Or have I messed up my configuration somehow?
Im "autoloading" all my services by doing this in my DI Extension rather than including them all through the the main services.yml. I thought this or the ordering of the yml includes maybe effecting it - but I have tried manually including everything but still no joy!
$finder = new Finder();
$finder->name('services.yml');
/**
* #var $file SplFileInfo
*/
foreach($finder->in(__DIR__.'/../') as $file) {
$loader = new Loader\YamlFileLoader($container, new FileLocator($file->getPath()));
$loader->load('services.yml');
}
Vendor/Bundle/Command/services.yml
services:
mtgu.command.slugify:
class: MightyStudios\MtguBundle\Command\SlugifyCommand
tags:
- { name: console.command }
arguments:
- #mtgu.api.card.list.response.data
I think this maybe just some config issue, but Google has failed me to find the answer! Has anyone else run into this problem and can they shed any light!?
Many thanks
A better structure would be to put your services files in the Resources/config directory of your bundle (See also all core bundles). However, that's aside.
The problem is described by the exception: The container cannot be retrieved as the application instance is not yet set. Which is thrown in the ContainerAwareCommand#getContainer() method when $this->application is null. The application is set in the first line of the Application#add() method.
This means that you call $this->getContainer() before you add the command to the application. Maybe you use it in your constructor?
If so, remove it and only use the container in Command#execute(), Command#interact() or Command#initialize().

Symfony2 : no extension to load Buzz

I'm facing an issue while trying to use Curl in Buzz for Symfony2 (I've finally managed to install it, see this post).
I use it it one on my bundles, and I've updated services.yml, adding these :
# cURL client for Buzz
buzz.client.curl:
class: Buzz\Client\Curl
public: false
calls:
- [setVerifyPeer, [false]]
# Buzz browser
buzz.browser:
class: Buzz\Browser
arguments: ['#buzz.client.curl']
And when I go and check my project's page, here's the error I get :
InvalidArgumentException: There is no extension able to load the configuration for "buzz.client.curl" (in myBundle) Looked for namespace "buzz.client.curl", found none
So from what I understand, I have to change one of Buzz's namespace declarations somewhere.
But does anybody know what, and where?
Well, my mistake, I simply didn't use the right format for my yml file.
Here is the code of the services, in case anyone has the issue. Think of the 4 spaces, that saves a lot of time...
services:
cURL client for Buzz
buzz.client.curl:
class: Buzz\Client\Curl
public: false
calls:
- [setVerifyPeer, [false]]
Buzz browser
buzz.browser:
class: Buzz\Browser
arguments: ['#buzz.client.curl']

Categories