วิธีรับค่าอินพุตของรหัสย่อภายในตัวกรอง


9

ฉันพยายามรับค่าอินพุตของรหัสย่อภายในฟังก์ชันที่ใช้โดยตัวกรอง แต่ดูเหมือนจะไม่สำเร็จ นี่คือสิ่งที่ฉันทำ:

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

ตอนนี้ฉันรู้ว่าการใช้$valueข้างในfilter_value()จะไม่ทำงานเนื่องจากขอบเขตของตัวแปร แต่การใช้$GLOBALS['value']ไม่ได้ผล

ฉันพยายามใช้$value = $atts['id']ภายในfilter_value();แต่ก็ไม่ประสบความสำเร็จเช่นกัน

ฉันจะใช้รหัสย่อเช่น[my-shortcode id='123']และส่งค่า 123 ไปยังตัวกรองได้อย่างไร

ขอบคุณ

คำตอบ:


7

ใช้ตัวแปรทั่วโลกจะทำงาน นี่คือการสาธิต:

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;
}

บันทึก Side, ประกาศฟังก์ชั่นภายในฟังก์ชันอื่นไม่ได้เป็นแนวปฏิบัติที่ดี


นี่มันแปลกจริงๆ ถ้าฉันตั้งค่าการใช้$GLOBALS['value'] = some valueแล้วเรียก$GLOBALS['value']มันใช้งานได้ แต่ถ้าฉันตั้งค่าโดยตรงเป็น$value = some valueแล้วโทรมันใช้$GLOBALS['value']มันไม่ทำงานในขณะที่มันควรจะทำงานตามคู่มือ PHP
Jack Johansson

คุณต้องตั้งค่า$valueเป็นขอบเขตส่วนกลางด้วยglobal $value;ก่อนที่จะเริ่มต้นด้วยค่า เช่นglobal $value; $value = $a['id']; จากนั้นในตัวกรองที่คุณสามารถทำได้global $value; echo $value;ช่วยได้ไหม?
Dave Romsey

ใช่ขอบคุณ. ผมอ่านเรื่องนี้ในคู่มือการใช้งานและในตัวอย่างแรกค่าที่มีการกำหนดไว้โดยตรง ฉันต้องกำหนดพวกมันนอกฟังก์ชั่น ANY เพื่อให้สามารถใช้งานได้โดยตรง$GLOBALS['value'];หรือไม่
Jack Johansson

2
เย็น. ดีใจที่เราได้รับมัน ในตัวอย่างแรกจากเอกสารเหล่านั้นตัวแปรจะถูกประกาศนอกฟังก์ชั่นและภายในขอบเขตส่วนกลาง ดังนั้นไม่globalจำเป็นต้องใช้คำหลัก ในตัวอย่างของเราเราได้ทำงานจากภายในขอบเขตของฟังก์ชันจึงglobalจำเป็นต้องใช้คำหลัก
Dave Romsey

1
ตัวกรองเป็นเพื่อนของเรา! :-) ฉันแน่ใจว่ามีผู้ตอบคำถามกระตือรือร้นที่จะตอบคำถามของคุณหากคุณต้องการความช่วยเหลือเพิ่มเติม!
Dave Romsey

7

นี่คือวิธีแก้ปัญหาบางอย่าง:

วิธีการ # 1

คุณสามารถตัดคำจำกัดความposts_whereของรหัสย่อและการเรียกกลับของตัวกรองในคลาสเพื่อให้สามารถส่งผ่านค่าที่กำหนดระหว่างวิธีการเรียนเช่นเป็นตัวแปรส่วนตัว

วิธีการ # 2

อีกวิธีหนึ่งคือการส่งผ่านค่าเป็นอินพุตไปยังWP_Queryการเรียกกลับของรหัสย่อของคุณ:

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

จากนั้นภายในตัวกรอง posts_where ของคุณคุณสามารถเข้าถึงได้:

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

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

    return $where;

}, 10, 2 );

วิธีการ # 3

... หรือคุณสามารถปรับตัวอย่างโดย @the_dramatist เพื่อให้สามารถลบการเรียกกลับหลังจากนั้นโดยการกำหนดฟังก์ชันที่ไม่ระบุชื่อให้กับตัวแปร:

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

ตรวจสอบเช่นเอกสาร PHPเกี่ยวกับวิธีการกำหนดฟังก์ชั่นที่ไม่ระบุชื่อกับคำหลักการใช้งานให้กับตัวแปร

ป.ล. : ฉันคิดว่าฉันได้เรียนรู้เกี่ยวกับตัวแปรนี้เป็นครั้งแรกโดยใช้ @gmazzap เพื่อให้ง่ายต่อการลบการโทรกลับของตัวกรองที่ไม่ระบุชื่อ

หวังว่ามันจะช่วย!


ขอบคุณ Birgire, ชนิดและคำตอบที่แม่นยำเช่นเคย คุณแนะนำให้กำหนดฟังก์ชั่นภายในฟังก์ชั่นมากกว่าโดยใช้ตัวแปรที่ไม่ซ้ำกันทั่วโลกหรือไม่? ถ้าใช่คุณช่วยเล่าได้ไหม
Jack Johansson

นั่นไม่ใช่ความคิดที่ดีถ้าเราจำเป็นต้องใช้ฟังก์ชั่นนั้นซ้ำอีกครั้งและมันติดอยู่ในขอบเขตของฟังก์ชั่นอื่นและมันจะยากสำหรับผู้พัฒนารายอื่นเช่นข้ามตัวกรองด้วยการเรียกกลับที่ไม่ระบุชื่อ ดังนั้นในฐานะที่เป็นปลั๊กอินอย่างเป็นทางการสำหรับ wp.org repo ฉันมักจะพยายามอนุญาตให้นักพัฒนารายอื่นสามารถลบตัวกรองได้ง่ายที่สุด ;-) โดยทั่วไปแล้วฉันจะพยายามหลีกเลี่ยงการเพิ่ม Globals มากขึ้นเนื่องจากอาจมีปัญหาต่าง ๆ เข้าใกล้ หากเราได้รับในมุมที่มีโครงสร้างปลั๊กอินของเราแล้วบางทีมันอาจจะเป็นสัญญาณที่จะใช้โครงสร้างทางเลือกสิ่งที่อาจจะ ;-)
birgire

ฉันเดาว่าฉันจะใช้วิธีที่ 3 ของคุณ ดูเหมือนว่าจะทำงานในกรณีของฉัน ไชโย!
Jack Johansson

แน่ใจว่าสิ่งที่ดีที่สุดสำหรับคุณ ฉันอาจจะไปกับ # 1 หรือ # 2 โดยไม่มีฟังก์ชั่น anyomous เพื่อลบออกได้อย่างง่ายดายอีกครั้ง ;-) @JackJohansson
birgire

2
เราจริงสามารถส่งผ่านข้อโต้แย้งที่กำหนดเองและค่านิยมของพวกเขาเพื่อWP_Queryที่จะกำหนดเป้าหมายอินสแตนซ์ที่ได้รับและเข้าถึงได้ผ่านตัวกรองต่างๆเช่นposts_where, และpre_get_posts posts_clausesนั่นคือสิ่งที่เราทำในแนวทางที่ 2
Birgire

4

คุณสามารถใช้useคำหลักของPHP ดังนั้นด้วยความช่วยเหลือของuseคำสำคัญนี้คุณสามารถนำตัวแปรภายในฟังก์ชั่น และคุณสามารถเขียนฟังก์ชันที่ไม่ระบุชื่อเพื่อลดรหัส ดังนั้นสิ่งทั้งหมดจะเป็น -

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

หวังว่าจะช่วย


ฟังก์ชั่นนี้ยอดเยี่ยม แต่ฟังก์ชั่นนิรนามนั้นยากที่จะปลดล็อค
Dave Romsey

2
Ooh, การลบฟังก์ชั่นที่ไม่ระบุชื่อได้ถูกครอบคลุมโดย @birgire ในคำตอบสำหรับคำถามอื่น เย็น!
Dave Romsey

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.