Làm cách nào để có được các giá trị đầu vào của shortcode bên trong bộ lọc?


9

Tôi đang cố gắng để có được giá trị đầu vào của một shortcode bên trong một hàm được sử dụng bởi bộ lọc, nhưng dường như không có thành công. Đây là những gì tôi đã làm:

function my_shortcode_function($atts){
    $value = $atts['id'];
    function filter_value(){
        echo $value;
    }
    add_filter('posts_where','filter_value');
}
add_shortcode('my-shortcode','my_shortcode_function');

Bây giờ tôi biết sử dụng $valuebên trong filter_value()sẽ không hoạt động vì phạm vi thay đổi, nhưng thậm chí sử dụng $GLOBALS['value']không hoạt động.

Tôi thậm chí đã thử sử dụng $value = $atts['id']bên trong filter_value();nhưng cũng không thành công.

Làm cách nào tôi có thể sử dụng shortcode của mình như thế nào [my-shortcode id='123']và chuyển giá trị 123 vào bộ lọc?

Cảm ơn.

Câu trả lời:


7

Sử dụng một biến toàn cầu sẽ làm việc. Đây là một minh chứng:

function wpse_shortcode_function( $atts ){
    // User provided values are stored in $atts.
    // Default values are passed to shortcode_atts() below.
    // Merged values are stored in the $a array.
    $a = shortcode_atts( [
                'id'   => false,
    ], $atts );

    // Set global variable $value using value of shortcode's id attribute.
    $GLOBALS['value'] = $a['id'];

    // Add our filter and do a query.
    add_filter( 'posts_where', 'wpse_filter_value' );

    $my_query = new WP_Query( [
        'p' => $GLOBALS['value'],
    ] );

    if ( $my_query->have_posts() ) {
        while ( $my_query->have_posts() ) {
            $my_query->the_post();
            the_title( '<h1>', '</h1>');
        }
        wp_reset_postdata();
    }

    // Disable the filter.
    remove_filter( 'posts_where', 'wpse_filter_value' );
}
add_shortcode( 'my-shortcode', 'wpse_shortcode_function' );

function wpse_filter_value( $where ){
    // $GLOBALS['value'] is accessible here.

    // exit ( print_r( $GLOBALS['value'] ) );

    return $where;
}

Lưu ý bên cạnh, khai báo một chức năng trong một chức năng khác không phải là một thực hành tốt .


Điều này thực sự kỳ lạ. Nếu tôi đặt giá trị bằng cách sử dụng $GLOBALS['value'] = some valuevà sau đó gọi $GLOBALS['value']nó thì nó hoạt động, nhưng nếu tôi đặt giá trị trực tiếp $value = some valuevà sau đó gọi nó bằng cách sử dụng $GLOBALS['value']thì nó không hoạt động, trong khi nó sẽ hoạt động theo hướng dẫn PHP.
Jack Johansson

Bạn phải đặt thành $valuephạm vi toàn cầu global $value;trước khi khởi tạo nó với một giá trị. Ví dụ global $value; $value = $a['id']; , trong bộ lọc, bạn có thể làm global $value; echo $value;gì?
Dave Romsey

Vâng cảm ơn. Tôi đang đọc này trên hướng dẫn, và trong ví dụ đầu tiên các giá trị được định nghĩa trực tiếp. Tôi có phải xác định chúng bên ngoài chức năng BẤT K to để có sẵn trực tiếp sử dụng $GLOBALS['value'];không?
Jack Johansson

2
Mát mẻ. rất vui vì chúng tôi đã nhận nó. Trong ví dụ đầu tiên từ các tài liệu đó, các biến được khai báo bên ngoài hàm và trong phạm vi toàn cục. Vì vậy, không cần globaltừ khóa. Trong các ví dụ của chúng tôi, chúng tôi đã làm việc trong phạm vi chức năng, vì vậy globaltừ khóa là cần thiết.
Dave Romsey

1
Bộ lọc là bạn của chúng tôi! :-) Tôi chắc chắn một số người trả lời háo hức sẽ có mặt để trả lời câu hỏi của bạn nếu bạn cần thêm trợ giúp!
Dave Romsey

7

Dưới đây là một số cách giải quyết:

Cách tiếp cận số 1

Bạn có thể gói định nghĩa của shortcode và posts_wheregọi lại của bộ lọc trong một lớp để có thể chuyển xung quanh một giá trị đã cho giữa các phương thức lớp, ví dụ như một biến riêng .

Cách tiếp cận số 2

Một cách tiếp cận khác là chuyển giá trị dưới dạng đầu vào WP_Querytrong hàm gọi lại của shortcode của bạn:

$query = new WP_Query ( [ 'wpse_value' => 5, ... ] );

và sau đó trong bộ lọc tests_where bạn có thể truy cập nó:

add_filter( 'posts_where', function( $where, \WP_Query $query )
{

    if( $value = $query->get( 'wpse_value' ) )
    {
        // can use $value here
    }

    return $where;

}, 10, 2 );

Cách tiếp cận số 3

... hoặc bạn cũng có thể điều chỉnh ví dụ bằng @the_dramatist để có thể xóa cuộc gọi lại sau đó bằng cách gán hàm ẩn danh cho một biến:

function my_shortcode_function( $atts, $content )
{
    // shortcode_atts stuff here

    $value = 5; // just an example  

    // Add a filter's callback
    add_filter( 'posts_where',  $callback = function( $where ) use ( $value ) {
        // $value accessible here
        return $where;
    } );

    // WP_Query stuff here and setup $out

    // Remove the filter's callback
    remove_filter( 'posts_where', $callback );

    return $out;
}

add_shortcode( 'my-shortcode', 'my_shortcode_function' );   

Kiểm tra ví dụ các tài liệu PHP về cách gán một hàm ẩn danh, với từ khóa use, cho một biến.

ps: Tôi nghĩ rằng lần đầu tiên tôi đã biết về thủ thuật gán biến này bởi @gmazzap, để giúp loại bỏ cuộc gọi lại của bộ lọc ẩn danh dễ dàng hơn.

Hy vọng nó giúp!


Cảm ơn birgire, tử tế và trả lời chính xác như mọi khi. Bạn có khuyên bạn nên xác định một chức năng bên trong một chức năng bằng cách sử dụng một biến duy nhất toàn cầu không? Nếu có, bạn có thể vui lòng cho tôi biết tại sao?
Jack Johansson

Đó sẽ không phải là một ý tưởng tốt, nếu chúng ta cần sử dụng lại chức năng đó và nó bị mắc kẹt trong phạm vi của chức năng khác và sẽ khó khăn hơn cho các nhà phát triển khác, ví dụ như bỏ qua bộ lọc với các cuộc gọi lại ẩn danh. Vì vậy, với tư cách là một plugin chính thức cho repo wp.org, rất có thể tôi sẽ cố gắng cho phép các nhà phát triển khác loại bỏ các bộ lọc dễ dàng nhất có thể ;-) Nói chung tôi cũng sẽ cố gắng tránh thêm nhiều toàn cầu, vì có thể có nhiều vấn đề khác nhau với điều đó tiếp cận. Nếu chúng ta đi vào một góc với cấu trúc plugin của mình, thì có thể đó là dấu hiệu để sử dụng cấu trúc thay thế, bất kể đó là gì ;-)
birgire

Tôi đoán tôi đang đi với cách tiếp cận thứ 3 của bạn. Có vẻ để làm việc trong trường hợp của tôi. Chúc mừng!
Jack Johansson

chắc chắn bất cứ điều gì làm việc tốt nhất cho bạn. Tôi có thể đi với số 1 hoặc số 2 mà không có chức năng bất thường để dễ dàng xóa nó một lần nữa ;-) @JackJohansson
birgire

2
Chúng tôi thực sự có thể chuyển các đối số tùy chỉnh và các giá trị của chúng WP_Queryđể nhắm mục tiêu một thể hiện cụ thể và truy cập nó thông qua các bộ lọc khác nhau như posts_where, pre_get_postsposts_clauses. Đó là những gì chúng tôi làm trong cách tiếp cận # 2.
bạch dương

4

Bạn có thể sử dụng usetừ khóa của PHP . Vì vậy, với sự trợ giúp của usetừ khóa này, bạn có thể mang lại biến trong một hàm. Và bạn cũng có thể viết hàm ẩn danh để giảm mã. Vì vậy, toàn bộ điều sẽ

/**
 * How to get shorcode's input values inside a filter?
 *
 * @param $atts
 */
function my_shortcode_function($atts){
    $value = $atts['id'];
    add_filter('posts_where',function() use ( $value ){
        echo $value;
    });

}
add_shortcode('my-shortcode','my_shortcode_function');

Mong rằng sẽ giúp.


Điều này thật tuyệt, nhưng các chức năng ẩn danh rất khó để mở ra.
Dave Romsey

2
Ôi, loại bỏ chức năng ẩn danh hiện đã được @birgire trình bày trong một câu trả lời khác cho câu hỏi. Mát mẻ!
Dave Romsey

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.