サポート » 使い方全般 » taxsonomy-A.php 内に タクソノミーBで区切った表示をさせたい

  • 解決済 fubasami

    (@fubasami)


    カスタム投稿で「料理」を制作したとします。
    タクソノミーに「食材」と「料理時間」を設定しました。

    食材(taxsonomy-A)
    -肉(termA-1)
    -魚(termA-2)
    -野菜(termA-3)

    料理時間(taxsonomy-B)
    -10分(termB-1)
    -20分(termB-2)
    -30分(termB-3)

    taxsonomy-A.phpの中で
    termB-1に属する物だけ表示、termB-2に属する物だけ表示、termB-3に属する物だけ表示、
    と教示するり方を教えていただけないでしょうか?

    taxsonomy-A.php で 肉が選択されている場合
    taxsonomy-A.phpの中で以下のような表示をしたいと考えています。

    【肉料理】
    10分
     記事1/記事3/記事13
    20分
     記事4/記事6/記事20
    30分
     記事2/記事7/記事15

12件の返信を表示中 - 1 - 12件目 (全12件中)
  • トピック投稿者 fubasami

    (@fubasami)

    よろしくお願いいたします。

    トピック投稿者 fubasami

    (@fubasami)

    以下の方法で一応、肉-10分、20分、30分 等表示できました。
    ただ、40分が加わった時にまた修正が必要なので、
    引き続きループ処理で表示するやり方を模索中です。

    <h3>10分</h3>
    <?php while (have_posts()) : the_post(); ?>
    <?php
    $cat = get_the_category();
    $catslug = $cat[0]->category_nicename;
    ?>
    <?php if ( is_object_in_term($post->ID, ‘taxsonomy-B’,’termB-1′) ): ?>
    <h4>“><?php the_title_attribute(); ?></h4>
    <?php endif; ?>
    <?php endwhile; ?>

    <h3>20分</h3>
    <?php while (have_posts()) : the_post(); ?>
    <?php
    $cat = get_the_category();
    $catslug = $cat[0]->category_nicename;
    ?>
    <?php if ( is_object_in_term($post->ID, ‘taxsonomy-B’,’termB-2′) ): ?>
    <h4>“><?php the_title_attribute(); ?></h4>
    <?php endif; ?>
    <?php endwhile; ?>

    <h3>30分</h3>
    <?php while (have_posts()) : the_post(); ?>
    <?php
    $cat = get_the_category();
    $catslug = $cat[0]->category_nicename;
    ?>
    <?php if ( is_object_in_term($post->ID, ‘taxsonomy-B’,’termB-3′) ): ?>
    <h4>“><?php the_title_attribute(); ?></h4>
    <?php endif; ?>
    <?php endwhile; ?>

    LABE

    (@latobeam)

    いろいろ方法はあると思いますが、こちらはメインループでは投稿を並び替えるだけにし、サブループで表示するという方法です。

    <?php
    $post_lists = array();
    // メインループ
    while ( have_posts() ):
        the_post();
        $the_terms = get_the_terms($post, 'taxsonomy-B');
        $the_term = reset($terms);
        if ( empty($post_lists[$the_term->term_id]) ):
            $post_lists[$the_term->term_id] = array($the_term->name);
        endif;
        $post_lists[$the_term->term_id][] = $post;
    endwhile;
    // サブループ
    foreach ( $post_lists as $term_id => $post_list ):
        // ターム毎のループ
        foreach ( $post_list as $key => $_post ):
            if ( $key === 0 ): ?>
    <h3><?php echo $_post; ?></h3>
    <?php   else:
    <h4><a href="<?php echo esc_url(get_permalink($_post)); ?>"><?php echo strip_tags(get_the_title($_post)); ?></a></h4>
    <?php   endif;
        endforeach;
    endforeach;
    ?>

    まずメインループ内で $post_lists に、タクソノミーBのタームごとに投稿データを格納していき、多次元配列を作ります。
    この時、ターム名もついでに取得しておきます。
    次にサブループを作り、ターム毎にさらにループを組んで表示します。
    サブループ内でタームの情報が必要なら $term_id にタームIDが格納されています。
    投稿がもし複数のタームを持つなら、(タームID順で)最初のタームにしか表示されません。

    動作確認はしていませんが、参考にしてください。

    トピック投稿者 fubasami

    (@fubasami)

    お礼遅くなりました。
    ありがとうございます。

    いろいろ工夫してみましたが、
    本質を理解できていないので修正に至りませんでした。

    <h3><?php echo $_post; ?></h3>
    が空っぽになるのが直せませんでした。

    ありがとうございました。

    LABE

    (@latobeam)

    ごめんなさい、コードの7行目の変数名が普通に間違ってました。
    reset($terms) ではなく reset($the_terms) ですね。
    それと、19行目(下から6行目)の else: のあとで ?> を書くのを忘れていました。
    初歩的なミスばかりですみません、動作確認はするものですね……
    ただ、これらのミスだと <h4> も正しく表示されないはずですが、大丈夫でしたか?

    それと、上記のコードだと万一投稿がタームを持たない場合にエラーになりそうなので、修正してみました。

    <?php
    $post_lists = array();
    // メインループ
    while ( have_posts() ):
        the_post();
        $the_terms = get_the_terms($post, 'taxsonomy-B');
        if ( ! $the_terms ):
            continue;
        endif;
        $the_term = reset($the_terms);
        $the_term_id = $the_term->term_id;
        if ( empty($post_lists[$the_term_id]) ):
            $post_lists[$the_term_id] = array($the_term->name);
        endif;
        $post_lists[$the_term_id][] = $post;
    endwhile;
    // サブループ
    foreach ( $post_lists as $term_id => $post_list ):
        // ターム毎のループ
        foreach ( $post_list as $key => $_post ):
            if ( $key === 0 ): ?>
    <h3><?php echo $_post; ?></h3>
    <?php   else: ?>
    <h4><a href="<?php echo esc_url(get_permalink($_post)); ?>"><?php echo strip_tags(get_the_title($_post)); ?></a></h4>
    <?php   endif;
        endforeach;
    endforeach;
    ?>

    これでどうでしょうか。

    $_postはスーパーグローバル変数じゃないんでしょうか。
    echoじゃ表示されないんじゃないでしょうか。

    ものすごく細かくて意地悪な話かと思いますが、少しだけ進言させてください。
    postなど環境準備語とそれに近いものは独自用途での変数名に使用しないほうがいいとおもいます。
    PHPのプログラミングについてのお話なのでワードプレス本体とは離れてしまうので簡単にお話できればと思うのですが
    foreach の書き方で私が実践しているものをご紹介いたします。
    ちょっと初心者むけでいらっとするかとおもいますが、もしか初心者の方にも目に留まれば参考いただけるといいなと思い、かきます。

    foreach(配列変数を最初から最後までひとつづつ代用して終了するループ)
    foreach($post_list(対象となる配列変数) as(当該位置のデータを次の変数に代入する) $key(連想配列の配列名) => $_post(連想配列のデータ名) )

    なのですが、一般的なトレンドは

    foreach ( $arrayed_data as $key => $value )

    です。このKEYとVALUEはループ内でしか利用できない一時的な変数なのでこの名前で問題ないと思います。
    ただこれをさらにループの中におさめるなどの多段になると同じ名前が利用できません。
    なので毎回、一段であっても

    foreach ( $arrayed_data as $key_ad(arrayed_dataの略) => $value_ad )

    と対象の変数の略語をつけるようにしています。ロシアの人の名前で「父親の名前をミドルネームにする」みたいなものです。
    すると一時変数だけども用途が可視化されるのでプログラミングが捗ると思います。

    foreachの中に同じ変数でforeachをまわすとどっちのデータかわからない、というかあとから入れた変数がはいってしまうので
    ごちゃまぜになり思った結果がでなくなると思いますのでそれを回避もできます。

    同じようにスーパーグローバルといった環境で準備されている変数名などに一時的なデータをいれてしまうと
    全体がへんなことになってしまう可能性があります。
    $post はワードプレスが記事を読みだしたときにループ用でよくつかっているのをみかける変数ですね。
    $_POSTはPHPがPOST形式でデータが転送されてきたときの受信変数に使用されます。

    いかがでしょうか。

    スーパーグローバル変数は大文字なんですね。勉強になりました。

    LABE

    (@latobeam)

    勉強になります。

    foreach ( $arrayed_data as $key => $value ) という書き方は普段は使っていますが、ここではあえて、何の変数かわかりやすいように書きました。
    $_post という変数名については、WordPressのソースファイルのあちこちで使われているので、おそらくグローバル変数や準備語の類ではないと考えておりました。
    もちろん避けられる問題は避けるに越したことはないので、変数名を変えるのもやぶさかではありません。

    トピック投稿者 fubasami

    (@fubasami)

    2週間経ってしまいましたが、やっと着手&8割型うまくいきました!
    ありがとうございます!

    もし、どなたかにこのメッセージが届いたらで良いのですが、
    タームの「説明」の欄に番号を付け足したので、
    その番号でソートして一覧を出力する方法を教えていただけないでしょうか?

    ‘orderby’ => ‘description’

    をどこに挟めば良いか、お手数ですがお教えください。
    よろしくお願いします。

    LABE

    (@latobeam)

    もしかして、なのですが、そのアイデアはこの記事が元ネタですか?
    http://labe.wp.xdomain.jp/post/367
    違ったらごめんなさい。ちなみにこの記事を書いたのは俺です。

    ところで、俺がこのトピックの上記で紹介した方法は、その orderby とは全く異なる方法でデータを処理しているため、残念ながらその方法は使えません。
    しかし、タームの「説明」が“PHPの配列のキー名として使用可能な文字”(半角英数字など)のみで記述されており、かつ各ターム間で重複がないなら、少し修正すれば実現可能です。

    <?php
    $post_lists = array();
    // メインループ
    while ( have_posts() ):
        the_post();
        $the_terms = get_the_terms($post, 'taxsonomy-B');
        if ( ! $the_terms ):
            continue;
        endif;
        $the_term = reset($the_terms);
        $the_term_id = (int) $the_term->description;
        if ( empty($post_lists[$the_term_id]) ):
            $post_lists[$the_term_id] = array($the_term->name);
        endif;
        $post_lists[$the_term_id][] = $post;
    endwhile;
    // サブループ
    ksort($post_lists);
    foreach ( $post_lists as $term_id => $post_list ):
        // ターム毎のループ
        foreach ( $post_list as $key => $_post ):
            if ( $key === 0 ): ?>
    <h3><?php echo $_post; ?></h3>
    <?php   else: ?>
    <h4><a href="<?php echo esc_url(get_permalink($_post)); ?>"><?php echo strip_tags(get_the_title($_post)); ?></a></h4>
    <?php   endif;
        endforeach;
    endforeach;
    ?>

    前回のコードから2ヶ所だけ変わっています。
    11行目が変わっているのと、17行目と18行目の間に1行追加しています。

    トピック投稿者 fubasami

    (@fubasami)

    ありがとうございます!
    お礼遅くなってしまい、申し訳ありません。

    他の箇所で‘orderby’ => ‘description’使用していたので、
    ここでも使えると思い、書いてみました。

    LABE様の記事は初見でした^^
    拝見させていただきます。

12件の返信を表示中 - 1 - 12件目 (全12件中)
  • トピック「taxsonomy-A.php 内に タクソノミーBで区切った表示をさせたい」には新たに返信することはできません。