カスタムフィールドの値(meta_value)を処理した値で記事を並べ替える方法です。
以前に似たような記事タイトル、「カスタムフィールドの値(meta_value)でソート」がありましたが、そこで紹介した二つの方法の後者の方です。その二つとは:
- query_postsに渡す配列でorderby=meta_valueを指定する方法(この記事を見る)
- sql文を使って直接データベースを解析する方法(今回紹介する方法)
活用例としては、
カスタムフィールドに記録されたメーカー価格を基準に、商品ごとに異なる割引計算をした販売価格で、安い順 / 高い順 で表示したいような場合です。
カスタムフィールドの値を直接対象としてソートするなら上記方法の前者でよいのですが、計算した値でソートするとなるとWordpressの関数では対応しきれなくなってしまいます。その場合は、上記方法の後者、つまりWordpressのデータベースを解析してソートすることになります。
//データベースの投稿記事テーブルのイメージ | ID | 記事タイトル | -------------------- | 1 | テレビA | | 2 | テレビB | | 3 | テレビC | | 4 | 冷蔵庫A | | 5 | 冷蔵庫C | //データベースのカテゴリテーブルのイメージ | カテゴリID | 記事ID | ---------------------- | 11 | 1 | | 11 | 2 | | 11 | 3 | | 12 | 4 | | 12 | 5 | //データベースのメタ(カスタムフィールド)テーブルのイメージ | meta_key | meta_value | 記事ID | ----------------------------------- |'メーカー価格'| '240000' | 1 | | '割引率' | '20' | 1 | |'メーカー価格'| '180000' | 2 | | '割引率' | '30' | 2 | |'メーカー価格'| '360000' | 3 | | '割引率' | '50' | 3 | |'メーカー価格'| '120000' | 4 | | '割引率' | '20' | 4 | |'メーカー価格'| '78000' | 5 | | '割引率' | '20' | 5 |
<?php //何を。抽出したい値(投稿ID) $sql = "SELECT P.ID\n"; //どこから。基本とするデータベース内のテーブル(投稿記事のテーブル) $sql = "FROM {$wpdb->posts} AS P\n"; //結合したいテーブル(カテゴリテーブルを記事IDで結合) //INNER JOIN は、結合する二つのテーブル双方に存在する行のみを抽出 $sql = "INNER JOIN {$wpdb->term_relationships} AS T ON P.ID=T.object_id\n"; //結合したいテーブル(カスタムフィールドテーブルの'キー名'を記事IDで結合) //LEFT JOIN は、結合する二つのテーブル片方がNULLでもすべてを結合する $sql = "LEFT JOIN {$wpdb->postmeta} AS M1 ON P.ID=M1.post_id AND M1.meta_key = 'キー名(メーカー価格)'\n"; $sql = "LEFT JOIN {$wpdb->postmeta} AS M1 ON P.ID=M2.post_id AND M2.meta_key = 'キー名(割引率)'\n"; //WHERE以下は抽出条件 //'カテゴリID'のカテゴリで $sql = "WHERE T.term_taxonomy_id = 'カテゴリID'\n"; //かつ、公開されている記事を $sql = "AND P.post_status='publish'\n"; //次のソートで抽出 //CAST(値 AS SIGNED):文字列を数値とみなす //M1.meta_value - (M1.meta_value * M2.meta_value/100 → メーカー価格 - (メーカー価格 * 割引率) = 販売価格 //ASC:昇順で $sql = "ORDER BY CAST( M1.meta_value - (M1.meta_value * M2.meta_value/100 ) AS SIGNED) ASC\n"; $priceSortArr = $wpdb->get_results($sql, ARRAY_A); ?>
これで前述のテーブルは、指定した条件にしたがって結合され、計算結果の「販売価格」でソートされる。
| P.ID | P.記事タイトル | T.カテID | M1.メタキー | M1.メタ値 | M2.メタキー | M2.メタ値 | 販売価格 | -------------------- | 2 | テレビB | 11 | 'メーカー価格' | '180000' | '割引率' | '30' | 60000 | | 3 | テレビC | 11 | 'メーカー価格' | '360000' | '割引率' | '50' | 180000 | | 1 | テレビA | 11 | 'メーカー価格' | '240000' | '割引率' | '20' | 192000 |
//抽出結果は2次元配列になっているので、1次元配列に for ($i = 0; $i < count($priceSortArr); $i++) { $priceIdArr[] = $priceSortArr[$i]['ID']; } ?> [/php] これでquery_postsに、post__inを使用して抽出したIDリストを渡せばOKのように思われるが、query_postsは記事日時順に並べかえてしまう。post__inに羅列した順番どおりに記事を表示するには、プラグインが必要となります。(わずか数行なので、functions.phpに書いてしまってもよいかも) プラグイン:<a href="http://wordpress.org/extend/plugins/sort-query-by-post-in/" target="_blank">Sort Query by Post In</a> [php][/php] query_posts( array( 'post__in' => $priceIdArr, 'orderby' => 'post__in' ) );
ちょっと長くなりましたが、こんな感じです。