Symfony Dependency injection to class - symfony

I have a class in App\Util which needs the MailerInterface Dependency. So I added it directly to the constructor like this:
public function __construct(MailerInterface $mailer)
{
$this->mailer = $mailer;
}
Then I added the argument in the services.yaml:
services:
...
App\Util\OwnerMailValidation:
arguments: ['#mailer']
In the end I used exactly the same code as provided by the symfony documentation but I keep getting the error:
Too few arguments to function App\Util\OwnerMailValidation::__construct(), 0 passed [...] 1 expected
My complete servicey.yaml:
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
App\Controller\:
resource: '../src/Controller/'
tags: ['controller.service_arguments']
App\Util\OwnerMailValidation:
class: App\Util\OwnerMailValidation
arguments: ['#mailer']

If you have a single implementation of MailerInterface you shouldn't write anything in your service.yaml
Symfony can figure it out on his own.
If it still doesn't work try to do this
App\Util\OwnerMailValidation:
arguments:
$mailer: '#<the class that implements MailerInteface that you want to inject>'
As #cerad said autowiring works if you inject your class into another.
If you're doing $validation = new OwnerMailValidation(); it just won't work because it requires a MailerInterface in the constructor.
You should inject your OwnerMailValidation into the controller method or into the class constructor.

Try this config:
services:
...
App\Util\OwnerMailValidation:
class: App\Util\OwnerMailValidation

Related

FullCalendarBundle handle event error in symfony 3.4

I installed fullcalendarbundle, and I configured it as it is mentioned on the Github
https://github.com/tattali/CalendarBundle/blob/master/src/Resources/doc/doctrine-crud.md#3-create-the-crud, I can display the calendar. But when I try to create calendar event. I have error
The "AppBundle\Repository\CalendarEventsRepository" entity repository implements "Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepositoryInterface", but its service could not be found. Make sure the service exists and is tagged with "doctrine.repository_service".
Here is my repository
<?php
namespace AppBundle\Repository;
use AppBundle\Entity\CalendarEvents;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;
class CalendarEventsRepository extends ServiceEntityRepository
{
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, CalendarEvents::class);
}
}
My services.yml configured like this.
parameters:
services:
#default configuration for services in *this* file
_defaults:
autowire: true
autoconfigure: true
public: false
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{Entity,Repository,Tests}'
AppBundle\Controller\:
resource: '../../src/AppBundle/Controller'
public: true
tags: ['controller.service_arguments']
# AppBundle\Service\ExampleService:
# arguments:
# $someArgument: 'some_value'
# AppBundle\Twig\PlanningExtension:
# tags: ['twig.extension']
# adding the required tag to all repository services
#AppBundle\Repository\CalendarEventsRepository:
# arguments:
# - '#doctrine.orm.entity_manager'
# - '#=service("doctrine.orm.entity_manager").getClassMetadata("AppBundle\\Entity\\CalendarEvents")'
# tags:
# - { name: doctrine.repository_service }
I'm on symfony 3.4. I looked for several solutions without success, if you have a solution. I will be glad you help me.
If you want to autowire repositories, modify the exclude setting:
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{Entity,Repository,Tests}'
...defines: autowire everything in src/AppBundle, except those classes in the subfolders Entity, Repository, and Tests. By removing Repository from that list, you allow autowiring for your repositories

Symfony 4.3 - Cannot autowire service argument that references class "Symfony\Component\Security\Core\Security"

I'm using Symfony 4.3.
I have a problem with autowiring service argument in controller method.
It seems like Security class cannot be found.
I installed Security component by composer require symfony/security
This is row from "composer show":
symfony/security v4.3.4 Symfony Security Component
Composer.json:
"symfony/security": "4.3.*",
Services.yaml:
parameters:
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']
HomeController.php:
use App\Service\DB\DBALProvider;
class HomeController extends AbstractController
{
/**
* #Route("/", name="index")
*/
public function index(DBALProvider $DBALProvider)
{
DBALProvider.php:
use Symfony\Component\Security\Core\Security;
use Doctrine\ORM\EntityManagerInterface;
class DBALProvider
{
private $entityManager;
private $context;
private $user;
public function __construct(EntityManagerInterface $entityManager, Security $security)
{
Error that displays when I enter "/" route
Cannot resolve argument $DBALProvider of "App\Controller\HomeController::index()": Cannot autowire service "App\Service\DB\DBALProvider": argument "$security" of method "__construct()" references class "Symfony\Component\Security\Core\Security" but no such service exists.
Thanks for any suggestions.
composer require symfony/security-bundle
is the solution (thanks to Cerad).
https://symfony.com/doc/current/security.html
Well I though that composer require symfony/security install all necessary bundles.

Symfony Argument n passed to *** must be an instance of Swift_Mailer, null giveno

I'm struggling with Symfony 3.4 and autowiring.
He here an exemple of the error message :
Argument 2 passed to App\Controller\MainController::contact() must be an instance of Swift_Mailer, null given
It's the same message with every Service I pass as argument.
There is probably something missing in the configuration but I can't figure out what...
Any clue ?
// config/services.yaml
parameters:
google_recaptcha_site_key: '%env(GOOGLE_RECAPTCHA_SITE_KEY)%'
services:
_defaults:
autowire: true
autoconfigure: true
public: false
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
App\Controller\:
resource: '../src/Controller'
public: true
tags: ['controller.service_arguments']
// src/Controller/MainController.php
namespace App\Controller;
use Exception;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Validator\Validation;
class MainController extends AbstractController
{
public function contact(
Request $request,
\Swift_Mailer $mailer,
Validation $validation,
) { ... }
}
I did manage to solve my problem.
I had Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle enabled, and it seems that we can't have sensio/framework-extra-bundle and symfony/flex (or maybe with additionnal configuration).

Symfony autowiring Event Listener

Symfony 4.2.2
To cache all responses in one controller, I'm using an event listener for the kernel.controller event. My Event listener needs a couple of services and info:
EnityManagerInterface
the controller being cached
kernel cache folder
I have set this up like this:
namespace App\Listener;
use App\Controller\DataOutputController;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
class CachedOutput{
protected $cacheFolder;
protected $em;
protected $controller;
public function __construct($cacheFolder, EntityManagerInterface $em, DataOutputController $controller )
{
$this->cacheFolder = $cacheFolder;
$this->em = $em;
$this->controller = $controller;
}
public function findCachedObject(FilterControllerEvent $event, $eventName, TraceableEventDispatcher $dispatcher
){
$params = $event->getRequest()->attributes->get('_route_params');
$fileType = $this->em->getRepository('App:FileType')->find($params->get('fileType'));
$dataSet = $this->controller->getDataSet($params->get('dataSetSearch')?:'latest', $fileType->getType());
$cacheFile = $this->cacheFolder.'/output/DS'.$dataSet->getId().'-FT'.$fileType->getId().'.html';
if (file_exists($cacheFile)){
$fh = fopen($cacheFile,'r');
return new Response(fpassthru($fh));
}
}
}
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.
public: true # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
bind:
$projectDir: '%kernel.project_dir%'
# 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']
controller.return_cached_output:
class: App\Listener\CachedOutput
arguments:
$cacheFolder: "%kernel.cache_dir%"
tags:
- { name: kernel.event_listener, event: kernel.controller, method: findCachedObject }
However, I still get an error regarding the cache folder:
Cannot autowire service "App\Listener\CachedOutput": argument "$cacheFolder" of method "__construct()" has no type-hint, you should configure its value explicitly.
What am I missing?
Update:
Have tried to use alias for the service like this:
App\Listener\CachedOutput:
public: false
arguments:
$cacheFolder: "%kernel.cache_dir%"
tags:
- { name: kernel.event_listener, event: kernel.controller, method: findCachedObject }
return_cached_output:
alias: App\Listener\CachedOutput
public: true
with no success
You need to type-hint in your __construct(string $cacheFolder, ...)

Symfony 3.3.5 config service

I have some class ObjectManager and want create service for him, I create config
services:
_defaults:
autowire: true
autoconfigure: true
public: false
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{Entity,Repository,Tests}'
AppBundle\Service\:
resource: '../../src/AppBundle/Service'
public: true
app.object_manager:
class: AppBundle\Service\ObjectManager
arguments:
- '#jms_serializer'
- '#validator'
and after get this service in controller and have error
$objectManager = $this->get('app.object_manager');
You have requested a non-existent service "app.object_manager".
Why this happened, symfony 3.3.5 have different way for config services ?
First of all, when you want to be able to call a service with get, you have to define it public.
app.object_manager:
class: AppBundle\Service\ObjectManager
public: true
But you can do that also in top of the services.yml, to define, that all services are public:
services:
_defaults:
autowire: true
autoconfigure: true
public: true
That way, you don't have to do it explicitly at every service.
Furthermore, I would recommend you, to use the new autowiring feature of Symfony. That way, you do not have to define a service in the services.yml.
Just define the constructor in your ObjectManager class like that:
class ObjectManager
{
private $jms_serializer;
private $validator;
public function __construct(SerializerInterface $jms_serializer, ValidatorInterface $validator)
{
$this->jms_serializer = $jms_serializer;
$this->validator = $validator;
}
}
He will find the correct services by autowiring then. And you do not have to define anything in the services.yml.
So, to sum up your services.yml should just contain the following:
services:
_defaults:
autowire: true
autoconfigure: true
public: true
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{Entity,Repository,Tests}'
Looks like you need to explicitly define your services as public since Symfony 3 if you want to use them through get().
# app/config/services.yml
services:
# default configuration for services in *this* file
_defaults:
# ...
public: false
More info here - http://symfony.com/doc/current/service_container.html#public-versus-private-services
You can actually use Symfony 3.3+ to it's full potential.
If I understand you correctly, you need to get AppBundle\Service\ObjectManager to your Controller.
In that case...
1. Modify your services.yml
services:
_defaults:
autowire: true
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{Entity,Repository,Tests}'
2. Require AppBundle\Service\ObjectManager via constructor (anywhere you need it)
use AppBundle\Service\ObjectManager;
final class MyController
{
/**
* #var ObjectManager
*/
private $objectManager;
public function __construct(ObjectManager $objectManager)
{
$this->objectManager = $objectManager;
}
public function someAction()
{
$this->objectManager->someCoolMethod();
}
}
That's all!
Nothing fancy, just pure Symfony awesomes!

Resources