Search code examples
phpwordpresswoocommercehook-woocommerceorders

WooCommerce sort order items by categories


{UPDATE}

I want to sort products on backend order details by category menu order. So my categories are Clothing, Decor, Music, and products must be ordered in this way.

I tried with this snippet

add_filter( 'woocommerce_order_get_items', 'filter_order_get_items_by_categories12', 10, 3 );
function filter_order_get_items_by_categories12($items, $order) {
    global $woocommerce, $wpdb;

        $c1 = $wpdb->get_results( "select t1.order_item_name,t1.order_item_id,t5.name,t2.meta_value from
        wp_woocommerce_order_items as t1 LEFT JOIN wp_woocommerce_order_itemmeta as t2 ON t1.order_item_id =
        t2.order_item_id LEFT JOIN wp_term_relationships as t3 ON t2.meta_value = t3.object_id LEFT JOIN wp_term_taxonomy
        as t4 ON t3.term_taxonomy_id = t4.term_taxonomy_id LEFT JOIN wp_terms as t5 ON t4.term_id = t5.term_id where
        t1.order_id = '" . $order->get_id() . "' and t1.order_item_type='line_item' and t2.meta_key='_product_id' and
        t4.taxonomy='product_cat' ORDER BY `t5`.`name` ASC" );
         
        $sorted_item_ids     = array();
        
        foreach ( $c1 as $data ) {
            if ( !in_array( $data->order_item_id, $sorted_item_ids ) ) {

                $sorted_item_ids[] = $data->order_item_id;
            }
        }
        if( count($items) > 1 ) {
            $item_categories = $sorted_items_ids = array();
            
            foreach ($items as $item_id => $item) {
  
      // Get the product category(ies) term(s) name(s) - (array)
        $term_ids = wp_get_post_terms( $item->get_product_id(), 'product_cat', array('fields' => 'ids') );

            }

            foreach ( $term_ids as $term ) {
            // Categories by slug
             $product_cat_id= $term->id;
            }
            $item_categories[$product_cat_id] = $item_id;
        } 
        
        $query = new WP_Query( array(
       'posts_per_page'  =>  -1,
       'post_type'       =>  array( 'shop_order' ), // <== HERE MISSING
    ) );
   

    // Loop in the Query
  
            // Get the post ID
             $post_id = $query->post->ID;

            // Get the corresponding item ID for the current product ID
            $item_id = $item_categories[ $post_id ];

            // Get the new sorted array of items
            $sorted_items_ids[$item_id] = $items[$item_id];

    wp_reset_query();

    return $sorted_items_ids;
}

This version give me first item how must be, but gives error enter image description here

Error is

Fatal error: Uncaught Error: Call to a member function get_name() on null in /home/wordcamp16870/www/vladi/wp-content/plugins/woocommerce/includes/admin/meta-boxes/views/html-order-fee.php:18 Stack trace: #0 /home/wordcamp16870/www/vladi/wp-content/plugins/woocommerce/includes/admin/meta-boxes/views/html-order-items.php(72): include() #1 /home/wordcamp16870/www/vladi/wp-content/plugins/woocommerce/includes/admin/meta-boxes/class-wc-meta-box-order-items.php(41): include('/home/wordcamp1...') #2 /home/wordcamp16870/www/vladi/wp-admin/includes/template.php(1389): WC_Meta_Box_Order_Items::output(Object(WP_Post), Array) #3 /home/wordcamp16870/www/vladi/wp-admin/edit-form-advanced.php(688): do_meta_boxes(Object(WP_Screen), 'normal', Object(WP_Post)) #4 /home/wordcamp16870/www/vladi/wp-admin/post.php(206): require('/home/wordcamp1...') #5 {main} thrown in /home/wordcamp16870/www/vladi/wp-content/plugins/woocommerce/includes/admin/meta-boxes/views/html-order-fee.php on line 18
There has been a critical error on this website. Please check your site admin email inbox for instructions.

Any help will be appreciated!! Thanks in advance!


Solution

  • add_filter( 'woocommerce_order_get_items', 'filter_order_get_items_by_categories12', 10, 3 );
    
    function filter_order_get_items_by_categories12( $items, $order ) {
        global $woocommerce, $wpdb;
    
        $c1 = $wpdb->get_results( "select t1.order_item_name,t1.order_item_id,t5.name,t2.meta_value from
            wp_woocommerce_order_items as t1 LEFT JOIN wp_woocommerce_order_itemmeta as t2 ON t1.order_item_id =
            t2.order_item_id LEFT JOIN wp_term_relationships as t3 ON t2.meta_value = t3.object_id LEFT JOIN wp_term_taxonomy
            as t4 ON t3.term_taxonomy_id = t4.term_taxonomy_id LEFT JOIN wp_terms as t5 ON t4.term_id = t5.term_id where
            t1.order_id = '" . $order->get_id() . "' and t1.order_item_type='line_item' and t2.meta_key='_product_id' and
            t4.taxonomy='product_cat' ORDER BY `t5`.`name` ASC" );
    
        $sorted_item_ids = array();
    
        foreach ( $c1 as $data ) {
            if ( !in_array( $data->order_item_id, $sorted_item_ids ) ) {
    
                $sorted_item_ids[] = $data->order_item_id;
            }
        }
        $sorete_arr = [];
        foreach ( $sorted_item_ids as $value ) {
            if ( $items[ $value ] instanceof WC_Order_Item_Product )
                $sorete_arr[ $value ] = $items[ $value ];
        }
    
    
    
        return ($sorete_arr) ? $sorete_arr : $items;
    }