質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
WordPress

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

1回答

2354閲覧

カスタム投稿内のカスタムフィールドをランダムに表示したい

d_jomko

総合スコア14

WordPress

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2019/07/29 10:24

前提・実現したいこと

カスタム投稿(shop)の中に「お客様の声」という繰り返しフィールドのカスタムフィールドを持っています。
【お客様の声】というページを作成し、
カスタムフィールドの「お客様の声」をランダムで全て出力したいです。
かつ実現可能であればページ送りも実装したいと思っています。

該当のソースコード

妥協点として下記コードで出力はできましたが
当たりまえですが、一店舗一件しかお客様の声が出力できませんでした。

php

1 $paged = get_query_var('paged') ? get_query_var('paged') : 1; 2 $args = array( 3 'post_type' => 'shop', 4 'posts_per_page' => 10, 5 'paged' => $paged 6 ); 7 $the_query = new WP_Query($args); 8 if ($the_query->have_posts()) : 9 while ($the_query->have_posts()) : $the_query->the_post(); 10 11 // お客様の声 12 $rows = get_field('shop_voice'); // 配列を格納 13 $rand_row = $rows[array_rand($rows)]; // 配列からランダムで値を取得 14 $rand_ttl = $rand_row['ttl']; 15 $rand_comment = $rand_row['comment']; 16 $rand_img = $rand_row['img']; 17 $image = wp_get_attachment_image_src( $rand_img, 'voice_img' ); 18 $image_url = $image[0];

試したこと

全記事を取得し、
カスタムフィールド「お客様の声」を配列へ足していき、
それをランダムで出力しようと考えましたが、
こちらもうまくいきませんでした。

php

1$voice_array = array(); 2 $args = array( 3 'post_type' => 'shop' //投稿タイプの指定 4 ); 5 $lastposts = get_posts($args); 6 foreach($lastposts as $post) : 7 setup_postdata($post); 8 $voices = get_field('shop_voice'); 9 $voice_array = array_merge($voice_array,$voices); 10 11 $rand_row = $voices[array_rand($voices)]; 12 $rand_ttl = $rand_row['ttl']; 13 $rand_comment = $rand_row['comment'];

ヒントをいただけますと幸いです。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

説明不足だけど、Advanced Custom Fields プラグイン使われてますよね?

簡易で良ければこんな感じで取得できます。

「簡易」としたのは、本来ならば、ACFでは、それぞれのカスタムフィールドの名前とfieldkeyというのが対になって作成され、同じ名前のカスタムフィールドのでも別々に扱う事ができるようになっているからです。
そこをこのコードでは無視しています。

※大人しく、通常のWP_Queryで選択するfieldに、

PHP

1GROUP_CONCAT( 2 {$wpdb->postmeta}.meta_value 3 ORDER BY {$wpdb->postmeta}.meta_key DESC 4 SEPARATOR '@@' 5 ) AS comment

を追加するやり方にしました。またページネーションなしの方は邪魔なので削除しました。
これできっとget_the_titleを含めて他の関数も使えるはずです。

PHP

1$paged = (get_query_var('paged')) ? get_query_var('paged') : 1; 2$args = array( 3 'post_type' => 'shop', 4 'paged' => $paged, 5 'posts_per_page' => 10, 6 'orderby' => 'rand', 7); 8 9add_filter( 'posts_fields', 'custom_posts_fields' ); 10add_filter( 'posts_where', 'custom_posts_where' ); 11add_filter( 'posts_join', 'custom_posts_join' ); 12add_filter( 'posts_groupby', 'custom_groupby' ); 13$comments = new WP_Query( $args ); 14remove_filter( 'posts_fields', 'custom_posts_fields' ); 15remove_filter( 'posts_where', 'custom_posts_where' ); 16remove_filter( 'posts_join', 'custom_posts_join' ); 17remove_filter( 'posts_groupby', 'custom_groupby' ); 18 19if( $comments->have_posts()): while( $comments->have_posts() ):$comments->the_post(); 20 21echo $post->comment; 22 23endwhile;endif; 24if( function_exists( 'wp_pagenavi' ) ){ 25 wp_pagenavi( array( 'query'=>$comments ) ); 26} 27wp_reset_postdata(); 28 29 30 31//以下functcions.phpに追記 32function custom_posts_fields( $fields ){ 33 global $wpdb; 34 return $fields .= " 35 ,GROUP_CONCAT( 36 {$wpdb->postmeta}.meta_value 37 ORDER BY {$wpdb->postmeta}.meta_key DESC 38 SEPARATOR '@@' 39 ) AS comment 40 "; 41} 42 43function custom_posts_join( $join ){ 44 global $wpdb; 45 return $join = " INNER JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id "; 46} 47 48function custom_posts_where( $where ){ 49 global $wpdb; 50 return $where .= " 51 AND ( 52 {$wpdb->postmeta}.meta_key like 'shop_voice_%_ttl' 53 OR 54 {$wpdb->postmeta}.meta_key like 'shop_voice_%_comment' 55 OR 56 {$wpdb->postmeta}.meta_key like 'shop_voice_%_img' 57 ) "; 58 59} 60 61function custom_groupby( $groupby ){ 62 global $wpdb; 63 return $groupby = " 64 {$wpdb->posts}.ID 65 ,SUBSTRING( {$wpdb->postmeta}.meta_key, 1, LOCATE( '_', {$wpdb->postmeta}.meta_key, 12 ) )"; 66}

投稿2019/07/29 11:57

編集2019/07/31 03:01
yukikp

総合スコア797

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

d_jomko

2019/07/30 02:40

言葉足らずですみません、おっしゃる通りACFを使用しています。 参考にさせていただき、下記コードで実現できました! ありがとうございます。 もう一点ヒントいただけたらありがたいのですが、 これを10件でページネーションを実現したいのですが 「WP-PageNavi」プラグインで実現可能でしょうか。 --------------------------------------------- <?php global $wpdb; // お客様の声の取得 $results = $wpdb->get_results(" SELECT P.ID ,GROUP_CONCAT( PM.meta_value ORDER BY PM.meta_key DESC SEPARATOR '@@' ) AS comment FROM $wpdb->posts AS P INNER JOIN $wpdb->postmeta AS PM ON P.ID = PM.post_id WHERE P.post_status IN ('publish') AND ( PM.meta_key like 'shop_voice_%_ttl' OR PM.meta_key like 'shop_voice_%_comment' OR PM.meta_key like 'shop_voice_%_img' ) GROUP BY P.ID ,SUBSTRING( PM.meta_key, 1, 12) "); // 結果のシャッフル shuffle( $results ); // ループ開始 foreach( $results as $r ) : ### 投稿ID $target_id = $r->ID; ### 投稿URL $permalink = get_permalink( $target_id ); ### 投稿タイトル $post = get_post($target_id); $title = get_the_title($post); ### お客様の声 $target_voice = $r->comment; // 分割 $target_voice = explode( "@@", $target_voice); // 画像情報 $image = wp_get_attachment_image_src( $target_voice[1], 'voice_img' ); $image_url = $image[0]; ?> <div class="box"> <h3><?php echo $target_voice[0]; ?></h3> <div class="flex"> <figure> <?php if($target_voice[1]) : ?> <img src="<?php echo $image_url; ?>" alt="<?php echo $title; ?>"> <?php else: ?> <img src="<?php echo get_template_directory_uri(); ?>/assets/images/shop/dummy.png" alt="<?php the_title(); ?>"> <?php endif; ?> </figure> <div class="text"> <p><?php echo $target_voice[2]; ?></p> <ul class="flex"> <li class="btn btn_red"> <a href="<?php echo $permalink; ?>"><?php echo $title; ?></a> </li> <li class="btn btn_green"> <a href="<?php echo $permalink; ?>#voiceSection">他のお客様の声</a> </li> </ul> </div> </div> </div> <?php endforeach; ?> ---------------------------------------------
yukikp

2019/07/30 02:51 編集

検証してなかった部分があったので無事動いて良かったです。 WP-PageNaviプラグインは、メインループあるいはサブループで使われるものなので、このままだと無理です。 上記やり方は、SQL文を直接書いてデータベースに渡しているので、WordPressの「そう言った機能」を使っていません。 後で追記してみるのでそれならできるかなあ。 ちなみに、 GROUP BY P.ID ,SUBSTRING( PM.meta_key, 1, 12) を次のようにして GROUP BY P.ID ,SUBSTRING( PM.meta_key, 1, 12) ORDER BY RAND() さらに shuffle( $results ); をコメントアウトしたらどうなります?ランダムになりますか?
d_jomko

2019/07/30 02:56

>> 後で追記してみるのでそれならできるかなあ。 ありがとうございます! >> ランダムになりますか? ランダムになります! WPだとしても SQL文も勉強しないとカスタマイズに限度があるんですね。 スキルアップがまだまだ必要だと日々感じています。。
yukikp

2019/07/30 03:03

それと、 SUBSTRING( PM.meta_key, 1, 12) => SUBSTRING( PM.meta_key, 1, 13) に変更しました。
d_jomko

2019/07/30 03:33

ありがとうございます。 こちらでも問題なく動作しました!
d_jomko

2019/07/30 03:48

ページネーションのコードヒントもいただけたらありがたいです。
yukikp

2019/07/30 05:09

ページネーションこれで行くかな。
d_jomko

2019/07/30 09:31

ありがとうございます、ほぼ思い通りです。 本当にすごいです! 投稿タイトルのみ取れないんですが function custom_posts_join( $join ) にpost_titleの分のテーブルを追加するイメージでしょうか。
d_jomko

2019/07/30 09:37

参考にさせてもらって下記で実装してます。 何故か投稿タイトルだけとれないのでvar_dump('$post->comment')してみると title箇所が空欄だったので、どこかで追加しないといけないんだろうなということまではわかりました。 ---------------------------------- <?php $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; $args = array( 'post_type' => 'shop', 'paged' => $paged, 'posts_per_page' => 10, 'orderby' => 'rand', ); add_filter( 'posts_fields', 'custom_posts_fields' ); add_filter( 'posts_where', 'custom_posts_where' ); add_filter( 'posts_join', 'custom_posts_join' ); add_filter( 'posts_groupby', 'custom_groupby' ); $comments = new WP_Query( $args ); remove_filter( 'posts_fields', 'custom_posts_fields' ); remove_filter( 'posts_where', 'custom_posts_where' ); remove_filter( 'posts_join', 'custom_posts_join' ); remove_filter( 'posts_groupby', 'custom_groupby' ); if( $comments->have_posts()): while( $comments->have_posts() ):$comments->the_post(); echo $post->post_title; ### 投稿ID $target_id = $post->ID; ### 投稿URL $permalink = get_permalink( $target_id ); ### 投稿タイトル $target_post = get_post($target_id); $target_title = get_the_title($target_id); ### お客様の声 $target_voice = $post->comment; // 分割 $target_voice = explode( "@@", $target_voice); // 画像情報 $image = wp_get_attachment_image_src( $target_voice[1], 'voice_img' ); $image_url = $image[0]; ?> <div class="box"> <h3><?php echo $target_voice[0]; ?></h3> <div class="flex"> <figure> <?php if($target_voice[1]) : ?> <img src="<?php echo $image_url; ?>" alt="<?php echo $title; ?>"> <?php else: ?> <img src="<?php echo get_template_directory_uri(); ?>/assets/images/shop/dummy.png" alt="<?php $title; ?>"> <?php endif; ?> </figure> <div class="text"> <p><?php echo $target_voice[2]; ?></p> <ul class="flex"> <li class="btn btn_red"> <a href="<?php echo $permalink; ?>"><?php echo $title; ?></a> </li> <li class="btn btn_green"> <a href="<?php echo $permalink; ?>#voiceSection">他のお客様の声</a> </li> </ul> </div> </div> </div> <?php endwhile;endif; if( function_exists( 'wp_pagenavi' ) ){ wp_pagenavi( array( 'query'=>$comments ) ); } wp_reset_postdata(); ?> ----------------------------------
yukikp

2019/07/30 10:47 編集

今回の場合、 $post->post_title; では、shop投稿タイプのタイトルは取得できません。 shopの投稿ID: $post->ID shopのタイトル:get_the_title( $post->ID ) shopのパーマリンク:get_the_permalink( $post->ID ) お客様の声:$post->comment; です。
yukikp

2019/07/30 10:47 編集

みたところ、 ・$titleが突然現れている(変数になんの代入もない) ・echo $title;とすべきところを echo が抜けている 感じですね。
d_jomko

2019/07/31 01:18

下記のようにしてみたのですが、 パーマリンク・お客様の声は取れるのですが、 タイトルだけ取れないです。 変数に入れないで「get_the_title( $post->ID )」を直接書いても同様です。 $comments = new WP_Query( $args );とは別に $args直後に$the_query = new WP_Query( $args );を書くと何故か1ページ目のみは取れます。 -------------------------- ### 投稿ID $target_id = $post->ID; ### 投稿URL $permalink = get_permalink($target_id); ### 投稿タイトル $target_title = get_the_title($target_id); ### お客様の声 $target_voice = $post->comment; --------------------------
yukikp

2019/07/31 02:30

タイトルとは、お客様のコメントがつけられた店舗記事のタイトルですか?
d_jomko

2019/07/31 02:31

shop投稿タイプのタイトルです! get_the_title( $post->ID )の箇所です。
yukikp

2019/07/31 02:39

また、一つ上でも書きましたが $target_title = get_the_title($target_id) これは良いのですが、「実装しました」としてあるコードでは、$target_titleが使われずに、なぜか$titleという変数が使われている上、$titleの中身を表示させたいのだろうと思われる部分でechoが抜けています。
d_jomko

2019/07/31 02:47

言葉足らずですみません。 echo $target_title;でも echo get_the_title( $post->ID );に書き換えても取れないです。 こちら何か原因ありますでしょうか。 パーマリンク、投稿IDは問題なく取得できているのですが、、、。
yukikp

2019/07/31 02:55

d_jomkoさんの言うとおり、取得するカラムでpost_titleを追加するのが必須でした。 修正版をアップしたのでご確認ください。
yukikp

2019/07/31 03:02

余分なデータはいらないかなと思い、データベースから選択するカラムを制限していましたが、他の関数も使えるように、取得するデータを通常のWP_Queryに追加する形にしました。
d_jomko

2019/07/31 03:30

出力できました。 長々と本当にありがとうございました! まだまだ勉強が必要だとかなり思いました、、、。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問