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.