Welcartで作ったショッピングサイトの商品一覧ページに、「価格が安い順」「新着順」などで並べ替えるソート機能を付けたい——商品点数が増えてくると、ユーザーの使い勝手を左右する重要な機能です。
結論から言うと、商品価格をACFのカスタムフィールドに自動保存しておき、そのメタ値をキーに並べ替えることで、価格順ソートを実装できます。この記事では、価格の自動登録からセレクトボックスでのソート実装までを解説します。
今回は、WordPress標準のカスタムフィールドではなく、プラグイン「ACF(Advanced Custom Fields)」でカスタムフィールドを作ります。ただし、WelcartでACFを使うには、パッチプラグイン「WCEX Patch for ACF」のインストールが必要です。詳しくは以前の記事を参照してください。
パッチを導入できたら、カスタムフィールドで「search_price」という名前のフィールドを作っておきます(フィールド名は任意でかまいません)。詳しい導入方法はこちらの記事をご覧ください。
まず、商品価格が自動でsearch_priceフィールドに登録されるように、functions.phpに次のコードを記述します。ACFのフィールド値を更新するには、update_field()というACFの関数を使います。
function set_search_price($post_id, $post)
{
if (wel_get_product($post_id)) {
$price = usces_the_firstPrice('return', $post);
update_field('search_price', $price, $post_id);
}
}
add_action('save_post', 'set_search_price', 99, 2);
save_postフックで、商品の保存時(登録・更新時)に価格を取得し、search_priceフィールドへ書き込んでいます。wel_get_product()で「Welcartの商品かどうか」を判定し、商品のときだけ処理する点がポイントです。これで、商品を登録・更新するたびに、価格が自動でカスタムフィールドに保存されます。
次に、archive.phpなどの商品一覧ページに、ソート用のセレクトボックスを設置します。
<div class="sortarea">
<form name="itemsort" method="get" id="sort_form" class="sort_form">
<select name='sort_select' onChange="document.forms['itemsort'].submit()">
<option value="sort1" <?php if (!isset($_REQUEST['sort_select']) || $_REQUEST['sort_select'] == 'sort1') echo ' selected="selected"'; ?>>新着順</option>
<option value="sort2" <?php if (isset($_REQUEST['sort_select']) && $_REQUEST['sort_select'] == 'sort2') echo ' selected="selected"'; ?>>価格が高い順</option>
<option value="sort3" <?php if (isset($_REQUEST['sort_select']) && $_REQUEST['sort_select'] == 'sort3') echo ' selected="selected"'; ?>>価格が安い順</option>
</select>
</form>
</div>
<?php $sortset = $_GET['sort_select']; ?>
<?php $sortall = array(
"sort1" => "cat=$cat&order=DESC&posts_per_page=20&paged=",
"sort2" => "cat=$cat&order=DESC&orderby=meta_value_num&meta_key=search_price&posts_per_page=20&paged=",
"sort3" => "cat=$cat&order=ASC&orderby=meta_value_num&meta_key=search_price&posts_per_page=20&paged=",
); ?>
<?php if ($sortset != '') {
$sort = $sortall[$sortset];
} else {
$sort = $sortall["sort1"];
} ?>
<?php query_posts($sort . $paged); ?>
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post();
usces_the_item(); ?>
//商品のループ出力
<?php endwhile; ?>
<?php endif; ?>
セレクトボックスの項目を選んだ瞬間にsubmitされ、ソートがかかるようにしています。価格順(sort2・sort3)では、先ほど作ったsearch_priceをmeta_keyに指定し、orderby=meta_value_numで数値として並べ替えているのがポイントです。meta_valueではなくmeta_value_numを使うことで、価格が文字列ではなく数値として正しくソートされます。
なお、上記はquery_posts()を使ったシンプルな実装です。query_posts()はメインクエリを書き換えるため扱いに注意が必要で、規模の大きいサイトではpre_get_postsフックを使う方法のほうが安全とされています。まずは動く形として押さえつつ、必要に応じて実装方法を見直すとよいでしょう。
もう1点、実装時の注意です。フォームのセレクトボックスのname(ここではsort_select)と、PHP側で値を受け取る$_GETのキーは、必ず一致させてください。ここがずれていると、選んだ並び順が反映されず、常に新着順のままになってしまいます。動かないときは、まずこの名前の対応を確認するのが近道です。
save_postフックでカスタムフィールドに自動保存するmeta_value_numで並べ替えれば、価格順ソートが実装できる商品点数が多いショップほど、ソート機能はユーザーの買い物体験を左右します。価格をカスタムフィールドに持たせておく仕組みを作っておけば、価格順以外の並べ替えにも応用できます。