カスタムフィールドのソート
-
こんにちは。
1つのカスタムフィールドの値(cf_point)でソートしていたのですが、グループ(cf_group)でソートさせた後にcf_pointでソートさせたいと思っています。
現在のコードは下記です。まだグループでソートできていません。
<?php query_posts( array( 'post_type' => 'shop', 'paged' => get_query_var('paged'), 'orderby'=>'meta_value', 'meta_key'=>'cf_point', 'order'=>'DESC' )); while (have_posts()) : the_post(); get_template_part('top-shop'); endwhile; wp_reset_query(); ?>
この並び替えに加えグループの並び替えを加えたいです。
cf_point cf_group
10 A
24 B
32 C
43 B
34 A
64 B
43 Cこちらを Aグループから順に ポイントが高い順に並べたいと考えています。
cf_point cf_group
34 A
10 A
64 B
43 B
24 B
43 C
32 Cその際どのように記述すればよいでしょうか。
よろしくお願い致します。
-
できればquery_postsを使いたいですが、そもそも仕様上無理なのでしょうか、うまくいきません。。。全く違うやり方でも、うまく並び替えできればと考えております。
引き続きご指導いただければ幸いです。「グループ(cf_group)」って、どこに入っているのですか。これもカスタムフィールドですか?
+---------+----------+------------+ | post_id | meta_key | meta_value | +---------+----------+------------+ | 1 | cf_point | 10 | +---------+----------+------------+ | 1 | cf_group | A | +---------+----------+------------+ | 2 | cf_point | 24 | +---------+----------+------------+ | 2 | cf_group | B | +---------+----------+------------+
こんな感じに読めるのですが… 合ってますか?
MySQL の機能としては、簡単です。が、それを WordPress にやらせるにはどうしたらいいのか…
上の形式で保存されているデータを、
+---------+----------+------------+----------+------------+ | post_id | meta_key | meta_value | meta_key | meta_value | +---------+----------+------------+----------+------------+ | 1 | cf_point | 10 | cf_group | A | +---------+----------+------------+----------+------------+ | 2 | cf_point | 24 | cf_group | B | +---------+----------+------------+----------+------------+
のような形で取得できれば、どのカラムを使ってもソートできます(meta_value はインデックスがないので、不利ですが)。これは同じテーブルを 2 回 JOIN で連結すれば実現できます。たとえば、
SELECT p.ID, m.meta_key AS grp, m.meta_value AS grpval, mm.meta_key AS pnt, mm.meta_value AS pntval FROM $wpdb->posts AS p INNER JOIN $wpdb->postmeta AS m ON m.post_id=p.ID INNER JOIN $wpdb->postmeta AS mm ON mm.post_id=p.ID WHERE (p.post_type='shop' AND p.post_status='publish') AND m.meta_key='cf_group' AND mm.meta_key='cf_point' GROUP BY p.ID ORDER BY m.meta_value ASC, mm.meta_value DESC
みたいな文を使います。グループ昇順、ポイント降順でソートされた並びになると思います。問題は、これを WordPress にどうやって作らせるかですよねぇ…
一応、
$sql = "上の文"; // ダブルクォートを使ってください $res = $wpdb->get_results($sql); print_r($res);
してみて、お望みの順番になっているかどうか確認してみてください。タイプミスがあるかもしれません。WordPress の方は、後で。
kjmtshさま、ご回答いただきありがとうございます!
$sql = "SELECT p.ID, m.meta_key AS grp, m.meta_value AS grpval, mm.meta_key AS pnt, mm.meta_value AS pntval FROM $wpdb->posts AS p INNER JOIN $wpdb->postmeta AS m ON m.post_id=p.ID INNER JOIN $wpdb->postmeta AS mm ON mm.post_id=p.ID WHERE (p.post_type='shop' AND p.post_status='publish') AND m.meta_key='cf_group' AND mm.meta_key='cf_point' GROUP BY p.ID ORDER BY m.meta_value ASC, mm.meta_value DESC"; $res = $wpdb->get_results($sql); print_r($res);
と入力したところ、実行したSQLのメッセージで
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '$sql = "SELECT p.ID, m.meta_key AS grp, m.meta_value AS grpval, ' at line 1
と表示されました。ロリポップサーバーのphpMyAdminにログインして実行しております。
データベース初心者のため、コードエラーの原因がわかりません。どのようなエラーが考えられますでしょうか。よろしくお願い致します。phpMyAdmin にこれをそのまま入れちゃだめですぅ。下をコピーして使ってくださいませ。「テーブルの接頭辞」が “wp_” でない場合は、そこを書き換えてね。
SELECT p.ID, m.meta_key AS grp, m.meta_value AS grpval, mm.meta_key AS pnt, mm.meta_value AS pntval FROM wp_posts AS p INNER JOIN wp_postmeta AS m ON m.post_id=p.ID INNER JOIN wp_postmeta AS mm ON mm.post_id=p.ID WHERE (p.post_type='shop' AND p.post_status='publish') AND m.meta_key='cf_group' AND mm.meta_key='cf_point' GROUP BY p.ID ORDER BY m.meta_value ASC, mm.meta_value DESC;
WordPress に実行させるコードです。
functions.php に以下を書きます。
function my_query() { add_filter('posts_fields_request', 'my_fields'); add_filter('posts_where_request', 'my_where'); add_filter('posts_groupby_request', 'my_groupby'); add_filter('posts_join_request', 'my_join'); add_filter('posts_orderby_request', 'my_orderby'); $posts_per_page = 5; $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; $args = array( 'posts_per_page' => $posts_per_page, 'paged' => $paged, ); $the_query = new WP_Query($args); return $the_query; } function my_fields($fields) { global $wpdb; $fields = "$wpdb->posts.*, m.meta_key AS grp, m.meta_value AS grpval, mm.meta_key AS pnt, mm.meta_value AS pntval"; return $fields; } function my_where($where) { global $wpdb; $post_type = 'shop'; $meta_key1 = 'cf_group'; $meta_key2 = 'cf_point'; $where = "AND $wpdb->posts.post_type='{$post_type}' AND $wpdb->posts.post_status='publish'"; $where .= " AND m.meta_key='{$meta_key1}' AND mm.meta_key='{$meta_key2}'"; return $where; } function my_groupby($groupby) { global $wpdb; $groupby = "$wpdb->posts.ID"; return $groupby; } function my_join($join) { global $wpdb; $join = "INNER JOIN $wpdb->postmeta AS m ON m.post_id=$wpdb->posts.ID"; $join .= " INNER JOIN $wpdb->postmeta AS mm ON mm.post_id=$wpdb->posts.ID"; return $join; } function my_orderby($orderby) { $orderby = "m.meta_value ASC, mm.meta_valu DESC"; return $orderby; }
テンプレートファイルでの使い方。
$the_query = my_query(); // 引数は全て functions.php で処理する if ($the_query->have_posts()) : while ($the_query->have_posts()) : $the_query->the_post(); the_title(); // 通常のテンプレートタグはそのまま使う echo $post->grp; // カスタムフィールドには echo が必要 echo $post->grpval; echo $post->pnt; echo $post->pntval; endwhile; endif; wp_reset_postdata();
ページングは通常どおり行われますので、functions.php の posts_per_page で指定してください。タイプミスがあるかもしれません。
kjmtshさま、ご回答ありがとうございます。
function.phpは転写し、エラー等ありませんでした。テンプレートファイルでの使い方ですが、私の場合
<?php query_posts( array( 'post_type' => 'shop', 'paged' => get_query_var('paged'), 'orderby'=>'meta_value', 'meta_key'=>'cf_point', 'order'=>'DESC' )); while (have_posts()) : the_post(); get_template_part('top-shop'); endwhile; wp_reset_query(); ?>
の記述部分をどのように変更させればよいでしょうか。質問ばかり恐縮です。宜しくお願い致します。
こんな感じでいいでしょうか。カラーリングできるエディタに張り付けて、コメントを読んでください。
<?php // $the_query 変数に投稿データとメソッドをセットする(必須) $the_query = my_query(); // if 条件判定 // have_posts() のかわりに、$the_query->have_posts() を使う if ($the_query->have_posts()) : // ループ開始 // have_posts() のかわりに $the_query->have_posts() を使う while ($the_query->have_posts()) : // the_post() のかわりに $the_query->the_post() を使う // テンプレート関数が使えるようにするためには必須 $the_query->the_post(); /* * テンプレートタグ * 表示したい場所で使う */ the_ID, the_title(); the_content(); the_excerpt();// etc... /* * カスタムフィールドの出力 1 * the_meta() の出力は、'cf_group: A' 形式でカスタマイズできない */ the_meta(); /* * カスタムフィールドの出力 2 * get_post_meta($post->ID, 'meta_key', true) の出力は、 * meta_value の値 A, B, など echo が必要 */ echo get_post_meta($post->ID, 'cf_group', true); /* * $post->meta_key はキーを、$post->meta_value は値を出力 * echo が必要 */ echo $post->grp; echo $post->grpval; echo $post->pnt; echo $post->pntval; // ループ終了 endwhile; // if 条件終了 endif; // 投稿データ制御をメインループに戻す wp_reset_postdata(); ?>
query_posts() は必要ありません。imanishi さんの場合、top-shop.php を読み込んで、ループ内の表示を制御しているので、そのファイル内で、cf_point の値を表示したいところで、
echo $post->pntval
を、cf_group の値を表示したいところで、echo $post->grpval
を書いてください。ちゃんとしたものにしたい場合は、これらを使って、テンプレート用の関数を一つ定義するのがスマートなのですが、今、時間がないので、これでご勘弁を。
- トピック「カスタムフィールドのソート」には新たに返信することはできません。