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_Notices
class. And here's what I found out!
Well, before I talk about WC_Admin_Notices
class, first let's talk about your first question!
"the notice doesn't appear"
Because when the woocommerce_order_status_changed
hook fires there is no screen associated with it and it's not just notices, for example if you try to do a print_r
and/or an echo
they 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 using die
function. In order to test this, you could do this:
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!');
}
But if you replace the die('You hit the right hook!')
function with echo
or print_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_Notices
class. If there is no screen associated with the woocommerce_order_status_changed
hook, then how does this class work? Well, here's how:
class-wc-admin-notices.php
Class
$notices
which is a simple empty array.add_custom_notice
method, 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_notices
method, it'll check the $notices
array, 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 called html-notice-custom.php
in the following path:yourwebsite.com > wp-content > plugins > woocommerce > includes > admin > views > html-notice-custom.php
html-notice-custom.php
Template
The html-notice-custom.php
file is responsible for outputting the html markup for custom notices and it'll give them a class called updated
which will trigger a css rule that has a light purple color.
WC_Admin_Notices
class 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_Notices
uses and write our own solution without using WC_Admin_Notices
class.
We could use one of the following approaches:
$_SESSION
+ admin_notices
hookcookie
or local storage
+ admin_notices
hookdatabase
+ admin_notices
hookI think, if we use $_SESSION
+ admin_notices
hook 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.php
file of your active theme.
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']);
}
}
Note:
$old_status
is not equal to the $new_status
.$notice
variable, I put raw text, not html, since we put a p
tag in the html section/template of the admin_notices
hook.notice-error
class for the div
tag which shows the red color
for the notice. You could replace it with notice-warning
, or notice-info
or notice-success
.This answers has been fully tested on woocommerce 5.7
and works fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With