Magento 2.3 – Unable to Pass Array to Email Layout Template

emailemail-templatesmagento2magento2.3

I've created a module to capture and pass submitted custom option selections from a product which I intend to then send via email (for quotes). Everything is working except my attempts to pass the array of custom option information to a layout template.

I parse and append the options to the email parameters in Post.php, and then attempt to pass the options object from the email template to the layout template where I want to iterate over each of the options. However, $block->getOptions() (see below) always returns null.

The $params['options'] is populated correctly, so the issue is just passing the data to the layout template. If I don't try to pass the options to the layout template, it's working fine. It only errors (Error filtering template: Warning: Invalid argument supplied for foreach()) because $options is null.

Am I passing the options data to the template incorrectly?

Post.php

<?php

...

public function execute()
{
    ...

    try {
        ...

        // Send email
        $this->sendEmail($this->validatedParams());

        ...
    }

}

private function sendEmail($post)
{
    $this->mail->send(
        $post['raq_email'],
        ['data' => new DataObject($post)]
    );
}

private function validatedParams()
{
    $request = $this->getRequest();
    $params = $request->getParams();

    ...


    // Parse options to strings
    $options = [];

    ...

    $optionsObj = $this->objectFactory->create();
    $optionsObj->setData($options);
    $params['options'] = $optionsObj;

    return $params;
}

Mail.php

public function send($replyTo, array $variables)
    {
        /** @see \Vendor\Quoteform\Controller\Index\Post::validatedParams() */
        $replyToName = !empty($variables['data']['name']) ? $variables['data']['name'] : null;

        $this->inlineTranslation->suspend();
        try {
            $transport = $this->transportBuilder
                ->setTemplateIdentifier($this->quoteConfig->emailTemplate())
                ->setTemplateOptions(
                    [
                        'area' => Area::AREA_FRONTEND,
                        'store' => $this->storeManager->getStore()->getId()
                    ]
                )
                ->setTemplateVars($variables)
                ->setFrom($this->quoteConfig->emailSender())
                ->addTo($this->quoteConfig->emailRecipient())
                ->setReplyTo($replyTo, $replyToName)
                ->getTransport();

            $transport->sendMessage();
        } finally {
            $this->inlineTranslation->resume();
        }
    }

email_product_custom_options.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="Email Product Custom Options" design_abstraction="custom">
    <body>
        <block class="Magento\Framework\View\Element\Template" name="email_product_custom_options" template="Vendor_Quoteform::email/productCustomOptions.phtml" cacheable="false"/>
    </body>
</page>

email_template.html

{{template config_path="design/email/header_template"}}

<table class="message-details">
  <tr>
    <td>
      <b>{{trans "Name"}}</b>
    </td>
    <td>{{var data.raq_name}}</td>
  </tr>
  <tr>
    <td>
      <b>{{trans "Email"}}</b>
    </td>
    <td>{{var data.raq_email}}</td>
  </tr>
  <tr>
    <td>
      <b>{{trans "Phone"}}</b>
    </td>
    <td>{{var data.raq_telephone}}</td>
  </tr>
</table>

{{layout handle="email_product_custom_options" options=$options area="frontend"}}

{{template config_path="design/email/footer_template"}}

productCustomOptions.phtml

<?php $options = $block->getOptions();?>
<table>
    <?php foreach($options as $k => $v): ?>
    <?php foreach($v as $title => $value): ?>
    <tr>
        <td><?= $title ?></td>
        <td><?= $value ?></td>
    </tr>
    <?php endforeach; ?>
    <?php endforeach; ?>
</table>

Best Answer

Difficult to know without seeing your email send logic but typically you need to build objects which you then pass through to email templates.

https://magento.stackexchange.com/a/283338/70343

So I would have thought you would be better passing the block template output as a variable.

Related Topic