つながるnet

カスタムフィールドの値(meta_value)の計算値でソートする

カスタムフィールドの値(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' ) );

ちょっと長くなりましたが、こんな感じです。

直接メールしてみる

お名前 (必須)
メールアドレス (必須)
件名
ご相談内容
画像文字をご入力ください
captcha

コメントを残す