Skip to content

Instantly share code, notes, and snippets.

@barryhughes
Created September 18, 2024 23:40
Show Gist options
  • Save barryhughes/4b91d476cdf71d8da2117d4d3c0cc18c to your computer and use it in GitHub Desktop.
Save barryhughes/4b91d476cdf71d8da2117d4d3c0cc18c to your computer and use it in GitHub Desktop.
WooCommerce (9.3.x and earlier): redirect to the canonical single product URL if the category slug is invalid.
<?php
/**
* When the product permalink structure is `product/%product_cat%`, WooCommerce (9.3.x or earlier)
* accepts any value as the `%product_cat%`, which is not always desirable.
*
* This snippet attempts to detect this situation, and will redirect to the canonical URL as needed.
* You can add it as a mu-plugin. For example:
*
* wp-content/mu-plugins/canonical-product-redirect.php
*
* ⚠ This outlines a possible solution, but every site is different so be sure to test and be ready
* to remove it in the event it causes problems.
*/
add_action(
'template_redirect',
function () {
global $wp_rewrite;
// Go no further if WooCommerce did not initialize, if we are not looking at a request
// for a single product, or if the $wp_rewrite global is unavailable.
if (
! did_action( 'woocommerce_init' )
|| ! is_product()
|| ! is_a( $wp_rewrite, WP_Rewrite::class )
) {
return;
}
// In the event we are dealing with ugly permalinks, this will be empty.
$specified_category_slug = get_query_var( 'product_cat' );
// If we cannot determine that a category slug was passed via the permalink, go no further.
if ( ! is_string( $specified_category_slug ) || strlen( $specified_category_slug ) < 1 ) {
return;
}
// What category slug did we expect? Normally this maps back to the first assigned product_cat
// term. However, this is filterable so we use the relevant helper function to figure this out.
$expected_category_slug = wc_product_post_type_link( '%product_cat%', get_post( get_the_ID() ) );
// If the provided and expected category slugs match, go no further.
if ( $specified_category_slug === $expected_category_slug ) {
return;
}
// Redirect along with any query vars.
$query_vars = isset( $_GET ) && is_array( $_GET ) ? $_GET : array();
wp_safe_redirect( add_query_arg( $query_vars, wc_get_product( get_the_ID() )->get_permalink() ) );
exit();
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment