カスタムクエリ変数が登録されてクエリ文字列に存在する場合、is_front_page()
であってもクエリが'page' == get_option( 'show_on_front' )
trueに設定されないという長年のWordPressコアバグ( #16373 )があります。完全な詳細はtracチケットにありますが、最終的にはフロントページがget_option( 'page_on_front' )
ではなく無効なページを返します。
私は、フロントページのクエリ文字列にカスタムクエリ変数を渡す必要があるという特定のユースケースを持っています(登録されたクエリ変数を渡すためのフォームを使用し、順番にテーマオプションをフィルタリングする - フロントエンドテーマオプションデモ)上記のtracのチケットは無効としてクローズされたので、回避策が必要です。
次のように、フロントページのテンプレートを簡単に十分に強制することができます。
function themeslug_force_front_page_template( $template ) {
if ( '' != get_query_var( 'foobar' ) ) { // Registered custom query var
return get_front_page_template();
}
return $template;
}
add_filter( 'template_include', 'themeslug_force_front_page_template' );
ただし、基になるクエリ条件は影響を受けません。そのため、is_front_page()
がtrue
であることに依存するコード(サイトのフロントページにのみ表示されるスライダなど)は、まだ正しく表示されません。
$query
をpre_get_posts
に変更しようとしましたが、これはうまくいかないようです。
function themeslug_force_static_front_page( $query ) {
if ( $query->is_main_query() ) {
if ( 'page' == get_option( 'show_on_front' ) ) {
if ( '' != get_query_var( 'foobar' ) ) { // Registered custom query var
$query->set( 'page_id', get_option( 'page_on_front' ) );
$query->set( 'is_home', false );
$query->set( 'is_page', true );
$query->set( 'is_front_page', true );
}
}
}
}
add_action( 'pre_get_posts', 'themeslug_force_static_front_page' );
照会条件は変更されません。コールバック内で誤って試行していますか?特にis_front_page()
というクエリ条件を強制するための別の、あるいはより良い方法はありますか?
page_id
doesの設定はpre_get_posts
コールバックで機能することに注意してください。
$query->set( 'page_id', get_option( 'page_on_front' ) );
template_include
フィルタを省略した場合、表示されるページは実際にはフロントページに割り当てられているページです。ただし、get_page_template()
ではなくget_front_page_template()
が使用されます。そのため、page_id
にpre_get_posts
を設定すると、is_page()
がtrueになります。しかし、前述のバグはis_front_page()
がtrue
に設定されるのを防ぎます。
@ toschoの要求ごとに、ここにコンテキスト用のいくつかのquery varコードを示します。
クエリ変数を登録します。
/**
* Add options-related query variables
*/
function themslug_add_theme_demo_query_vars( $qvars ) {
$qvars[] = 'demo_foo';
$qvars[] = 'demo_bar';
$qvars[] = 'demo_baz';
return $qvars;
}
add_filter( 'query_vars', 'themeslug_add_theme_demo_query_vars' );
(foo
、bar
、およびbaz
はテーマオプション - 背景、さまざまな色など)
それらがどのように使われるかは単にテーマオプションにフィルタを追加することです - その部分は質問の範囲外であるので、ここではそれを省略します。
それらはカスタムウィジェット経由でフロントエンドに出力されます。ウィジェットの出力は単なるフォームです。これがフォームフィールドの一例です。
<h3>Foo</h3>
<input name="demo_foo" id="demo_foo" class="pickcolor" type="text" value="<?php echo $foo_setting; ?>" data-default-color="<?php echo $foo_setting; ?>" />
送信時に生成されたクエリ文字列:
www.example.com/?foo=some_value
is_front_page() のどの部分でfalseが返されるのかを確認しましたか?
私は問題解決のためにTracのチケットからの設定に従うことで再現することができました。私の場合、この関数の中で is_page() への呼び出しはfalse
を返していました。
これはpage_id
に$wp_query->set()
を使用したことが原因で、is_page
がquery_vars
を変更するだけで、「クエリの状態」自体を変更することはないと思います。
この2行をコードに追加することで、これに対する回避策を作成できました。
$query->is_page = true;
$query->queried_object = get_post(get_option('page_on_front') );
(私の設定では)URLが(query_varがURLにあっても)フロントページに正しく表示され、is_front_page()
がtrue
を返すという結果になりました。
私はこれがあなたをいくらかさらに助けていることを願っています。
WP_Query クラスの定義を見ると、変数$query_vars
と変数$is_page
があることがわかります。
あなたが使ったset
関数($query->set( 'is_page', true );
)は query var をセットするだけです:
function set($query_var, $value) {
$this->query_vars[$query_var] = $value;
}
$query->is_page = true
に保存されている状態情報は変更されず、代わりにクエリvar $query->query_vars['is_page'] = true
が設定されます。
あなたがOOPアプローチから来て、WP_Query::set()
を古典的なクラス設定関数として理解するならば、それは少し誤解を招くようなものです - そうではありません。
私はそのTracチケットでも答えました、しかしここでの基本問題はこれよりずっと簡単であると思います。
Demo_foo、demo_bar、demo_bazを "クエリ変数"としてフックしていますが、そうではありません。少なくとも、意図した意味ではありません。
URLの後の?foo = bar文字列はしばしばクエリ文字列と呼ばれますが、「クエリ変数」は実際にはメインクエリに影響を与える単なる変数です。変数をフックしなくても消えず、メインのWP_Queryオブジェクトに読み込まれません。
そしてあなたの場合、それはまさにあなたが望むものであるように見えます。あなたの変数はテーマのオプションであり、それらはメインのQueryの一部ではありません(データベースから投稿を取得します)。表示する投稿を選択するためにそれらを使用しているのではなく、テーマのオプションなどを設定するためにそれらを使用しています。
あなたがそれらをquery_varsとしてフックしないのであれば、それらはメインのWP_Queryオブジェクトにまったく影響を与えません。 get_query_varを使用する代わりにメインの$ _GETスーパーグローバルからそれらを取得する必要があります。また、反射型XSS攻撃を防ぐために適切なサニタイズを実行する必要があります。追加の回避策を追加するのではなく、最初の段階で問題の原因となっているコード。