odan / slim4-skeleton

A Slim 4 Skeleton
https://odan.github.io/slim4-skeleton/
MIT License
439 stars 80 forks source link

Twig + Mailer Integration Issue #9

Closed fvtorres closed 4 years ago

fvtorres commented 4 years ago

Hey @odan

I went though your Tutorial, the Twig implementation and the Mailer Implementation. Would like to thank you for these awesome tutorials.

So good so far, but when I tried to use Twig inside emails, it simply doenst work. I was following the official documentation in Mailer, but I get an error: Type: Symfony\Component\Mime\Exception\LogicException Code: 0 Message: A message must have a text or an HTML part or attachments. File: /vendor/symfony/mime/Email.php Line: 405

I found a reference in this github: symfony/symfony#35990

If this is easy to solve, I guess it would be nice to be in your tutorials

fvtorres commented 4 years ago

Here is the Official Documentation I mentioned

https://symfony.com/doc/current/mailer.html#twig-html-css

odan commented 4 years ago

To render twig templates in emails just add the a new container definition for BodyRendererInterface:class in config/container.php

use Symfony\Component\Mime\BodyRendererInterface;
use Slim\Views\Twig;
// ...

BodyRendererInterface::class => function(ContainerInterface $container)
{
    return new BodyRenderer($container->get(Twig::class)->getEnvironment());
},

To define the contents of your email with Twig, use the TemplatedEmail class (and not the Email class). This class extends the normal Email class but adds some new methods for Twig templates:

Then inject the BodyRendererInterface instance via constructor injection where you need it.

Usage

use Symfony\Bridge\Twig\Mime\TemplatedEmail;

$email = (new TemplatedEmail())
    ->from('odan@example.com')
    ->to(new Address('fvtorres@example.com'))
    ->subject('Thanks for signing up!')

    // path of the Twig template to render
    ->htmlTemplate('emails/signup.html.twig')

    // pass variables (name => value) to the template
    ->context([
        'username' => 'foo',
    ])
;

 // Render the email twig template
$this->bodyRenderer->render($mail);

// Send email
$this->mailer->send($mail);
fvtorres commented 4 years ago

Wow!

That worked like a charm!!

Thank you very much!! Have been 3 days trying to do that.

Now I will integrate: cssinliner-extra twig/inky-extra league/commonmark

I guess the proccess is about the same. Declare in Container and call before rendering right?

Thanks a lot for your help!

fvtorres commented 4 years ago

Success! Here is the code I used in container.php:

use Twig\Extra\CssInliner\CssInlinerExtension;
use Twig\Extra\Inky\InkyExtension;
use Twig\Extra\Markdown\MarkdownExtension;
use Twig\Extra\Markdown\DefaultMarkdown;
use Twig\Extra\Markdown\MarkdownRuntime;
use Twig\RuntimeLoader\RuntimeLoaderInterface;

  // Twig templates
    Twig::class => function (ContainerInterface $container) {
        $config = $container->get(Configuration::class);
        $settings = $config->getArray('twig');

        $options = $settings['options'];
        $options['cache'] = $options['cache_enabled'] ? $options['cache_path'] : false;

        $twig = Twig::create($settings['paths'], $options);

        $twig->addRuntimeLoader(new class implements RuntimeLoaderInterface {
            public function load($class) {
                if (MarkdownRuntime::class === $class) {
                    return new MarkdownRuntime(new DefaultMarkdown());
                }
            }
        });

        // Add more extension here
        $twig->addExtension(new CssInlinerExtension());
        $twig->addExtension(new InkyExtension());
        $twig->addExtension(new MarkdownExtension());

        return $twig;
    },
odan commented 4 years ago

Thanks for sharing.

fvtorres commented 4 years ago

The cssinliner-extra and twig/inky-extra are working by using that approach!

But the Markdown is being called as a filter but not producing any result. Maybe because it isn't linking to the league/commonmark, but I receive no errors at all,

Will keep trying here. If I discover will post here

Thanks!

fvtorres commented 4 years ago

Well, could't get the Markdown to work. It apparently is running (or at least some part of it), but nothing happpens.

I'm wondering if the code is in the right place:

$twig->addRuntimeLoader(new class implements RuntimeLoaderInterface {
        public function load($class) {
            if (MarkdownRuntime::class === $class) {
                return new MarkdownRuntime(new DefaultMarkdown());
            }
        }
    });

If you have some more time, could I ask for some more help?

Thanks!

odan commented 4 years ago

Yes, it looks correct.

https://github.com/odan/slim4-skeleton/issues/12#issuecomment-623713126