Swift_Mailer Symfony 3 добавляет прослушиватель событий для отправки события

Как добавить eventListener в событие отправки swiftmailer? Каждый раз, когда я отправляю электронное письмо, я создаю файл и прикрепляю его к электронному письму, и после отправки я хочу отменить связь с этим файлом. Как это сделать? Спасибо.

 file_put_contents($path, implode(";\r\n", $result));
$message = (new \Swift_Message('VAT checking result !'))
            ->setFrom('[email protected]')
            ->setTo($vat->getEmail())
             ->setBody(
                    'Hello, ...' ,'text/')
             ->attach(\Swift_Attachment::fromPath($path));
// START send result email
    $mailer = $this->container->get('mailer');

    $listener = $this->container->get('app.service.send_email_listener');
    $listener->setPathToFile($path);
    $mailer->registerPlugin($listener);

    $mailer->send( $message );
    // END send email to admin

//unlink($path);  email will not be sent

Я пытался зарегистрировать слушателя так

app.service.send_email_listener:
    class: AppBundle\Listener\SendEmailListener
    public: true
    tags:
         - { name: swiftmailer.plugin }

это класс слушателя:

namespace AppBundle\Listener;

use \Swift_Events_SendListener as base;

class SendEmailListener implements base
{
    private $pathToFile;

    public function setPathToFile($path)
    {
        $this->pathToFile = $path;
    }
    public function getPathToFile($path)
    {
        return $this->pathToFile;
    }


    /**
     * Invoked immediately before the Message is sent.
     *
     * @param \Swift_Events_SendEvent $evt
     */
    public function beforeSendPerformed(\Swift_Events_SendEvent $evt)
    {

    }

    /**
     * Invoked immediately after the Message is sent.
     *
     * @param \Swift_Events_SendEvent $evt
     */
    public function sendPerformed(\Swift_Events_SendEvent $evt)
    {
        if($this->pathToFile){
            unlink($this->pathToFile);
        }
    }
}

РЕДАКТИРОВАТЬ Он выполняет метод, но Swift не может передавать файл в потоковом режиме, потому что файл не связан до завершения отправки... Это из dev_logs:

[2018-05-24 20:40:18] php.CRITICAL: Uncaught Exception: Unable to open file for reading [C:\Users\\projects\vat\web\vatfiles\122.txt] {"exception":"[object] (Swift_IoException(code: 0): Unable to open file for reading [C:\\Users\\\projects\\vat\\web\\vatfiles\\122.txt] at C:\\Users\\projects\\vat\\vendor\\swiftmailer\\swiftmailer\\lib\\classes\\Swift\\ByteStream\\FileByteStream.php:144)"} []

person Andrew Vakhniuk    schedule 24.05.2018    source источник
comment
Symfony 2.3+ автоматически зарегистрирует плагин Swiftmailer, когда вы пометите службу swiftmailer.plugin. Таким образом, вам не нужно вызывать $mailer->registerPlugin($listener);, но установка пути все равно будет работать в службе. Я предлагаю использовать магию __destruct() в вашей службе/контроллере для unlink файлов. Таким образом, как только ваша служба/контроллер будет выпущена, все связанные файлы будут удалены.   -  person Will B.    schedule 25.05.2018
comment
Большое спасибо Фирье. Это сработало. Не могли бы вы добавить свой комментарий в качестве ответа, и я приму его   -  person Andrew Vakhniuk    schedule 25.05.2018


Ответы (1)


В качестве альтернативы использованию плагина Swiftmailer я рекомендую использовать __destruct волшебный метод в вашем сервисе/контроллере, который использует файлы. __destruct будет вызываться при освобождении объекта и разъединит любой из объявленных путей.

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class YourController extends Controller
{
    private $paths = [];

    public function someAction()
    {
         $this->paths[] = $path;
         file_put_contents($path, implode(";\r\n", $result));
         $message = (new \Swift_Message('VAT checking result !'))
            ->setFrom('[email protected]')
            ->setTo($vat->getEmail())
            ->setBody('Hello, ...' ,'text/')
            ->attach(\Swift_Attachment::fromPath($path));
         $mailer = $this->container->get('mailer');
         $mailer->send( $message );

         return $this->redirectToRoute('some_route');
    }

    public function __destruct()
    {
        if ($this->paths) {
            array_map('unlink', $this->paths);
        }
    }

}

ПРИМЕЧАНИЕ. Этот подход может не сработать, если вы используете буфер для отправки электронных писем, поскольку электронное письмо не будет отправлено до тех пор, пока не будут достигнуты пороговые значения для спула.


Symfony 2.3+ автоматически зарегистрирует плагин Swiftmailer, когда вы пометите службу swiftmailer.plugin. Таким образом, нет необходимости вызывать $mailer->registerPlugin($listener);, где swiftmailer просто проигнорирует повторяющиеся регистрации плагинов.

person Will B.    schedule 25.05.2018