Làm thế nào để buộc một truy vấn có điều kiện?


7

Có một lỗi cốt lõi WordPress tồn tại lâu dài ( # 16373 ), trong đó, nếu các biến truy vấn tùy chỉnh được đăng ký và hiện trong chuỗi truy vấn, truy vấn sẽ không được đặt thành is_front_page()đúng, ngay cả khi 'page' == get_option( 'show_on_front' ). Chi tiết đầy đủ có trong vé trac, nhưng kết quả cuối cùng là trang trước trả về một trang không hợp lệ thay vì get_option( 'page_on_front' ).

Tôi có một trường hợp sử dụng nhất định trong đó tôi cần chuyển các biến truy vấn tùy chỉnh cho chuỗi truy vấn trên trang trước (sử dụng biểu mẫu để chuyển các biến truy vấn đã đăng ký, lần lượt được sử dụng để lọc tùy chọn Chủ đề - bản demo tùy chọn Chủ đề phía trước ). Vé trac đã đề cập ở trên đã bị đóng là không hợp lệ, vì vậy tôi cần một cách giải quyết.

Tôi có thể buộc mẫu trang trước đủ dễ dàng, như vậy:

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' );

Tuy nhiên, các điều kiện truy vấn cơ bản không bị ảnh hưởng. Vì vậy, bất kỳ mã nào phụ thuộc vào is_front_page()việc true(chẳng hạn như một thanh trượt chỉ hiển thị trên trang đầu của trang) sẽ vẫn không hiển thị đúng.

Tôi đã cố gắng sửa đổi $querytại pre_get_posts, nhưng điều này dường như không hoạt động:

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' );

Các điều kiện truy vấn không được sửa đổi. Tôi đang cố gắng không chính xác trong cuộc gọi lại của tôi? Có cách nào khác / tốt hơn để buộc các điều kiện truy vấn, đặc biệt is_front_page()không?

Biên tập

Lưu ý rằng cài đặt page_id không hoạt động trong cuộc pre_get_postsgọi lại:

$query->set( 'page_id', get_option( 'page_on_front' ) );

Nếu tôi bỏ qua template_includebộ lọc, thì trang hiển thị thực sự là trang được gán cho trang trước; tuy nhiên, get_page_template()được sử dụng, chứ không phải là get_front_page_template(). Vì vậy, thiết lập page_idtại pre_get_postskhông gây ra is_page()là đúng. Nhưng lỗi nói trên ngăn không cho is_front_page()được đặt thành true.

Chỉnh sửa 2

Yêu cầu của Per @ toscho, đây là một số mã var truy vấn, cho ngữ cảnh.

Đăng ký biến truy vấn:

/**
 * 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' );

(Ở đâu foo, barbazlà các tùy chọn Chủ đề - nền, nhiều màu sắc, v.v.)

Cách chúng được sử dụng chỉ đơn giản là thêm bộ lọc vào tùy chọn Chủ đề - phần đó nằm ngoài phạm vi của câu hỏi, vì vậy tôi sẽ bỏ qua nó ở đây.

Chúng là đầu ra ở mặt trước thông qua Widget tùy chỉnh. Đầu ra Widget chỉ là một hình thức. Đây là một ví dụ về một trong các trường mẫu:

<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; ?>" />

Đã tạo chuỗi truy vấn khi gửi:

www.example.com/?foo=some_value

Bạn có thể thêm một trường hợp thử nghiệm đơn giản, ví dụ. mã đăng ký truy vấn var?
fuxia

Chắc chắn, đăng ký var truy vấn hoạt động tốt và mọi thứ sử dụng nó đều hoạt động tốt - nhưng tôi sẽ thêm một ví dụ cho ngữ cảnh.
Chip Bennett

Câu trả lời:


7

Bạn đã kiểm tra phần nào của is_front_page () đang khiến nó trả về sai chưa?

Tôi có thể tái tạo vấn đề bằng cách làm theo thiết lập từ vé trac. Trong trường hợp của tôi bên trong hàm này, lệnh gọi is_page () đã trả về false.

Tôi đoán điều này là do sử dụng $wp_query->set()cho page_idis_pagechỉ khiến query_varsthay đổi, bạn không thay đổi "trạng thái của truy vấn".

Tôi đã có thể tạo một cách giải quyết cho việc này bằng cách nối thêm hai dòng này vào mã của bạn:

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

Kết quả nào (trong thiết lập của tôi) trong trang được hiển thị chính xác trên trang đầu (mặc dù truy vấn có mặt trong URL) và cũng is_front_page()trả về true.

Tôi hy vọng điều này sẽ giúp bạn phần nào hơn nữa.


Nếu bạn nhìn vào định nghĩa của lớp WP_Query , bạn sẽ thấy rằng có một biến $query_varsvà một biến $is_page.

Các setchức năng mà bạn sử dụng ( $query->set( 'is_page', true );) không chỉ thiết lập một var query :

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

Nó không thay đổi thông tin trạng thái được lưu trong đó $query->is_page = true, thay vào đó, nó đặt var truy vấn $query->query_vars['is_page'] = true.

Đó là một chút sai lầm nếu bạn đến từ cách tiếp cận OOP và hiểu WP_Query::set()như là một hàm setter lớp cổ điển - điều này không có.


1
+1. Điều này đang làm việc trên kết thúc của tôi là tốt. Cảm ơn bạn! Bạn có thể giải thích "trạng thái của truy vấn" một chút, trong bối cảnh $query->set( 'is_page', true )vs $query->is_page = true?
Chip Bennett

1
@ChipBennett Đã cố gắng giải thích thêm một chút.
s1lv3r

3

Tôi đã trả lời trong vé Trac đó, nhưng tôi nghĩ vấn đề cơ bản ở đây đơn giản hơn thế này rất nhiều.

Bạn đang kết nối trong demo_foo, demo_bar, demo_baz là "Biến truy vấn", nhưng chúng không; ít nhất, không phải trong ý nghĩa dự định.

Trong khi chuỗi? Foo = bar sau URL thường được gọi là chuỗi truy vấn, "biến truy vấn" thực sự chỉ là các biến ảnh hưởng đến truy vấn chính. Nếu bạn không nối vào một biến, nó sẽ không biến mất, nó sẽ không được đọc bởi đối tượng WP_Query chính.

Và trong trường hợp của bạn, điều đó dường như là chính xác những gì bạn muốn. Các biến của bạn là các tùy chọn chủ đề, chúng không phải là một phần của Truy vấn chính (lấy các bài đăng từ cơ sở dữ liệu). Bạn không sử dụng chúng để chọn bài đăng nào sẽ hiển thị, bạn đang sử dụng chúng để đặt tùy chọn chủ đề, v.v.

Nếu bạn không nối chúng vào dưới dạng truy vấn, thì chúng sẽ không ảnh hưởng đến đối tượng WP_Query chính. Bạn sẽ phải lấy chúng từ siêu lớp chính $ _GET thay vì sử dụng get_query_var và bạn sẽ phải thực hiện vệ sinh đúng cách trên chúng để ngăn chặn các cuộc tấn công XSS phản chiếu (sử dụng esc_attr hoặc bất cứ điều gì phù hợp), nhưng điều này sẽ giải quyết vấn đề chính của bạn bằng cách loại bỏ mã gây ra vấn đề ở nơi đầu tiên, thay vì thêm vào một cách giải quyết khác.


Điều đó chắc chắn giải quyết trường hợp sử dụng cụ thể của tôi (và chứng minh tại sao báo cáo lỗi vẫn không hợp lệ) - nhưng câu hỏi cơ bản là làm thế nào để sửa đổi điều kiện truy vấn. Những gì xảy ra với $queryđối tượng và các điều kiện của nó là ... hơi ít so với tài liệu tốt, và vẫn có thể là một chút bí ẩn. :)
Chip Bennett
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.