ignore_shipping_classes implementation recommendations
-
Let’s start with the code in question:
$shipping_classes = $this->get_shipping_classes();
if ( ! empty($shipping_classes)) {
$prepared_shipping_classes = [];
foreach ($shipping_classes as $shipping_class) {
$prepared_shipping_classes[$shipping_class->term_id] = $shipping_class->name;
}
$this->instance_form_fields = array_merge($this->instance_form_fields, [
'ignore_shipping_classes' => [
'title' => __('Disable this method for these shipping classes', 'woocommerce-shopup-venipak-shipping'),
'type' => 'ignore_shipping_classes', // 'multiselect',
'default' => null,
'description' => __('If at least one has product has selected shipping classes it will disable this shipping method', 'woocommerce-shopup-venipak-shipping'),
'desc_tip' => true,
'options' => array(), // $prepared_shipping_classes
]
] );
}Intention here is to display extra settings field when shipping classes are used in WooCommerce shipping settings for the particular shipping method (courier or pickup).
Why is this bad? Shipping method is also initialized on cart and checkout pages (frontend), but we don’t need to display any settings there, so these 2 SQL queries (one for courier and one for pickup) could be removed to improve the performance.
Proposed solution:
$this->instance_form_fields = [
...
'min_amount_for_free_shipping' => [
'title' => __('Minimum Order Amount For Free Shipping', 'woocommerce-shopup-venipak-shipping'),
'type' => 'price',
'placeholder' => wc_format_localized_price(0),
'description' => __('Users will need to spend this amount to get free shipping (if enabled above).', 'woocommerce-shopup-venipak-shipping'),
'desc_tip' => true
],
'ignore_shipping_classes' => [
'title' => __('MB: Disable this method for these shipping classes', 'woocommerce-shopup-venipak-shipping'),
'type' => 'ignore_shipping_classes', // define custom field type instead of 'multiselect',
'default' => null,
'description' => __('If at least one has product has selected shipping classes it will disable this shipping method',
'woocommerce-shopup-venipak-shipping'),
'desc_tip' => true,
'options' => [], // pass empty array instead of $prepared_shipping_classes
],
];First step, move
ignore_shipping_classesinside$this->instance_form_fields. We replacingmultiselectfield type with customignore_shipping_classes(can be anything not taken by WooCommerce) and we also pass empty array for options.Next, lets remove the code that retrieves shipping classes and appends array with setting we already defined in step 1.
$shipping_classes = $this->get_shipping_classes();
if ( ! empty($shipping_classes)) {
...
}Last step is to create a new method within the same shipping class to render our custom field.
/**
* Inject multiselect options for custom field; This will only trigger when
* settings form is rendered.
*
* @param string $key
* @param array $data
*
* @return string
*/
public function generate_ignore_shipping_classes_html( $key, $data ) {
$shipping_classes = $this->get_shipping_classes();
if ( ! empty( $shipping_classes ) ) {
$prepared_shipping_classes = [];
foreach ( $shipping_classes as $shipping_class ) {
$prepared_shipping_classes[ $shipping_class->term_id ] = $shipping_class->name;
}
// Set options for the field.
$data['options'] = $prepared_shipping_classes;
// Pass all the options and configurations to multiselect renderer.
return $this->generate_multiselect_html( $key, $data );
}
return ''; // method expects string as a result.
}We still retaining the old logic of not displaying the settings field unless the shipping classes are found, but we also avoid unnecessary queries on the frontend pages without loosing the usability and functionality on the backend.
Note: You should be ale to observe queries with Query Monitor.
There is one more function
get_shipping_classes()call insidecalculate_shipping(). From the first sight it could be removed (haven’t tested that bit yet) as well, even if$ignored_classes = $this->get_option('ignore_shipping_classes', []);option is not set / initialized as it won’t throw any warning/error/notification and return value specified as second param ([]).The block could be simplified to (untested):
$ignored_classes = $this->get_option( 'ignore_shipping_classes', [] );
if ( is_array( $ignored_classes ) && ! empty( $ignored_classes ) ) {
$found_shipping_classes = $this->find_shipping_classes_for_package( $package );
foreach ( $found_shipping_classes as $found_class ) {
if ( in_array( $found_class, $ignored_classes ) ) {
return;
}
}
}Test only, if we have any ignored classes selected, otherwise proceed with other checks and creating the rate.
The topic ‘ignore_shipping_classes implementation recommendations’ is closed to new replies.