I have assembled some custom code which I am using in my functions.php file on my Wordpress/Woocommerce site. The code was originally sourced from here: adding a products per page dropdown to woocommerce.
My code is designed to add a products per page (PPP) drop down box to any archive pages which contain more than one paginated pages worth of products.
The issue I am facing can be highlighted using the following scenario:
- A theoretical archive page contains 100 products.
- The PPP function allows for '12', '24', '36' or 'all' products to show.
- The default is set to show '12' products per page.
- If you navigate to page 6 on this archive, everything works correctly (6 x 12 = 72 [which is less than 100]).
- If you now change the dropdown to '36', because page 6 (6 x 36 = 216 [which is more than 100]) doesn't exist due to a lack of products, a 404 error is presented instead.
The current code can be found here:
add_action( 'woocommerce_before_shop_loop', 'UmbrellaTrading_products_per_page_archive_dropdown', 25 );
add_action( 'woocommerce_after_shop_loop', 'UmbrellaTrading_products_per_page_archive_dropdown', 25 );
function UmbrellaTrading_products_per_page_archive_dropdown() {
$per_page = filter_input(INPUT_GET, 'perpage', FILTER_SANITIZE_NUMBER_INT);
echo '<div class="utwc-perpage">';
echo '<select onchange="if (this.value) window.location.href=this.value">';
$orderby_options = array(
'12' => '12',
'24' => '24',
'36' => '36',
'-1' => 'All'
);
foreach( $orderby_options as $value => $label ) {
echo "<option ".selected( $per_page, $value )." value='?perpage=$value'>$label</option>";
}
echo '</select>';
echo '</div>';
}
add_action( 'pre_get_posts', 'UmbrellaTrading_products_per_page_archive_dropdown_pre_query' );
function UmbrellaTrading_products_per_page_archive_dropdown_pre_query( $query ) {
$per_page = filter_input(INPUT_GET, 'perpage', FILTER_SANITIZE_NUMBER_INT);
if( $query->is_main_query() && !is_admin() && is_post_type_archive( 'product' ) || is_product_category() ) {
$query->set( 'posts_per_page', $per_page );
}
}
The issue seems to be a result of the URL structure. It initially leaves the URL untouched:
https://umbrellatrading.co.uk/shop
It also leaves the URL untouched when pagination is triggered:
https://umbrellatrading.co.uk/shop/page/3
This is where the issue then arises; Because the URL currently adds the PPP code after the pagination, when a PPP URL is generated for a page that doesn't exist, there is nothing preventing this within the code, so a 404 occurs.
https://umbrellatrading.co.uk/shop/page/3?perpage=24
In order for the code to work correctly and without error, I believe the correct URL behaviour should be set (as below) to always redirect to the first page of the referring URL's pagination results, i.e. If you're on page 3 of an archive results page and you trigger the PPP code by selecting from the dropdown on the front end, you should be redirected to page 1 of the same archive level, only with the amended PPP. The URL should therefore look like this.
https://umbrellatrading.co.uk/shop?perpage=24
My question: How can I remove the pagination section ('/page/3' in the example above) of the URL from within my code, but still add the PPP query to the end?
To assist; I can see the full URL is being picked up here in my code: echo '<select onchange="if (this.value) window.location.href=this.value">';, however I am unsure how to cut this into pieces and reconfigure it to show the correct URL structure.