2017-01-16 2 views
0

J'ai configuré swiftmailer pour spouler des emails en utilisant le type de fichier. voici ma config swiftmailerSymfony - lance la commande console sur kernel.terminate

swiftmailer: 
    transport: "%mailer_transport%" 
    host:  "%mailer_host%" 
    username: "%mailer_user%" 
    password: "%mailer_password%" 
    spool: 
     type: file 
     path: "%kernel.root_dir%/../var/spool" 

Lorsque j'envoie des e-mails, il est parfaitement spoulé. Je cours la commande suivante pour expédier des email par la suite.

bin/console swiftmailer:spool:send --env=dev 

Selon Symfony documentation

the console command should be triggered by a cron job or scheduled task and run at a regular interval. 

Mon problème est, je ne peux pas utiliser crontab car Cron peut être configuré avec un minimum d'intervalle de 1 minute que je ne peux pas se permettre. Je veux utiliser le processus d'arrière-plan avec une exécution immédiate après que la réponse est renvoyée au navigateur, ce qui minimise l'exécution des spools au strict minimum.

je tenté de résoudre ce problème en créant une classe d'écouteur d'événements et d'écouter kernel.terminate, et exécuter la commande en fonction shell_exec ou exec, voici le code de référence.

app.kernel.terminate.listener: 
     arguments: ["@kernel"] 
     class: AppBundle\EventListener\KernelTerminateListener 
     tags: 
      - { name: kernel.event_listener, event: kernel.terminate } 

Voici ma EventListener classe

<?php 

namespace AppBundle\EventListener; 

use Symfony\Component\HttpKernel\Event\PostResponseEvent; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; 
use Cocur\BackgroundProcess\BackgroundProcess; 

class KernelTerminateListener 
{ 
    protected $kernel; 

    protected $console; 

    public function __construct($kernel) 
    { 
     $this->kernel = $kernel; 
     $this->console = $this->kernel->getRootDir().'/../bin/console '; 
    } 

    public function onKernelTerminate(PostResponseEvent $event) 
    { 
     $command = $this->console.'swiftmailer:spool:send --env='.$this->kernel->getEnvironment(); 
     shell_exec($command); 
    } 
} 

Ce que je suis en train ici est d'exécuter bin/console swiftmailer:spool:send --env=dev sur l'événement kernel.terminate, malheureusement cela ne fonctionne pas, aucune indication sur la façon d'aborder ce problème est apprécié.

Merci.

+0

Que signifie «cela ne fonctionne pas»? – COil

+0

Il ne distribue pas l'email, alors que si je fais écho '$ command' et copiez le coller dans le terminal, cela fonctionne. Je peux voir que même si elle est exécutée, les fichiers spoule ne sont pas traités, généralement les fichiers spoule sont supprimés si elle est traitée, et dans mon cas, elle ne supprime pas. –

+0

Quelle est la sortie de 'shell_exec ($ commande);', peut-être un bon problème? – COil

Répondre

1

S'il vous plaît utiliser le type de bobine de mémoire de Mailer rapide, il fait exactement ce que vous voulez

Lorsque vous utilisez bobiner pour stocker les e-mails à la mémoire, ils sera envoyé juste avant la fin du noyau. Cela signifie que l'e-mail est envoyé uniquement si la totalité de la requête a été exécutée sans aucune exception non gérée ou erreur. Pour configurer swiftmailer avec l'option de mémoire, utilisez la configuration suivante:

+0

Si vous lisez attentivement, il dit, il est exécuté juste avant la fin du noyau, cela ne signifie pas qu'il fonctionne en arrière-plan, il dit simplement qu'il est exécuté en dernier, j'ai essayé ceci et malheureusement cela ne répond pas mon exigence :-) –

+0

avant le noyau terminé = kernel.terminate event = après que la réponse a été envoyée au client et que fastcgi_finish_request() a été appelé –

+0

Vous avez raison, j'ai trouvé plusieurs références qui expliquent ce que vous essayez de dire, malheureusement n'a pas fonctionné pour moi peut-être à cause de la raison expliquée ici http://stackoverflow.com/questions/23719821/response-returned-only-after-kernel-terminate-event merci de m'avoir indiqué la bonne direction. +1 –

-1

Peut-être que c'était un problème avec PHP, j'utilise MAMP et OSX est pré-installé avec PHP, fondamentalement, j'ai deux php version installée, et pour une raison quelconque, quand j'ai donné le bon chemin PHP ça marche, voici ma classe d'écoute mis à jour que je retitré à MailerSpoolListener

<?php 

namespace AppBundle\EventListener; 

use Symfony\Component\HttpKernel\Event\PostResponseEvent; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; 
use Cocur\BackgroundProcess\BackgroundProcess; 

class MailerSpoolListener 
{ 
    protected $kernel; 

    protected $php; 

    protected $console; 

    protected $env; 

    protected $command; 

    protected $muteOutput; 

    public function __construct($kernel) 
    { 
     $this->kernel = $kernel; 
     $this->php = PHP_BINDIR.'/php'; 
     $this->command = 'swiftmailer:spool:send'; 
     $this->console = $this->kernel->getRootDir().'/../bin/console'; 
     $this->env = $this->kernel->getEnvironment(); 
     $this->muteOutput = '> /dev/null 2>/dev/null &'; 
    } 

    public function onKernelTerminate(PostResponseEvent $event) 
    { 
     $command = $this->php.' '.$this->console.' '.$this->command.' --env='.$this->env.' '.$this->muteOutput; 
     $process = shell_exec($command); 
    } 
}