【问题标题】:Adding recipients to Woocommerce email notifications based on product variation term根据产品变体术语将收件人添加到 Woocommerce 电子邮件通知
【发布时间】:2017-08-14 11:43:42
【问题描述】:

我创建了一个 Woocommerce 插件并要求它做两件事:

  1. 根据购物车中的产品变体向特定电子邮件地址发送通知消息。

  2. 电子邮件必须只包含相关产品,而不是包含其他属性的产品。

例如:

产品 A 有一个名为 Chef 的属性,其中 chef-one 和 chef-2 作为变量术语。用户可以从一号厨师或二号厨师中选择产品A。

如果用户从 chef-one 中选择产品 A,则必须向 chefone@email.com 发送一封通知电子邮件,其中包含所订购产品的名称(因为它会显示在常规的 Woocommerce 通知电子邮件中)。

如果用户从一号厨师中选择产品A,从二号厨师中选择产品B,则必须向厨师一发送仅包含产品A的通知电子邮件,并且必须向厨师二发送仅包含产品的通知电子邮件B.

我使用https://www.skyverge.com/blog/how-to-add-a-custom-woocommerce-email/ 上的教程创建了插件,并对其进行了调整以适应上述目的。

我还改编了代码,找到了以下解决方案: Adding a custom woocommerce email based on the product attribute Woocommerce - Need to send email to specific address based on zip code

这是我的插件类文件中的代码:

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

/**
 * A custom WAKIKI Order WooCommerce Email class
 *
 * @since 0.1
 * @extends \WC_Email
 */

class WC_Wakiki_Order_Email extends WC_Email {


/**
 * Set email defaults
 *
 * @since 0.1
 */
public function __construct() {

    // set ID, this simply needs to be a unique name
    $this->id = 'wc_wakiki_order';

    // this is the title in WooCommerce Email settings
    $this->title = 'WAKIKI Order';

    // this is the description in WooCommerce email settings
    $this->description = 'WAKIKI Order Notification emails are sent when a customer places an order on the website';

    // these are the default heading and subject lines that can be overridden using the settings
    $this->heading = 'WAKIKI Delivery Order';
    $this->subject = 'WAKIKI Delivery Order';

    // these define the locations of the templates that this email should use, we'll just use the new order template since this email is similar
    $this->template_html  = 'emails/admin-new-order.php';
    $this->template_plain = 'emails/plain/admin-new-order.php';

    // Trigger on new paid orders
    add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ) );
    add_action( 'woocommerce_order_status_failed_to_processing_notification',  array( $this, 'trigger' ) );

    // Call parent constructor to load any other defaults not explicity defined here
    parent::__construct();

    // this sets the recipient to the settings defined below in init_form_fields()
    $this->recipient = $this->get_option( 'recipient' );

    // if none was entered, just use the WP admin email as a fallback
    if ( ! $this->recipient )
        $this->recipient = get_option( 'admin_email' );
}


/**
 * Determine if the email should actually be sent and setup email merge variables
 *
 * @since 0.1
 * @param int $order_id
 */
public function trigger( $order_id ) {

    // Bail if no order ID is present
    if ( ! $order_id )
        return;

      $order = new WC_Order( $order_id );

      // Find the product_id
      $items = $order->get_items();
      foreach ( $items as $item ) {
          $product_id = $item['product_id'];
      }
            // From the product_id get the product attribute
            $product = new WC_Product( $product_id );  // create an object of WC_Product class

            $patt = $product->get_attributes();  // call get_attributes method

            // Condition valid to send the email (if the attributes is chef)
            if ( array_key_exists('pa_chef', $patt) ) 

            // Determine which email address to send to, based on Product Attribute Term)
            add_filter( 'new_order' , 'add_recipient', 20, 2 );

            function add_recipient( $email, $order ) {
                $additional_email = "info@email.com";
                $terms = get_terms("pa_chef");
                if( $order->$term->name == "pa_chef-one" ){
                 $email = explode( ',', $email );
                 array_push( $email, $additional_email );
}
return $email;
}



    {
            // Send the email
            // Setup order object
            $this->object = new WC_Order( $order_id );
            $this->recipient    = $this->object->billing_email;

            // Replace variables in the subject/headings
            $this->find[] = '{order_date}';
            $this->replace[] = date_i18n( woocommerce_date_format(), strtotime( $this->object->order_date ) );

            $this->find[] = '{order_number}';
            $this->replace[] = $this->object->get_order_number();

            if ( ! $this->is_enabled() || ! $this->get_recipient() )
                return;

            // Send the email!
            $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );

        }

        else
        {
            return; //do nothing if there is not chef attribute
        }
}


/**
 * get_content_plain function
 *
 * @since 0.1
 * @return string
 */
public function get_content_plain() {
    ob_start();
    woocommerce_get_template( $this->template_plain, array(
        'order'         => $this->object,
        'email_heading' => $this->get_heading()
    ) );
    return ob_get_clean();
}


/**
 * Initialize Settings Form Fields
 *
 * @since 2.0
 */
public function init_form_fields() {

    $this->form_fields = array(
        'enabled'    => array(
            'title'   => 'Enable/Disable',
            'type'    => 'checkbox',
            'label'   => 'Enable this email notification',
            'default' => 'yes'
        ),
        'recipient'  => array(
            'title'       => 'Recipient(s)',
            'type'        => 'text',
            'description' => sprintf( 'Enter recipients (comma separated) for this email. Defaults to <code>%s</code>.', esc_attr( get_option( 'admin_email' ) ) ),
            'placeholder' => '',
            'default'     => ''
        ),
        'subject'    => array(
            'title'       => 'Subject',
            'type'        => 'text',
            'description' => sprintf( 'This controls the email subject line. Leave blank to use the default subject: <code>%s</code>.', $this->subject ),
            'placeholder' => '',
            'default'     => ''
        ),
        'heading'    => array(
            'title'       => 'Email Heading',
            'type'        => 'text',
            'description' => sprintf( __( 'This controls the main heading contained within the email notification. Leave blank to use the default heading: <code>%s</code>.' ), $this->heading ),
            'placeholder' => '',
            'default'     => ''
        ),
        'email_type' => array(
            'title'       => 'Email type',
            'type'        => 'select',
            'description' => 'Choose which format of email to send.',
            'default'     => 'html',
            'class'       => 'email_type',
            'options'     => array(
                'plain'     => __( 'Plain text', 'woocommerce' ),
                'html'      => __( 'HTML', 'woocommerce' ),
                'multipart' => __( 'Multipart', 'woocommerce' ),
            )
        )
    );
}

这是我所能得到的最接近的,但它不起作用。我怀疑问题出在“根据产品属性术语确定要发送到哪个电子邮件地址”这一行附近。插件一直在加载,直到我添加了该部分。

函数是否应该在单独的插件文件中?

我还需要帮助才能让电子邮件仅包含与发送至的供应商相关的信息。

非常感谢任何帮助使该插件工作的帮助。

【问题讨论】:

  • 我已经更新了答案中的代码……

标签: php wordpress woocommerce attributes email-notifications


【解决方案1】:

过滤器 new_order WooCommerce 中不存在 (或您的代码中)

正确的过滤器钩子(位于WC_Email类核心代码,第269行)是这个:

$recipient  = apply_filters( 'woocommerce_email_recipient_' . $this->id, $this->recipient, $this->object );

在这个钩子中,$this-&gt;id 对你来说是“new_order”。

你的代码有很大的错误:

  • 术语名称应该类似于 "one""chef-one"但绝对不是 "pa_chef-one",因为 "pa_chef" 是您属性的分类 slug “厨师”。
  • 多个电子邮件收件人不在一个数组中,而是在一个逗号分隔的字符串中。

所以正确的代码应该是这样的:

add_filter( 'woocommerce_email_recipient_new_order', 'add_recipient', 10, 2 );
function add_recipient( $recipient, $order )
{
    if ( ! is_a( $order, 'WC_Order' ) ) return $recipient;

    // Additional email recipient
    $additional_email = "info@email.com";

    // The term name "pa_chef-one" is very strange … It should be "one" or "chef-one" (may be)
    $term_slug = "one";

    $has_term = false;

    // Iterating through each order item
    foreach ($order->get_items() as $item_id => $item_obj) {
        $variation_id = $item_obj->get_variation_id();
        $variation_obj = wc_get_product($variation_id);
        $variation_attributes = $variation_obj->get_attributes();
        foreach( $variation_attributes as $taxonomy_key => $term_value ){

            if( $taxonomy_key == "pa_chef" && $term_value == $term_slug ){
                $recipient .= ','. $additional_email;
                $has_term = true;
                break; // stop the 2nd loop
            }
        }
        if( $has_term ) break; // stop the 1st loop
    }
    return $recipient;
}

代码进入您的活动子主题(或主题)的 function.php 文件或任何插件文件中。

为 WooCommerce 版本 3+ 制作


类似的答案:

Add the New order email notification attachment to the vendor email

Woocommerce email notification recipient conditionally based on custom field

WooCommerce email notifications: different email recipient for different cities

【讨论】:

  • 感谢@LoicTheAztec 的反馈和对代码的改进。我已将上面的 sn-p 添加到插件的类文件中,在“确定要发送到哪个电子邮件地址”的行下方以及“返回 $email;”的上方。 - 当我激活插件时仍然收到错误。是否“返回 $recipient;”替换“$email”功能?这是我的第一个插件,因此我可能需要进行一定的反复试验。
  • @CraigdeGouveia 我不完全确定我的代码是否 100%,但钩子是正确的。函数中的参数是正确的。 (我在最后的答案中添加了一些带有这个钩子的旧答案的工作参考......)。我已经测试了 foreach 循环周围的所有代码,它也可以工作。现在问题可能出在您将在此函数中设置的术语名称或 slug 中。问题也可能出在其他地方。我希望你能找到方法。但这里的主要问题是围绕着钩子,而这个钩子就是为此而生的。
猜你喜欢
  • 2020-10-03
  • 1970-01-01
  • 2021-03-22
  • 2021-07-22
  • 1970-01-01
  • 2023-03-23
  • 2019-05-30
  • 2018-09-14
相关资源
最近更新 更多