Reputation: 11
I'm trying to automate a call to a controller which sends email. So I would like to be able to call this controller from a symfony command. The controller function works when I call the url from my browser. But when i call the function from my command i get errors from Swift Mailer, it asks me to provide an argument in order to construct the swift mailer ($mailer).
I have tried to inject \Swift_Mailer inside the call of my action but it justs shows me another argument error for the Swift_Transport.
Here is the code for my Command file and the signature and beginning of my Controller action:
//../src/Command/mailCommand.php
class mailCommand extends Command {
//...
public function execute (InputInterface $input, OutputInterface $output) {
$controller = new MailController();
//try 1
$controller->warningMailAction();
//try 2
//$transport = (new \Swift_SmtpTransport('smtp://smtp.myadress.fr', 25));
// $controller->warningMailAction(new \Swift_Mailer($transport));
$output->writeln('coucou !');
}
}
//---------------------------------------
//../src/Controller/MailController.php
public function warningMailAction(\Swift_Mailer $mailer) {}
I run on symfony 4.3.2, I don't know how to fix this, everything i try leads me to more error. Every help is appreciated, tell me if you need more of my code to understand the problem
Upvotes: 0
Views: 651
Reputation: 11
I think it works. Thanks to your valuable help @msg. I'll post here my final code in case it could be usefull for anyone having the same trouble.
This is my mailCommand.php
public function __construct(MailController $mailController, \Swift_Mailer $mailer)
{
$this->controller = $mailController;
$this->mailer = $mailer;
parent::__construct();
}
protected function configure () {
static $defaultName = 'app:mailAuto';
$this->setName($defaultName);
$this->setDescription("Permet d'envoyer des mails automatiquement lorsque le parc n'est pas à jour");
$this->setHelp("Je serai affiche si on lance la commande bin/console app:mailAuto -h");
}
public function execute (InputInterface $input, OutputInterface $output) {
$this->controller->warningMailAction($this->mailer);
$output->writeln('Hello there !');
}
Inside my controller i have not changed anything. I use the $mailer normally.
Thank you to everybody who helped me.
Upvotes: 1
Reputation: 8181
A Controller
is a ServiceSubscriber
. This means that upon instancing, the container injects some basic services into it.
By calling new
you are instancing it directly without using the container and the services it uses aren't there. You could pass the Container
via the setContainer
method, or just inject the Controller into your command, its instancing will be taken care of by the container.
You just have to pass your controller dependency to your command __construct
:
use App\Controller;
class mailCommand extends Command
{
private $controller;
public function __construct(MailController $mailController)
{
$this->controller = $mailController;
}
public function execute(InputInterface $input, OutputInterface $output)
{
$this->controller->mailWarning(...);
// Other stuff
}
}
However, controllers are special since they can receive additional services injected in their methods, as is the case with mailWarning
. This happens during the controller resolution phase. Since this will be called via a command, you will have to take care of this dependency too. Instead of instancing it manually you could get it from the container as well:
public function __construct(MailController $mailController, \SwiftMailer $mailer)
You can learn more about how all this works in the Service Container Reference.
Upvotes: 1