Как принудительно выполнить условный запрос?


Существует давняя ошибка в ядре WordPress (#16373) в котором, если пользовательские переменные запроса зарегистрированы и присутствуют в строке запроса, запрос не установит is_front_page() значение true, даже если 'page' == get_option( 'show_on_front' ). Полная информация содержится в билете 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 работает ли в 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() является истинным. Но вышеупомянутая ошибка не позволяет is_front_page() установить значение true.

Редактировать 2

По запросу @toscho, вот некоторый код 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
Author: Chip Bennett, 2014-01-18

2 answers

Вы проверяли, какая часть is_front_page() заставляет его возвращать значение false?

Я мог бы воспроизвести проблему, выполнив настройку из билета trac. В моем случае внутри этой функции возвращался вызов is_page() false.

Я предполагаю, что это связано с использованием $wp_query->set() для page_id и is_page только вызывает изменение query_vars, вы не изменяете само "состояние запроса".

Я смог создать обходной путь для этого, добавление этих двух строк в ваш код:

$query->is_page = true;
$query->queried_object = get_post(get_option('page_on_front') );

Что привело (в моей настройке) к правильному отображению страницы на главной странице (несмотря на то, что в URL-адресе присутствует query_var), а также is_front_page() возвращению true.

Я надеюсь, что это поможет вам в дальнейшем.


Если вы посмотрите на определение класса WP_Query, вы увидите, что существует переменная $query_vars и переменная $is_page.

Используемая вами функция set ($query->set( 'is_page', true );) устанавливает только a запрос var:

function set($query_var, $value) {
    $this->query_vars[$query_var] = $value;
}

Он не изменяет информацию о состоянии, сохраненную в $query->is_page = true, вместо этого он задает var запроса $query->query_vars['is_page'] = true.

Это немного вводит в заблуждение, если вы исходите из ООП-подхода и понимаете WP_Query::set() как классическую функцию определения классов, которой она не является.

 7
Author: s1lv3r, 2014-01-19 00:53:10

Я тоже ответил в этом билете Trac, но я думаю, что основная проблема здесь намного проще, чем это.

Вы используете demo_foo, demo_bar, demo_baz в качестве "Переменных запроса", но это не так; по крайней мере, не в предполагаемом смысле.

В то время как строка ?foo=bar после URL-адреса часто называется строкой запроса, "переменные запроса" на самом деле являются просто переменными, которые влияют на основной запрос. Если вы не подключаете переменную, она не исчезает, она просто не читается основным Объект WP_Query.

И в вашем случае, похоже, это именно то, чего вы хотите. Ваши переменные - это параметры темы, они не являются частью основного запроса (который получает сообщения из базы данных). Вы не используете их для выбора сообщений для отображения, вы используете их для настройки параметров темы и тому подобного.

Если вы не подключите их как query_vars, то они вообще не повлияют на основной объект WP_Query. Вам нужно будет получить их из главного суперглобала $_GET вместо использования get_query_var, и вам придется выполнить надлежащую очистку их, чтобы предотвратить отражающие атаки XSS (используя esc_attr или что-то подходящее), но это должно решить вашу основную проблему, в первую очередь устранив код, вызывающий проблему, вместо добавления дополнительного обходного пути.

 3
Author: Otto, 2014-01-19 01:34:40