在 WooCommerce 管理订单列表中添加可排序和可搜索的“客户国家/地区”列

Posted

技术标签:

【中文标题】在 WooCommerce 管理订单列表中添加可排序和可搜索的“客户国家/地区”列【英文标题】:Add a sortable and searchable "customer country" column in WooCommerce admin order list 【发布时间】:2022-01-05 06:05:05 【问题描述】:

我向 WooCommerce 订单表(在管理仪表板中)添加了一个“客户国家/地区”列,但我不知道如何使其可排序。有什么帮助吗?如果它也可以被搜索,那将是一个很好的奖励。

我当前的代码:

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

【问题讨论】:

【参考方案1】:

要使其可排序,您可以使用manage_edit-shop_order_sortable_columnspre_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' );

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

【讨论】:

以上是关于在 WooCommerce 管理订单列表中添加可排序和可搜索的“客户国家/地区”列的主要内容,如果未能解决你的问题,请参考以下文章

在 WooCommerce 管理订单列表中添加可排序和可搜索的“客户国家/地区”列

将自定义批量操作添加到 Woocommerce 3 中的管理订单列表

在 Woocommerce 订单管理列表中显示用户失败并取消订单计数

在 WooCommerce 管理员订单列表上显示产品图片的问题

WooCommerce:将自定义 Metabox 添加到管理订单页面

在 Woocommerce 管理订单编辑页面中以编程方式添加自定义订单备注