I'm new to WordPress development and I'm currently encountering a dead-end.
I want an admin notice to be displayed in a WooCommerce order after the order's status has been changed.
With the following code, the notice doesn't appear:
<?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();
I have tried setting the "priority" parameter of the "admin_notices" action to 20, without success (I think it would have been useful if the nested action was the same as the one first called).
However, when I call "admin_notices" action directly in testTheNotice() method (and thus not calling "woocommerce_order_status_changed" action), it works (on every admin page, which is not what I want).
I thought it was because the notice() was somehow not recognised, but it actually is: the code below displays "This notice appears on the order page." on a blank page (which is not what I want and only for test purpose).
<?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();
I'm aware there's a special class and method for WooCommerce admin notices, and writing below code in notice() displays a notice, but with a purple border (because of the "update" css class, which I haven't found how to change) instead of a red border (which would be possible thanks to the "error" css class, which I don't know how to apply).
$adminNotice = new WC_Admin_Notices();
$adminNotice->add_custom_notice("Test",'<p>This notice appears on the order page.</p>');
$adminNotice->output_custom_notices();
Good question. It got me curious and made me dig into this
WC_Admin_Noticesclass. And here's what I found out!Well, before I talk about
WC_Admin_Noticesclass, first let's talk about your first question!Because when the
woocommerce_order_status_changedhook fires there is no screen associated with it and it's not just notices, for example if you try to do aprint_rand/or anechothey won't show anything either because there is no screen associated with that hook. The only way you could find out that you hit that hook is by usingdiefunction. In order to test this, you could do this:But if you replace the
die('You hit the right hook!')function withechoorprint_r, they won't show anything no matter how high you set the priority of the hook.It gets interesting when you use
WC_Admin_Noticesclass. If there is no screen associated with thewoocommerce_order_status_changedhook, then how does this class work? Well, here's how:$noticeswhich is a simple empty array.add_custom_noticemethod, it'll store the values you gave it, into the database and into the "options" table. The key would be "woocommerce_admin_notice_{the name you gave for example test}", and the value would be the message/notice you defined. That's all it does! It stores your message/notice into the database.output_custom_noticesmethod, it'll check the$noticesarray, and check the database for any key value pairs stored in the options table with the format I just mentioned in number 2! Then, it uses a template calledhtml-notice-custom.phpin the following path:The
html-notice-custom.phpfile is responsible for outputting the html markup for custom notices and it'll give them a class calledupdatedwhich will trigger a css rule that has a light purple color.So the overall workflow of the
WC_Admin_Noticesclass is:Technically, that's all it does, well, in the simplest terms!
Since we don't want that custom light purple template, we could use the workflow that
WC_Admin_Noticesuses and write our own solution without usingWC_Admin_Noticesclass.We could use one of the following approaches:
$_SESSION+admin_noticeshookcookieorlocal storage+admin_noticeshookdatabase+admin_noticeshookI think, if we use
$_SESSION+admin_noticeshook approach, it'd be both safe and fast without even query the database for a simple string of text. Here's the solution I can think of at this moment:Code goes into the
functions.phpfile of your active theme.Note:
$old_statusis not equal to the$new_status.$noticevariable, I put raw text, not html, since we put aptag in the html section/template of theadmin_noticeshook.notice-errorclass for thedivtag which shows thered colorfor the notice. You could replace it withnotice-warning, ornotice-infoornotice-success.This answers has been fully tested on woocommerce
5.7and works fine.