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
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
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.
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 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, ...)
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!