我目前正在使用Prestashop 1.6.1.5建立一个商店。
我必须发送的电子邮件很多,我想在一个地方管理我的电子邮件骨架 我认为更简单的方法是将电子邮件管理为智能文件和[扩展我的布局] [1]。
现在有人以透明和全球的方式管理电子邮件布局吗?
谢谢,
本。
潜入MailCore类,我看到可以在使用三个钩子(简化和评论)发送之前操纵电子邮件模板:
// Init empty templates strings.
$template_html = '';
$template_txt = '';
// Manipulate strings before importing templates.
Hook::exec('actionEmailAddBeforeContent', array(
'template_html' => &$template_html,
'template_txt' => &$template_txt,
// ...
), null, true);
// Import templates.
$template_html .= Tools::file_get_contents(/* ... */);
$template_txt .= strip_tags(html_entity_decode(Tools::file_get_contents(/* ... */), null, 'utf-8'));
// Manipulate strings after importing templates.
Hook::exec('actionEmailAddAfterContent', array(
'template_html' => &$template_html,
'template_txt' => &$template_txt,
// ...
), null, true);
// Some MailCore stuff.
// Inject custom vars before generate email content
$extra_template_vars = array();
Hook::exec('actionGetExtraMailTemplateVars', array(
'template_vars' => $template_vars,
'extra_template_vars' => &$extra_template_vars,
// ...
), null, true);
$template_vars = array_merge($template_vars, $extra_template_vars);
// Generate and send email
所以在我看来,使用这些钩子是管理我的电子邮件布局的好方法,但我不知道如何定义钩子调用的函数。
为了使其全球化,我尝试覆盖MailCore(进入 /override/classes/Mail.php ):
class Mail extends MailCore {
public function __construct($id = null, $id_lang = null, $id_shop = null) {
parent::__construct($id, $id_lang, $id_shop);
PrestaShopLogger::addLog('MailCore overrided!');
}
// Prepend a header to template.
public function hookActionEmailAddBeforeContent($params) {
PrestaShopLogger::addLog('hookActionEmailAddBeforeContent called!');
$params['template_html'] .= '<h1>{myheader}</h1>';
}
// Append a footer to template.
public function hookActionEmailAddAfterContent($params) {
PrestaShopLogger::addLog('hookActionEmailAddAfterContent called!');
$params['template_html'] .= '<h1>{myfooter}</h1>';
}
// Add my custom vars.
public function hookActionGetExtraMailTemplateVars($params) {
PrestaShopLogger::addLog('hookActionGetExtraMailTemplateVars called!');
$params['extra_template_vars']['myheader'] = 'This is a header';
$params['extra_template_vars']['myfooter'] = 'This is a footer';
}
}
清除Prestashop缓存后,类覆盖工作(从构造函数中记录)但没有调用我的钩子。
我还尝试使用$this->registerHook('...');
将钩子注册到我的类constructoe中,但没有任何效果。
如果有人可以提供帮助,那就太棒了。
谢谢,
本。
答案 0 :(得分:1)
@TheDrot:感谢这些有用的解释: - )
正如TheDrot指出的那样,这封电子邮件有点混乱。我想:
所以我决定覆盖MailCore类并实现以下基本但工作的“布局扩展”系统 当然,这个解决方案的主要缺点是在更新Prestashop时我必须保持我的覆盖功能是最新的。
我处于单一语言环境中,我不需要文本电子邮件的布局,但管理多种语言和文本电子邮件也很容易。
以下代码当然可以大大改进,它只是一个快速演示。
布局放置在 / themes / {theme} / mails / layouts 目录中。
可以使用电子邮件中可用的任何变量,并使用{{CONTENT}}
标记定义内容位置。
/themes/mytheme/mails/layouts/my-layout.html :
<h1>A header</h1>
{{CONTENT}}
<h1>A footer</h1>
在电子邮件模板中,使用{extends:name-of-layout}
标记:
/themes/mytheme/mails/en/password_query.html :
{{extends:my-layout}}
<p>
<b>
Hi {firstname} {lastname},
</b>
</p>
<p>
You have requested to reset your {shop_name} login details.<br/>
Please note that this will change your current password.<br/>
To confirm this action, please use the following link:
</p>
<p>
<a href="{url}" class="button">Change my pasword</a>
</p>
这是主要功能:如果“extends”标签存在于模板中并且建立了所需的布局,则使用模板填充布局。
/override/classes/Mail.php :
public static function layout($theme_path, $template, $content) {
preg_match("/^\{\{extends\:(\w+)\}\}/", ltrim($content), $m);
if (!isset($m[1]) || !file_exists($theme_path . 'mails/layout/' . $m[1] . '.html')) {
return $content;
}
$content = ltrim(str_replace('{{extends:' . $m[1] . '}}', '', $content));
$layout = Tools::file_get_contents($theme_path . 'mails/layout/' . $m[1] . '.html');
return str_replace('{{CONTENT}}', $content, $layout);
}
然后在一个地方修改发送功能,将布局功能应用于模板:
public static function Send($id_lang, $template, $subject, $template_vars, $to, $to_name = null, $from = null, $from_name = null, $file_attachment = null, $mode_smtp = null, $template_path = _PS_MAIL_DIR_, $die = false, $id_shop = null, $bcc = null, $reply_to = null) {
// ...
$template_html = '';
$template_txt = '';
Hook::exec('actionEmailAddBeforeContent', array(
'template' => $template,
'template_html' => &$template_html,
'template_txt' => &$template_txt,
'id_lang' => (int) $id_lang
), null, true);
$template_html .= Tools::file_get_contents($template_path . $iso_template . '.html');
$template_txt .= strip_tags(html_entity_decode(Tools::file_get_contents($template_path . $iso_template . '.txt'), null, 'utf-8'));
Hook::exec('actionEmailAddAfterContent', array(
'template' => $template,
'template_html' => &$template_html,
'template_txt' => &$template_txt,
'id_lang' => (int) $id_lang
), null, true);
// Apply self::layout function to template when acquired.
$template_html = self::layout($theme_path, $template_path . $iso_template . '.html', $template_html);
// ...
}
答案 1 :(得分:0)
对于自定义邮件,您不需要挂钩或覆盖任何内容。在致电Mail::send()
之前,您需要做的就是通过聪明的{header}
,{content}
,{footer}
生成三个模板变量。
public function someModuleMailFunc($email_template)
{
$header_tpl = $this->context->smarty->createTemplate('path_to_header_tpl_smarty');
$header_tpl->assign(array(
// assign header template vars
));
// put some conditionals here to load a proper content for specific mail
if ($email_template == 'some_mail_template') {
$content_tpl = $this->context->smarty->createTemplate('path_to_content_tpl_smarty');
$content_tpl->assign(array(
// assign content template vars
));
}
$footer_tpl = $this->context->smarty->createTemplate('path_to_footer_tpl_smarty');
$footer_tpl->assign(array(
// assign footer template vars
));
$email_vars = array(
'{header}' => $header_tpl->fetch(),
'{content}' => $content_tpl->fetch(),
'{footer}' => $footer_tpl->fetch()
);
Mail::send('en', $email_template, $subject, $email_vars, $to);
}
现在确保您拥有这样的some_email_template.html
结构。
{header}
{content}
{footer}
由于您使用可以调用语言函数{l s='text'}
的智能模板,因此您也不需要为每种语言都设置电子邮件模板。
示例仅适用于html模板,添加处理txt模板的代码。
要更改核心电子邮件......现在这就是复杂的事情。
一种方法是挂钩actionEmailAddAfterContent
和actionGetExtraMailTemplateVars
。
public function hookActionEmailAddAfterContent($params)
{
// here we can replace the email templates with {header} {content} {footer}
// this param is passed by reference
$params['template_html'] = '{header}{content}{footer}';
}
public function hookActionGetExtraMailTemplateVars($params)
{
// here we generate vars for {header} {content} {footer}
$header_tpl = $this->context->smarty->createTemplate('path_to_header_tpl_smarty');
$header_tpl->assign(array(
// assign header template vars
));
// existing template vars can be accessed with $params['template_vars']
// so they can be reinserted into your templates
// put some conditionals here to load a proper content for specific mail
if ($params['template'] == 'some_mail_template') {
$content_tpl = $this->context->smarty->createTemplate('path_to_content_tpl_smarty');
$content_tpl->assign(array(
// assign content template vars
));
}
$footer_tpl = $this->context->smarty->createTemplate('path_to_footer_tpl_smarty');
$footer_tpl->assign(array(
// assign footer template vars
));
// this param is also passed by reference
$params['extra_template_vars']['{header}'] = $header_tpl->fetch();
$params['extra_template_vars']['{content}'] = $content_tpl->fetch();
$params['extra_template_vars']['{footer}'] = $footer_tpl->fetch();
}
这样,额外的参数将被Mail::send()
选中,因为我们之前修改了模板,它会将标题内容和页脚插入其中。
问题在于,您仍然需要为每种语言添加电子邮件模板文件,即使它们从未使用过,因为Mail::send()
仍然会在执行这些挂钩之前尝试加载它们。除非你想要覆盖当然的方法。
同样通过后台为管理员编辑电子邮件变得毫无用处,因为除了{header}{content}{footer}
之外,您的自定义模块邮件和编辑核心邮件都没有任何效果。
电子邮件模板的全部内容有点混乱,我不知道为什么开发人员决定以这种方式创建邮件系统而不是使用smarty。也许为了更容易实现后台电子邮件编辑...我不知道。也许如果任何prestashop dev看到这个,他们可能会解释它。