WooCommerce uses a number of global variables, if you’ve spent any time looking at code snippets then you’ll often see code like this
global $product;
Which is used to get a reference to the current product that is being displayed, typically on the shop screen or the single product page.
Click here for more details about the "Learning WooCommerce Development By Example" book
Recently whilst looking through the WooCommerce slack channel, I saw a question which asked
Does anyone know when the
global $productis set up? when is the earliest you can access it.
The question was answered by Brian Henry via an ingenious code snippet, so I thought I’d write a quick blog post about the code to try and cement it into my brain. Here’s the code that Brian posted.
global $has_product_global_been_set;
$has_product_global_been_set = function() {
global $product;
if( !empty( $product ) ) {
$was_set = current_action();
error_log( "global \$product first set on action {$was_set}" );
global $has_product_global_been_set;
remove_action( 'all', $has_product_global_been_set, 999 );
}
};
add_action( 'all', $has_product_global_been_set, 999 );
I’ll go through what the code is doing line by line
- Firstly, it sets up a global variable named
$has_product_global_been_set - It then assigns a function to this variable
- The first line of the function gets a reference to the global
$productvariable - It then checks to see if the
$productvalue has been set via PHP’s empty function - If the
$productvariable is set then it it writes the name of the current running action to the$was_setvariable - It then logs then name of the action in the
$was_setvariable using the error_log function. I recently wrote a blog post about usingerror_logand the associated constants you need to set it up in WordPress. - Now the function has discovered an action in which the
$productvariable is set, it stops itself from running by removing itself from the “all” hook - It does this by firstly getting a reference to itself using the
global $has_product_global_been_set;code to retrieve the reference that was written into the global scope in the first two lines of the code. - It then calls the remove_action function to unhook itself from the “all” action, this will ensure that the function is not run for any future actions that are fired and that the log entry that records which action the
$productvariable is set in will only be written once. If the code to unhook the function had not been added then the log entry would have been written multiple times for each action that fired after the$productvariable was set. - Finally the
$has_product_global_been_setvariable containing the function is hooked up to the “all” action. Notice how a variable is used that contains a reference to the function rather than providing the function name as a string.
If you add the code to your functions.php file then it will log the first action that fires after the $product value is set.
One the shop page it logs
[23-May-2021 10:53:26 UTC] global $product first set on action woocommerce_shop_loop
On the single product page it logs
[23-May-2021 10:56:07 UTC] global $product first set on action wp
Providing you’ve used the default logging settings for WordPress then the logs above will be written to the “debug.log” file inside the “wp-content” directory of your WordPress site.
Conclusion
Hopefully that snippet will help you, I think there are quite a few ways that the code could be used to dig into how the WordPress or WooCommerce codebase works.
Click here to enroll in our Free WooCommerce Coding Course
I may write some further blog posts about the “all” hook in the future as it is very useful debugging tool, if you have any ideas about what you’d like me to write about or have questions or queries about this article then please don’t hesitate to let me know in the comments.