Welcart_basicテーマは、SKUが複数あると縦にダラダラと長く表示される問題点があります。
そこでSKUを分解し、どのSKUを表示するのか?をラジオボタンやセレクトBOXで選択できる様にカスタマイズします。
1.SKU選択の表示サンプル
下記がSKUが1つしか表示されないサンプル画像です。
(この商品にはSKUが6個ありますが、その中の1つだけが表示されています)
①で表示する商品を選択すると、②のエリアに関連するSKU情報が1つだけ表示されます。
上記でボディカラーに特別色を選択すると、標準色の時に指定するボディカラーは非表示になります。
特別色のライトニングイエローが選択されたので、標準色のボディカラーは非表示になります。
実際の操作感はサンプルサイトのスープラ、86、コペンで操作して見て下さい。
2.上記を実現する為の必要条件
1.PHPプログラムに渡すキー情報
この商品はどの様に表示して欲しいのか?をPHPプログラムに渡す必要があります。
この為には「商品リストを価格順に並べる為にカスタムフィールドを利用する」で利用した、カスタムフィールドを使います。
例えば
①SKU選択に表示させるラベルは?
上記の例では「モデル選択」と「ボディカラー選択」を指定しています。
②また各々の表示方法は「ラジオボタン形式」か「セレクトボックス形式」か?を指定しています。
下記リンクはカスタムフィールドの指定サンプルです。コラップスの開閉で見て下さい。
オプションの表示方法は「シングルセレクト」で必須項目に✔を付けて下さい。
2.SKUコードの記述ルール
次にSKUの記述ルールです。
■SKUコードの記述ルール
①SKUコードはSKU1とSKU2から構成され、二つは「_アンダースコア」で連結します。
②ここで使える文字は、英数字、漢字、記号はスペース、ハイフン「-」、括弧「()」のみです。
③SKU2の最後に「全角の*」を付けると、SKU2のラベルと同じ名前のオプションを探し連動させます。
下記は上記の例のSKUコード一覧です。
SKUコード | SKU名 | 価格 | |
1 | SZ_標準色* | 排気量:1,998 馬力:197PS エントリモデル | 4995000 |
2 | SZ-R_標準色* | 排気量:1,998 馬力:258PS | 6013000 |
3 | RZ_標準色* | 排気量:2.997 馬力:387PS | 7313000 |
4 | SZ_ライトニングイエロー | 排気量:1,998 馬力:197PS ライトニングイエロー | 5028000 |
5 | SZ-R_ライトニングイエロー | 排気量:1,998 馬力:258PS ライトニングイエロー | 6046000 |
6 | RZ_ライトニングイエロー | 排気量:2.997 馬力:387PS ライトニングイエロー | 7346000 |
3.表示の制御方法
SKUの表示/非表示はクラス名で制御します。
しかしクラス名は文字[a-zA-Z0-9]およびISO 10646のU+0080以上の文字、さらにハイフン「-」およびアンダースコア「_」しか利用できません。
そこで、sku名の中のスペース、ハイフン「-」、括弧「()」は総てアンダースコア「_」に変更して、これを表示/非表示で利用します。
PHPで上記変換を変換を行う関数
preg_replace("/[\s()-]/","_",$sku)
jqueryで上記変換を行う関数
$sku.replace( /[\s()-]/g , '_');
3.具体的なプログラム
1.カスタムフィールドを追加するプログラム
このプログラムは「商品リストを価格順に並べる為にカスタムフィールドを利用する」で作成したプログラムを下記の様にカスタマイズします。
①func¥welcart¥settiong¥add_meta_key.phpへの記述
<?php /******************************************************************** カスタムフィールドを新設するプログラム ********************************************************************/ function add_meta_key() { global $post, $usces; $id = $post->ID; //現在のIDの抽出 // 価格情報 $price = usces_the_firstPrice( 'return' ); //welcartの売価の読み込み update_post_meta( $id, 'price', $price ); //WPメタデータに売価を新規追加/更新 // SKU1設定 $aku1_label = get_post_meta($id,'sku1_label',true); //WPメタのsku1_labelの読み込む if($aku1_label == ''){update_post_meta( $id, 'sku1_label', 'SKU1ラベル');} //ラベルの新規追加 $aku1_type = get_post_meta($id,'sku1_type',true); //WPメタのsku1_typeの読み込む if($aku1_type == ''){update_post_meta( $id, 'sku1_type','1はradio、2はselect');} //表示タイプの新規追加 // SKU2 $aku2_label = get_post_meta($id,'sku2_label',true); //WPメタのsku2_labelの読み込む if($aku2_label == ''){update_post_meta( $id, 'sku2_label', 'SKU2ラベル');} //ラベルぼの新規追加 $aku2_type = get_post_meta($id,'sku2_type',true); //WPメタのsku2_typeの読み込む if($aku2_type == ''){update_post_meta( $id, 'sku2_type','1はradio、2はselect');} //表示タイプの新規追加 } add_action( 'save_post', 'add_meta_key' ); ?>
関数名 | 解説 |
get_post_meta($id, $key, $single) | キーを指定して値を取得する $id :投稿ID $key :取得したいキー $single :trueは値を取得、flaseは配列で取得 |
update_post_meta( $id,$key, $data) | 指定した投稿に存在するカスタムフィールドの値を更新します。 $id :投稿ID $key :更新したいキー $data :キーの値 カスタムフィールが無い場合は新規追加 カスタムフィールがある場合は更新になります |
add_action( ‘save_post‘, ‘関数名’ ) | アクションフック関数 投稿や固定ページが作成または更新されたとき実行されるアクションです。 |
②functions.phpへの記述
/* メタデータに価格情報を書き込む */ get_template_part('func/welcart/setting/add_meta_key');
2.個別商品ページのカスタマイズプログラム
個別商品ページの表示プログラムは子テーマフォルダの中の「wc_templates」フォルダの中の「wc_item_single.php」になりますが、これを大幅改造します。
既存の「wc_item_single.php」を下記に置き換えます。
<?php get_header();?> <div id='primary' class='site-content'> <div id='content' role='main'> <h1 id='page_title'><?php the_title(); ?></h1> <?php usces_remove_filter(); ?> <!-- カートページ、会員ページで制御している the_title や the_content のフィルターを無効化 --> <?php usces_the_item(); ?> <!-- これを実行しないとオプションデータが読めません --> <div id='panel'> <div id='img_box'> <?php my_image_slic(3);?> </div> <div id='item_box'> <h2 class='item_name'><?php usces_the_itemName(); ?></h2> <div class='item_code'>商品コード:<?php usces_the_itemCode(); ?></div> <?php usces_get_item_custom($post->ID, 'list', 'echo');?> <?php my_sku_disp();?> </div><!-- item_box end --> </div><!-- panel end --> <hr id='h-line'> <div class='item-description'> <?php the_content(); ?> </div> <?php my_edit_post_link('商品編集','<','>');?> <!-- 商品編集へのリンク --> </div><!-- #content --> </div><!-- #primary --> <?php get_sidebar(); ?> <?php relation_products(5,2);?> <!-- 関連商品の表示 --> <?php get_footer(); ?> <style> #panel{display:flex;} #img_box{width:40%;} #item_box{width:60%;padding-left:60px;} @media screen and (max-width:767px){ #panel{ flex-direction:column;} #img_box{width:100%;} #item_box{width:100%;padding:0 10px;} } #page_title{ /* ページタイトル */ font-size:1.785712em;; font-weight:bold; line-height: 1.3; display:flex; align-items:center;/* 横線と文字を中央値で合わせる */ } #page_title:after{ content: ''; /* 後ろ付ける文字はなし */ flex-grow:1; /* 画面一杯に伸長する */ height:1px; /* 横線の幅 */ background:#444; /* 横線の色 */ margin-left:1em; /* 横線のスタート位置 */ } .item_name{font-size:1.5em;margin-bottom:0;} /* 商品名 */ .item_code{ /* 商品コード */ font-size:1.2em; margin-bottom:30px; } #h-line{ height:1px; background-color:#444; width:100%; margin-left:0; } .item_custom_field li{ /* カスタムフィールで設定 */ font-size: 1em; text-decoration: underline dotted; text-underline-position:under; margin:2px 0; } </style>
上記で利用している関数
関数名 | 関数区分 | 解説 |
usces_remove_filter() | welcart | カートページ、会員ページで制御している the_title や the_content のフィルターを無効化 |
usces_the_item() | welcart | これをコールしないとオプションデータが読めません |
my_image_slic() | ユーザ関数 | 商品画像をサムネール付きスライダで表示させる |
usces_the_itemName() | welcart | 商品名を表示します |
usces_the_itemCode() | welcart | 商品コードを表示します |
usces_get_item_custom() | welcart | カスタムフィールドを表示します |
my_sku_disp() | ユーザ関数 | SKU情報を表示させる。3項を見て下さい。 |
relation_products() | ユーザ関数 | 関連商品を表示します |
3.SKUの表示プログラム
上記の「wc_item_single.php」の中でCALLされているmy_sku_disp()は下記になります。
子テーマ¥func¥welcart¥item¥my_sku_disp.phpに下記を記述します。
<?php /******************************************************************** SKU選択に基づきSKUを表示制御するルーチン SKUの選択処理はjqueryで制御 *********************************************************************/ function my_sku_disp() { global $post, $usces; $ID = $post -> ID; // POST ID の取得 $skus = $usces->get_skus($ID); // SKUアレーの取得 $count = count($skus); // SKUの個数 $sku1_label = get_post_meta($ID, 'sku1_label',true); // SKU1ラベル名称 $sku1_type = get_post_meta($ID, 'sku1_type',true); // SKU1表示方法 $sku2_label = get_post_meta($ID, 'sku2_label',true); // SKU2のラベル名称 $sku2_type = get_post_meta($ID, 'sku2_type',true); // SKU2表示方法 $sku1 = []; // SKU1の配列宣言 $sku2 = []; // SKU2の配列宣言 // SKUコードを読み込んで分解し、SKU1とSKU2のリストを作成する foreach($skus as $no => $sku){ $get_code = explode('_',$sku['code']); // SKUコード分解 if($get_code[0] != '' && !in_array( $get_code[0], $sku1)){ // SKU1にNewコードはあるか? array_push( $sku1 ,$get_code[0] );} // ない場合は追加 if($get_code[1] != '' && !in_array( $get_code[1], $sku2)){ // SKU2にNewコードはあるか? array_push( $sku2 , $get_code[1] );} // ない場合は追加 } // SKUタイプの判定 if (count($sku1) == 1 && count($sku2) == 0){$type = 1;} // SKUが1つの場合はtype1 elseif(count($sku1) > 1 && count($sku2) == 0){$type = 2;} // SKU1だけが複数の場合はtype2 else{$type = 3;} // SKU1、SKU2がある場合はtype3 ?> <span class='sku_type' <?php echo 'sku1_type='.$sku1_type;?> <?php echo 'sku2_type='.$sku2_type;?>></span> <!-- SKU1,2の表示方法をjqueryに知らせる--> <span class='disp_type' <?php echo 'disp_type='.$type;?>></span> <!-- skuタイプをjqueryに知らせる--> <?php if($type != 1):?> <!-- 表示タイプ2,3の時のSKU選択処理--> <span class='sku_label'><i class='chick_icon fas fa-check-circle'></i> <?php echo ' '.$sku1_label;?></span> <!-- SKU1の表示 --> <?php if($sku1_type == 1):?><!-- ラジオボタンの場合 --> <form class="sku_block"> <?php foreach($sku1 as $no => $val):?> <input id ='sku1_<?php echo $no;?>' type='radio' name='sku1' value='<?php echo $val;?>'> <label for='sku1_<?php echo $no;?>'><?php echo $val;?></label> <?php endforeach;?> </form> <?php else:?><!-- セレクトBOXの場合 --> <select name='sku1' class='sku_block'> <?php foreach($sku1 as $no => $val):?> <option name='sku1' value='<?php echo $val;?>'><?php echo $val;?></option> <?php endforeach;?> </select> <?php endif;?> <!-- SKU2の表示 --> <?php if($type == 3):?> <span class='sku_label'><i class='chick_icon fas fa-check-circle'></i> <?php echo ' '.$sku2_label;?></span> <?php if($sku2_type == 1):?><!-- ラジオボタンの場合 --> <form class="sku_block"> <?php foreach($sku2 as $no => $val):?> <input id ='sku2_<?php echo $no;?>' type='radio' name='sku2' value='<?php echo $val;?>' sku2_lb='<?php echo $sku2_label;?>' > <label for='sku2_<?php echo $no;?>' ><?php echo $val;?></label> <?php endforeach;?> </form> <?php else:?><!-- セレクトBOXの場合 --> <select name='sku2' class='sku_block' sku2_lb='<?php echo $sku2_label;?>'> <?php foreach($sku2 as $no => $val):?> <option name='sku2' value='<?php echo $val;?>' ><?php echo $val;?></option> <?php endforeach;?> </select> <?php endif;?> <?php endif;?> <?php endif;?> <!-- 個別SKUの表示 --> <form action="<?php echo USCES_CART_URL; ?>" method="post" > <?php foreach($skus as $no => $sku):?> <div class='sku_data sku_data_<?php echo preg_replace("/[\s()-]/","_",$sku["code"]);?>'> <?php my_option_foreach($sku); ?> <!-- オプションの表示 --> <hr><b><?php echo $sku['name'];?></b><br> <!-- SKU名の表示 --> <?php my_itemPrice_foreach($sku); ?> <!-- SKU価格の表示 --> <?php my_itemGpExp_foreach($sku,'数量割引'); ?> <!-- 業務パック割引の表示 --> <?php my_discount_foreach($sku); ?> <!-- 獲得ポイントや値引き情報を表示 --> <?php my_itemQuant_foreach($sku);?> <!-- カウンタ形式の購入数量入力 --> <?php my_cart_input_foreach($sku,'blue'); ?> <!-- カートへの投入ボタン!--> <div class="error_message"><?php usces_singleitem_error_message($ID,$sku['code']); ?></div> </div> <?php endforeach;?> </form> <style> .sku_label{ display:flex; justify-content:flex-start; align-items:center; font-size:16px; font-weight:bold; margin-top:10px;} .chick_icon{font-size:20px;color:red;} .sku_block{ display:flex; justify-content:flex-start; flex-wrap:wrap; flex-basis:10%; } .sku_block input{display:none;} .sku_block label { padding:3px 6px; margin-left:10px; border:1px solid black; border-radius:5px; color:#fff; background:#777; cursor: pointer;} .sku_block input:checked + label{ background:blue; text-shadow: 0 0 1px rgba(0,0,0,.7);} .sku_block{ margin-left:20px; font-weight:bold; color:blue; } </style> <?php } ?>
functions.phpには下記を記述します
get_template_part('func/welcart/item/my_sku_disp'); /* SKUの表示 */
上記のプログラムの中で使われている下記関数は事前に作成しておいて下さい。
関数名 | リンク先(ここにプログラムがあります) |
my_itemPrice_foreach() | foreachループの中で使える、SKU価格の表示 |
my_itemGpExp_foreach() | foreachループの中で使える、業務パック割引の表示 |
my_discount_foreach() | foreachループの中で使える、獲得ポイントや値引き情報を表示 |
my_itemQuant_foreach() | foreachループの中で使える、カウンタ形式の購入数量入力 |
my_cart_input_foreach() | foreachループの中で使える、カートへの投入ボタン |
4.jqueryプログラム
最後は、SKUの表示プログラムが表示したHTMLを読み込んで画面をコントロールするjqueryプログラムです。
my_jquery.jsに下記を追加します。
/************************************************************************/ /* SKU DISP 表示切替 */ /************************************************************************/ $(function(){ if(!location.href.match(/item/)){return;} //商品詳細ページ以外なら終了 const sku1_type = $('.sku_type').attr('sku1_type'); //sku1の表示方法の取得 let sku1_taget,sku1_select; //sku1の変数定義 if(sku1_type == 1){ //radioの場合 sku1_taget = 'input[name=sku1]'; sku1_select = 'checked'; } else{ //selectの場合 sku1_taget = 'select[name=sku1]'; sku1_select = 'selected'; } const sku2_type = $('.sku_type').attr('sku2_type'); //sku2の表示方法の取得 let sku2_taget,sku2_select; //sku2の変数定義 if(sku2_type == 1){ //radioの場合 sku2_taget = 'input[name=sku2]'; sku2_select = 'checked'; } else{ //selectの場合 sku2_taget = 'select[name=sku2]'; sku2_select = 'selected'; } // 初期設定 $(sku1_taget + ':first').prop(sku1_select,true); //sku1の最初の要素を選択状態にする $(sku2_taget + ':first').prop(sku2_select,true); //sku2の最初の要素を選択状態にする $('.sku_data').css('display','none'); //総てのskuデータを非表示 $('.sku_data').first().css('display','block'); //始めのskuデータを表示 //sku2とオプションを連動させる場合の初期処理 let sku,sku1,sku2; let sku2_lb,op_lb_class,op_seclect_class,new_lb; sku2 = $(sku2_taget + ':' + sku2_select).val(); //SKU2の値を取得 sku2_lb = $(sku2_taget + ':' + sku2_select).attr('sku2_lb'); //SKU2のラベル取得 op_lb_class = '.' + sku2_lb + ' .option_label'; //上記ラベルが付いたオプションのラベルのクラス op_seclect_class = '.' + sku2_lb + ' .option_select'; //上記ラベルが付いたオプションのセレクトBOXのクラス new_lb = '<span class="sku_label"><i class="chick_icon fas fa-check-circle"></i>'+' '+ sku2 + 'の' + sku2_lb + '</span>';//カスタマイズしたラベル if(sku2 != null){ if(sku2.match(/*/) != null){$(op_lb_class).html(new_lb);} //*が付いてないsku2にはカスタマイス下オプションラベルを表示 } $(op_seclect_class).css('margin-left','20px'); //カスタマイズしたオプションBOXは少し右にシフト //sku1が変更された時の処理 let mod_sku; $(sku1_taget).change(function() { sku1 = $(this).val(); //クリックされたsku1名を取得 if($('.disp_type').attr('disp_type') == 2){sku = sku1;} //sku1のみの場合 else{ sku2 = $(sku2_taget + ':' + sku2_select).val(); //セレクトされているsku2名を取得 sku = sku1 + '_' + sku2; } mod_sku = sku.replace( /[\s()-]/g , '_'); //SKU名をクラス指定に使える様にカスタマイズ $('.sku_data').css('display','none'); //総てのskuデータを非表示 $('.sku_data_' + mod_sku ).css('display','block'); //指定されたskuだけを表示 }); //sku2が変更された時の処理 $(sku2_taget).change(function() { sku1 = $(sku1_taget + ':' + sku1_select).val(); //セレクトされているsku1名を取得 sku2 = $(this).val(); //クリックされたsku2名を取得 sku = sku1 + '_' + sku2; mod_sku = sku.replace( /[\s()-]/g , '_'); //クラス指定に使えるSKU名に変更 $('.sku_data').css('display','none'); //総てのskuデータを非表示 $('.sku_data_' + mod_sku ).css('display','block'); //指定されたskuだけを表示 //オプションの追加と表示/非表示制御 let op_class = '.' + sku2_lb; //sku2のラベルが付いたオプションのクラス if(sku2.match(/[*]/) == null){ //*が無いオプションの処理 $(op_class).css('display','none'); //オプションを非表示にする $add_op = '<option class="add-op" value='+ sku2 + ' selected="selected" >' + sku2 + '</option>'//新オプション項目の追加 $(op_class + ' select').append($add_op); //追加した新オプションを選択 } else{ //*があるオプションの処理 $('.add-op').remove(); //追加したオプション項目を削除 $(op_class).css('display','block'); //オプションを表示(ユーザがオプション項目を選択) } }); });
以上でSKUを1つだけにする個別商品画面が完了しました。