WordPress.org

Ready to get started?Download WordPress

Forums

[resolved] Trying to create plugin for results per page - Woocommerce (20 posts)

  1. DesignLoud
    Member
    Posted 1 year ago #

    Hey all, I need some help here if anyone is able to chime in and offer their support. So I want to create a plugin that will offer a dropdown on the catalog page of Woocommerce so that users can select how many products are being viewed per page. I almost (in my eyes) have it but cant quite work out the kinks. Any takers?

    Here is what I have:

    function woocommerce_sortby_page() {
    
    	if ('woocommerce_catalog_page_ordering'==$twelve)
      {
      add_filter('loop_shop_per_page', create_function('$cols', 'return 12;'));
      }
    elseif ('woocommerce_catalog_page_ordering'==$sixteen)
      {
      add_filter('loop_shop_per_page', create_function('$cols', 'return 16;'));
      }
      elseif ('woocommerce_catalog_page_ordering'==$twenty)
      {
      add_filter('loop_shop_per_page', create_function('$cols', 'return 20;'));
      }
      elseif ('woocommerce_catalog_page_ordering'==$twentyfour)
      {
      add_filter('loop_shop_per_page', create_function('$cols', 'return 24;'));
      }
      elseif ('woocommerce_catalog_page_ordering'==$twentyeight)
      {
      add_filter('loop_shop_per_page', create_function('$cols', 'return 28;'));
      }
    else
      {
      add_filter('loop_shop_per_page', create_function('$cols', 'return 4;'));;
      }
    }
    
    function woocommerce_catalog_page_ordering() {
    ?>
    <form action="<?php woocommerce_sortby_page ?>">
    <select name="woocommerce-sort-by-columns">
    <option value="<?php $twelve ?>">12</option>
    <option value="<?php $sixteen ?>">16</option>
    <option value="<?php $twenty ?>" selected>20</option>
    <option value="<?php $twentyfour ?>">24</option>
    <option value="<?php $twentyeight ?>">28</option>
    </select>
    </form>
    <?php
    }
    
    add_action( 'woocommerce_pagination', 'woocommerce_catalog_page_ordering', 20 );

    I'm sure I am probably way off but am new to plugins and relatively new to the codex and PHP..

    Here is how Woo does their "Show results per page" which I assume would be similar to what I need to do?

    <form class="woocommerce_ordering" method="POST">
    	<select name="sort" class="orderby">
    		<?php
    			$catalog_orderby = apply_filters('woocommerce_catalog_orderby', array(
    				'menu_order' 	=> __('Default sorting', 'woocommerce'),
    				'title' 		=> __('Sort alphabetically', 'woocommerce'),
    				'date' 			=> __('Sort by most recent', 'woocommerce'),
    				'price' 		=> __('Sort by price', 'woocommerce')
    			));
    
    			foreach ( $catalog_orderby as $id => $name )
    				echo '<option value="' . $id . '" ' . selected( $_SESSION['orderby'], $id, false ) . '>' . $name . '</option>';
    		?>
    	</select>
    </form>

    Thanks for the help and Happy Holidays!

  2. bcworkz
    Member
    Posted 1 year ago #

    The woo snippet you provide does not affect the results per page in itself, it must be done elsewhere. I would assume the result count is taken care of much like WP_Query, where a LIMIT parameter is appended to the query to only return the results appropriate for the particular page number. So if you specified 25 results per page and are querying for page 3, the LIMIT argument would be LIMIT 50, 25.

    I would think you would do something similar to the query for each page of products. To see how WP_Query does it, look at wp-includes/query.php around line 2534.

  3. DesignLoud
    Member
    Posted 1 year ago #

    Woocommerce actually has support for this through its actions and filters. Below is what has been updated and I feel like it is close but I cannot figure out how to apply the changes, say I click on 24, how should I go about getting the page to reload and apply the users selection. Does what I have below seem like I am on the right path? Anyone able to chime in on how to apply the users selection to the page?

    Updated code:

    function woocommerce_sortby_page () {
      $value = $_POST['value'];
      add_filter('loop_shop_per_page', create_function('$cols', 'return $value;'));
    }
    
    function woocommerce_catalog_page_ordering() {
    ?>
    <form action='<?php echo $_SERVER['PHP_SELF']; ?>' method='post'>
    <select name="woocommerce-sort-by-columns">
    <option value="12">12</option>
    <option value="16">16</option>
    <option value="20" selected>20</option>
    <option value="24">24</option>
    <option value="28">28</option>
    </select>
    </form>
    <?php
    } 
    
    add_action( 'woocommerce_pagination', 'woocommerce_catalog_page_ordering', 20 );
  4. bcworkz
    Member
    Posted 1 year ago #

    Yes, you are close.
    1. Assign a name to the form element, say name="results"
    2. Add an onchange attribute to the select element: onchange="document.forms['results'].submit();"
    3. The value passed is available as $_POST['woocommerce-sort-by-columns'], the form field name will be the array key.

  5. DesignLoud
    Member
    Posted 1 year ago #

    excuse me if this is a laughable question but where do I put the array key 'results'?

    Just to make sure I am paying attention here is where I am with it

    function woocommerce_sortby_page () {
      $value = $_POST['woocommerce-sort-by-columns'];
      add_filter('loop_shop_per_page', create_function('$cols', 'return $value;'));
    }
    
    function woocommerce_catalog_page_ordering() {
    ?>
    <form action="" method="post" name="results">
    <select name="woocommerce-sort-by-columns" onchange="document.forms['results'].submit();">
    <option value="12">12</option>
    <option value="16">16</option>
    <option value="20" selected>20</option>
    <option value="24">24</option>
    <option value="28">28</option>
    </select>
    </form>
    <?php
    } 
    
    add_action( 'woocommerce_pagination', 'woocommerce_catalog_page_ordering', 20 );
  6. DesignLoud
    Member
    Posted 1 year ago #

    Ya I have tried adding 'results' where I thought it went but I still cant get it right. It works all the way up to the point where it is actually supposed to display the results for the page.

    Excuse the noobness here but I appreciate you taking the time to help me learn it and get it going.

  7. bcworkz
    Member
    Posted 1 year ago #

    No, you got the placement right, the problem probably lies in the add_filter() function, or more specifically your use of create_function(). It's hard to explain, but $value is out of scope for the function created. I missed this the first time around because I don't know anything about woocommerce filters, so didn't even look at it.

    No worries about noobness, we were all noobs once.

    The first thing to try is to return the $_POST value directly to the filter, so create_function() becomes:
    create_function('$cols', 'return $_POST["woocommerce-sort-by-columns"];')
    Then you can remove the preceding $value = ... line. This may not work since I don't know the context from which the filter is initiated. If it doesn't work, you'll need to go back to the version you have now and declare $value as global. But choose a less generic global name like $dl_page_value. Then add the line global $dl_page_value; to both functions. And of course change the instances of $value to $dl_page_value accordingly.

    If you still have trouble, it may be useful to me to know what the $cols parameter passed in the filter is supposed to be, because you more than likely are supposed to return something similar.

  8. DesignLoud
    Member
    Posted 1 year ago #

    Thanks, Tried it out and still no luck.... yet.. Here is what I found in the Woo files, let me know if I need to look for something else or this isn't it.

    // Query vars that affect posts shown
    		if ( ! $q->is_tax( 'product_cat' ) && ! $q->is_tax( 'product_tag' ) )
    			$q->set( 'post_type', 'product' );
    		$q->set( 'meta_query', $meta_query );
    	    $q->set( 'post__in', $post__in );
    	    $q->set( 'posts_per_page', $q->get( 'posts_per_page' ) ? $q->get( 'posts_per_page' ) : apply_filters( 'loop_shop_per_page', get_option( 'posts_per_page' ) ) );

    Here are a couple of files I think might be relative as well since they call the 'loop_shop_per_page':
    content-product.php

    content-product_cat.php

  9. DesignLoud
    Member
    Posted 1 year ago #

    Wow, after tons of exploring on the internet, a full nights sleep and a cup of coffee (make that two cups) I finally got it!! Thanks so much for your help!

    Now I only face two small problems:
    1) how do I get the number of results per page that the user sets display through all pages? Currently I can select 4 products per page and the page I am on adjusts but when I click on next page it goes back to default.

    2) This isnt as big of a deal but is there anyway to make the option the user chooses the 'selected' one when the page refreshes? In other words when I click on 24 results per page and hit submit, when the page reloads with the adjustments the dropbox still has the first option as the selected tag.

    here is what is currently working:

    function woocommerce_catalog_page_ordering() {
    ?>
    <form action="" method="POST" name="results">
    <select name="woocommerce-sort-by-columns" id="woocommerce-sort-by-columns" class="sortby">
    <?php
    			$shopCatalog_orderby = apply_filters('woocommerce_sortby_page', array(
    			    ''       => __('Results per page', 'woocommerce'),
    				'4' 	=> __('4 per page', 'woocommerce'),
    				'12' 		=> __('12 per page', 'woocommerce'),
    				'24' 		=> __('24 per page', 'woocommerce'),
    			));
    
    			foreach ( $shopCatalog_orderby as $sort_id => $sort_name )
    				echo '<option value="' . $sort_id . '" ' . selected( $_SESSION['sortby'], $sort_id, false ) . '>' . $sort_name . '</option>';
    		?>
    </select>
    <input name="submitbutton" type="submit" value="submit" />
    </form>
    <?php
    
    } 
    
    function dl_sort_by_page() {
    global $dl_page_value;
      $dl_page_value = $_POST['woocommerce-sort-by-columns'];
    
      return $dl_page_value;
    }
    
    add_filter('loop_shop_per_page','dl_sort_by_page');
    add_action( 'woocommerce_pagination', 'woocommerce_catalog_page_ordering', 20 );

    Now im going to make that second cup o'joe :D

  10. bcworkz
    Member
    Posted 1 year ago #

    That's some good progress for only two cups!
    I know you've put lot's of time into this little thing, but it's like the proverb about give a man a fish and he eats for the day. Show him how to fish and he eats for life.

    About your remaining problems. Unfortunately, I don't know anything about woocommerce. It seems to me that if they had the foresight to provide these filters to allow extending their product, they would have provided methods for user selections to persist between page loads. But I've no idea how access them.

    I can talk about general theory so you have some idea what to look for and a direction to follow. First, keep it straight that what happens in the user's browser is completely separate from what happens on your server. The only relationship is maintained by an occasional packet of small bits of information. On a basic level, the server has no idea what the user's contextual experience is when it gets a page request. The request can be part of some hot and heavy shopping spree, or the very first page for a casual drive by. The server doesn't know, it's a new page request either way.

    There's essentially two ways for information to persist between page loads. One is the bit of information is included somehow in the next page request, which is what you are retrieving with the $_POST array. The other is the bit of information is stored on the user's browser as a cookie, which the next page checks for when it arrives in the browser.

    The cookie method is good because the data persists as long as the cookie does. But the page needs to know how to deal with the data on it's own. It's beyond the server's control to some extent.

    The transmit method involves the server and can allow a customized response accordingly. But if the user leaves the page, the data could be lost, restoring things to default state.

    Either method could solve your problem, and I would expect woocomerce would use one or the other. If you can't find it, your next move would probably be to start a new thread either here or on the woocommerce support.

    If you did have to implement persistence on your own, you probably should go with cookies. Ensuring the data gets sent with all requests would be a nightmare. This would be a javascript or jquery implementation that runs on any page load and checks for a cookie, and if found, basically does the submit you are now doing manually via script. Good luck... and try to get some enjoyment out of this!

  11. DesignLoud
    Member
    Posted 1 year ago #

    Wow thanks for that head start and thanks so much for your help! Cheers

  12. mjrwebdesign
    Member
    Posted 1 year ago #

    Hi guys

    I stumbled upon your post as I needed the same functionality.

    I've played around with the code and got my select box working and it holds the value on page refresh without any cookies. i'm using woocommerce 1.6.6. Hope this helps anyone else who needs the same.

    Here's my code: Woocommerce Products per page filtering

  13. mjrwebdesign
    Member
    Posted 1 year ago #

    Hi Everyone

    Slight edit to code as the above wasn't begin triggered in IE as IE doesn't recognised 'results' as an object!

    on Line 5 find... onchange="document.forms['results'].submit();">
    change this to... onchange="submit();">

    Many thanks

  14. lukelukeluke
    Member
    Posted 12 months ago #

    This is amazing, but my pagination stops working. I get a 404 page not found error. Any ideas what is happening here?

    Thanks

    Luke

  15. mjrwebdesign
    Member
    Posted 12 months ago #

    Luke

    What version of woocommerce are you using and are you using a pagination plugin or is it built into your theme?

    Mark

  16. lukelukeluke
    Member
    Posted 12 months ago #

    Hello mark,

    thanks for reply.

    it is the latest version of woocommerce. 2.08

    The pagination is built into the theme. It is proffet theme from themeforest. Pagination works fine normally.

    for example if i do this -

    add_filter( 'loop_shop_per_page', create_function( '$cols', 'return 2;' ), 20 );

    Then it works.

  17. lukelukeluke
    Member
    Posted 12 months ago #

    It is working!

    No idea why. I didn't change anything but it just fixed itself!

  18. mjrwebdesign
    Member
    Posted 12 months ago #

    Hi Luke

    I was using woocommerce 1.6.6 when I submitted the code. The pagination has had a overhaul in woocommerce 2.0. Are you using woocommerce's built-in pagination or the theme's pagination and have you got the newest version of the proffet theme.

    I'm using flexishop 2 and i'm upgrading to woocommerce 2.0 this weeks so I will try and resolve this on my test site in the next few days as I will need this functionality when I upgrade the plugin for my client.

  19. DesignLoud
    Member
    Posted 12 months ago #

    Hey Luke, I dont know who's version you were using but if it was our version found here then all you should need to do is replace the "your-web-address.com" with your actual web address.. Version should not matter since we are writing our own functions and hooking in to Woocommerce, which has and I anticipate it remaining the same in future updates.

    Hope this helps, thanks

  20. lukelukeluke
    Member
    Posted 12 months ago #

    Thanks for getting back to me. It seems to be working now. Great work by the way!

    Luke

Topic Closed

This topic has been closed to new replies.

About this Topic