2026年6月20日
2026年6月20日
WooCommerceのバリエーション商品が正しく動かない問題を解決する方法
はじめに
WooCommerceのバリエーション商品(サイズ・カラー選択など)で「選択できない」「価格が変わらない」「在庫ありなのに選択不可になる」問題は、バリエーション数の上限・属性設定・JavaScriptエラーが原因です。
症状・原因
- バリエーションのドロップダウンが空のまま
- サイズ・カラーを選択しても価格・在庫が更新されない
- 50個以上のバリエーションがある商品でAjaxが失敗する
- 特定の組み合わせだけ選択できない
解決手順
ステップ1:バリエーション設定の現状を確認する
# バリエーション商品の状態を確認
wp eval "
\$product = wc_get_product(123);
if (!\$product || \$product->get_type() !== 'variable') {
echo '可変商品ではありません';
exit;
}
printf('Variations: %d, Attributes: %d' . PHP_EOL,
count(\$product->get_children()),
count(\$product->get_attributes())
);
foreach (\$product->get_children() as \$variation_id) {
\$v = wc_get_product_object('variation', \$variation_id);
printf(' #%d: %s - 在庫:%s 価格:%s' . PHP_EOL,
\$variation_id,
implode('/', \$v->get_variation_attributes()),
\$v->get_stock_status(),
\$v->get_price()
);
}
"
# バリエーション上限を確認
wp option get woocommerce_ajax_variation_threshold # デフォルト30
ステップ2:バリエーションのAjax上限を引き上げる
// functions.php: バリエーション数の上限を引き上げる
// デフォルト30個を超えるとAjaxで動的取得になる
// ① Ajax 取得のしきい値を変更(ページ読み込みに含めるバリエーション数)
add_filter('woocommerce_ajax_variation_threshold', fn() => 100);
// ② 非常に多いバリエーション(100個以上)の場合はAjax取得を最適化
add_filter('woocommerce_available_variation', function(array $variation_data, WC_Product $product, WC_Product_Variation $variation): array {
// 不要なデータを削除して転送量を削減
unset($variation_data['description']);
unset($variation_data['dimensions_html']);
return $variation_data;
}, 10, 3);
// ③ バリエーションのAjaxエンドポイントをデバッグ
add_action('wp_ajax_woocommerce_get_variation', function(): void {
error_log('[WC Variation Ajax] ' . json_encode($_POST));
}, 1);
# バリエーション数の多い商品を確認
wp eval "
\$products = wc_get_products(['type' => 'variable', 'limit' => -1]);
foreach (\$products as \$p) {
\$count = count(\$p->get_children());
if (\$count > 50) {
printf('#%d %s: %d variations' . PHP_EOL, \$p->get_id(), \$p->get_name(), \$count);
}
}
"
ステップ3:バリエーション属性を正しく設定する
// functions.php: バリエーション属性をプログラムで管理
// ① グローバル属性を登録
function register_product_attributes(): void {
$attributes = [
['name' => 'サイズ', 'slug' => 'size', 'terms' => ['S', 'M', 'L', 'XL']],
['name' => 'カラー', 'slug' => 'color', 'terms' => ['レッド', 'ブルー', 'グリーン', 'ブラック']],
];
foreach ($attributes as $attr) {
$taxonomy = 'pa_' . $attr['slug'];
if (!taxonomy_exists($taxonomy)) {
wc_create_attribute([
'name' => $attr['name'],
'slug' => $attr['slug'],
'type' => 'select',
'order_by' => 'menu_order',
'has_archives' => false,
]);
}
foreach ($attr['terms'] as $term) {
if (!term_exists($term, $taxonomy)) {
wp_insert_term($term, $taxonomy);
}
}
}
}
add_action('init', 'register_product_attributes');
// ② 可変商品にバリエーションをプログラムで追加
function add_product_variation(int $product_id, array $attributes, array $data): int {
$variation = new WC_Product_Variation();
$variation->set_parent_id($product_id);
$variation->set_attributes($attributes); // ['pa_size' => 'M', 'pa_color' => 'ブルー']
$variation->set_regular_price($data['price']);
$variation->set_stock_quantity($data['stock'] ?? null);
$variation->set_manage_stock(!empty($data['stock']));
$variation->set_status('publish');
return $variation->save();
}
ステップ4:バリエーション選択時の価格・在庫更新を修正する
// functions.php: バリエーション選択時の動作をカスタマイズ
// ① バリエーションデータにカスタム情報を追加
add_filter('woocommerce_available_variation', function(array $data, WC_Product $product, WC_Product_Variation $variation): array {
// 配送日数をバリエーションデータに追加
$shipping_days = $variation->get_meta('_shipping_days');
$data['shipping_days'] = $shipping_days ?: '3〜5';
// 在庫数を表示
if ($variation->managing_stock()) {
$data['stock_quantity_display'] = $variation->get_stock_quantity() . '個在庫あり';
}
return $data;
}, 10, 3);
// ② バリエーション選択後にカスタムJSでUIを更新
add_action('woocommerce_after_variations_form', function(): void {
?>
<script>
jQuery(document).on('found_variation', function(event, variation) {
// カスタムデータをUIに反映
if (variation.shipping_days) {
jQuery('.shipping-info').text('配送目安:' + variation.shipping_days + '営業日');
}
if (variation.stock_quantity_display) {
jQuery('.stock-info').text(variation.stock_quantity_display);
}
});
jQuery(document).on('reset_data', function() {
jQuery('.shipping-info, .stock-info').text('');
});
</script>
<?php
});
ステップ5:バリエーションの一括操作と最適化
# 全バリエーションの価格を一括更新
wp eval "
\$product = wc_get_product(123);
foreach (\$product->get_children() as \$variation_id) {
\$variation = wc_get_product(\$variation_id);
// 現在価格の10%引きにセール価格を設定
\$price = \$variation->get_regular_price();
if (\$price) {
\$variation->set_sale_price(\$price * 0.9);
\$variation->save();
}
}
echo '全バリエーションにセール価格を設定しました';
"
# 在庫0のバリエーションを非表示に
wp eval "
global \$wpdb;
\$zero_stock = \$wpdb->get_col(
\"SELECT post_id FROM {$wpdb->postmeta}
WHERE meta_key = '_stock' AND meta_value = '0'
AND post_id IN (SELECT ID FROM {$wpdb->posts} WHERE post_type = 'product_variation')\"
);
foreach (\$zero_stock as \$id) {
update_post_meta(\$id, '_stock_status', 'outofstock');
}
echo count(\$zero_stock) . '件の在庫0バリエーションを更新しました';
"
// functions.php: 使われていないバリエーションを削除
function cleanup_unused_variations(int $product_id): int {
$product = wc_get_product($product_id);
if (!$product || $product->get_type() !== 'variable') {
return 0;
}
$deleted = 0;
foreach ($product->get_children() as $variation_id) {
$variation = wc_get_product($variation_id);
if (!$variation) {
continue;
}
// 在庫0かつ販売実績なしのバリエーションを削除
if ($variation->get_stock_quantity() === 0 &&
$variation->get_total_sales() === 0) {
$variation->delete(true);
$deleted++;
}
}
return $deleted;
}
注意事項
woocommerce_ajax_variation_thresholdの値を大きくすると初期ページ読み込みのJSONデータが増え、ページが重くなります。バリエーションが100個を超える場合はAjax取得(しきい値を超えた場合のデフォルト動作)に任せる方が良いです- バリエーション属性のスラッグは
pa_プレフィックスが付きます。size属性のタクソノミー名はpa_sizeです。get_attributes()で確認できます - WooCommerceのバリエーション上限は技術的には無制限ですが、50個を超えるとパフォーマンスが低下します。50個以上の場合はカスタムフィールド+Ajax検索などの代替手段を検討してください
まとめ
WooCommerceバリエーションエラーの解決は①get_children()でバリエーション数と設定状態を確認、②woocommerce_ajax_variation_thresholdフィルターでAjaxしきい値を調整(デフォルト30→100)、③wc_create_attribute()とwp_insert_term()でグローバル属性・タームをプログラム登録、④woocommerce_available_variationフィルターでバリエーション選択時のデータをカスタマイズしJSでUI更新、⑤get_sale_price()とset_sale_price()でバリエーション価格を一括管理します。