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

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

ただいまの
回答率

90.84%

  • PHP

    18631questions

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

  • WordPress

    6410questions

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

カスタムフィールドの値から関連記事を表示する方法

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 222

matsuzakaq

score 219

前提と目的

プラグイン「smart custom field」でカスタムフィールドを作りました。

tag_singleというフィールド名のチェックボックスです。

このチェックボックスをタグのように扱い、同じチェックがある記事を関連記事として表示させたいです。
イメージ説明

やってみたこと

次のコードを書いてみたのですが、なぜか「同じチェックの記事」でなく、全ての記事がなんでもかんでも表示されてしまう状況です。

どのように修正したらいいでしょうか?

<!--ここがあやしい-->
<?php
$hastag = get_post_meta( $post->ID, 'tag_single', true );
if( !empty( $hastag ) ) {
    $tags = SCF::get( 'tag_single' );
    foreach( $tags as $tag ) {
        $tagkwds[] = $tag->post_name;
    }
} ?>

<!--以下からは大丈夫なはず-->
<?php
$myposts = get_posts( array(
    'post_type' => 'post',
    'posts_per_page' => '8',
    'post__not_in' => array( $post->ID ),
    'category__in' => $catkwds,
    'orderby' => 'rand'
) ); ?>

<?php if( $myposts ): ?>

<section class="related-section">
    <div id="content-wrap">
        <div class="content">
            <?php foreach($myposts as $post):
            setup_postdata($post); ?>

                <?php get_template_part( 'template-parts/list', 'single' ); ?>

            <?php endforeach; ?>
        </div>
    </div>
</section>

<?php wp_reset_postdata(); ?>

<?php endif; ?>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • matsuzakaq

    2018/05/14 17:35

    はい、本来は例えば不動産さんサイトで「新築・築5年・築10年」とチェックしたり、お土産屋さんサイトで「女性向け・男性向け」とチェックしたり、など、記事作成時の利便性を高めるため。という目的で設置されるフィールドだと思います。

    キャンセル

  • matsuzakaq

    2018/05/14 17:36

    そして質問のコードは「https://it-tantou.com/3059/」から拝借いたしました。カテゴリの場合はこのコードで出来ました。「カテゴリじゃなくカスタムフィールドだから、上の部分だけ変えよう」と思ったので、<!--ここがあやしい-->の部分だけを変えて、できずに質問した。という経緯です。

    キャンセル

  • KazuhiroHatano

    2018/05/14 17:47

    理解していないコードをコピペするのは避けましょう

    キャンセル

回答 1

checkベストアンサー

0

以下からも全然大丈夫じゃない

SCFのことはよく知らんがsmart custom fieldなんて名前なんだから
SCF::get()が返しているのはpost_metaの値だろう

使うのはcategory__inじゃなくmeta_query

なんか色々ごっちゃになってそうなのでついでにこれも貼っときます
WPデータベース構造
カスタムフィールドはwp_postmetaテーブルに
tagやcategoryはwp_termsに入ってます
入ってるとこから違います


追記

SCFのことよく知らないので、一つ確認したいことがあります

$hastag = get_post_meta( $post->ID, 'tag_single', true );


複数にチェックを入れた場合にこの$hastagはもしかしてarrayですか?
それともチェックした項目のうちどれかひとつの値でしょうか?
var_dumpしてみてください


複数の値をシリアライズして一つのフィールドに入れるタイプのやつだと
検索はかなりしんどいので確認でした

さて

$hastag = get_post_meta( $post->ID, 'tag_single', true );
if( !empty( $hastag ) ) {
    $tags = SCF::get( 'tag_single' );
    foreach( $tags as $tag ) {
        $tagkwds[] = $tag->post_name;
    }
} 


ここら辺まるっと要りません

「同じカスタムフィールドの値」を持ってるものを検索したいんだから
値をそのまま取り出して検索に使えばいいだけです

$tags = get_post_meta( $post->ID, 'tag_single');

これでmeta_queryのvalueに使う値は取れました
あとはこれを使ってget_postsすればいいだけです

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/14 17:31

    ご検討ありがとうございます。
    「チェックした項目のうちどれかひとつの値」でした。
    例えば全てにチェックしたらfluitsだけが出力されます。
    もちろんチェックが1つだけならそれが出力されます。

    キャンセル

  • 2018/05/14 18:07 編集

    下記の【1】【2】【3】の方法を試してみましたけれど、全てチェックの有無にかかわらずいろんな記事が表示されてしまいました。

    ただ、【3】だけはチェックした値が出力されました。

    キャンセル

  • 2018/05/14 18:13 編集

    【1】ご回答のバージョン
    →「#test1」はArrayでした…(>_<)

    <?php
    $tags = get_post_meta( $post->ID, 'tag_single');
    echo '<p id="test1">'.$tags.'<p>';
    ?>

    <?php
    $myposts = get_posts( array(
    'post_type' => 'post',
    'posts_per_page' => '8',
    'post__not_in' => array( $post->ID ),
    'meta_query' => $tags,
    'orderby' => 'rand'
    ) ); ?>

    以下同じ

    キャンセル

  • 2018/05/14 18:16 編集

    【2】SCF向けにしたバージョン
    →「#test2」はArrayでした…(>_<)

    <?php
    $tags = SCF::get('tag_single');
    echo '<p id="test2">'.$tags.'<p>';
    ?>

    <?php
    $myposts = get_posts( array(
    'post_type' => 'post',
    'posts_per_page' => '8',
    'post__not_in' => array( $post->ID ),
    'meta_query' => $tag,
    'orderby' => 'rand'
    ) ); ?>

    以下同じ

    キャンセル

  • 2018/05/14 18:19 編集

    【3】SCF向けにしてループしたバージョン
    →「#test3」はチェックした値が全て出力されました…(^^)

    <?php
    $tags = SCF::get('tag_single');
    foreach ($tags as $tag) {
    echo '<p id="test3">'.$tag.'<p>';
    }
    ?>

    <?php
    $myposts = get_posts( array(
    'post_type' => 'post',
    'posts_per_page' => '8',
    'post__not_in' => array( $post->ID ),
    'meta_query' => $tag,
    'orderby' => 'rand'
    ) ); ?>

    以下同じ

    キャンセル

  • 2018/05/14 18:30

    このサイトによるとチェックボックスの出力は【3】の方法のようです。
    https://www.akecre.com/wordpress/display_scf/#i-5

    あとは
    'meta_query' => $tag,
    がおかしいのですよね。

    うーん。。

    キャンセル

  • 2018/05/14 18:31

    meta_queryのリンク先に答えはあります
    リンク先からちょっと下に行けばmeta_queryのサンプルコードがあります

    https://wpdocs.osdn.jp/関数リファレンス/WP_Query#Custom_Field_Parameters

    meta_query初めての時はここ注意
    >(meta_query はクエリがひとつだけでも入れ子の配列を指定しなければなりません。)

    キャンセル

  • 2018/05/14 18:34

    さて、meta_queryのvalueに使う値は用意できました
    あとはkeyとcompareですね

    キャンセル

  • 2018/05/14 20:23

    ありがとうございます。かなり迫ってこれました。最後に1つだけ教えてください(>_<)

    あと出来ないのが、「1つでも一致したら」という'compare'です。



    下記【現在のコード】のように「LIKE」を使うのが一番近い表示になりました。ですがこれだと、

    ・記事Xのチェック:fluits
    ・記事Yのチェック:fluits、dlink

    というときに、Xの関連記事としてYは出るのですが、逆にYの関連記事としてXが出ないのです。

    かといって「LIKE」でなく「=」や「IN」でもダメでした。

    ほかに「1つでも一致したら」という条件の'compare'はないのでしょうか?

    【現在のコード】
    <?php
    $myposts = get_posts( array(
    'post_type' => 'post',
    'posts_per_page' => '8',
    'post__not_in' => array( $post->ID ),
    'meta_query' => array(
    array(
    'key' => 'tag_single',
    'value' => $tag,
    'compare' => 'LIKE'
    )
    ),
    'orderby' => 'rand'
    ) ); ?>

    キャンセル

  • 2018/05/14 20:27

    そこはINでok、valueは値の配列、つまりget_post_meta( $post->ID, 'tag_single',false);で取得した値そのまま

    キャンセル

  • 2018/05/14 20:42 編集

    んっと、それだと何も表示されないのです。


    【INバージョン】
    →「#var_IN]の値はArrayになる。何も表示されない。

    <?php
    $tags = get_post_meta( $post->ID, 'tag_single' );
    foreach ($tags as $tag);
    echo '<p id="var_IN">'.$tag.'</p>';
    ?>

    <?php
    $myposts = get_posts( array(
    'post_type' => 'post',
    'posts_per_page' => '8',
    'post__not_in' => array( $post->ID ),
    'meta_query' => array(
    array(
    'key' => 'tag_single',
    'value' => $tag,
    'compare' => 'IN'
    )
    ),
    'orderby' => 'rand'
    ) ); ?>


    【LIKEバージョン】
    →「#var_LIKE]の値はチェック全てが出る。しかし、Xの関連記事としてYは出るのですが、逆にYの関連記事としてXが出ない。

    <?php
    $tags = get_post_meta( $post->ID, 'tag_single' );
    foreach ($tags as $tag);
    echo '<p id="var_LIKE">'.$tag.'</p>';
    ?>

    <?php
    $myposts = get_posts( array(
    'post_type' => 'post',
    'posts_per_page' => '8',
    'post__not_in' => array( $post->ID ),
    'meta_query' => array(
    array(
    'key' => 'tag_single',
    'value' => $tag,
    'compare' => 'LIKE'
    )
    ),
    'orderby' => 'rand'
    ) ); ?>

    キャンセル

  • 2018/05/14 20:45

    'value' => $tag,

    'value' => $tags,

    get_post_meta( $post->ID, 'tag_single' )の値はそのまま
    そのまま渡す

    キャンセル

  • 2018/05/14 20:51

    うーん。こう↓ですよね…?
    これですと「#var_IN2」はArrayが表示されてしまいます。


    【INバージョンその2】

    <?php
    $tags = get_post_meta( $post->ID, 'tag_single' );
    echo '<p id="var_IN2">'.$tags.'</p>';
    ?>

    <?php
    $myposts = get_posts( array(
    'post_type' => 'post',
    'posts_per_page' => '8',
    'post__not_in' => array( $post->ID ),
    'meta_query' => array(
    array(
    'key' => 'tag_single',
    'value' => $tags,
    'compare' => 'IN'
    )
    ),
    'orderby' => 'rand'
    ) ); ?>

    キャンセル

  • 2018/05/14 22:45

    そりゃ$tagsはArrayですからねぇ
    implodeするなりせんと文字列にはなりませんねぇ

    get_post_meta( $post->ID, 'tag_single', true )が
    Arrayじゃないか確かめたのが引っかかってるんだと思いますが
    あそこで確かめたのはDBの一つのカラムにまとめて
    値が入れられてないかということです

    検索に使う値としてどうかとかではないです

    キャンセル

  • 2018/05/14 23:03

    ギブアップです。どう書けばいいのか教えていただけませんでしょうか…?

    キャンセル

  • 2018/05/14 23:24

    投稿の取得はできましたか?まだそこからできてないですか?

    キャンセル

  • 2018/05/14 23:29

    >implodeするなりせんと文字列にはなりませんねぇ
    とのこと。implodeというのをあれこれ使ってみたのですが、うまくいかず。
    そこで文字列にするための方法としてtrueを入れればいいとわかり、やってみました。すると、Arrayでなくチェックボックスの値が出るようにはなりました。こうです。しかし、関連記事は表示されない様子です…。泣きそうです。笑

    <?php
    $tags = get_post_meta( $post->ID, 'tag_single',true );
    echo '<p id="var_TRUE">'.$tags.'</p>';
    ?>

    <?php
    $myposts = get_posts( array(
    'post_type' => 'single',
    'posts_per_page' => '8',
    'post__not_in' => array( $post->ID ),
    'meta_query' => array(
    array(
    'key' => 'tag_single',
    'value' => $tags,
    'compare' => 'IN'
    )
    ),
    'orderby' => 'rand'
    ) ); ?>

    キャンセル

  • 2018/05/14 23:56

    meta_queryのvalueに使いたいのは配列です
    get_post_meta( $post->ID, 'tag_single',true )の戻り値は配列ではありません
    get_post_meta( $post->ID, 'tag_single')の戻り値が欲しい配列です
    get_post_meta( $post->ID, 'tag_single')の値だったら投稿の取得はできましたか?

    キャンセル

  • 2018/05/15 00:03 編集

    それで投稿の取得(関連記事として表示することですよね?)ができるのは、上の20:42に書いた【LIKEバージョン】だけでした。

    $tagsでなく$tagですが、うーん。$tagsであってるのでしょうか?
    ほんっと~うにわからないので教えて頂くわけにはいきませんでしょうか?

    再掲ですみません↓

    【LIKEバージョン】
    →「#var_LIKE]の値はチェック全てが出る。しかし、Xの関連記事としてYは出るのですが、逆にYの関連記事としてXが出ない。

    <?php
    $tags = get_post_meta( $post->ID, 'tag_single' );
    foreach ($tags as $tag);
    echo '<p id="var_LIKE">'.$tag.'</p>';
    ?>

    <?php
    $myposts = get_posts( array(
    'post_type' => 'post',
    'posts_per_page' => '8',
    'post__not_in' => array( $post->ID ),
    'meta_query' => array(
    array(
    'key' => 'tag_single',
    'value' => $tag,
    'compare' => 'LIKE'
    )
    ),
    'orderby' => 'rand'
    ) ); ?>

    キャンセル

  • 2018/05/15 00:26

    【INバージョンその2】でも結局投稿の取得もできなかったんですか?
    それでLIKEなら通るとなるとやっぱりSCFは複数の値を
    一つのカラムに全部まとめて入れてるんじゃないかって疑惑があるんですが
    本当にget_post_meta( $post->ID, 'tag_single',true )なら
    複数の値のうち一つだけしか返らなかったんですか?

    最悪relationをorにして$tagの数だけLIKEでmeta_queryを書くという手もありますが
    get_post_meta( $post->ID, 'tag_single',true )なら配列は返らなかった
    というのを信用するなら【INバージョンその2】は投稿の取得はできるはずです

    キャンセル

  • 2018/05/15 00:51

    もう一つ可能性があるのは、SCFが値はが配列であるかないかに関わらずシリアライズしてDBに値を入れているという可能性でしょうか、あまりないとは思いますが

    キャンセル

  • 2018/05/15 01:25 編集

    >【INバージョンその2】でも結局投稿の取得もできなかったんですか?
    それでLIKEなら通るとなると

    あ、誤解があるかもしれません。

    【INバージョンその2】は
    'value' => $tags,
    ですが、

    【LIKEバージョン】は
    'value' => $tag,
    です。

    なので、「それでLIKEなら通るとなると」というより、「LIKEにしてtagにしたら通るとなると」という感じです。

    これをもし、「LIKEにしただけでtagsのまま」だと、「wp-includes/class-wp-meta-query.php on line 577」というエラーが返ってきます。



    で、、、、

    >本当にget_post_meta( $post->ID, 'tag_single',true )なら
    複数の値のうち一つだけしか返らなかったんですか?

    ですが、もう一度調べましたが、『『大っっっ変申し訳ございません!!』』
    複数の場合、複数が出力されました。出力結果は

    値A| 値B

    という感じです。



    蛇足ですがこうなった経緯をご説明します。

    実は、質問時はSCFを利用しており、その場合は
    $tags = get_post_meta( $post->ID, 'tag_single',true );
    だと一つだけしか返りませんでした。
    正しくは
    $tags = SCF::get('tag_single');
    としなければならなかったからだと思います。
    そしてこちらは「IN」で仰るようにできました。

    問題はその後、20:23 以降はSCFを使わない、普通のカスタムフィールドのチェックボックスで関連記事を設置する目的にコッソリすり替えておりました。実はSCFを使った 'tag_single' と、使わない 'tag_single' で実験していたのです。

    そしてこの場合、
    get_post_meta( $post->ID, 'tag_single',true );
    だと複数返るようでした。

    この場合は一つだけか複数かを確認するのを怠ったせいで、上述の『『大っっっ変申し訳ございません!!』』が起こってしまったという次第でございます。

    ほんとうにごめんなさい。。心からお詫びいたします。

    キャンセル

  • 2018/05/15 01:56

    SCFは結局、複数の値を一つのフィールドにまとめて入れるタイプだったみたいですね
    しかも区切り文字で区切って分ける奴ですか、面倒ですね…

    配列かどうかと聞いてしまったのは、ちょっとその可能性を想定できてなかったです

    正直検索に使うことを考えるとまだシリアライズされてた方がマシなんですよ
    複数の値が一つのフィールドにまとめられてると、LIKEを使わざるを得ないわけなんですが
    そうなると、「ear」を検索すると「year」も「earth」も引っかかるって感じになっちゃう
    シリアライズされていればs:[文字数]:[文字列]で入っているので
    検索キーワードをシリアライズして検索すれば単語内での一致に引っ掛けてしまうことがないのです

    まあ、そうなってしまっている以上、先に書いたように
    relationをorにして$tagの数だけLIKEでmeta_queryを書く
    というように対応するしかないですね

    単語内に別の単語が内包されるケースを想定して書くなら
    区切り文字、先頭、終端を交えてRLIKEで書く感じでしょうかね
    処理重そう…

    キャンセル

  • 2018/05/15 02:08

    >区切り文字で区切って分ける奴

    区切り文字で出てくるのは、普通のカスタムフィールドのチェックボックスを
    get_post_meta( $post->ID, 'tag_single',true );
    で出力した場合です。

    あ、ひょっとして、これ、普通のカスタムフィールドじゃないかもしれません。「WP user fronted」(WPUF)というプラグインで「ユーザー投稿時にチェックするカスタムフィールド」なのです。

    なので正確には「SCFのカスタムフィールド」と「WPUFのカスタムフィールド」のそれぞれで実験していて、SCFはINで出来たけど、WPUFは出来ない。という状況でした。

    まぁそれはいいですね。いずれにせよ、下記の解決策を示して頂いて感謝です。

    >relationをorにして$tagの数だけLIKEでmeta_queryを書く

    なるほどなるほど。ありがとうございます。タグは幸い6つなので、ぎりちょんで許容範囲です。(;'∀')

    なんとか今夜中にトライしてみます。(ネムイ…笑)

    夜分までお付き合い頂きまして、誠にありがとうございますっ!

    キャンセル

  • 2018/05/15 02:58 編集

    あれ?でも、「fluits、cake、vegetables、dlink、desert、alcohol」と6種類あるとします。

    次のようにすると、「fluitsにチェックが入った記事では、fluitsにチェックが入った記事を表示」などを6通りはできます。
    けれど、「fluitsとcakeにチェックが入ってるとき、fluitsにチェックが入った記事と、cakeにチェックが入った記事を表示」というのはできないのではないでしょうか?

    'meta_query' => array(
    'relation' => 'OR',
    array(
    'key' => 'tag_single',
    'value' => 'fluits'
    'compare' => 'LIKE'
    )
    array(
    'key' => 'tag_single',
    'value' => 'cake'
    'compare' => 'LIKE'
    )
    array(
    'key' => 'tag_single',
    'value' => 'vegetables'
    'compare' => 'LIKE'
    )
    array(
    'key' => 'tag_single',
    'value' => 'dlink'
    'compare' => 'LIKE'
    )
    array(
    'key' => 'tag_single',
    'value' => 'desert'
    'compare' => 'LIKE'
    )
    array(
    'key' => 'tag_single',
    'value' => 'alcohol'
    'compare' => 'LIKE'
    )
    ),

    キャンセル

  • 2018/05/15 03:40

    思ったのですが、縦棒で区切っているのを、配列に入れなおす。という方法ではいかがでしょうか?

    このようなイメージです↓(これではできませんでしたが笑)

    <?php
    $tag_single = get_post_meta(get_the_ID(),'tag_single',false);
    foreach($tag_single as $tag_single1) {
    foreach (explode('|', $tag_single1) as $val) {
    $tags = array(trim($val)); //1つずつ配列に戻れ!
    }
    }
    ?>

    <?php
    $myposts = get_posts( array(
    'post_type' => 'post',
    'posts_per_page' => '8',
    'post__not_in' => array( $post->ID ),
    'meta_query' => array(
    array(
    'key' => 'tag_single',
    'value' => $tags,
    'compare' => 'IN'
    )
    ),
    'orderby' => 'rand'
    ) ); ?>

    キャンセル

  • 2018/05/15 09:31

    複数の値をまとめるやつと、まとめないやつが
    混在してるのはよろしくありません
    使うのをどっちかだけにしてください

    入力値に互換性がないはずです

    検索に使うなら一つにまとめない方にした方がいいです

    キャンセル

  • 2018/05/15 10:11

    なるほど。考えておりませんでした。仰る通りですね。わかった風な口を聞いてしまってすみません。ありがとうございます。

    キャンセル

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

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    18631questions

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

  • WordPress

    6410questions

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