使用选择下拉列表更改Woocommerce中显示的产品数量

Trying to add a drop-down on products listing to change the displayed number of products. I am working on the latest version of Wordpress (4.8.2) and Woocommerce (3.1.2).

This is my code on functions.php

//save and load the chosen option from session
function jc_get_products_per_page(){

    global $woocommerce;

    $default = 5;
    $count = $default;
    $options = jc_get_products_per_page_options();

    // capture form data and store in session
    if(isset($_POST['jc-woocommerce-products-per-page'])){ 
        // set products per page from dropdown
        $products_max = intval($_POST['jc-woocommerce-products-per-page']);
        if($products_max != 0 && $products_max >= -1){
            $woocommerce->session->jc_product_per_page = $products_max;
            return $products_max;
        }
    }
    // load product limit from session
    if(isset($woocommerce->session->jc_product_per_page)){
        // set products per page from woo session
        $products_max = intval($woocommerce->session->jc_product_per_page);
        if($products_max != 0 && $products_max >= -1){
            return $products_max;
        }
    }
    return $count;
}
add_filter('loop_shop_per_page','jc_get_products_per_page');

//set the options for the dropdown
function jc_get_products_per_page_options(){
    $options = apply_filters( 'jc_products_per_page', array(
        5 => __('5', 'woocommerce'),
        10 => __('10', 'woocommerce'),
        15 => __('15', 'woocommerce'),
        20 => __('20', 'woocommerce')
    ));

    return $options;
}
//display the dropdown on front-end
function jc_woocommerce_products_per_page(){

    $options = jc_get_products_per_page_options();

    $current_value = jc_get_products_per_page();
    ?>
    <div class="products-per-page">
        <span>View:</span>
        <form action="" method="POST" class="woocommerce-products-per-page">
            <select name="jc-woocommerce-products-per-page" onchange="this.form.submit()">
            <?php foreach($options as $value => $name): ?>
                <option value="<?php echo $value; ?>" <?php selected($value, $current_value); ?>><?php echo $name; ?></option>
            <?php endforeach; ?>
            </select>
        </form>
    </div>
    <?php
}

add_action('woocommerce_after_shop_loop', 'jc_woocommerce_products_per_page', 1);

So the problem is that when I change the dropdown, the page reload but the number of displayed products stay the same. The default. Any idea what is going wrong?

Edit: I tried to add a return 2; on the first row of the function and still doesn't work. So, it seems the add_filter doesn't work

I grabbed your code as is from your initial post and dropped it into a theme I'm developing for WooCommerce and it worked like a charm.

Obviously, that's not your case. But this leads me to believe that something else is likely also hooking into the loop_shop_per_page filter after your code is being called.

Before refactoring all of your code try setting the priority on your add_filter to something high, like so:

add_filter('loop_shop_per_page','jc_get_products_per_page', 99);

That should help to determine if it is an issue with your filter being overwritten by the same filter being called in another plugin or elsewhere in your theme.

Okay I've changed my answer completely and tested the solution, so it should work, only thing is that the pagination was fully working, but it would be good if someone could improve on my answer.

Looking at woocommerce Docs however you should be filtering the $cols variable for it to work. Apologises I couldn't tell exactly what you where doing with your code above so I've rewritten the scripts from scratch - but I think if you just used the $cols then you'd of probably of got there yourself.

Here's the new code:

    add_filter( 'loop_shop_per_page', 'new_loop_shop_per_page', 20 );
    add_action('woocommerce_after_shop_loop', 'new_loop_shop_per_page', 1);
    add_action( 'woocommerce_product_query', 'mywoocommerce_products_per_page', 1, 50 );



    function new_loop_shop_per_page( $cols ) {

        session_start();
        $default = "5";
        $cols = $default;
        $submittedValue = "";
       // global $submittedvalue;
        $value0 = "5";
        $value1 = "10";
        $value2 = "15";
        $value3 = "20";

        if (isset($_POST["ProductsPerPage"])) {

         $_SESSION['ProductsPerPage'] = $_POST['ProductsPerPage'];
         $submittedvalue = $_SESSION['ProductsPerPage'];

        }

        ?>
        <form action="" name="products" method="post">
        <select project="ProductsPerPage" id="ProductsPerPage" name="ProductsPerPage">
         <option value = "<?php echo $value0; ?>"<?php echo ($value0 == $submittedvalue)?" SELECTED":""?>><?php echo $value0; ?></option>
         <option value = "<?php echo $value1; ?>"<?php echo ($value0 == $submittedvalue)?" SELECTED":""?>><?php echo $value1; ?></option>
         <option value = "<?php echo $value2; ?>"<?php echo ($value0 == $submittedvalue)?" SELECTED":""?>><?php echo $value2; ?></option>
         <option value = "<?php echo $value3; ?>"<?php echo ($value0 == $submittedvalue)?" SELECTED":""?>><?php echo $value3; ?></option>
        </select>
        <input type="submit" name="submit" id="submit" value="Submit" />

        </form>


      <?php
      global $submittedvalue;
      $cols = $submittedValue;
      return $cols;

      }


function mywoocommerce_products_per_page( $query ) {
    if ( $query->is_main_query() ) {
         session_start();
         global $submittedvalue;
         //$submittedvalue = '5';
         $_SESSION['ProductsPerPage'] = $_POST['ProductsPerPage'];
         $submittedvalue = $_SESSION['ProductsPerPage'];
         $query->set( 'posts_per_page', $submittedvalue );

    }
}

add_filter( 'redirect_canonical', 'custom_disable_redirect_canonical' );
function custom_disable_redirect_canonical( $redirect_url ) {
    if ( is_paged() && is_singular() ) $redirect_url = false; 
    return $redirect_url; 
}

If someone could help getting the pagination to work as well, it would be helpful.

Try change your jc_get_products_per_page() function with something like this.

    function() jc_get_products_max($ppp=5) {
        if(!empty($ppp)) {
            $ppp = (int)$ppp;
            if($ppp != 0 && $ppp >= -1){
                return $ppp;
            }
        }           
    }
    function jc_get_products_per_page(){    
        global $woocommerce; 
        $count = jc_get_products_max();  
        $options = jc_get_products_per_page_options();
        if(isset($_POST['jc-woocommerce-products-per-page'])){ 
                $count = jc_get_products_max($_POST['jc-woocommerce-products-per-page']);
        } else {
            if(isset($woocommerce->session->jc_product_per_page)){
                    $count = jc_get_products_max($woocommerce->session->jc_product_per_page);
            }
        }
        $woocommerce->session->jc_product_per_page = $count;
        return $count;
    }