How to setup console application with autowire commands? - symfony

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

Related

PHPUnit WebTestCase using native session when mock session is configured, Symfony 5

I am getting the "Failed to start the session because headers have already been sent" error when running the sample smoke test url example from Symfony, https://symfony.com/doc/5.3/best_practices.html#smoke-test-your-urls
<?php
namespace App\Tests;
use Generator;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class ApplicationAvailabilityFunctionalTest extends WebTestCase
{
/**
* #dataProvider urlProvider
*/
public function testPageIsSuccessful($url)
{
$client = self::createClient();
$client->request('GET', $url);
$this->assertResponseIsSuccessful();
}
public function urlProvider(): Generator
{
yield ['/'];
}
}
I have configured mock sessions in my config/packages/framework.yaml file. There are no other overrides in the config/packages/test folder.
when#test:
framework:
test: true
session:
storage_factory_id: session.storage.factory.mock_file
The phpunit.xml.dist file has the appropriate environment specified for the "test" environment.
<server name="APP_ENV" value="test" force="true" />
It makes no difference whether I execute the test form within PHPStorm or from console via php bin/phpunit. I must be missing something with the configuration. Any ideas?
Here is a stack trace leading to the native session:
Answered my own question, but #dbrumann had me heading in the right direction with the event listener hint. Thanks
I added to services.yaml, the event listeners only for non-test environments.
when#dev:
services:
Symfony\Component\HttpKernel\Profiler\Profiler: '#profiler'
App\EventListener\RequestListener:
tags:
- { name: kernel.event_listener, event: kernel.request }
App\EventListener\ResponseListener:
tags:
- { name: kernel.event_listener, event: kernel.response }
when#prod:
services:
App\EventListener\RequestListener:
tags:
- { name: kernel.event_listener, event: kernel.request }
App\EventListener\ResponseListener:
tags:
- { name: kernel.event_listener, event: kernel.response }

Problem when loading Service by injection

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

Define services parameters inside a sf4 bundle

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%'

Example on how to config google cloud storage with KnpGaufetteBundle

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

Create a log system in symfony2

I want to create a system of logs in symfony2 and I have a question, so I have in service.yml :
services:
my_logger:
class: Monolog\Logger
arguments: [Debug]
calls:
- [pushHandler, [#my_log_handler]]
my_log_handler:
class: Monolog\Handler\StreamHandler
arguments: [/home/vagrant/Workspace/symfony/app/logs/test.log, 100]
I have a class in Utils/Logs like this :
class Logs {
public static function logInfo($a_log) {
$sc = new ContainerBuilder();
$logguer = $sc->get('my_logger');
$logguer->info($a_log);
}
}
And my controller :
$categories = array();
Logs::logInfo(print_r($categories));
The question is how to modify Utilis/Logs class to be possible to call logInfo method? Help me please...Thx in advance...It's possible to create this?

Resources