Fresh WordPress online store plugin

Some time ago I needed to create an online store on WordPress. There are many good solutions in the official repository. Among them, the leader - Woocommerce has long stood out. I think he does not need an introduction. A multimillion army of users, hundreds of paid and free extensions and incredible flexibility. This is why Woocommerce has over 5 million active installations and covers a large share of online stores worldwide.



Still, I decided to invent my bike. Partly, to upgrade skills, partly to try to make a non-resource-intensive and fast enough ecommerce plugin. I recently posted it in the official repository , therefore, I invite everyone to test it. In this article I will not do an overview of the possibilities, but I will only talk about some interesting technical solutions.







Permalinks Problem



In general, permalinks in WordPress are one of the most difficult sites, as they require solving a number of problems of connections and dependencies. WpStore has the ability to manage permalinks. For example, you can remove the product



slug from the product



url, change to your own or add the category slug or even category nesting to it. Links to products may look like this: ./-/---/---/-/



. Not bad.



I had to sweat a lot to get categories nesting. Using the wp_get_object_terms,



function wp_get_object_terms,



we obtain the categories of the specified product, and then in the cycle we collect the weaknesses and form the url hierarchy from parent to child. To display the necessary links we use the post_link filter. Here is just part of the code (you can see the full code in the source):



 add_filter( 'post_link', 'wpsl_post_type_permalink', 20, 3 ); add_filter( 'post_type_link', 'wpsl_post_type_permalink', 20, 3 ); function wpsl_post_type_permalink( $permalink, $post_id, $leavename ) { .... /** * Works only in the admin panel when changing the structure of permanent links or creating/updating the product * In the frontend to display links to products using $post->guid * Relevant if the structure of permalinks are used %category% or %categories% */ if ( is_admin() ) { // get all terms (product categories) of this post (product) by hierarchicaly // change %category% if ( strpos( get_option( 'product_permalink' ), '%category%' ) !== false && $terms = wpsl_get_terms_hierarchicaly( $post->ID, 'product_cat' ) ) { $custom_slug = str_replace( '%category%', isset( $terms[0] ) && is_object( $terms[0] ) ? $terms[0]->slug : '', $custom_slug ); } // change %categories% if ( strpos( get_option( 'product_permalink' ), '%categories%' ) !== false && $terms = wpsl_get_terms_hierarchicaly( $post->ID, 'product_cat' ) ) { foreach( $terms as $term ) { $hierarchical_slugs[] = $term->slug; } $custom_slug = str_replace( '%categories%', implode( '/', $hierarchical_slugs ), $custom_slug ); } else { $custom_slug = str_replace( '%categories%', 'product', $custom_slug ); } } .... return $permalink; }
      
      





But at this point, a performance problem arose. The site began to work more slowly, especially on the output page of several products. For example, on the category page with the output of only 16 products, almost 90 queries were made to the database and the server response time increased dramatically by about 25-30%.



It turned out that when calling the_permalink function , WordPress performs many operations: it gets the type of CNC and collects the post data depending on this type. To display 1 link WordPress produces several non-cached requests to the database. Moreover, the process of obtaining taxonomies and hierarchies of goods is not the fastest.



Since the constant generation of the link does not suit us, it is logical to store it somewhere and then just pull it from there. It was decided to use the special guid



field of the guid



table. Although WP developers do not recommend changing it, we can still ignore this warning for several reasons:





In order to keep the links in the database correctly, we save_post



function on the save_post



event that updates the guid field:



 add_action( 'save_post', 'wpsl_guid_rewrite', 100 ); function wpsl_guid_rewrite( $id ) { if( !is_admin() ) return; if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return false; if ( strpos( get_option( 'product_permalink' ), '%category%' ) !== false || strpos( get_option( 'product_permalink' ), '%categories%' ) !== false ) { if( $id && get_post_type( (int)$id ) == 'product' ){ global $wpdb; $wpdb->update( $wpdb->posts, [ 'guid' => ( get_permalink( $id ) ) ], [ 'ID' => intval( $id ) ] ); } clean_post_cache( $id ); } }
      
      





We post_type_link



have to intercept the output of the link on the post_type_link



hook and output the generated link:



 add_filter( 'post_type_link', 'wpsl_get_permalink_change', 10, 4 ); function wpsl_get_permalink_change( $post_link, $post, $leavename, $sample ){ if ( isset( $post->guid ) && $post->guid && $post->post_type == 'product' && ( strpos( get_option( 'product_permalink' ), '%category%' ) !== false || strpos( get_option( 'product_permalink' ), '%categories%' ) !== false ) ) { return $post->guid; } return $post_link; }
      
      





Here we check the completeness of the guid field, post type and CNC type. If the values โ€‹โ€‹of the three parameters suit us, display the previously saved link.



Now, the best part is: look at the results. The number of queries to the database decreased by almost 2 times - from almost 90 to 44! And the server response time on the test hosting dropped to an acceptable 0.24 seconds.



Updating the guid field occurs not only during the creation and editing of goods. The plugin has a built-in system for importing goods through csv, so the update also occurs when the import is complete.



Update: plugin documentation



All Articles