1
votes

I have been looking at the Symfony 4.1 documentation on using the Swift_mailer. However, it appears the documentation is only assumed it being used in the Controller classes. I'm trying to create a Service with some reusable functions that send email.

I created a EmailService.php file in my service directory. When creating a new instance of this service, it quickly throws and error:

"Too few arguments to function App\Service\EmailService::__construct(), 0 passed in *MyApp\src\Controller\TestController.php on line 33 and exactly 1 expected"

I'm not sure how to pass \Swift_Mailer $mailer into the __construct correctly? I have auto wiring enabled in the services.yaml, so i'm not sure what I need to do differently?

class EmailService
{
    private $from = 'support@******.com';
    private $mailer;

    public function __construct(\Swift_Mailer $mailer)
    {
        $this->mailer = $mailer;
    }

How do I pass the \Swift_Mailer into this EmailService construct?

I tried adding this to my config\services.yaml with no success:

App\Service\EmailService:
        arguments: ['@mailer']
2
And how are you trying to access your EmailService? I suspect you are trying to new it.Cerad
Correct, "new EmailService()"Speedy059
Please use either Constructor injection or inject the service into your action by just adding it as argument to the method e.g. public function index(Request $request, EmailService $emailService) {...}.dbrumann

2 Answers

1
votes

As mentioned by dbrumann in a comment, I needed to follow the proper way of injecting services.

First, I needed to add the services to config/services.yaml

#config/services.yaml
emailservice:
    class: App\Service\EmailService
    arguments: ['@swiftmailer.mailer.default', '@twig']
    public: true

Second, I need to setup the service to accept both the mailer, and twig for rendering the template.

#App/Service/EmailService.php
<?php
namespace App\Service;

class EmailService
{
    private $from = 'support@*****.com';
    private $mailer;
    private $templating;

    public function __construct(\Swift_Mailer $mailer, \Twig\Environment $templating)
    {
        $this->mailer       = $mailer;
        $this->templating   = $templating;
    }
   public function userConfirmation(string $recipient, string $confCode) : bool
   {

        $message = (new \Swift_Message())
        ->setSubject('Some sort of string')
        ->setFrom($this->from)
        ->setTo($recipient)
        ->setBody(
            $this->templating->render(
                'email/UserConfirmation.html.twig',
                array('confCode' => $confCode)
            ),
            'text/html'
        )
        /*
         * If you also want to include a plaintext version of the message
        ->addPart(
            $this->renderView(
                'emails/UserConfirmation.txt.twig',
                array('confCode' => $confCode)
            ),
            'text/plain'
        )
        */
    ;
    return $this->mailer->send($message);
  }
}

Third, to call it from the controller, make sure your controller is extending Controller and not the AbstractController! Crucial step!! Here is an example based on the parameters I require in my service:

public function userConfirmation()
{
     $emailService   = $this->get('emailservice');
     $sent = $emailService->userConfirmation('[email protected]', '2ndParam');
     return new Response('Success') //Or whatever you want to return
 }

I hope this helps people. AbstractController does not give you the proper access to the service containers.

-1
votes
#config/services.yaml

    App\Service\EmailService
        arguments: ['@swiftmailer.mailer.default']
        public: true

And in your controller :

public function userConfirmation(EmailService $emailService)
{    
     $sent = $emailService->userConfirmation('[email protected]', '2ndParam');
     return new Response('Success') //Or whatever you want to return
 }

Use FQCN "App\Service\MyService" to declare services in services.yaml and a proper legacy_aliases.yaml file to declare legacy aliases like "app.service.my.service" it helps keep your services.yaml clean...