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

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

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

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

PHP

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Q&A

解決済

4回答

1915閲覧

フィルターフックをメインループにのみ適用したいのにサブループにも適用されてしまう。

nymaeb1x

総合スコア4

WordPress

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

PHP

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

0グッド

0クリップ

投稿2020/02/19 06:24

前提・実現したいこと

WordPress である外部プラグインで提供されているフィルターフックをメインループのみに実行させたいです。

現在、カスタム投稿ページ(single-users)の個別ページには記事そのもののメインループがあり、
サブループにはその他のおすすめ記事のサムネが表示されます。

発生している問題・エラーメッセージ

functions.phpに条件を指定したつもりですが、サブループにも関数の処理が適用されてしまいます。
どうすればサブループを適用外にすることができますか?
メインループとサブループを判別する為のコードが分かれば問題解決すると思うのですが、なかなか見つからず。。。

PHP

1// functions.php 2add_filter( 'some_hook', 'my_func', 10, 4 ); 3function my_func($html) { 4 // メインクエリーの時だけ実行したい。 5 if ( is_singular('users') && is_main_query() ) { 6 // $html を編集しreturnする 7 } 8}

念のため、以下にループのコードも。。。

PHP

1// single-users.php 2// メインループ 3<main> 4 <?php while ( have_posts() ) : the_post(); ?> 5 <?php get_template_part( 'template-parts/content', 'users' ); ?> 6 <?php endwhile; ?> 7 <?php wp_reset_postdata(); ?> 8</main> 9 10// サブループ 11<?php 12$args = array( 13 'post_type' => 'users', 14 'taxonomy' => 'users_category', 15 'posts_per_page' => 6, 16 'orderby' => 'rand', 17 'post__not_in'=> array($post->ID) 18); 19 20if ( $the_query->have_posts() ): 21 $the_query = new WP_Query( $args ); 22 while ( $the_query->have_posts() ) : $the_query->the_post(); 23 get_template_part( 'template-parts/content', 'archive-users' ); 24 endwhile; 25endif; 26wp_reset_postdata(); 27?>

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

WordPress 5.1.4

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

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

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

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

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

kei344

2020/02/19 11:29

まだ質問が「受付中」になっていますが、どのように解決したのかを回答文に書き、「解決済」にされてはいかがでしょうか。
nymaeb1x

2020/02/19 11:34

ご指摘ありがとうございます。 自己解決方法は本質や本題とはあまり関係ないところにあった為、有益性に欠ける内容になってしまいますが この状態でクローズした方がよろしいでしょうか?
kei344

2020/02/19 11:46

「どこに問題があったか」もしくは「何を勘違いしていたか(関係ない部分の問題をどうしてフィルタの問題だと想定したか)」を提示されれば自己解決でも(あとから見た人にとって)有益だと思いますよ。
nymaeb1x

2020/02/19 11:50

分かりました!ご指摘いただいた後にしたためていたのでこの後自己解決を提示します。
guest

回答4

0

is_main_query()はグローバル変数$wp_queryがmain_queryであるかどうかを判定するものなので
おおよそ非推奨であるquery_postsを使ってるでもない限り常にtrueを返すことになるはずです

サブループがメインループの入れ子になっていないなら
メインクエリがループ中か否かによって判定ができるかもしれません

php

1if($GLOBALS['wp_query']->in_the_loop){ 2 //メインクエリがループ中であれば処理 3}

しかし、サブループがメインクエリの入れ子になっていると
結局サブループでも処理が走ることになるため
あまり良い方法ではないかもしれません

wp_query自体に備わってるpre_get_postsフィルタフックなどは
wp_query自身を引数に取るので、$query->is_main_query();で
処理されているクエリがメインクエリなのかを知ることができます

pre_get_postsで行える処理ならばこっちを使った方が無難です

投稿2020/02/19 09:50

編集2020/02/19 12:06
KazuhiroHatano

総合スコア7802

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

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

nymaeb1x

2020/02/19 11:12

ご回答ありがとうございます。$wp_queryに関して不勉強で失礼いたしました。 in_the_loop、私も悶々としながらトライしてみました。結果はなんだか妙な挙動でした。 $GLOBALS['wp_query']とは指定していなかった為、また後でやり直してみます。 今回の私の問題の本質は別の部分にあった事が判明し解決はしましたが、今後のためにも追加でご教示いただけると助かります。 仮にメインループとサブループで異なる動作をさせたい場合、下記の様にpre_get_postsアクションフック内に更に入れ子で今回使用するフィルターフックを入れていく方法は有効なのでしょうか? 少なくとも下記のやり方で試したところ、うまく行きませんでした。 ``` PHP add_action( 'pre_get_posts', 'call_my_filter' ); function call_my_filter( $query ) { // メインクエリーの時だけ実行したい。 if ( $query->is_main_query() ) { add_filter( 'some_hook', 'my_func', 10, 4 ); } } function my_func($html) { if ( is_singular('users') ) { // $html を編集しreturnする } } ``` 上記の方法だと、呼び出されるフィルターフックの実行タイミング次第では、せっかく呼び出し元のアクションフックでメインループ判定が出来たとしても、同一ページ内のためその後のサブループでもフィルターフックが実行されてしまうことになる可能性はありますか?
KazuhiroHatano

2020/02/19 11:51

>その後のサブループでもフィルターフックが実行 されるでしょうね、フィルタフックは実行されたら消えるわけではないので ループ(the_post)によって更新されるのは$postとそれに伴う値だけで どのクエリのループなのかを知る術はありません しかし知ることができるようにはすることはできます the_postフィルタには$postと$wp_queryの両方が引数として渡されるので $postのプロパティに$wp_queryへの参照をつけておけば global $postを通じて現在のクエリを取得することができるようになります https://developer.wordpress.org/reference/hooks/the_post/ 任意のプロパティを好き勝手につけれてしまうPHPの緩さを利用している上 目的に対して手段が冗長なのでお勧めは致しかねますが・・・
nymaeb1x

2020/02/19 12:05

早速のご回答ありがとうございます。 やはり、そうでしたか。。。 だんだんと私の理解の上を超えてきており、やはりまだまだ勉強が必要と感じました。 熟読させていただき、今後のさらなる理解につなげさせていただきます。 丁寧なご回答ありがとうございました。
guest

0

通常、メインクエリーは、関数リファレンス/is main query にある通り、is_main_query() で、判別できます。

どのフックをお使いかわかりませんが、フックはどのタイミングで実行されるのでしょうか?

フックの中で、条件判断に利用している条件や関数の値がどうなっているか確認してみると値はどうなっているでしょうか?

投稿2020/02/19 09:36

CHERRY

総合スコア25171

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

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

nymaeb1x

2020/02/19 11:29

ご回答ありがとうございます。 is_main_query()はメインクエリーを判定するものであり、メインループを判定するものではないということですね。なんとなく理解できてきました。 質問内容を特定の機能に絞らず抽象化した方が良いのかなと思い、あえて記載しませんでしたが、 今回利用したフックは、いわゆるオレオレの「いいね」ボタンのようなものを実装する外部のプラグインが予め用意しているものです。 プラグインサイト:https://favoriteposts.com/ 使用したフィルターフック /** * Customize the Favorites Button HTML */ add_filter( 'favorites/button/html', 'custom_favorites_button_html', 10, 4 ); function custom_favorites_button_html($html, $post_id, $favorited, $site_id) { return $html; } 上記フィルターは、特定のカスタム投稿タイプのシングルページで表示する「いいね」ボタンのデザインやコードを改変する為に利用するつもりでした。 そこでこの関数内に、メインループであることを判定するための関数を入れようと試行錯誤したのですが、結局は処理がメインループにもサブループにも適用されてしまいました。(つまりどちらもtrue)
guest

0

自己解決

問題箇所

メインループとサブループでどちらも同じ出力系の関数を使ってしまっていた為に、それぞれに同じフィルターフックが適用されていた。

解決方法

根本的な取り組みでは無いかも知れませんが、メインループとサブループで関数の使い分けで解決することにしました。
メインループでは外部プラグインが用意していた the_から始まる出力系の関数を使い、
サブループでは get_で始まる取得系の関数で必要なデータを抽出&組み立てることで別パターンを作成しました。(元々両方ともthe_系でやってしまっていた。。。)

実際に使い分けた関数(https://favoriteposts.com/)

PHP

1// メインループで使用 2/** 3* Echo the total favorite count for a post 4* Post ID not required if inside the loop 5* @param int $post_id 6* @param int $site_id - defaults to current site 7*/ 8the_favorites_count($post_id, $site_id); 9 10// サブループで使用 11/** 12* Get the total favorite count for a post 13* Post ID not required if inside the loop 14* @param int $post_id 15* @param int $site_id - defaults to current site 16*/ 17get_favorites_count($post_id, $site_id); 18

single-users.php

PHP

1// メインループ 2<main> 3 <?php while ( have_posts() ) : the_post(); ?> 4 <?php get_template_part( 'template-parts/content', 'users' ); ?> // このテンプレートパート内でthe_favorites_count()を利用 5 <?php endwhile; ?> 6 <?php wp_reset_postdata(); ?> 7</main> 8 9// サブループ 10<?php 11$args = array( 12 'post_type' => 'users', 13 'taxonomy' => 'users_category', 14 'posts_per_page' => 6, 15 'orderby' => 'rand', 16 'post__not_in'=> array($post->ID) 17); 18 19if ( $the_query->have_posts() ): 20 $the_query = new WP_Query( $args ); 21 while ( $the_query->have_posts() ) : $the_query->the_post(); 22 get_template_part( 'template-parts/content', 'archive-users' ); // このテンプレートパート内でget_favorites_count()を利用しデータをゴニョゴニョ 23 endwhile; 24endif; 25wp_reset_postdata(); 26?> 27

投稿2020/02/19 12:07

nymaeb1x

総合スコア4

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

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

0

メインループとサブループの判定による解決ではないところに問題がありました。お騒がせしてすみません!

投稿2020/02/19 09:23

nymaeb1x

総合スコア4

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問