WooCommerce 自定义邮件中 PHP echo 不生效的解决方案
在使用 WooCommerce 开发自定义邮件功能时,很多开发者会遇到一个常见问题:明明在模板中写了 PHP 的 echo 语句,但邮件发送后却看不到对应的输出内容。这个问题通常不是代码语法错误,而是对 WooCommerce 邮件渲染机制的理解偏差导致的,下面我们来详细分析原因并给出对应的解决方案。
问题原因分析
首先要明确 WooCommerce 自定义邮件的渲染逻辑:WooCommerce 的邮件模板并不是直接执行 PHP 代码输出内容,而是通过特定的变量传递和渲染机制生成邮件内容。如果直接在邮件模板中使用 echo 输出动态内容,很可能会因为以下原因不生效:
- 邮件渲染过程中,echo 输出的内容没有被正确捕获到最终的邮件内容流中
- 自定义邮件没有正确绑定需要传递的变量,导致模板中无法获取到对应数据
- 邮件模板的加载方式错误,没有走 WooCommerce 标准的模板加载流程
解决方案一:使用 WooCommerce 标准变量传递方式
WooCommerce 邮件类本身支持通过 $this->find、$this->replace 或者直接在邮件类中定义公共属性来传递变量,模板中直接调用这些变量即可,不需要额外使用 echo。
首先我们自定义一个邮件类,继承 WooCommerce 的 WC_Email 基类,在类中定义需要传递的变量:
// 自定义邮件类,继承 WC_Email
class WC_Custom_Email extends WC_Email {
public $custom_content; // 定义需要传递的自定义内容变量
public function __construct() {
$this->id = 'custom_email';
$this->title = '自定义邮件';
$this->description = '这是自定义的 WooCommerce 邮件';
$this->template_html = 'emails/custom-email-html.php'; // HTML 邮件模板路径
$this->template_plain = 'emails/custom-email-plain.php'; // 纯文本邮件模板路径
parent::__construct();
}
// 触发邮件发送的方法
public function trigger( $order_id, $custom_content = '' ) {
if ( ! $order_id ) {
return;
}
$this->object = wc_get_order( $order_id );
$this->custom_content = $custom_content; // 给自定义变量赋值
$this->recipient = $this->object->get_billing_email();
if ( $this->is_enabled() && $this->recipient ) {
$this->send( $this->recipient, $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
}
// 获取邮件内容的方法
public function get_content_html() {
return wc_get_template_html(
$this->template_html,
array(
'order' => $this->object,
'email_heading' => $this->get_heading(),
'custom_content'=> $this->custom_content, // 把变量传递到模板
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this
)
);
}
// 纯文本邮件内容逻辑类似,此处省略
public function get_content_plain() {
// 纯文本模板逻辑,和 HTML 模板类似传递变量即可
}
}然后在对应的邮件模板文件 custom-email-html.php 中,直接使用传递过来的变量,不需要额外 echo:
<?php
/**
* 自定义邮件 HTML 模板
* @var WC_Order $order
* @var string $custom_content
* @var string $email_heading
*/
defined( 'ABSPATH' ) || exit;
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<h2><?php echo esc_html( $email_heading ); ?></h2>
<p>订单号:<?php echo esc_html( $order->get_order_number() ); ?></p>
<p>自定义内容:<?php echo esc_html( $custom_content ); ?></p>
<p>感谢您的购买!</p>
</body>
</html>这种方式下,变量是通过 WooCommerce 标准的模板加载函数 wc_get_template_html 传递的,模板中只需要按照正常的 PHP 语法输出即可,不会出现 echo 不生效的问题。
解决方案二:检查模板加载路径是否正确
如果变量传递正确但依然看不到输出,需要检查邮件模板的路径是否符合 WooCommerce 的加载规则:
- WooCommerce 会优先从主题目录下的
woocommerce/emails/目录加载模板,如果找不到才会去插件默认的模板目录找 - 确保模板文件的命名和邮件类中定义的
template_html路径完全一致,不要写错文件名或者目录层级
可以通过以下代码测试模板是否被正确加载:
// 测试模板路径是否正确
$test_template = wc_locate_template( 'emails/custom-email-html.php' );
if ( file_exists( $test_template ) ) {
echo '模板路径正确:' . $test_template;
} else {
echo '未找到对应模板文件';
}解决方案三:避免在非模板文件中直接输出
有些开发者会尝试在邮件触发的钩子函数中直接用 echo 输出内容,这是错误的做法。邮件内容是在渲染阶段生成的,钩子函数中的 echo 输出不会进入邮件内容流,正确的做法是把需要输出的内容保存到变量中,再传递到邮件模板里。
错误的示例:
// 错误示例:钩子中直接 echo 不生效
add_action( 'woocommerce_order_status_completed', 'send_custom_email' );
function send_custom_email( $order_id ) {
$order = wc_get_order( $order_id );
// 这里直接 echo 内容不会进入邮件
echo '订单已完成,订单号:' . $order->get_order_number();
// 初始化自定义邮件类并触发发送
$mailer = new WC_Custom_Email();
$mailer->trigger( $order_id );
}正确的示例:
// 正确示例:把内容传递到邮件类
add_action( 'woocommerce_order_status_completed', 'send_custom_email' );
function send_custom_email( $order_id ) {
$order = wc_get_order( $order_id );
$custom_content = '订单已完成,订单号:' . $order->get_order_number();
// 初始化自定义邮件类,传递自定义内容
$mailer = new WC_Custom_Email();
$mailer->trigger( $order_id, $custom_content );
}总结
WooCommerce 自定义邮件中 echo 不生效的核心原因是没有遵循 WooCommerce 的邮件渲染机制,只需要做到三点即可解决:第一,通过邮件类的属性传递变量,再用 wc_get_template_html 把变量注入模板;第二,确保邮件模板的路径和命名符合 WooCommerce 的加载规则;第三,不要在非模板的钩子函数中直接 echo 内容,所有动态内容都通过变量传递到模板中输出。按照这个思路调整代码,就能正常在自定义邮件中显示动态内容了。