当 woocommerce_order_status_changed 挂钩触发时,Woocommerce admin_notices 不起作用

Chl*_*loé 5 php wordpress woocommerce hook-woocommerce wordpress-admin

我是 WordPress 开发新手,目前遇到了死胡同。

我希望在订单状态更改后在 WooCommerce 订单中显示管理员通知。

使用以下代码,不会出现该通知:

<?php

class TestNotice {
    public function testTheNotice() {
        add_action('woocommerce_order_status_changed', [$this, 'test'], 10, 4);
    }

    public function test(int $id, string $statusFrom, string $statusTo, WC_Order $order)
    {
        add_action('admin_notices', [$this, 'notice']);
    }

    public function notice()
    {
        ?>
        <div class="notice notice-error is-dismissible">
            <p>This notice appears on the order page.</p>
        </div>
        <?php
    }

}

$testNotice = new TestNotice();
$testNotice->testTheNotice();
Run Code Online (Sandbox Code Playgroud)

我尝试将“admin_notices”操作的“优先级”参数设置为20,但没有成功(我认为如果嵌套操作与第一次调用的操作相同,这会很有用)。

但是,当我直接在方法中调用“admin_notices”操作testTheNotice()(因此不调用“woocommerce_order_status_changed”操作)时,它可以工作(在每个管理页面上,这不是我想要的)。

我以为这是因为notice()不知何故无法识别,但实际上是:下面的代码显示“此通知出现在订单页面上”。在空白页上(这不是我想要的,仅用于测试目的)。

<?php

class TestNotice {
    public function testTheNotice() {
        add_action('woocommerce_order_status_changed', [$this, 'test'], 10, 4);
    }

    public function test(int $id, string $statusFrom, string $statusTo, WC_Order $order)
    {
        call_user_func([$this, 'notice']); die();
    }

    public function notice()
    {
        ?>
        <div class="notice notice-error is-dismissible">
            <p>This notice appears on the order page.</p>
        </div>
        <?php
    }

}

$testNotice = new TestNotice();
$testNotice->testTheNotice();
Run Code Online (Sandbox Code Playgroud)

我知道 WooCommerce 管理通知有一个特殊的类和方法,并且在notice()显示通知中编写下面的代码,但带有紫色边框(因为“更新”css 类,我还没有找到如何更改)红色边框(这可能要归功于“error”css 类,我不知道如何应用它)。

$adminNotice = new WC_Admin_Notices();
$adminNotice->add_custom_notice("Test",'<p>This notice appears on the order page.</p>');
$adminNotice->output_custom_notices();
Run Code Online (Sandbox Code Playgroud)

Ruv*_*vee 7

好问题。这引起了我的好奇心,让我深入研究这WC_Admin_Notices门课。这就是我发现的!

好吧,在讲课之前WC_Admin_Notices,我们先来谈谈你的第一个问题!

“通知没有出现”

因为当woocommerce_order_status_changed钩子触发时,没有与之关联的屏幕,并且不仅仅是通知,例如,如果您尝试执行 aprint_r和/或 an,echo它们也不会显示任何内容,因为没有与该钩子关联的屏幕。您可以发现自己已命中该钩子的唯一方法是使用die函数。为了测试这一点,您可以这样做:

add_action('woocommerce_order_status_changed', 'test', 99, 4);

function test($order_id, $old_status, $new_status, $order_object)
{
  die('You hit the right hook!');
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您将die('You hit the right hook!')函数替换为echoprint_r,则无论您将挂钩的优先级设置多高,它们都不会显示任何内容。


当你使用WC_Admin_Notices类时它会变得有趣。如果没有与woocommerce_order_status_changed钩子关联的屏幕,那么这个类如何工作?嗯,方法如下:

class-wc-admin-notices.php班级

  1. 它有一个名为的属性$notices,它是一个简单的空数组。
  2. 当您调用add_custom_notice方法时,它会将您提供的值存储到数据库和“选项”表中。键为“woocommerce_admin_notice_{您为测试指定的名称}”,值将是您定义的消息/通知。这就是它的全部作用!它将您的消息/通知存储到数据库中。
  3. 当您调用output_custom_notices方法时,它将检查$notices数组,并检查数据库中存储在选项表中的任何键值对,其格式与我刚刚在第 2 项中提到的格式相同!html-notice-custom.php然后,它使用在以下路径中调用的模板:

yourwebsite.com > wp-content > 插件 > woocommerce > 包含 > 管理 > 视图 > html-notice-custom.php
html-notice-custom.php模板

html-notice-custom.php文件负责输出自定义通知的 html 标记,并为它们提供一个名为 的类,updated该类将触发具有浅紫色的 css 规则。


那么整个WC_Admin_Notices班级的工作流程是:
  • 将您的自定义消息存储到数组或数据库中
  • 当屏幕加载时检索存储的键和值对!

从技术上讲,用最简单的术语来说,这就是它所做的一切!


由于我们不需要自定义浅紫色模板,因此我们可以使用WC_Admin_Notices使用并编写我们自己的解决方案的工作流程,而无需使用WC_Admin_Notices类。

我们可以使用以下方法之一:

  • $_SESSION使用+admin_notices钩子的组合
  • cookie使用or local storage+ admin_noticeshook的组合
  • database使用+admin_notices钩子的组合

我认为,如果我们使用$_SESSION+admin_notices钩子方法,它既安全又快速,甚至不需要查询数据库来获取简单的文本字符串。这是我目前能想到的解决方案:

代码进入functions.php您的活动主题的文件中。

add_action('woocommerce_order_status_changed', 'test', 99, 4);

function test($order_id, $old_status, $new_status, $order_object)
{

  if ( $order_object && ($old_status != $new_status) ) 
  {

    $notice = 'This notice appears on the order page.';

    session_start();

    $_SESSION['your_custom_message_name'] = $notice;

  }
}

add_action('admin_notices', 'your_them_displaying_custom_admin_notice');

function your_them_displaying_custom_admin_notice()
{
  session_start();
  if (isset($_SESSION['your_custom_message_name'])) {

?>
    <div class='notice notice-error is-dismissible'>
      <p><?php echo $_SESSION['your_custom_message_name'] ?></p>
    </div>
<?php
    unset($_SESSION['your_custom_message_name']);
  }
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 仅当存在订单且$old_status不等于 时,此方法才有效$new_status
  • $notice变量中,我放置了原始文本,而不是 html,因为我们p在钩子的 html 部分/模板中放置了一个标签admin_notices
  • 我已使用notice-errorclass 来div显示red color通知的标签。您可以将其替换为notice-warning, 或notice-infonotice-success

这个答案已经在 woocommerce 上经过充分测试5.7并且工作正常。