いつもお世話になっております。最近wordpressもphpも皆様のおかげでだいぶ慣れたきました。
今回、お知恵を拝借したいのは、要約した箇条書きにすると以下のようになります。
- 顧客のサーバーにカスタム投稿タイプで商品が登録されている
- その商品にはカスタムフィールドに値段が設定されているが、他の処理で必要なためカンマ区切りの金額になっている
- WP_Queryで値段でソートして全件取得したところ、カンマ前までの数値でソートされており、
12,200 12,800 12,300
のように値段順にきちんとソートされない - 商品数が多いのと他の処理ではカンマが必要なためデータの変更は出来ない
- どうにかしてカンマが入ってても
12,200 12,300 12,800
のようにソートしたい
追記3 ついに成功・解決したコードと方法論
いただいたアドバイスとグーグル先生に聞きまくってついに希望通りの結果が得られましたので記載します。
クエリーを投げてる部分、このままでは値段順に並ばない。
php
1$args = array( 2 'post_type' => 'product', // 取得する投稿タイプのスラッグ, 3 'posts_per_page' => 18, 4 'paged' => $paged, 5 'orderby' => 'meta_value_num', 6 'order' => 'DESC', 7 'meta_key' => '値段', 8 'post_status' => 'publish', 9 ); 10 $wp_query = new WP_Query( $args ); 11
アドバイスをいただいてposts_requestをフックしてSQLを書き換えるコード
php
1add_filter('posts_request', function ($query) { 2 global $template; 3 4 if( basename($template) != "search.php" ) { 5 return $query; 6 } 7 8 //echo "<br>" . $query . "<br>"; 9 10 $pos3 = mb_strrpos( $query, "L" ); 11 $queryLimit = mb_substr( $query, $pos3 ); 12 13 //echo "<br>" . $queryLimit . "<br>"; 14 15 //echo "<br>" . "enter overwite query" . "<br>"; 16 $query = 17 " 18 SELECT SQL_CALC_FOUND_ROWS wp_posts.* 19 FROM wp_posts 20 INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) 21 INNER JOIN ( 22 SELECT meta_id, post_id, meta_key, CAST(REPLACE(meta_value,',','') AS DECIMAL) AS meta_value_no_comma 23 FROM wp_postmeta 24 WHERE wp_postmeta.meta_key = '値段' 25 ORDER BY `meta_value_no_comma` DESC ) AS wp_postmeta2 ON ( wp_posts.ID = wp_postmeta2.post_id) 26 WHERE 1=1 AND ( wp_postmeta.meta_key = '値段' ) AND wp_posts.post_type = 'product' AND ((wp_posts.post_status = 'publish')) 27 GROUP BY wp_posts.ID 28 ORDER BY `meta_value_no_comma` DESC " . $queryLimit; 29 30 //echo "<br>" . $query . "<br>"; 31 32 return $query; 33});
これで思い通りの結果を得られました。キモとなったのは別名に対して ` バッククオートで囲めば別名で使用できるということでした。
sql
1SELECT SQL_CALC_FOUND_ROWS wp_posts.* 2FROM wp_posts 3INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) 4INNER JOIN ( SELECT meta_id, post_id, meta_key, CAST(REPLACE(meta_value,',','') AS DECIMAL) AS meta_value_no_comma 5 FROM wp_postmeta 6 WHERE wp_postmeta.meta_key = '値段' 7 ORDER BY `meta_value_no_comma` DESC ) AS wp_postmeta2 8 ON ( wp_posts.ID = wp_postmeta2.post_id) 9WHERE 1=1 AND ( wp_postmeta.meta_key = '値段' ) 10AND wp_posts.post_type = 'product' 11AND ((wp_posts.post_status = 'publish')) 12GROUP BY wp_posts.ID 13ORDER BY `meta_value_no_comma` DESC 14LIMIT 0, 18 15```参考になったリンクも記載しておきます 16 17[MySQL の ORDER BY 句でカラムの別名が使えない](https://techblog.recochoku.jp/2723) 18 19[MySqlのデベロッパーページの別名の使用方法](https://dev.mysql.com/doc/refman/5.6/ja/problems-with-alias.html) 20 21--- 22 23### 追記2 さらにアドバイスをいただいて試したこと 24KazuhiroHatano様がしきりにJOINして別名とおっしゃていたのが何となく引っかかっていて、progateではwhereにしかサブクエリを書くものがなかったので 25whereにしか書けないのかと、思い込んでいましたが、再度のアドバイスでも同じことをおっしゃってらしたので、 26もしや・・・と思い。グーグルで```SQL JOIN サブクエリ```で検索かけたらHITして**JOINでも使えるじゃん!**と分かり。 27**SQLを書き直しました。が、しかし、今度は別のエラーメッセージが表示されるようになりました。** 28 29再度書き直したSQL 30```SQL 31SELECT SQL_CALC_FOUND_ROWS wp_posts.* 32FROM wp_posts 33INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) 34INNER JOIN ( 35 SELECT post_id, meta_key, CAST(REPLACE(meta_value,',','') AS DECIMAL) 36 FROM wp_postmeta 37 WHERE 1=1 AND ( wp_postmeta.meta_key = '値段' ) AND wp_posts.post_type = 'product' AND ((wp_posts.post_status = 'publish')) 38 ) AS wp_postmeta2 39WHERE 1=1 AND ( wp_postmeta.meta_key = '値段' ) AND wp_posts.post_type = 'product' AND ((wp_posts.post_status = 'publish')) 40GROUP BY wp_posts.ID 41ORDER BY wp_postmeta2.meta_value+0 DESC LIMIT 0, 18" 42
新たに出てきたエラーメッセージはこちらです。
Unknown column 'wp_posts.post_type' in 'where clause'
申し訳ありませんが、再度アドバイスをいただけたら幸いです。
追記 アドバイスをいただいてから試したこと
function.phpに以下の記述を追加
php
1add_filter('posts_request', function ($query) { 2 global $template; 3 $original_sql = "SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1 AND ( wp_postmeta.meta_key = '値段' ) AND wp_posts.post_type = 'product' AND ((wp_posts.post_status = 'publish')) GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value+0 DESC LIMIT 0, 18"; 4 5 if( basename($template) != "search.php" ) { 6 return $query; 7 } 8 9 echo "<br>" . $query . "<br>"; 10 11 $pos1 = mb_strrpos( $query, "L" ); 12 $original_sql = mb_substr( $original_sql, 0, $pos1-6 ); 13 14 $pos2 = mb_strrpos( $query, "L" ); 15 $queryLimit = mb_substr( $query, $pos2 ); 16 17 $query = mb_substr( $query, 0, $pos2 ); 18 19 echo "<br>" . str_replace(PHP_EOL, '', str_replace(' ', '', $original_sql)) . "<br>"; 20 echo "<br>" . str_replace(PHP_EOL, '', str_replace(' ', '', $query)) . "<br>"; 21 22 echo "<br>" . $queryLimit . "<br>"; 23 24 if (str_replace(PHP_EOL, '', str_replace(' ', '', $original_sql)) == str_replace(PHP_EOL, '', str_replace(' ', '', $query))) { 25 26 echo "<br>" . "enter overwite query" . "<br>"; 27 $query = 28 " 29 SELECT SQL_CALC_FOUND_ROWS wp_posts.*, wp_postmeta.non_comma_value 30 FROM wp_posts 31 INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) 32 WHERE 1=1 AND ( wp_postmeta.meta_key = '値段' ) AND wp_posts.post_type = 'product' AND ((wp_posts.post_status = 'publish')) AND ( 33 SELECT *, CAST(REPLACE(meta_value,',','') AS DECIMAL) AS non_comma_value 34 FROM wp_postmeta 35 WHERE wp_posts.ID = wp_postmeta.post_id 36 ) 37 GROUP BY wp_posts.ID 38 ORDER BY non_comma_value+0 DESC 39 " . $queryLimit; 40 } 41 42 echo "<br>" . $query . "<br>"; 43 44 return $query; 45}); 46
上記のコードで変更前のSQLをDUMPしたものが下記で
SQL
1SELECT SQL_CALC_FOUND_ROWS wp_posts.* 2 FROM wp_posts 3 INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1 AND ( wp_postmeta.meta_key = '値段' ) AND wp_posts.post_type = 'product' AND ((wp_posts.post_status = 'publish')) 4 GROUP BY wp_posts.ID 5 ORDER BY wp_postmeta.meta_value+0 DESC 6 LIMIT 0, 18
私のコードで修正したSQLが以下になります。
SQL
1SELECT SQL_CALC_FOUND_ROWS wp_posts.*, wp_postmeta.non_comma_value 2 FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1 AND ( wp_postmeta.meta_key = '値段' ) 3 AND wp_posts.post_type = 'product' 4 AND ((wp_posts.post_status = 'publish')) 5 AND ( SELECT *, CAST(REPLACE(meta_value,',','') AS DECIMAL) AS non_comma_value 6 FROM wp_postmeta WHERE wp_posts.ID = wp_postmeta.post_id ) 7 GROUP BY wp_posts.ID 8 ORDER BY non_comma_value+0 DESC 9 LIMIT 0, 18
が、このSQLを実行する前にSQL構文チェッカーで問題なしと出たので、実行してみたところ以下のエラーメッセージが出て
ここからどこをどうやって直せばいいのか分かりません。
Unknown column 'wp_postmeta.non_comma_value' in 'field list'
直すべきところをアドバイスいただけたら幸いですm(_ _)m
やったこと、試したこと
・まずカスタムフィールドでソートする方法が判らず、検索条件を変えて色々グーグル先生に教わって
やっと、なんとかカスタムフィールドで値段順にソートできるようになった。
・しかし詳細を見てみると上記の通り正しくソートされていないことが判明
・custom_WP_Queryみたいなのを作って対応できないかグーグル先生に2時間聞いてみたが、答えが見つからなかった。
・再度、検索条件を変えてグーグル先生に質問すること2時間。解決策がHITせず、こちらに来たしだいです
以下が検索に使っているコードです。これをどうすれば思い通りの結果が得られるか、お知恵を貸していただけませんでしょうか。
php
1<?php 2 $args = array( 3 'post_type' => 'product', // 取得する投稿タイプのスラッグ, 4 'posts_per_page' => 18, 5 'paged' => $paged, 6 'orderby' => 'meta_value_num', 7 'order' => 'DESC', 8 'meta_key' => '値段', 9 'post_status' => 'publish', 10 ); 11 $wp_query = new WP_Query( $args ); 12?> 13
以上となります。なにとぞよろしくお願いします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/10/09 20:06
2020/10/13 03:59
2020/10/13 04:42
2020/10/13 04:59
2020/10/14 05:25
2020/10/14 05:49
2020/10/19 05:45