サポート » 使い方全般 » get_tags に渡した orderby が適用されない

  • 解決済 masterpiece1249

    (@masterpiece1249)


    Wordpress 5.3 です。

    投稿や固定ページに設定するタグを名前順で取得したくて、

    get_tags(['orderby' => 'name']);

    としましたが、タグの登録順の配列が返ってきたためおかしいと思い、
    関数の挙動を調べておりました。

    get_tags は wp-includes/category.php 278 行目に定義されており、
    その中で get_terms を呼び出しておりました。

    get_terms は wp-includes/taxonomy.php 1138 行目に定義されており、
    その中で WP_Term_Query::query を呼び出しておりました。

    WP_Term_Query::query は wp-includes/class-wp-term-query.php 286 行目に定義されており、
    その中で $this->get_terms を呼び出しておりました。

    WP_Term_Query::get_terms は同ファイル 300 行目に定義されており、
    この関数が呼び出された時点で、メンバ変数 $this->query_vars には、

    ['taxonomy' => ['post_tag'], 'orderby' => 'name']

    このような配列が入っておりました。
    この情報は 401 ~ 405 行目で変数 $orderby に格納されます。

    if ( $orderby ) {
    	$orderby = "ORDER BY $orderby";
    }
    
    $order = $this->parse_order( $this->query_vars['order'] );

    ここで $orderby には “t.name” が、$order には “ASC” が入ります。
    これでクエリの準備が出来たように思いましたが、まだ中々クエリは投げられず
    そうしている内に 657 ~ 665 行目でおかしなことが起こります。

    $clauses = apply_filters( 'terms_clauses', compact( 'fields', 'join', 'where', 'distinct', 'orderby', 'order', 'limits' ), $taxonomies, $args );
    
    $fields   = isset( $clauses['fields'] ) ? $clauses['fields'] : '';
    $join     = isset( $clauses['join'] ) ? $clauses['join'] : '';
    $where    = isset( $clauses['where'] ) ? $clauses['where'] : '';
    $distinct = isset( $clauses['distinct'] ) ? $clauses['distinct'] : '';
    $orderby  = isset( $clauses['orderby'] ) ? $clauses['orderby'] : '';
    $order    = isset( $clauses['order'] ) ? $clauses['order'] : '';
    $limits   = isset( $clauses['limits'] ) ? $clauses['limits'] : '';

    なんとここで $orderby に新しく情報を格納してしまいます。
    terms_clauses というフィルターから取ってきた情報を入れるので、
    この処理の後、$orderby の中には “ORDER BY t.term_order” という文字列が格納されていました。

    そうすると、get_tags の時点でどんなパラメータを渡そうが、
    そしてそれが 401 ~ 405 行目できちんと情報が格納されたにもかかわらず、
    ここで全て書き換えられてしまうということなので、全く意味がわからないのです。

    get_tags にパラメータを渡すことはもはや無意味なのでしょうか。
    3.1.0 から追加されたというこのフィルターをどうにか上手く使って情報を渡すしかないのでしょうか。

    get_tags で登録順で返ってくるのは、$orderby が強制的に
    term_order に変わってしまうからなのでしょうが、
    取ってきた後に連想配列をソートして名前順にすることも
    もちろん技術的には可能ですが、それが本当に想定された実装方法なのでしょうか。

    長くなって大変恐縮ではございますが、
    お詳しい方がいらっしゃいましたらご指南頂けますと幸いです。

2件の返信を表示中 - 1 - 2件目 (全2件中)
  • こんにちは

    $orderby は、

    $clauses = apply_filters( 'terms_clauses', compact( 'fields', 'join', 'where', 'distinct', 'orderby', 'order', 'limits' ), $taxonomies, $args );

    ここで、配列にまとめられて terms_clauses フックのコールバック関数を経由して $clauses ($clauses[‘orderby’]) に代入されます。

    よって、

    $orderby = isset( $clauses['orderby'] ) ? $clauses['orderby'] : '';

    この $orderby には、terms_clauses フックのコールバック関数が登録されていない場合やコールバック関数で変更されていない場合は、元の $orderby が代入されます。

    名前順にならないのは、Custom Taxonomy Order 等のタグを並び替えるプラグインやテーマにより terms_clauses フックで変更されているものだと思われます。テーマを変更したり、プラグインをひとつひとつ無効にしてみてください。

    トピック投稿者 masterpiece1249

    (@masterpiece1249)

    ご返信ありがとうございます。

    compact という関数で連想配列を作って代入していたのですね。
    プラグインからフィルターによって処理が変更されていたようでした。

    対象のプラグインを無効にすることで解決いたしました。
    誠にありがとうございました。

2件の返信を表示中 - 1 - 2件目 (全2件中)
  • トピック「get_tags に渡した orderby が適用されない」には新たに返信することはできません。