Symfony 4 argument has no type-hint, you should configure its value explicitly - service

Symfony 4.2.3
Recently upgraded from version 3.4 to 4.2.3 and got my project working, but
when setting autoconfigure in services.yaml to true, I will receive this error message:
Cannot autowire service "App\EventListener\RedirectToLocaleActiveListener": argument "$localeActive" of method "__construct()" has no type-hint, you should configure its value explicitly.
My services.yaml
parameters:
locale: de
locale_active: de
app_locales: de|en
uploads_directory_name: uploads
uploads_profile_directory_name: profiles
uploads_directory: '%kernel.root_dir%/../public/%uploads_directory_name%'
profile_directory: '%kernel.root_dir%/../public/%uploads_directory_name%/%uploads_profile_directory_name%'
google_recaptcha_site_key: '%env(GOOGLE_RECAPTCHA_SITE_KEY)%'
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
App\Controller\:
resource: ../src/Controller
tags:
- controller.service_arguments
locales:
class: App\Util\Locales
arguments:
- '%locale_active%'
- '%app_locales%'
- '#session'
app.locale:
class: App\EventListener\LocaleListener
tags:
- {name: kernel.event_subscriber}
app.redirect_to_locale_active:
class: App\EventListener\RedirectToLocaleActiveListener
arguments:
- '#router'
- '%locale_active%'
tags:
- {name: kernel.event_subscriber}
My RedirectToLocaleActiveListener.php
<?php
namespace App\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* Class RedirectToLocaleActiveListener
* When a user enters to the homepage without the parameter locale,
* the subscriber redirects the user to the main locale.
*
* #package App\EventListener
*/
class RedirectToLocaleActiveListener implements EventSubscriberInterface
{
/**
* #var UrlGeneratorInterface
*/
private $urlGenerator;
/**
* #var string
*/
private $localeActive;
/**
* #param UrlGeneratorInterface $urlGenerator
* #param $localeActive
*/
public function __construct(UrlGeneratorInterface $urlGenerator, $localeActive)
{
$this->urlGenerator = $urlGenerator;
$this->localeActive = $localeActive;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => 'onKernelRequest',
];
}
/**
* #param GetResponseEvent $event
*/
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if ('/' == $request->getPathInfo()) {
$route = $this->urlGenerator->generate('app_index', ['_locale' => $this->localeActive]);
$response = new RedirectResponse($route);
$event->setResponse($response);
}
}
}
What I've tried:
adding 'string' to $localActive in __construct of RedirectToLocaleActiveListener
Result:
Cannot autowire service "App\EventListener\RedirectToLocaleActiveListener": argument "$localeActive" of method "__construct()" is type-hinted "string", you should configure its value explicitly.

arguments of scalar type cannot be auto-wired. You need to wire them manually.
You can try wiring the argument explicitly in the service definition:
App\EventListener\RedirectToLocaleActiveListener
arguments:
$urlGenerator: '#router'
$localeActive: '%locale_active%'
tags:
- {name: kernel.event_subscriber}
Documentation:
https://symfony.com/doc/current/service_container.html#manually-wiring-arguments
Or you can make use of the local service binding feature to bind a parameter to a scalar argument:
services:
_defaults:
bind:
$localeActive: '%locale_active%'
Documentation:
https://symfony.com/blog/new-in-symfony-3-4-local-service-binding

If your service name is not equal to fqcn, such as:
app.ext.telegram_bot_api:
class: 'App\Ext\TelegramBot\Bot'
and somewhere your using automatic services resolution like this:
# 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/{Entity,Document,Migrations,Tests,Kernel.php}'
your should create alias between your service name and fqcn like that:
'App\Ext\TelegramBot\Bot': '#app.ext.telegram_bot_api'
so your automatic services resolution should know about your service extra configuration.

Related

symfony6 $this->container->get('app.our.useful.thing')

I am sorry, I read the docs, but I don't get symfony6 anymore.
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.
# 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/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/EventListener
app.our.useful.thing:
class: App\OurUsefulThing
public: true
My src/OurUsefulThing.php:
<?php
namespace App;
class OurUsefulThing
{
public function sayHello()
{
return "Hello Service";
}
}
In the controller:
public function someActionName(Request $request)() {
$value = $this->container->get('app.our.useful.thing')->sayHello();
}
Error Message
Service "app.our.useful.thing" not found: even though it exists in the app's container, the container inside "App\Controller\CategoriesController" is a smaller service locator that only knows about the "form.factory", "http_kernel", "parameter_bag", "request_stack", "router", "security.authorization_checker", "security.csrf.token_manager", "security.token_storage", "serializer" and "twig" services. Try using dependency injection instead.
It was in symfony4 so easy. What I am doing wrong?

symfony 3.4 : forms : Use Data Transformers

trying to use data transformer, I have an error when loadding my html form
In my formType class
use Doctrine\ORM\EntityManagerInterface;
class PmpType extends AbstractType
{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
}
in my app\config\services.yml
services:
# default configuration for services in *this* file
_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: true
but I received this error
Type error: Too few arguments to function myApp\Bundle\Form\PmpType::__construct(), 0 passed in \vendor\symfony\symfony\src\Symfony\Component\Form\FormRegistry.php on line 92 and exactly 1 expected
What do I miss
Thx for hepl
OK
I don't understand why but I have toset the service for my class :
in service.yml, I add
seims_pmp.pmptype:
class: SEISM\PmpIG56Bundle\Form\PmpType
arguments: ["#doctrine.orm.entity_manager"]
tags: [form.type]
and now it's working

How to configure Monolog to store logs into MongoDB with Symfony2 and Doctrine

Would it be possible to get a full example of how is it possible to configure Monolog to store its logs into MongoDB using Symfony 2.6 and Doctrine 2?
Full configuration
/app/parameters.yml
mongodb_server: "mongodb://localhost:27017"
mongodb_username: "vagrant"
mongodb_password: "password"
mongodb_database: "testdb"
/app/config.yml
# Doctrine2 MongoDB Bundle
# http://symfony.com/doc/current/bundles/DoctrineMongoDBBundle/index.html
doctrine_mongodb:
default_database: %mongodb_database%
connections:
default:
server: %mongodb_server%
options:
password: %mongodb_password%
username: %mongodb_username%
db: %mongodb_database%
connect: true
log:
server: %mongodb_server%
options:
password: %mongodb_password%
username: %mongodb_username%
db: %mongodb_database%
connect: true
document_managers:
default:
auto_mapping: true
log:
auto_mapping: false
logging: false
/app/services.yml
mongolog:
class: Doctrine\MongoDB\Connection
factory_service: doctrine_mongodb.odm.log_connection
factory_method: getMongoClient
/app/config_dev.yml
In this example I decided to store everything (debug level) as always into the dev.log and just errors, warnings and notices on mongo.
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
console:
type: console
bubble: false
verbosity_levels:
VERBOSITY_VERBOSE: INFO
VERBOSITY_VERY_VERBOSE: DEBUG
channels: ["!doctrine"]
console_very_verbose:
type: console
bubble: false
verbosity_levels:
VERBOSITY_VERBOSE: NOTICE
VERBOSITY_VERY_VERBOSE: NOTICE
VERBOSITY_DEBUG: DEBUG
channels: ["doctrine"]
mongo:
type: mongo
level: notice # change as desired
mongo:
id: mongolog
database: %mongodb_database%
collection: logs
/app/config_prod.yml
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: mongo
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
console:
type: console
mongo:
type: mongo
level: notice
mongo:
id: mongolog
database: %mongodb_database%
collection: logs
Now let's trigger a PHP notice and check if it'll be stored on MongoDB properly :-)
<?php trigger_error('hello world!', E_USER_NOTICE);
Adding HTTP request headers to Monolog record
/app/services.yml
kernel.listener.exception_listener:
class: AppBundle\EventListener\ExceptionListener
arguments:
- #logger
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
AppBundle\EventListener\ExceptionListener
<?php
namespace AppBundle\EventListener;
use Monolog\Handler\MongoDBHandler;
use Symfony\Bridge\Monolog\Logger;
use Symfony\Component\Debug\ExceptionHandler;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
/**
* Class ExceptionListener
* #package AppBundle\EventListener
* #author Francesco Casula <fra.casula#gmail.com>
*/
class ExceptionListener extends ExceptionHandler
{
/**
* #var Logger
*/
private $logger;
/**
* #param Logger $logger
*/
public function __construct(Logger $logger)
{
$this->logger = $logger;
}
/**
* #return Logger
*/
public function getLogger()
{
return $this->logger;
}
/**
* #param GetResponseForExceptionEvent $event
*/
public function onKernelException(GetResponseForExceptionEvent $event)
{
foreach ($this->getLogger()->getHandlers() as $handler) {
if ($handler instanceof MongoDBHandler) {
$handler->pushProcessor(function (array $record) use ($event) {
$record['extra']['headers'] = $event->getRequest()->headers->all();
return $record;
});
break;
}
}
}
}

Symfony "Could not load type" service yaml

I tried to create a service in Symfony 2.2 for one of my form :
service.yml:
tyg_user.settings.form:
class: Symfony\Component\Form\Form
factory_method: createNamed
factory_service: form.factory
arguments:
- tyg_user_settings
- tyg_user_settings_name
tyg_user.settings.form.type:
class: TyG\UserBundle\Form\Settings\SettingsFormType
tags:
- { name: form.type, alias: tyg_user_settings }
tyg_user.settings.form.handler:
class: TyG\UserBundle\Form\Settings\SettingsFormHandler
scope: request
arguments:
- #tyg_user.settings.form
- #request
- #fos_user.user_manager
SettingsForm.php
<?php
namespace TyG\UserBundle\Form\Settings;
use Symfony\Component\Form\FormBuilderInterface as FormBuilder;;
use Symfony\Component\Form\AbstractType;
class SettingsForm extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('birthday', 'birthday')
->add('email', 'email')
->add('showmail')
->add('showbirthday')
;
}
public function getName()
{
return 'tyg_user_settings';
}
}
?>
But an error occuered :
Could not load type "tyg_user_settings_name
This occurs when I get my form through the service container :
$this->container->get('tyg_user.settings.form');
I used to do create my service through the xml format but when I change to the yml format I can't figure out how to to make it works
The tyg_user_settings_name is referencing a form type alias.
If you are wanting it to reference a parameter you should use %tyg_user_settings_name% instead.

Locale in Routing, Default Language also without Parameter

I want to define the page language via url on a Symfony2 installation. My routing works via annotation inside the controller.
routing.yml
_index:
resource: "#MyMainBundle/Controller/SiteController.php"
type: annotation
siteController.php
/**
* #Route( "/{_locale}/{site}", name="_site_site", defaults={"_locale" = "en"}, requirements={"site" = "about|cities|download|blog", "_locale" = "en|de|fr|es"} )
*/
This works quiet well, but waht I want, is that the following url call the same action.
http://example.com/download
http://example.com/en/download
http://example.com/de/download
Without the languge-parameter, the page should switch back to the default language, but this is something I can handle inside my action.
I found this Answer, but could not get it to work at all.
Symfony2 default locale in routing
Just add another #Route annotation that does not include the locale.
/**
* #Route("/{_locale}/{site}/")
* #Route("/{site}/")
*/
This also works within annotations.yaml
frontend_controllers:
resource: ../../src/Controller/Frontend
type: annotation
prefix:
- /
- /{_locale}
defaults:
_locale: 'en'
Another simular solution for Symfony 5 that worked for me :
# config/routes/annotations.yaml
controllers:
resource: '../../src/Controller/'
type: annotation
prefix:
fr: ''
en: '/en'
Symfony documentation : https://symfony.com/doc/current/routing.html#localized-routes-i18n
Also if you have an api prefix you can use next config
controllers:
resource: ../../src/Controller/
type: annotation
prefix:
- api
- api/{_locale}
defaults:
_locale: en