Cara Menambahkan Filter Produk di Halaman Order WooCommerce
Install & aktifkan plugin Code Snippets
Masuk Snippets → Add New.
Isi Title bebas, misalnya: Filter Orders by Product (ID/SKU).
Paste kode snippet ini:
/**
* WooCommerce Orders: Filter by Product (ID atau SKU)
* - Menambahkan field filter di layar Orders
* - Bekerja di mode lama (posts) DAN HPOS
*/
add_action('restrict_manage_posts', function($post_type){
if ($post_type !== 'shop_order') return;
$current_id = isset($_GET['_product_id']) ? absint($_GET['_product_id']) : '';
$current_sku = isset($_GET['_product_sku']) ? sanitize_text_field($_GET['_product_sku']) : '';
echo '<div style="margin-left:6px;display:inline-block;">';
echo '<label for="_product_id" style="margin-right:4px;">Product ID:</label>';
echo '<input type="number" min="1" name="_product_id" id="_product_id" value="'.esc_attr($current_id).'" />';
echo '</div>';
echo '<div style="margin-left:6px;display:inline-block;">';
echo '<label for="_product_sku" style="margin-right:4px;">SKU:</label>';
echo '<input type="text" name="_product_sku" id="_product_sku" value="'.esc_attr($current_sku).'" />';
echo '</div>';
}, 20);
/**
* Utility: Ambil array order_id yang mengandung product_id (atau SKU).
*/
function yb_get_order_ids_by_product( $product_id = 0, $sku = '' ) {
global $wpdb;
// Resolve SKU -> product_id jika perlu
if ( $product_id <= 0 && $sku !== '' ) {
$product_id = (int) $wpdb->get_var(
$wpdb->prepare(
"SELECT p.ID
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND pm.meta_key = '_sku'
WHERE p.post_type IN ('product','product_variation')
AND pm.meta_value = %s
LIMIT 1",
$sku
)
);
}
if ( $product_id <= 0 ) {
return array(); // tidak ada filter produk
}
// Ambil order IDs yang punya line_item dengan _product_id = $product_id
$order_ids = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT oi.order_id
FROM {$wpdb->prefix}woocommerce_order_items oi
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim
ON oim.order_item_id = oi.order_item_id
WHERE oi.order_item_type = 'line_item'
AND oim.meta_key = '_product_id'
AND oim.meta_value = %d",
$product_id
)
);
// Jika produk yang dimaksud adalah parent variable, sertakan variasi (opsional)
// Ambil semua variation child dan gabungkan hasilnya
$variation_ids = $wpdb->get_col(
$wpdb->prepare(
"SELECT p.ID FROM {$wpdb->posts} p
WHERE p.post_type = 'product_variation' AND p.post_parent = %d",
$product_id
)
);
if ( ! empty( $variation_ids ) ) {
$in_variations = implode( ',', array_map( 'absint', $variation_ids ) );
$var_order_ids = $wpdb->get_col(
"SELECT DISTINCT oi.order_id
FROM {$wpdb->prefix}woocommerce_order_items oi
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim
ON oim.order_item_id = oi.order_item_id
WHERE oi.order_item_type = 'line_item'
AND oim.meta_key = '_product_id'
AND oim.meta_value IN ($in_variations)"
);
$order_ids = array_unique( array_merge( $order_ids, $var_order_ids ) );
}
return array_map( 'absint', $order_ids );
}
/**
* MODE LAMA (orders sebagai post): filter query list table via pre_get_posts.
*/
add_action('pre_get_posts', function( $q ){
if ( ! is_admin() || ! $q->is_main_query() ) return;
if ( $q->get('post_type') !== 'shop_order' ) return;
$product_id = isset($_GET['_product_id']) ? absint($_GET['_product_id']) : 0;
$product_sku = isset($_GET['_product_sku']) ? sanitize_text_field($_GET['_product_sku']) : '';
if ( ! $product_id && $product_sku === '' ) return;
$order_ids = yb_get_order_ids_by_product( $product_id, $product_sku );
// Jika tidak ada, paksa kosong agar list table tidak menampilkan order lain
$order_ids = empty($order_ids) ? array(0) : $order_ids;
// Batasi hasil hanya ke order_id yang cocok
$q->set( 'post__in', $order_ids );
}, 20);
/**
* HPOS (High-Performance Order Storage): filter args WC_Order_Query untuk list table.
* WooCommerce akan memanggil hook ini ketika menyiapkan query di layar Orders (HPOS aktif).
*/
add_filter('woocommerce_shop_order_list_table_prepare_items_query_args', function( $args ){
$screen = function_exists('get_current_screen') ? get_current_screen() : null;
if ( ! $screen || $screen->id !== 'woocommerce_page_wc-orders' ) {
return $args;
}
$product_id = isset($_GET['_product_id']) ? absint($_GET['_product_id']) : 0;
$product_sku = isset($_GET['_product_sku']) ? sanitize_text_field($_GET['_product_sku']) : '';
if ( ! $product_id && $product_sku === '' ) return $args;
$order_ids = yb_get_order_ids_by_product( $product_id, $product_sku );
$order_ids = empty($order_ids) ? array(0) : array_map('absint', $order_ids);
// WC_Order_Query mendukung 'include' untuk membatasi ID
$args['include'] = $order_ids;
return $args;
}, 20);
Di bagian Scope/Run snippet, pilih Only run in administration area (agar hanya aktif di wp-admin).
Klik Save Changes and Activate.
Buka WooCommerce → Orders.
Di bar filter atas, akan muncul field Product ID dan SKU.
Masukkan Product ID (atau SKU) produk yang ingin difilter → klik Filter.
(Opsional) Untuk produk variabel, cukup isi ID parent; variasi akan otomatis ikut terjaring.
Jika ingin menonaktifkan: Snippets → toggle off snippet tersebut.
Troubleshooting cepat: jika field belum muncul, clear cache, pastikan snippet active, dan WooCommerce aktif (snippet ini kompatibel HPOS maupun mode lama).