Implementing Custom WC_Data classes

Overview

In this topic, we’ll provide an overview of extending WC_Data and then delve into some of the key considerations and a ‘cookbook’ process for extending each of the WC_Data families.

 

There’s a lot of information to cover here, don’t feel like you need to memorize all this–that’s a lot of extra brain space. Instead, refer back to this information frequently, whenever you need to customize the behavior of one or more data class families.

 

Let’s get started 🙂

Extending WC_Data

  • Generally, more complex families e.g. Product, Order, Order_Item are loaded by factories or factory methods in other classes. These families lend themselves well to custom classes that extend default functionality
  • With simpler WC_Data class families e.g. Coupons, Customer_Downloads, Webhooks, the constructors are often directly called by other classes in WooCommerce These families do not work well with creating custom extended classes. The ideal strategy is to use class specific hooks, or general WC_Data hooks or custom data stores to create the desired behavior
  • When a class has a singular name (e.g. WC_Shipping_Zone) and a plural name (e.g. WC_Shipping_Zones), the plural class is the “manager” class that will load the singular classIdeally, attempt to implement your customizations using hooks into the manager class

Extending the WC_Product Family

This is one of the most frequently extended classes. Be sure to checkout the WooCommerce Store before you reinvent the wheel with your new product type Many businesses offer unique items for sale to their customers that don’t fit well within the standard define WC_Product family. In this case, it can be advantageous to create a custom WC_Product Family type

  1. In the install function of your plugin or theme, add a term to the product_type taxonomy that defines your custom type
  2. Add the product type to your shop manager area with the ‘product_type_selector’ filter*

*Note: Steps 1 and 2 are the absolute minimum to add a custom product type. The product factory will use WC_Product_Simple as it’s default class. You can fully customize behavior from there, using conditional action and filter hooks, if you choose.

Extending the WC_Product Family (cont)

  1. Create a custom product class name WC_Product_{Product_Type}. Using this naming convention will ensure WC_Product_Factory handles your custom type. This class can extend any of the existing WC_Product classes.
  2. Assign the custom product type a public method get_type() that returns the name of your new custom product_type term. this will also be used to determine which data store is loaded
  3. The new class will automatically use WC_Product_Data_Store_CPT. You can modify this by using the ‘woocommerce_product_data_stores filter’

Extending the WC_Order Family

Sometimes the way a customer purchases a product doesn’t map cleanly to WooCommerce’s Cart/Purchase Order System. A popular example of this is in a subscription scenario. In these cases, it can be efficient to extend the WC_Order family to implement that custom functionality

  1. Register your order type, during the ‘init’ action hook, with a callback that calls the wc_register_order_type($type, $args) function, which in turn registers your custom order type as a custom post type
  2. Create the class for your order type, Typically, this class will extend the WC_Order class which should have the same class name as used in the ‘class_name’ args in calling called the wc_register_order_type function.
  3. Create a method in your class named ‘get_type’ that returns the $type string registered in step one.
  4. OR…

Extending the WC_Order Family (cont)

  1. Create the class for your order custom type. Typically, this class will extend the WC_Order class to use as much of default functionality as applicable
  2. Use the ‘woocommerce_order_class’ filter to drive logic for loading your custom class

Finally, to actually use your custom order type on the front end, hook into the checkout process with the ‘woocommerce_create_order’ filter with your custom logic.

Extending the WC_Order_Item family

Standard WooCommerce Order Item types include products, coupons, fees, shipping, and taxes– basically anything directly involved in the calculation of the order’s total. Generally, these default fields are sufficient to manage most situations. However, if necessary, implementing your own custom order-item class is fairly easy.

  1. Review the hooks available to you in the WC_Checkout process. Ensure that you will be able to implement your desired conditions to load your custom order item type when necessary.
  2. Create your custom class which extends WC_Order_Item or one of its descendants
  3. Set the ‘get_type’ method of your custom class to return a string, unique to your class (this will be your ‘order_item_type’ value in the data store)

Extending the WC_Order_Item family (cont)

  1. Because of the way WC_Data_Store parses type names, It breaks the type on ‘-‘ markers, which creates a unique problem for order-item-types you will need to define the data store for your new class using the ‘woocommerce_data_stores’ filter. This can either be an existing data store, or your own custom data store
  2. Set your new custom class to be loaded using the ‘woocommerce_get_order_item_classname’ filter, which is in the WC_Order_FactoryThe order factory manages both the loading of Orders and Order_Items
  3. Implement the logic to utilize you custom class using the hook(s) that you identified in step 1

Extending the WC_Payment_Token family

In order to set up custom payment gateways with saved customer payment tokes you may to set up a custom Payment Token class to match that gateway’s requirements. Fortunately, WooCommerce offers a robust payment token API.

  1. Create your custom class extending the WC_Payment_Token with a name prefixed by WC_Payment_Token_{Your_Custom_Type}
  2. Set the $type property of your custom class to equal the suffix of your custom class* e.g. Your_Custom_Type in step one^^^
  3. You will likely want to implement some custom validation logic
  4. Associate the creation of your payment token with your custom payment gateway’s ‘add_payment_method()’ method While this information covers everything you need to get your token set up, there are other actions you will need to take to make your payment gateway work. Visit the Woo Wiki tutorial for more information

If, for some reason, you do not want to use the standard naming nomenclature, you may override default behavior using the ‘woocommerce_payment_token_class’ filter

Extending the WC_Coupon Family

WC_Coupon is involved in a series of interactions between WC_Cart and WC_Discounts.
For this reason, developers should avoid directly extending the WC_Coupon class and build custom coupon behavior either by creating a custom data store or with the following filters:

  1. Add a custom discount type using the ‘woocommerce_coupon_discount_types’ filter.
  2. Validate the custom coupon with the ‘woocommerce_coupon_is_valid’ filter.
  3. Add logic for calculating the coupon using the ‘woocommerce_coupon_get_discount_amount’ filter

WC_Customer_Download

The WC_Customer_Download constructor is directly called by WC_Download_Handler. Extending is not recommended. Instead, use these hooks to customize behavior:Found in the WC_Download_Handler class and the Data Store

Actions Filters
woocommerce_download_product woocommerce_file_download_filename
woocommerce_download_file_{file_download_method} woocommerce_file_download_method
woocommerce_grant_product_download_access woocommerce_download_file_xsendfile_file_path
woocommerce_download_file_xsendfile_lighttpd_file_path
woocommerce_download_file_xsendfile_x_accel_redirect_file_path
woocommerce_customer_get_downloadable_products
woocommerce_downloadable_file_permission_data
woocommerce_downloadable_file_permission_format

Alternately, you could customize behavior by implementing a custom data store, with logic that result in the desired behavior

The situation is even worse with WC_Customer_Download_Log. Your only hooks for customizing this class’s behavior are these filters:

  • woocommerce_downloadable_product_download_log_insert_data
  • woocommerce_downloadable_product_download_log_insert_format

Extending the WC_Customer family

The WC_Customer constructor is directly called by the WooCommerce final singleton class and loaded as it’s $customer property. For this reason, directly extending the WC_Customer class is not advisable.
Instead, use a custom data store to customize behavior and data, or use the following filters:

Extending the WC_Shipping_Zone family

The WC_Shpping_Zone constructor is directly called by WC_Shipping_Zones. Custom behavior can be generated with the following hooks:

Actions Filters
woocommerce_shipping_zone_method_added woocommerce_shipping_zone_shipping_methods A final cut on which shipping methods will be allowed in a given cart
woocommerce_shipping_zone_method_deleted woocommerce_valid_location_types
woocommerce_shipping_zone_loaded woocommerce_get_zone_criteriaUsed on $wpdb WHERE clauses for getting zones

Extending the WC_Webhook family

The wc-webhook-functions.php file loads the webhook API and directly calls the WC_Webhook constructor. To customize this behavior you should focus on the following filters:

  • woocommerce_webhook_topic_hooksTo implement your own custom webhook action
  • woocommerce_webhook_hooks
  • woocommerce_webhook_should_deliver
  • woocommerce_webhook_http_args
  • woocommerce_webhook_payloadFor complete control over the webhook’s payload

and the following actions:

  • woocommerce_new_webhook
  • woocommerce_webhook_process_delivery
  • woocommerce_webhook_deliveryFired with every webhook delivery

Conclusion

Wew! That’s a lot of info. You’re not expected to remember all that. Just remember that the information is here, and can be used as a cheat sheet anytime you want. And be sure to use the resources list to help dive deeper into a topic if you need more info.

You should now have confidence that, whatever WC_Data customization task is part of your next project, you’re armed for the task.

In the next section, we’re going to go one layer deeper–customizing the Data Stores.

Knowledge Check

Hint: Since this topic is mostly a “cookbook” the meta answers are in the front matter

×

Keyboard shortcuts

CTRL+Shift+F Search slideshow
F Fullscreen view
CTRL+Click Zoom in
Esc Topic overview
Right arrow,
Down arrow
Next slide
Left arrow,
Up arrow
Previous slide

Color codes

Tooltip
Hover over text more additional info
Link to an external resource
Link to an internal slide
If buttons aren't working, click in the screen to "focus" your browser
RSS
LinkedIn
Share