I'm trying to create a service, which can be injected anywhere. For this I am trying to pass as argument the HttpClient component of Symfony 4.3
I show you the service
https://i.stack.imgur.com/2384M.png
<?php
namespace App\Service\Callback;
use Symfony\Component\HttpClient\HttpClient;
class Back
{
private $client;
public function __construct(HttpClient $httpClient)
{
$this->client = $httpClient::create();
}
public function sendCallback ( $method, $urlCallback, $option)
{
$response = $this->client->request($method,$urlCallback,$option);
$statusCode = $response->getStatusCode();
return $statusCode;
}
}
Well, I'm trying to load it in the services.yml
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: 'en'
base_url_front: '%env(BASE_URL_FRONT)%'
mobile_type: 2
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
Nexy\Slack\Client: '#nexy_slack.client'
Symfony\Component\HttpClient\HttpClient: '#http.client'
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
App\Service\Models\:
resource: '../src/Service/Models'
tags: ['#doctrine.orm.entity_manager','#nexy_slack.client']
slack_client:
class: 'App\Service\SlackClient'
autowire : true
arguments: ['#nexy_slack.client','#kernel']
public : true
callback_client:
class: 'App\Service\Callback\Back'
autowire: true
arguments: ['#http.client']
public: true
App\Service\Apiclient\AteneaService:
arguments: ["%kernel.environment%"]
App\Service\Apiclient\UpmService:
arguments: ["%kernel.environment%"]
App\Service\Apiclient\HermesService:
arguments: ["%kernel.environment%"]
App\Service\Socket\:
resource: '../src/Service/Socket'
tags: ['#kernel','#nexy_slack.client']
The problem is that if I run php bin / console debug: autowiring in the terminal, to know if I created it, it returns the following error :
You have requested a non-existent service "http.client".
In the end what I want to achieve is something like this:
public function getClient(Back $back)
{
$back->sendCallback('GET','http://vro-back.localhost:8888/callback/test');
}
But I can not because I can not inject it.
At the end if you look at the services.yml, I'm trying to create an alias for an HttpClient component, so I can pass it as an argument to the constructor of the Back class
And the route that I'm trying to load, exists ...
Symfony \ Component \ HttpClient \ HttpClient;
This is the component with which I am trying to work
https://symfony.com/doc/current/components/http_client.html
I would appreciate any help.
You need to type-hint the interface instead
public function __construct(HttpClientInterface $httpClient)
{
$this->httpClient = $httpClient;
}
And remove service.yaml configuration
https://symfony.com/doc/current/components/http_client.html
Related
Here is a method signature in the controller :
public function myAction(Request $request, SessionInterface $session, LoggerInterface $logger)
This is what I wrote in services.yml :
AppBundle\Controller\:
resource: '../../Controller'
public: true
tags: ['controller.service_arguments']
Normally, all of the parameters (request, session and logger) are automatically injected.
I call this action of the controller using Ajax but there is a problem for logger (request and session are well injected):
Controller myAction requires that you provide a value for the "$logger" argument
This happens for one method only because the ajax calls to some other methods of the controller work perfectly.
The only difference I can see using some debug tools is that the one that does not work has connection : close though the others have connection: keep-alive.
I dont see why it is done differently.
When I erase the LoggerInterface parameter, it works good and connection is keep-alive like the others.
Can you help ?
Symfony 3 platform
services:
_defaults:
# automatically injects dependencies in your services
autowire: true
# automatically registers your services as commands, event subscribers, etc.
autoconfigure: true
# this means you cannot fetch services directly from the container via $container->get()
# if you need to do this, you can override this setting on individual services
public: false
I am trying to make a link that resends a confirmation token to a user after registering in Symfony3.
However, I get a deprecation message as follows:
User Deprecated: The "fos_user.mailer" service is private, getting it
from the container is deprecated since Symfony 3.2 and will fail in
4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.
Here is my controller:
public function resendActivationEmail($token, UserManagerInterface $userManager)
{
$user = $userManager->findUserByConfirmationToken($token);
if (is_null($user)) {return $this->redirectToRoute('fos_user_registration_register');}
$mailer = $this->get('fos_user.mailer');
$mailer->sendConfirmationEmailMessage($user);
return $this->redirectToRoute('fos_user_registration_check_email');
}
My services.yml:
services:
# default configuration for services in *this* file
_defaults:
autowire: truesubscribers, etc.
autoconfigure: true
public: false
I looked into the docs, it says that in Symfony3.4, services are private by default. I am using autowiring in my app, so how I get the fos_user.mailer without any deprecation warnings?
I tried setting Fosuserbundle services to public, doesnt help:
services.yml:
....
FOS\UserBundle:
public: true
Any help appreciated!
It's better to use DependencyInjection instead of call container directly. You should pass your mailer to your method:
public function resendActivationEmail($token, UserManagerInterface $userManager, \FOS\UserBundle\Mailer\MailerInterface $mailer)
{
$user = $userManager->findUserByConfirmationToken($token);
if (is_null($user)) {return $this->redirectToRoute('fos_user_registration_register');}
$mailer->sendConfirmationEmailMessage($user);
return $this->redirectToRoute('fos_user_registration_check_email');
}
For more informations about dependencyInjection : https://symfony.com/doc/3.4/service_container/injection_types.html
Use $mailer = $this->container->get('fos_user.mailer');
instead of $mailer = $this->get('fos_user.mailer');
I'm trying to configure a service inside a bundle. This service needs some parameters from the.env file but I can't declare these parameters in the service. Here's my code:
src/Dfc2/WsBundle/Services/WsManager/WsManager.yaml
parameters:
wsAdminUser: '%env(WSADMIN_USER)%'
wsAdminPassword: '%env(WSADMIN_PASSWORD)%'
services:
_defaults:
autowire: true
autoconfigure: true
public: false
WsManager:
public: true
class: App\Dfc2\WsBundle\Services\WsManager\WsManager
arguments:
$env: '%kernel.environment%'
$wsAdminUser: '%wsAdminUser%'
$wsAdminPassword: '%wsAdminPassword%'
src/Dfc2/WsBundle/Services/WsManager/WsManager.php constructor:
public function __construct($env, RequestStack $requestStack, SessionInterface $session, string $wsAdminUser, string $wsAdminPassword)
{
$this->environement = $env;
$this->wsAdminUser = $wsAdminUser;
$this->wsAdminPassword = $wsAdminPassword;
$this->session = $session;
$this->baseUrl = $requestStack->getCurrentRequest()->getBaseUrl() . WsParameters::URL_SUFFIX;
$this->setBaseUrl();
}
And this is the error message I get.
Cannot autowire service "App\Dfc2\WsBundle\Services\WsManager\WsManager": argument "$wsAdminUser" of method "__construct()" must have a type-hint or be given a value explicitly.
I don't understand what's wrong. Can you help me?
Thanks to Mathieu Dormeval and Cerad,
I changed my service definition like this and now it works:
services:
App\Dfc2\WsBundle\Services\WsManager\WsManager:
autowire: false
public: true
arguments:
$env: '%kernel.environment%'
$requestStack: '#request_stack'
$session: '#session'
$wsAdminUser: '%wsAdminUser%'
$wsAdminPassword: '%wsAdminPassword%'
Please help me with config Console App, in first - config
#!/usr/bin/env php
<?php
use ....
...
$container = new ContainerBuilder();
$config = new YamlFileLoader($container, new FileLocator(__DIR__));
$config->load('config.yml');
$output = $container->get('symfony.console_output');$logger = $container->get('logger');
//I want automatic injection!!!!
$helloCommand = new HelloCommand($container, $logger);
$application = $container->get('symfony.application');
$application->add($helloCommand);
$application->run(null, $output);
And my config.yml
services:
logger:
class: Symfony\Component\Console\Logger\ConsoleLogger
arguments:
- '#symfony.console_output'
symfony.application:
class: Symfony\Component\Console\Application
calls:
//by this variant autowire not working
- [add, [ '#app.command.hello_command' ]]
- [setDispatcher, ['#symfony.event_dispatcher']]
...
app.command.hello_command:
class: App\Command\HelloCommand
autowire: true
tags:
- { name: console.command }
So my HelloCommand has constructor with ContainerInterface and LoggerInterface and it work only if i set this arguments directly, other i have error about wrong constructor
Or may be exists another way for configuration with config.yml
for only logger - its will be simple by set ['#logger'] as arguments, but how can i set current container as argument?
Or i`ll have to install full symfony with httpkernel (but it does not need)
HelloCommand
http://pastebin.com/VRr3FM7Q
THE DECISION
app.command.hello_command:
class: App\Command\HelloCommand
arguments:
- '#service_container'
- '#logger'
tags:
- { name: console.command }
The problem lies in how you configure your command:
app.command.hello_command:
class: App\Command\HelloCommand
autowire: true
tags:
- { name: console.command }
This misses the 2 constructor arguments required: $container, $logger and is probably why you get the exception. You can add constructor arguments like this:
app.command.hello_command:
class: App\Command\HelloCommand
arguments:
- '#service_container'
- '#logger'
[...]
I'm not sure if the id for the service_container is right. I never pass the container or make things ContainerAware, but you get the general idea. ;)
I am trying to configure a KnpGaufretteBundle to use Google Cloud Storage for storing my files. This is the config:
## definition of the GCS service
app.google_cloud_storage.service:
class: \Google_Service_Storage
factory_class: Knp\Bundle\GaufretteBundle\DependencyInjection\Factory\GoogleCloudStorageAdapterFactory
factory_method: 'create'
arguments:
- "123#developer.gserviceaccount.com"
- "http://localhost/file.p12"
- "pwd"
## config of knp_gaufrette
knp_gaufrette:
stream_wrapper: ~
adapters:
gcs_minn_images:
google_cloud_storage:
service_id: 'app.google_cloud_storage.service'
bucket_name: 'minn-images'
filesystems:
gcs_minn_images_fs:
adapter: gcs_minn_images
The error message I got is:
ContextErrorException in GoogleCloudStorageAdapterFactory.php line 16:
Catchable Fatal Error: Argument 1 passed to Knp\Bundle\GaufretteBundle\DependencyInjection\Factory\GoogleCloudStorageAdapterFactory::create() must be an instance of Symfony\Component\DependencyInjection\ContainerBuilder, string given, called in /home/amine/NetBeansProjects/tuto/app/cache/dev/appDevDebugProjectContainer.php on line 724 and defined
According to the error message, I gave a string of stead of ContainerBuilder. Great! Let's add the ContainerBuilder to the arguments as follows:
## definition of the GCS service
app.google_cloud_storage.service:
class: \Google_Service_Storage
factory_class: Knp\Bundle\GaufretteBundle\DependencyInjection\Factory\GoogleCloudStorageAdapterFactory
factory_method: 'create'
arguments:
- #service_container
- "123#developer.gserviceaccount.com"
- "http://localhost/file.p12"
- "pwd"
The result is again an error:
Catchable Fatal Error: Argument 1 passed to Knp\Bundle\GaufretteBundle\DependencyInjection\Factory\GoogleCloudStorageAdapterFactory::create() must be an instance of Symfony\Component\DependencyInjection\ContainerBuilder, instance of appDevDebugProjectContainer given, called in /home/amine/NetBeansProjects/tuto/app/cache/dev/appDevDebugProjectContainer.php on line 724 and defined
So now, the error is telling me that I provide an instance of appDevDebugProjectContainer in stead of ContainerBuilder!!
Ok, let's have a look to /home/amine/NetBeansProjects/tuto/app/cache/dev/appDevDebugProjectContainer.php on line 724...
class appDevDebugProjectContainer extends Container{
// ...
/**
* Gets the 'app.google_cloud_storage.service' service.
*
* This service is shared.
* This method always returns the same instance of the service.
*
* #return \Google_Service_Storage A Google_Service_Storage instance.
*/
protected function getApp_GoogleCloudStorage_ServiceService()
{
return $this->services['app.google_cloud_storage.service'] =\Knp\Bundle\GaufretteBundle\DependencyInjection\Factory\GoogleCloudStorageAdapterFactory::create($this, '123#developer.gserviceaccount.com', 'http://localhost/file.p12', 'pwd');
}
I am really lost...
So, is there any complete example to config google cloud storage?
I finally found the solution. You have to create your own factory class as described in the documentation of the bundle:
Factory class
<?php
namespace Minn\AdsBundle\Factory;
/**
* Description of GoogleCloudStorageServiceFactory
*/
class GoogleCloudStorageServiceFactory {
public function createService() {
// creating the google client
$client = new \Google_Client();
// setting the service acount credentials
$serviceAccountName = '123#developer.gserviceaccount.com';
$scopes = array(
'https://www.googleapis.com/auth/devstorage.read_write',
);
$privateKey = file_get_contents('http://localhost/f.p12');
$privateKeyPassword = 'pwd';
$credential = new \Google_Auth_AssertionCredentials(
$serviceAccountName, $scopes, $privateKey, $privateKeyPassword);
// set assertion credentials
$client->setAssertionCredentials($credential);
// creating and returning the service
return new \Google_Service_Storage($client);
}
}
The config.yml file
app.google_cloud_storage.service:
class: \Google_Service_Storage
factory: [Minn\AdsBundle\Factory\GoogleCloudStorageServiceFactory, createService]
knp_gaufrette:
stream_wrapper: ~
adapters:
gcs_images:
google_cloud_storage:
service_id: 'app.google_cloud_storage.service'
bucket_name: 'images'
filesystems:
gcs_images_fs:
adapter: gcs_images
vich_uploader:
db_driver: orm
storage: gaufrette
mappings:
motors_files:
upload_destination: gcs_images_fs
namer: vich_uploader.namer_origname
delete_on_remove: true
That's was it...
Hope it will help others...