在 WooCommerce 管理员订单列表中添加一个可排序和可搜索的 "customer country" 列

Add a sortable and searchable "customer country" column in WooCommerce admin order list

我在 WooCommerce 订单中添加了一个“客户国家”列 table(在管理仪表板中),但我不知道如何让它排序table。有什么帮助吗?要是能做成可搜索的就好了

我当前的代码:

add_filter( 'manage_edit-shop_order_columns', function( $columns ) {
    $columns['customer_country'] = 'Customer Country';
    return $columns;
}, 10, 1 );

add_action( 'manage_shop_order_posts_custom_column', function( $column ) {
    global $post;
    if( 'customer_country' === $column ) {
        $order = wc_get_order( $post->ID );
        echo get_user_geo_country( $order->get_customer_ip_address() );
    }
}, 10, 1 );

add_filter( 'manage_edit-shop_order_sortable_columns', function( $columns ) {
    $columns['customer_country'] = 'customer_country';
    return $columns;
}, 10, 1 );

add_action( 'pre_get_posts', function( $query ) {
    if( ! is_admin() ) { return; }
    // ????
}, 10, 1 );

/** Get geolocated country name by IP **/
function get_user_geo_country( $user_ip ) {
    $geo      = new WC_Geolocation();              // Get WC_Geolocation instance object
    $user_geo = $geo->geolocate_ip( $user_ip );    // Get geolocated user data
    $country  = $user_geo['country'];              // Get the country code

    return WC()->countries->countries[ $country ]; // return the country name
}

要使其可排序,您可以使用 manage_edit-shop_order_sortable_columns 结合 pre_get_posts 钩子。

要使其可搜索,您可以使用 woocommerce_shop_order_search_fields 钩子。

所以你得到:

// Get geolocated country code by IP
function get_user_geo_country( $user_ip ) {
    // Get WC_Geolocation instance object
    $geo = new WC_Geolocation();

    // Get geolocated user data 
    $user_geo = $geo->geolocate_ip( $user_ip );
    
    // Get the country code
    $country = $user_geo['country'];

    // Return the country code
    return $country;
}
 
// Display new column on WooCommerce admin orders list (header)
function filter_manage_edit_shop_order_columns( $columns ) {    
    $columns['customer_country'] = __( 'Customer Country', 'woocommerce' );
    
    return $columns;
}
add_filter( 'manage_edit-shop_order_columns', 'filter_manage_edit_shop_order_columns', 10, 1 );

// Display details after order status column, on order admin list (populate the column)
function action_manage_shop_order_posts_custom_column( $column, $post_id ) {    
    // Compare
    if ( $column == 'customer_country' ) {
        // Get order
        $order = wc_get_order( $post_id );
    
        // Get shipping country code
        $user_geo_country = get_user_geo_country( $order->get_customer_ip_address() );
        
        // NOT empty
        if ( ! empty ( $user_geo_country ) ) {
            echo $user_geo_country;
        } else {
            echo __( 'N/A', 'woocommerce' );
        }
    }
}
add_action( 'manage_shop_order_posts_custom_column' , 'action_manage_shop_order_posts_custom_column', 10, 2 );

// Make custom column sortable
function filter_manage_edit_shop_order_sortable_columns( $sortable_columns ) {  
    return wp_parse_args( array( 'customer_country' => '_shipping_country' ), $sortable_columns );
}
add_filter( 'manage_edit-shop_order_sortable_columns', 'filter_manage_edit_shop_order_sortable_columns', 10, 1 );

// Orderby for custom sortable column
function action_pre_get_posts( $query ) {   
    // If it is not admin area, exit
    if ( ! is_admin() ) return;
    
    global $pagenow;

    // Compare
    if ( $pagenow === 'edit.php' && isset( $_GET['post_type'] ) && $_GET['post_type'] === 'shop_order' ) {      
        // Get orderby
        $orderby = $query->get( 'orderby' );

        // Set query
        if ( $orderby == '_shipping_country' ) {           
            $query->set( 'meta_key', '_shipping_country' );
            $query->set( 'orderby', 'meta_value' );
        }
    }
}
add_action( 'pre_get_posts', 'action_pre_get_posts', 10, 1 );

// Make searchable
function filter_woocommerce_shop_order_search_fields( $meta_keys ) {    
    $meta_keys[] = '_shipping_country';
    return $meta_keys;
}
add_filter( 'woocommerce_shop_order_search_fields', 'filter_woocommerce_shop_order_search_fields', 10, 1 );

这个工作相对容易。 唯一的缺点是您看不到完整的国家名称,而只能看到国家代码。这是因为搜索和排序挂钩需要一个元键。 WooCommerce 仅存储国家代码,作为每个订单的元数据,国家全名未存储在数据库中,因此无法使用。


如果你真的想要完整的国家名称。然后,除了国家代码之外,您还可以通过 woocommerce_thankyou 挂钩和 $order->update_meta_data()

添加完整的国家名称作为每个新订单的元数据

然后你得到:

// Get geolocated country name by IP
function get_user_geo_country( $user_ip ) {
    // Get WC_Geolocation instance object
    $geo = new WC_Geolocation();

    // Get geolocated user data 
    $user_geo = $geo->geolocate_ip( $user_ip );
    
    // Get the country code
    $country = $user_geo['country'];

    // Return the country name
    return WC()->countries->countries[ $country ];
}
 
function action_woocommerce_thankyou( $order_id ) {     
    // Get $order object
    $order = wc_get_order( $order_id );
    
    // Is a WC_Order
    if ( is_a( $order, 'WC_Order' ) ) {
        // Get full shipping country name
        $user_geo_country = get_user_geo_country( $order->get_customer_ip_address() );

        // NOT empty
        if ( ! empty( $user_geo_country ) ) {
            // Update meta data
            $order->update_meta_data( '_shipping_country_full_name', $user_geo_country );
        } else {
            // NOT available
            $na = __( 'N/A', 'woocommerce' );

            // Update meta data         
            $order->update_meta_data( '_shipping_country_full_name', $na );
        }
        
        // Save
        $order->save();
    }
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
 
// Display new column on WooCommerce admin orders list (header)
function filter_manage_edit_shop_order_columns( $columns ) {    
    $columns['customer_country'] = __( 'Customer Country', 'woocommerce' );
    
    return $columns;
}
add_filter( 'manage_edit-shop_order_columns', 'filter_manage_edit_shop_order_columns', 10, 1 );

// Display details after order status column, on order admin list (populate the column)
function action_manage_shop_order_posts_custom_column( $column, $post_id ) {    
    // Compare
    if ( $column == 'customer_country' ) {
        // Get order
        $order = wc_get_order( $post_id );
        
        // Get meta
        $shipping_country_full_name = $order->get_meta( '_shipping_country_full_name' );

        // NOT empty
        if ( ! empty ( $shipping_country_full_name ) ) {
            echo $shipping_country_full_name;
        } else {
            echo __( 'N/A', 'woocommerce' );
        }
    }
}
add_action( 'manage_shop_order_posts_custom_column' , 'action_manage_shop_order_posts_custom_column', 10, 2 );

// Make custom column sortable
function filter_manage_edit_shop_order_sortable_columns( $sortable_columns ) {  
    return wp_parse_args( array( 'customer_country' => '_shipping_country_full_name' ), $sortable_columns );
}
add_filter( 'manage_edit-shop_order_sortable_columns', 'filter_manage_edit_shop_order_sortable_columns', 10, 1 );

// Orderby for custom sortable column
function action_pre_get_posts( $query ) {   
    // If it is not admin area, exit
    if ( ! is_admin() ) return;
    
    global $pagenow;

    // Compare
    if ( $pagenow === 'edit.php' && isset( $_GET['post_type'] ) && $_GET['post_type'] === 'shop_order' ) {      
        // Get orderby
        $orderby = $query->get( 'orderby' );

        // Set query
        if ( $orderby == '_shipping_country_full_name' ) {           
            $query->set( 'meta_key', '_shipping_country_full_name' );
            $query->set( 'orderby', 'meta_value' );
        }
    }
}
add_action( 'pre_get_posts', 'action_pre_get_posts', 10, 1 );

// Make searchable
function filter_woocommerce_shop_order_search_fields( $meta_keys ) {    
    $meta_keys[] = '_shipping_country_full_name';
    return $meta_keys;
}
add_filter( 'woocommerce_shop_order_search_fields', 'filter_woocommerce_shop_order_search_fields', 10, 1 );

这样做的缺点是现有订单不会有该数据,因此您也必须为所有这些订单添加此数据, 然后可以使用以下函数再次添加:

function action_wp_footer() {
    $limit = 50;
    
    // Args
    $args = array(
        'limit'        => $limit,
        'meta_key'     => '_shipping_country_full_name',
        'meta_compare' => 'NOT EXISTS',
    );

    // Get orders
    $orders = wc_get_orders( $args );
    
    // NOT empty
    if ( ! empty ( $orders ) ) {
        // Loop through orders
        foreach ( $orders as $order ) {
            // Is a WC_Order
            if ( is_a( $order, 'WC_Order' ) ) {     
                // Get full shipping country name
                $user_geo_country = get_user_geo_country( $order->get_customer_ip_address() );
                
                // NOT empty
                if ( ! empty( $user_geo_country ) ) {
                    // Update meta data
                    $order->update_meta_data( '_shipping_country_full_name', $user_geo_country );
                } else {
                    // NOT available
                    $na = __( 'N/A', 'woocommerce' );

                    // Update meta data         
                    $order->update_meta_data( '_shipping_country_full_name', $na );
                }
                
                // Save
                $order->save();
            }
        }
    }
}
add_action( 'wp_footer', 'action_wp_footer' );

访问者每次 you/a 浏览您网站的前端页面时都会触发该功能。按 50(限制)处理订单只会更安全,并且会避免超时或错误。现有订单全部更新后,可取消此功能