「在庫がある商品だけを表示」ボタンを作る

スポンサーリンク

前から作りたかった、Welcartショップの在庫あり商品のみ絞り込みボタン。

Welcartで在庫の絞込みボタン

以下の記事を拝読して、アレンジして作ってみました。

WordPressのアーカイブページを人気順などで並び替えるボタンをつける – Ateitexe

もくじ

  1. PHPでデータを送受信するしくみ
  2. 作成:チェックボックスを成形
  3. 作成:functions.phpに、クエリ振り分け用のPHPを記述
  4. まとめ

1. PHPでデータを送受信するしくみ

今回は、表示クエリの再生成を、PHPのデータ送信によって行います。

PHPの話になるので私もあまり得意でないのですが、ない頭なりに書いてみます。

PHPには、入力された値を送信してページの表示内容を切り替えることが出来る機能があります。例えば、入力フォームなどはまさにその代表格です。

データ送信にはGETメソッドPOSTメソッドがあります。それぞれの違いは、ざっくり言うとこんな感じです。

  • GETメソッド
    • ちょっとしたデータを送信するのによい。
    • URLに「http://example.com/item/?sort=zaiko」というふうに末尾にパラメータがつく。
    • 「http://example.com/?cat=2」といった、WordPressのデフォルトのパーマリンクには使えない。
  • POSTメソッド
    • 長文のデータを送信するのによい。
    • URLにパラメータが出ない。
    • <a>要素で2ページ目以降に移動する場合、データを引き渡せない。

今回は、より簡単なGETメソッドで行います。

WordPressのデフォルトのパーマリンクを使っている場合は、今回紹介する方法は使えませんのでご注意下さい。

入力フォームの基本の書き方

入力フォーム自体は、HTMLを書いたことがあれば大体わかると思います。

まず、データ送信用の<form>タグに、action属性とmethod属性を追加します。method属性は「GETメソッド」か「POSTメソッド」かを指定するもので、省略した場合はGETと判断されます。

更に、基本のフォームの入力部品(input、textareaや送信ボタン)のうちの、送信したい入力データには、name属性としてデータ名をつけておきます。そうすればサーバー側で$_GET['データ名']でデータを受信して、次の動作に移ることが出来ます。

<form action="送信先URL" method="メソッド名(GETかPOST)">
    <input type="text" name="データ名" />
    <input type="submit" value="送信" />
</form>
 

これで基本の入力フォームはOKです。

次に、送信先URLのファイルに、入力されたデータにGETやPOSTがあった場合に、指定された処理を行うためのPHPを記述しておきます。以下はGETメソッドの例ですが、POSTの場合は$_POST['データ名']とします。

<?php
$data = $_GET['データ名'];
echo '「{$data}」を受信しました';

「データ名」を受信しました

このようなデータの動きは、PHPの基本となります。

PHPを学びたい方は「PHPプログラミングの教科書レビュー)」などをやってみると良いと思います。

参考文献:最初に「読む」PHP クジラ飛行机(ソシム社刊)

2. 作成:チェックボックスの成形

では、ここから実際の「在庫がある商品だけを表示」ボタンのフォーム作成です。

2-1. 現在のカテゴリーページのリンクを取得

<form>のaction属性に入れる送信先URLを取得します。送信先URLは、現在表示されているカテゴリーページでいいので、現在のURLを取得します。

現在表示中のカテゴリーページのURL取得には、WordPressのget_category_link();を使えばOKです。

<?php echo get_category_link($cat); ?>

※タグページの場合は、get_tag_link();を使います。タグページと同じ記述にするなら、未検証ですが、get_term_link();を使ってもいいかも。

2-2. フォームの成形

今回はチェックボックスタイプにしました。もちろん、submitを使って、CSSでテキストリンク風に装飾しても良いと思います。

<form method="GET" action="<?php echo get_category_link($cat); ?>">
    <input type="checkbox" name="sort" value="zaiko" onChange="this.form.submit()"
           <?php if(isset($_GET['sort']) == 'zaiko'){ echo 'checked';} ?>>
    <label>在庫有りのみ表示</label>
</form>

「チェックボックスを入れる=データ送信」としたかったので、チェックボックスのパーツに、onChange="this.form.submit()"という属性を追加(こちらを参考)。

更に、在庫有りのみの表示中は、チェックボックスにチェックが入った状態になるように、3行目で条件を入れています。

以上でチェックボックスは完成です。

3. 作成:functions.phpに、クエリ振り分け用のPHPを記述

次に、チェックボックスにチェックが入ったとき(=GETメソッドが送信された時)に、在庫がある商品だけを表示させるようにします。

方法としては、pre_get_postを利用したアクションフックです。以下のコードをfunctions.phpに記述します。

//在庫ありのみ表示
function my_sort_item( $query ) {
    if ( is_admin() || ! $query->is_main_query() ){
        return;
    if ( $query->is_category() ) {
        $sort = isset($_GET['sort']) && is_string($_GET['sort']) ? $_GET['sort'] : '';
        if ( $sort == 'zaiko' ) {
            $args = array(
                array(
                    'key' => '_isku_',
                    'value' => '"stocknum";s:1:"0"',
                    'compare' => 'NOT LIKE',
                ),
                array(
                    'key' => '_isku_',
                    'value' => '"stocknum";i:0',
                    'compare' => 'NOT LIKE',
                ),
            );
            $query->set('meta_query' , $args);
        }
    }
}
add_action( 'pre_get_posts', 'my_sort_item' );

※ここではカテゴリーページの場合でのみの条件分岐をしています。タグページも含めたい場合はis_tag();を5行目の条件に追加します。

6行目の$_GET['sort']で、sortというname属性を持ったフォームからのデータを受信。

7行目で、そのフォームのvalue属性がzaikoかどうかを判断。条件に当てはまる場合は8行目以降で在庫を除外するクエリを生成します。

その8行目~では、以前紹介した「在庫がゼロの商品をWP_Queryなどで除外する方法」を利用しています。在庫数が「0」になっているものが除外されるしくみです。

※在庫状態が「売り切れ」「入荷待ち」等でも、バックエンドでの在庫数が1以上の場合は除外されませんのでご注意下さい。

以上で完成です。

4. まとめ

特に商品が多く、在庫があるものとないものが常に混在しているショップには、有効なカスタマイズかなと思います。

もともとは、配布中の無料Welcart対応テーマで在庫絞込み機能を搭載しようと作ったコードでしたが、デフォルトのパーマリンクでは動かない(※)ので、今回は見送って記事だけ書くことにしました。

※WordPress公式ディレクトリに登録されるテーマは、誰がどのような状況で使っても問題なく動くようにしなければならない、という前提条件がある。

同時に価格による並べ替えにも挑戦しましたが、Welcartの商品価格は在庫数同様、データベース内ではシリアライズ(暗号化)されたSKUデータの一部となっており、一筋縄ではクエリ生成は出来なさそうです。

One Response to “「在庫がある商品だけを表示」ボタンを作る”

  1. […] で、困った時のウェルカスタムさんで探したところ「queryに在庫情報を組み込む現実的な解決法」が掲載されていた。しかし、在庫状態ではなく在庫数で判別しているので縛りがあるこ […]

Copyright© 2017 Welcart カスタマイズ ブログ All Rights Reserved.